@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
@@ -5,10 +5,12 @@
5
5
  import { fastagentVersion } from "../version.js";
6
6
  import { buildProgram } from "./kernel.js";
7
7
  import { DEPLOY_HOSTS } from "../deploy/hosts.js";
8
+ import { unsupportedRuntime } from "../runtime.js";
9
+ import { failStartup } from "./fail.js";
8
10
  // Help groups (clig: most common commands first) — the authoring loop leads, operations close.
9
- const DIR_ARG = {
10
- name: "[dir]",
11
- description: "workspace directory (the agent is here, or in a directory inside it)",
11
+ const AGENT_ARG = {
12
+ name: "[agent]",
13
+ description: "the agent directory, the one holding fastagent.config.ts",
12
14
  default: ".",
13
15
  };
14
16
  const MODEL = {
@@ -25,13 +27,6 @@ const BIND = {
25
27
  flags: "--bind <addr>",
26
28
  description: "bind address (dev defaults to 127.0.0.1; start defaults to all interfaces, which containers need)",
27
29
  };
28
- const NO_INVOKE = {
29
- flags: "--no-invoke",
30
- description: "do not serve POST /invoke on this run, nor POST /run — both are unauthenticated and run a turn with the " +
31
- "agent's full tools, so a serve meant to be reached only through its channels' signed webhooks should withhold " +
32
- "them (fastagent.config.ts http.invoke: false is the same choice, but it travels into a deployed image; this " +
33
- "flag outranks http.run: true, because a flag is what a definition you cannot edit still answers to)",
34
- };
35
30
  const TUNNEL = {
36
31
  flags: "--tunnel",
37
32
  description: "expose a public HTTPS URL via a Cloudflare quick tunnel (needs cloudflared) and auto-register " +
@@ -40,51 +35,42 @@ const TUNNEL = {
40
35
  };
41
36
  const init = {
42
37
  name: "init",
43
- summary: "scaffold a runnable agent and install its dependencies",
44
- description: "Scaffold a runnable agent and run npm install. The agent ALWAYS goes into a subdirectory of dir " +
45
- "(default .): ./fastagent/, or --agent-dir <name> — the rest of the directory gets zero writes, and " +
46
- "it is the WORKSPACE the agent works ON when you point fastagent there. Content is a " +
47
- "self-iterating agent: APPEND_SYSTEM.md (its standing instructions), a writing-great-skills " +
48
- "example skill, a fetch-url code tool, config, package.json, .gitignore. An existing AGENTS.md is " +
49
- "kept as project context.",
50
- args: [DIR_ARG],
38
+ summary: "create an agent in a directory of its own and install its dependencies",
39
+ description: "Create an agent in dir, which must be new or empty, then run npm install there. Content is a " +
40
+ "self-iterating agent: SYSTEM.md (its system prompt), a writing-great-skills " +
41
+ "example skill, config, package.json, .gitignore.",
42
+ args: [{ name: "<dir>", description: "the new agent's directory (created when missing)" }],
51
43
  flags: [
44
+ {
45
+ flags: "--content <source>",
46
+ description: "a directory or github:owner/repo the agent works on (repeatable): a repository in context.json, a " +
47
+ "directory of this machine in context.local.json",
48
+ repeatable: true,
49
+ },
52
50
  { flags: "--no-install", description: "scaffold everything but skip npm install" },
53
- { flags: "--agent-dir <name>", description: "name the agent directory (default fastagent)" },
54
51
  ],
55
52
  examples: [
56
- { cmd: "fastagent init", note: "the agent lands in ./fastagent/" },
57
- { cmd: "fastagent init my-project", note: "my-project/fastagent/ (created)" },
58
- { cmd: "fastagent init . --agent-dir bot", note: "./bot/ — any name works" },
53
+ { cmd: "fastagent init my-agent", note: "an agent that only talks" },
54
+ { cmd: "fastagent init reviewer --content ~/code/app", note: "works on ~/code/app" },
55
+ { cmd: "fastagent init triage --content github:acme/app", note: "works on a clone" },
59
56
  ],
60
- notes: "An agent is a directory holding a fastagent.config.ts — never its NAME, so --agent-dir can call it " +
61
- "anything (the name decides only which agent answers when a workspace holds several: see " +
62
- "FASTAGENT_AGENT). What the agent works ON (its cwd, where its AGENTS.md context is read from) is " +
63
- "the agent directory's parent — the project you ran init in — whether you point fastagent at the " +
64
- "project or at the agent directory. A directory resolves to ONE agent, at it or one level inside.",
57
+ notes: "An agent is a directory holding a fastagent.config.ts, and it is also the agent's working directory. " +
58
+ "It lives in a directory of its own, never inside a project or another agent: what it works on is declared " +
59
+ "as its content. Add a directory it only knows later with `fastagent content add <dir> --readonly`.",
65
60
  run: async (args, f) => (await import("./commands/init.js")).runInit(args[0], {
66
61
  install: f.install !== false,
67
- agentDir: typeof f.agentDir === "string" ? f.agentDir : undefined,
62
+ content: f.content ?? [],
68
63
  }),
69
64
  };
70
65
  const dev = {
71
66
  name: "dev",
72
67
  summary: "serve the agent locally, restarting on code edits",
73
- description: "Assemble the agent in dir (default .) and serve a local HTTP channel. SYSTEM.md/APPEND_SYSTEM.md/" +
74
- "AGENTS.md/skills/prompts " +
75
- "are re-read every turn (edits go live next turn); edits to code inputs — tools/, channels/, " +
76
- "fastagent.config.ts, package.json, .secrets/.env — restart the worker. Files the agent writes as " +
77
- "work product never trigger a restart.",
78
- args: [DIR_ARG],
79
- flags: [
80
- PORT,
81
- BIND,
82
- MODEL,
83
- { flags: "--no-watch", description: "serve once, no file-watching" },
84
- TUNNEL,
85
- NO_INVOKE,
86
- NO_INPUT,
87
- ],
68
+ description: "Open the agent (default .) and serve its channels, schedules and wake-ups. SYSTEM.md, AGENTS.md, " +
69
+ "skills/ and prompts/ are re-read for every message (edits go live with the next one); edits to code inputs " +
70
+ "(src/, fastagent.config.ts, package.json, .secrets/.env) restart the worker once its running messages finish. " +
71
+ "Files the agent writes as work product never trigger a restart.",
72
+ args: [AGENT_ARG],
73
+ flags: [PORT, BIND, MODEL, { flags: "--no-watch", description: "serve once, no file-watching" }, TUNNEL, NO_INPUT],
88
74
  examples: [
89
75
  { cmd: "fastagent dev" },
90
76
  { cmd: "fastagent dev --tunnel", note: "public URL + registered/guided webhooks" },
@@ -95,29 +81,16 @@ const dev = {
95
81
  model: f.model,
96
82
  watch: f.watch !== false,
97
83
  tunnel: f.tunnel === true,
98
- ...(f.invoke === false ? { invoke: false } : {}),
99
84
  input: f.input !== false,
100
85
  }),
101
86
  };
102
- const chat = {
103
- name: "chat",
104
- summary: "open the SAME assembled agent in pi's interactive TUI",
105
- description: "Open the SAME assembled agent in pi's interactive TUI (the real harness, not a crude REPL) — to " +
106
- "try it locally before serving. Same model/tool/skill/auth resolution as dev; pi handles " +
107
- "rendering, sessions, and /resume natively (its /login writes to the same fastagent auth file).",
108
- args: [DIR_ARG],
109
- flags: [MODEL],
110
- examples: [{ cmd: "fastagent chat" }],
111
- run: async (args, f) => (await import("./commands/chat.js")).runChat(args[0], { model: f.model }),
112
- };
113
87
  const info = {
114
88
  name: "info",
115
- summary: "print what the directory assembles into, without serving",
116
- description: "Print what dir (default .) ASSEMBLES into — model, prompt, context files (AGENTS.md), skills, " +
117
- "tools (+ collisions), channels, schedules, sessions, load diagnostics — WITHOUT serving. " +
118
- "Read-only (never creates sessions / writes .gitignore); an unset model is reported, not fatal. " +
89
+ summary: "print what the directory builds into, without serving",
90
+ description: "Print what the agent (default .) builds into — model, tools, extensions, channels, schedules, commands, " +
91
+ "secrets, content — WITHOUT opening or serving it. An unset model or secret is reported, not fatal. " +
119
92
  "Run it first when something looks off.",
120
- args: [DIR_ARG],
93
+ args: [AGENT_ARG],
121
94
  flags: [JSON_FLAG, MODEL],
122
95
  examples: [{ cmd: "fastagent info" }, { cmd: "fastagent info --json", note: "for CI" }],
123
96
  run: async (args, f) => (await import("./commands/info.js")).runInfo(args[0], {
@@ -125,71 +98,74 @@ const info = {
125
98
  model: f.model,
126
99
  }),
127
100
  };
128
- const tool = {
129
- name: "tool",
130
- summary: "run one tool directly with JSON args — no model, no server, no tokens",
131
- description: "Run one tool (from tools/ or config.tools) directly with JSON args — no model, no server, no " +
132
- "tokens. Fast feedback while authoring a tool.",
133
- args: [
134
- { name: "<name>", description: "the tool name as served (see `fastagent info`)" },
135
- { name: "[json-args]", description: "the tool's arguments as a JSON object", default: "{}" },
136
- DIR_ARG,
137
- ],
138
- examples: [{ cmd: `fastagent tool add '{"a":2,"b":3}'` }],
139
- notes: "Mounts the same tool set dev/start serve (all coding tools + config.tools + discovered tools/, " +
140
- "deduped), so a shadowed or broken tool is surfaced here exactly as it would be when serving.",
141
- run: async (args) => (await import("./commands/tool.js")).runTool(args[0], args[1], args[2]),
142
- };
143
101
  const invoke = {
144
102
  name: "invoke",
145
- summary: "run ONE turn against the assembled agent and exit",
146
- description: "Run ONE turn against the assembled agent and exit — no server, no TUI. The reply streams to " +
147
- "stdout, tool/diagnostics to stderr, a failed turn exits non-zero. The all-agent counterpart of " +
148
- "`tool`, for CI smoke and quick checks. Same model resolution as dev.",
149
- args: [{ name: "<message>", description: "the user message for the turn" }, DIR_ARG],
150
- flags: [MODEL, NO_INPUT],
151
- examples: [{ cmd: `fastagent invoke "summarize today's inbox"` }],
103
+ summary: "send ONE message to the agent and exit",
104
+ description: "Send ONE message to the agent and exit — no server. The answer streams to stdout, tool/diagnostics to " +
105
+ "stderr; --json prints the receipt and the message's events as JSON lines instead. A message that does not " +
106
+ "complete exits non-zero. Each run starts a new session and prints its id on stderr; --session <id> sends " +
107
+ "the message into that session instead, continuing it. Sessions are kept in <state>/invoke.sqlite, apart " +
108
+ "from the storage a serve holds, so it runs beside `dev`; one invoke of an agent runs at a time. Same model " +
109
+ "resolution as dev, a continued session included. --url <base> sends it to a served agent instead, over its " +
110
+ "Agent API, with the same output and exit code: a deployment checked as the agent was before it, with the " +
111
+ "key --key gives or the first FASTAGENT_API_KEY in .secrets/production/.env, which deploy writes. For CI " +
112
+ "smoke and quick checks, by a person or a coding agent.",
113
+ args: [{ name: "<message>", description: "the message to send" }, AGENT_ARG],
114
+ flags: [
115
+ MODEL,
116
+ NO_INPUT,
117
+ { flags: "--json", description: "the receipt and the message's events as JSON lines on stdout" },
118
+ { flags: "--session <id>", description: "continue the session an earlier invoke printed" },
119
+ { flags: "--url <base>", description: "send to the agent served at <base>, over its Agent API" },
120
+ { flags: "--key <key>", description: "the API key for --url (default: the agent's production one)" },
121
+ ],
122
+ examples: [
123
+ { cmd: `fastagent invoke "summarize today's inbox"` },
124
+ { cmd: `fastagent invoke "remember 42"`, note: "prints its session's id" },
125
+ { cmd: `fastagent invoke --session <id> "which number?"` },
126
+ { cmd: `fastagent invoke --url https://a.fly.dev "hello"`, note: "a deployment" },
127
+ ],
152
128
  run: async (args, f) => (await import("./commands/invoke.js")).runInvoke(args[0], args[1], {
153
129
  model: f.model,
154
130
  input: f.input !== false,
131
+ json: f.json === true,
132
+ ...(typeof f.session === "string" ? { session: f.session } : {}),
133
+ ...(typeof f.url === "string" ? { url: f.url } : {}),
134
+ ...(typeof f.key === "string" ? { key: f.key } : {}),
155
135
  }),
156
136
  };
157
137
  const models = {
158
138
  name: "models",
159
139
  summary: 'list the available "provider/modelId" model specs',
160
- description: 'List every "provider/modelId" spec the agent in this directory can name (pi\'s built-ins, the model ' +
161
- "catalogs and models.json files, its own over the machine's) — use one with --model or as `model` in " +
162
- "fastagent.config.ts. Outside an agent, or with -g, list the machine's.",
140
+ description: 'List every "provider/modelId" spec the agent in this directory can name (pi-ai\'s built-ins, with the models ' +
141
+ "pi's published catalog adds to them, and the providers its fastagent.config.ts declares) — use one with " +
142
+ "--model or as `model` in fastagent.config.ts. Outside an agent, or with -g, list the built-ins without the " +
143
+ "agent's providers. Every command that opens the agent refreshes the lists, asking at most every 4 hours once " +
144
+ "one is kept; --refresh asks now, and exits 1 when it cannot.",
163
145
  args: [{ name: "[search]", description: "case-insensitive substring filter" }],
164
146
  flags: [
165
- {
166
- flags: "--refresh",
167
- description: "fetch the model catalog first, into the agent's models-store.json (with -g, the machine's)",
168
- },
169
- { flags: "-g, --global", description: "the machine's catalog, ~/.fastagent/models-store.json" },
147
+ { flags: "-g, --global", description: "the built-ins, without the agent's providers" },
148
+ { flags: "--refresh", description: "fetch the model lists now, even when the kept ones are fresh" },
149
+ { flags: "--json", description: "the specs as JSON: spec, provider, id and name of each (its id, unnamed)" },
170
150
  ],
171
151
  examples: [
172
152
  { cmd: "fastagent models", note: "all specs" },
173
153
  { cmd: "fastagent models claude", note: "filter; provider-name matches rank first" },
174
- { cmd: "fastagent models --refresh", note: "models newer than the installed pi" },
154
+ { cmd: "fastagent models --refresh gpt", note: "a model released since the last refresh" },
175
155
  ],
176
- notes: "A refresh asks pi.dev for the providers the scope's credentials authenticate (the agent's, or with -g the " +
177
- "global auth.json and environment) and writes the answer to models-store.json. The agent's is part of the " +
178
- "definition: commit it, and it ships with a deploy. The machine's (-g) is read by every agent here and does " +
179
- "not ship. Nothing refreshes on its own.",
180
156
  run: async (args, f) => (await import("./commands/models.js")).runModels(args[0], {
181
- refresh: f.refresh === true,
182
157
  global: f.global === true,
158
+ refresh: f.refresh === true,
159
+ json: f.json === true,
183
160
  }),
184
161
  };
185
162
  const start = {
186
163
  name: "start",
187
- summary: "run the agent in production posture (same assembly as dev, no watching)",
188
- description: "Run the agent in dir (default .) in production posture — the SAME assembly as dev (your directory " +
189
- "is the agent), just no file-watching. No build step: start reads the definition directly; " +
190
- "model/http come from fastagent.config.ts (frozen by git).",
191
- args: [DIR_ARG],
192
- flags: [PORT, BIND, MODEL, TUNNEL, NO_INVOKE, NO_INPUT],
164
+ summary: "run the agent in production posture (opened as dev opens it, no watching)",
165
+ description: "Run the agent (default .) in production posture — opened as dev opens it (your directory " +
166
+ "is the agent), just no file-watching. model and http.port come from fastagent.config.ts.",
167
+ args: [AGENT_ARG],
168
+ flags: [PORT, BIND, MODEL, TUNNEL, NO_INPUT],
193
169
  examples: [
194
170
  { cmd: "fastagent start" },
195
171
  { cmd: "fastagent start --tunnel", note: "host a bot from your own box, no deploy" },
@@ -197,39 +173,37 @@ const start = {
197
173
  notes: "Precedence chains:\n" +
198
174
  " port: --port > PORT env > fastagent.config.ts http.port > 8787\n" +
199
175
  " bind: --bind > all interfaces (dev: 127.0.0.1)\n" +
200
- " /invoke: --no-invoke > fastagent.config.ts http.invoke > served\n" +
201
- " /run: --no-invoke > fastagent.config.ts http.run > http.invoke\n" +
202
- " (with GET /routines; both only where routines/ declares something)\n" +
203
- " state: FASTAGENT_STATE_DIR > <agent dir>/.state — mutable machine state\n" +
204
- " (sessions, channel state, schedule state); point it at a mounted\n" +
205
- " volume so a redeploy that replaces the directory never wipes it\n" +
206
- " secrets: FASTAGENT_SECRETS_DIR > <agent dir>/.secrets — .env + auth.json\n" +
207
- " sessions: <state>/sessions — no separate knob; move the state root\n" +
176
+ " state: FASTAGENT_STATE_DIR > <agent dir>/.state/production\n" +
177
+ " the agent's storage (agent.sqlite), channels, schedules; use a\n" +
178
+ " mounted volume so a redeploy never wipes it\n" +
179
+ " secrets: FASTAGENT_SECRETS_DIR > <agent dir>/.secrets/production\n" +
180
+ " .env + auth.json\n" +
181
+ " content: <agent dir>/content/<name> — a clone of github content; a\n" +
182
+ " deployment links content/ to its volume\n" +
208
183
  " auth: FASTAGENT_AUTH_PATH > <secrets>/auth.json\n" +
209
184
  " (project-level; point it at ~/.fastagent/.secrets/auth.json to\n" +
210
- " share one credential across projects)\n" +
211
- " endpoints: FASTAGENT_MODELS_PATH > ~/.fastagent/models.json, under the agent's\n" +
212
- " own models.json (the machine's; it does not ship with a deploy)",
185
+ " share one credential across projects)",
213
186
  run: async (args, f) => (await import("./commands/start.js")).runStart(args[0], {
214
187
  port: f.port,
215
188
  bind: f.bind,
216
189
  model: f.model,
217
190
  tunnel: f.tunnel === true,
218
- ...(f.invoke === false ? { invoke: false } : {}),
219
191
  input: f.input !== false,
220
192
  }),
221
193
  };
222
194
  const INGRESS = {
223
195
  flags: "--ingress <mode>",
224
- description: "Feishu/Lark ingress: websocket or webhook (interactive when omitted)",
196
+ description: "Feishu/Lark: set websocket or webhook in the selected environment; webhook also prepares its app now " +
197
+ "(unset: dev uses websocket, production uses webhook)",
225
198
  };
226
- const GROUP_BEHAVIOR = {
227
- flags: "--group-behavior <behavior>",
228
- description: "Slack/Feishu/Lark groups: context (recommended) or mentions (least privilege)",
199
+ const CHANNEL_ENVIRONMENT = {
200
+ flags: "--env <environment>",
201
+ description: "select independent app credentials and onboarding state (default: dev; production uses .secrets/production/.env)",
229
202
  };
230
203
  const NO_ONBOARD = {
231
204
  flags: "--no-onboard",
232
- description: "Slack: scaffold only; skip internal-app creation/OAuth",
205
+ description: "scaffold only: write the channel file (if missing) and its tools, and skip the app onboarding " +
206
+ "(Slack: internal-app creation/OAuth; Feishu/Lark: app creation and credential capture)",
233
207
  };
234
208
  const REPLACE_CONFIG = {
235
209
  flags: "--replace-config",
@@ -240,42 +214,61 @@ const channelSub = (kind, summary, description, notes) => ({
240
214
  name: kind,
241
215
  summary,
242
216
  description,
243
- args: [DIR_ARG],
217
+ args: [AGENT_ARG],
244
218
  flags: kind === "feishu" || kind === "lark"
245
- ? [INGRESS, GROUP_BEHAVIOR]
219
+ ? [CHANNEL_ENVIRONMENT, INGRESS, NO_ONBOARD, ...UNATTENDED_SETUP]
246
220
  : kind === "slack"
247
- ? [GROUP_BEHAVIOR, NO_ONBOARD, REPLACE_CONFIG]
248
- : [],
249
- examples: [{ cmd: `fastagent add ${kind}` }],
221
+ ? [CHANNEL_ENVIRONMENT, NO_ONBOARD, REPLACE_CONFIG, ...UNATTENDED_SETUP]
222
+ : [CHANNEL_ENVIRONMENT, JSON_FLAG],
223
+ examples: [
224
+ { cmd: `fastagent add ${kind}` },
225
+ ...(kind === "telegram" ? [] : [{ cmd: `fastagent add ${kind} --json`, note: "a coding agent" }]),
226
+ ],
250
227
  ...(notes ? { notes } : {}),
251
228
  run: async (args, f) => (await import("./commands/add.js")).runAddChannel(kind, args[0], {
252
229
  ingress: f.ingress,
253
- groupBehavior: f.groupBehavior,
230
+ environment: f.env,
254
231
  onboard: f.onboard !== false,
255
232
  replaceConfig: f.replaceConfig === true,
233
+ input: f.input !== false,
234
+ json: f.json === true,
235
+ ...(f.check !== undefined ? { check: f.check } : {}),
236
+ ...(f.timeout !== undefined ? { timeout: f.timeout } : {}),
237
+ ...(f.ticket !== undefined ? { ticket: f.ticket } : {}),
256
238
  }),
257
239
  });
240
+ /**
241
+ * How an app's setup runs with no one at a terminal: what the person provides is named, and their steps come back with
242
+ * a ticket to check (`add` in docs/cli.md).
243
+ */
244
+ const UNATTENDED_SETUP = [
245
+ { flags: "--json", description: "the outcome as one JSON object, with what to do next (agent_next_steps)" },
246
+ { flags: "--check <ticket>", description: "where a setup started without a terminal stands" },
247
+ { flags: "--timeout <seconds>", description: "how long that setup stays open (default 900)" },
248
+ { flags: "--ticket <id>", description: "the process that runs a ticket's setup", hidden: true },
249
+ NO_INPUT,
250
+ ];
258
251
  const add = {
259
252
  name: "add",
260
253
  summary: "connect a channel (telegram, slack, feishu, lark) or vendor a skill",
261
254
  description: "Scaffold channels/<kind>.ts — first-party adapter glue with the policy to edit in the optional " +
262
255
  "route() — or vendor an Agent Skills skill into skills/<name>/.",
263
256
  subcommands: [
264
- channelSub("telegram", "scaffold the Telegram bot channel (durable turns, live preview)", "Scaffold channels/telegram.ts — the Telegram bot channel with durable turns, a live-preview " +
257
+ channelSub("telegram", "scaffold the Telegram bot channel (durable turns, live preview)", "Scaffold src/channels/telegram.ts — the Telegram bot channel with durable turns, a live-preview " +
265
258
  "message pump, and an optional route() policy."),
266
- channelSub("slack", "scaffold the Slack Events API channel (files, threads, context, live preview)", "Choose group visibility, scaffold channels/slack.ts plus slack-send.ts, create a single-workspace " +
259
+ channelSub("slack", "scaffold the Slack Events API channel (files, threads, context, live preview)", "Scaffold src/channels/slack.ts plus its tools (src/tools/slack-send.ts, slack-threads.ts), create a single-workspace " +
267
260
  "internal Slack app from a manifest, and install it through OAuth. The channel provides signed " +
268
261
  "Events API ingress, durable turns, files, threads, context, and an edited live preview.", "Automated onboarding requires Slack App Configuration access + refresh tokens and a temporary " +
269
262
  "cloudflared tunnel. They stay in owner-readable local state and are never deployed; --no-onboard " +
270
263
  "keeps the explicit manual/scaffold-only path."),
271
- channelSub("feishu", "scaffold the Feishu channel AND create/configure the platform app", "Choose WebSocket or webhook, scaffold channels/feishu.ts, and create/configure the Feishu app " +
272
- "through scan-to-create, writing the matching credentials to .env.", "Feishu (open.feishu.cn) is the canonical implementation. WebSocket needs only App ID/Secret and " +
264
+ channelSub("feishu", "scaffold the Feishu channel AND create/configure the platform app", "Scaffold src/channels/feishu.ts and create/configure the Feishu app through scan-to-create, writing its " +
265
+ "credentials to the selected environment. Dev uses WebSocket; deploy --run creates a separate production app for webhook.", "Feishu (open.feishu.cn) is the canonical implementation. WebSocket needs only App ID/Secret and " +
273
266
  "no public URL; webhook additionally captures the Verification Token through a temporary tunnel. " +
274
- "Context-aware groups (recommended) request admin approval for im:message.group_msg before publish."),
275
- channelSub("lark", "scaffold the Lark (international) channel with guided credential setup", "Choose WebSocket or webhook, scaffold channels/lark.ts, and guide credential setup against the " +
276
- "international developer console.", "Lark international (open.larksuite.com) is Feishu's compatibility profile. WebSocket stops after " +
277
- "App ID/Secret validation; webhook and recommended context-aware group setup probe config " +
278
- "automation and fall back to explicit manual steps on the international config-route 404."),
267
+ "The app asks for the scopes that let the agent hear its group chats; any your tenant withholds are named."),
268
+ channelSub("lark", "scaffold the Lark (international) channel with guided credential setup", "Scaffold src/channels/lark.ts and guide credential setup against the international developer console. " +
269
+ "Dev uses WebSocket; deploy --run guides setup of a separate production app for webhook.", "Lark international (open.larksuite.com) is Feishu's compatibility profile. WebSocket stops after " +
270
+ "App ID/Secret validation and a permission check; webhook setup probes config automation and falls " +
271
+ "back to explicit manual steps on the international config-route 404."),
279
272
  {
280
273
  name: "skill",
281
274
  summary: "vendor an Agent Skills skill into skills/<name>/ (copied in, git-tracked)",
@@ -285,7 +278,7 @@ const add = {
285
278
  description: "a git ref (owner/repo/path, github default), a local path (./x, /abs), or a bare name " +
286
279
  "from your global skill dirs (~/.agents/skills, ~/.pi/agent/skills)",
287
280
  },
288
- DIR_ARG,
281
+ AGENT_ARG,
289
282
  ],
290
283
  flags: [
291
284
  { flags: "--update", description: "overwrite an existing skill (re-fetch from source); review with git diff" },
@@ -297,7 +290,9 @@ const add = {
297
290
  notes: "Writing your own skill needs no command: create skills/<name>/SKILL.md with name + " +
298
291
  "description frontmatter; it's auto-discovered. `add skill` is only for vendoring an " +
299
292
  "existing one.",
300
- run: async (args, f) => (await import("./commands/add.js")).runAddSkill(args[0], args[1], { update: f.update === true }),
293
+ run: async (args, f) => (await import("./commands/add.js")).runAddSkill(args[0], args[1], {
294
+ update: f.update === true,
295
+ }),
301
296
  },
302
297
  ],
303
298
  };
@@ -306,16 +301,18 @@ const deploy = {
306
301
  summary: "generate deploy artifacts + a runbook for docker, fly, railway, or agentcore (--run drives it)",
307
302
  description: "Generate Dockerfile/.dockerignore plus the target config and print an ordered runbook. " +
308
303
  "docker: fastagent.compose.yml, loopback port, persistent state volume. fly: fly.toml " +
309
- "(autostop=suspend, state→volume). railway: railway.json (healthcheck /health); its " +
310
- "volume/variables/App-Sleeping are dashboard/CLI steps the runbook states. agentcore: one " +
304
+ "(autostop=suspend, state→volume). railway: no config file; its volume/variables/App-Sleeping " +
305
+ "are dashboard/CLI steps the runbook states. agentcore: one " +
311
306
  "CloudFormation stack (AWS Bedrock AgentCore Runtime + forwarder Lambda for webhooks + " +
312
- "EventBridge rules for schedules; linux/arm64 image built locally). Durable ingress " +
313
- "remains operator-owned (agentcore's forwarder URL is the exception — the stack owns it).",
314
- args: [{ name: "<host>", description: "deploy target", choices: [...DEPLOY_HOSTS] }, DIR_ARG],
307
+ "the alarms the container sets for schedules and wake-ups; linux/arm64 image built locally). Durable ingress " +
308
+ "remains operator-owned (agentcore's forwarder URL is the exception — the stack owns it). " +
309
+ "Production values come from .secrets/production/.env, never the dev file. Interactive --run creates " +
310
+ "a separate Feishu/Lark production app when its credentials are missing.",
311
+ args: [{ name: "<host>", description: "deploy target", choices: [...DEPLOY_HOSTS] }, AGENT_ARG],
315
312
  flags: [
316
313
  {
317
314
  flags: "--run",
318
- description: "drive the target CLI to completion. Docker runs `docker compose up -d --build`; with a tunnel " +
315
+ description: "drive the target CLI to completion. Docker builds (pulling the base image) and runs `docker compose up -d`; with a tunnel " +
319
316
  "service, reads its URL and registers webhooks. Fly/Railway provision app/service + volume + " +
320
317
  "secrets + deploy + webhook setup. AgentCore builds/pushes the arm64 image and deploys the " +
321
318
  "stack (aws + docker CLIs). A model key in the value file travels; any other credential is a login on " +
@@ -334,16 +331,31 @@ const deploy = {
334
331
  description: "(railway --run) provision INTO the project this dir is already linked to (skip create); by " +
335
332
  "default --run refuses a pre-existing link (could be unrelated/production)",
336
333
  },
334
+ {
335
+ flags: "--json",
336
+ description: "with --run, for a coding agent: the deploy runs in a process of its own and the command returns its " +
337
+ "ticket, handing each step only a person can take (a host sign-in, a production app, the box's model " +
338
+ "login) to its user",
339
+ },
340
+ { flags: "--check <ticket>", description: "where a deploy started with --json stands" },
341
+ {
342
+ flags: "--code <code>",
343
+ description: "with --check: the code a host's approval page showed, when it could not reach this machine",
344
+ },
345
+ { flags: "--timeout <seconds>", description: "how long a deploy started with --json stays open (default 3600)" },
346
+ { flags: "--stop", description: "with --check: stop that deploy where it is (can leave the host half-changed)" },
347
+ { flags: "--ticket <id>", description: "the process that runs a ticket's deploy", hidden: true },
337
348
  NO_INPUT,
338
349
  ],
339
350
  examples: [
340
351
  { cmd: "fastagent deploy fly --run", note: "provision + deploy + webhooks" },
352
+ { cmd: "fastagent deploy fly --run --json", note: "a coding agent" },
341
353
  { cmd: "fastagent deploy docker --tunnel --run", note: "Compose + a public URL" },
342
354
  { cmd: "fastagent deploy railway", note: "print the runbook only" },
343
355
  { cmd: "fastagent deploy agentcore --run", note: "arm64 image + stack + webhooks" },
344
356
  ],
345
357
  notes: "Definition-read-only: the only writes are generated artifacts (never clobbered without " +
346
- "--force). A routine redeploy of an already-provisioned agent is just the host's own command " +
358
+ "--force). A plain redeploy of an already-provisioned agent is just the host's own command " +
347
359
  "(e.g. `railway up`).",
348
360
  run: async (args, f) => (await import("./commands/deploy.js")).runDeploy(args[0], args[1], {
349
361
  run: f.run === true,
@@ -351,61 +363,190 @@ const deploy = {
351
363
  force: f.force === true,
352
364
  intoLinked: f.intoLinked === true,
353
365
  input: f.input !== false,
366
+ json: f.json === true,
367
+ ...(f.check !== undefined ? { check: f.check } : {}),
368
+ ...(f.code !== undefined ? { code: f.code } : {}),
369
+ ...(f.timeout !== undefined ? { timeout: f.timeout } : {}),
370
+ ...(f.ticket !== undefined ? { ticket: f.ticket } : {}),
371
+ stop: f.stop === true,
354
372
  }),
355
373
  };
356
- const routine = {
357
- name: "routine",
358
- summary: "run and inspect the units of work this definition declares: run now, fire history, what exists",
374
+ const env = {
375
+ name: "env",
376
+ summary: "add, remove or list the commands the agent runs: its environment",
377
+ description: "The agent's environment is the `environment` of its context.json: `packages`, each a name from mise's registry " +
378
+ "or written with aqua:, github:, gitlab:, conda:, npm: or pypi:, with a version; `aptPackages`, Debian " +
379
+ "packages the image installs; and `variables`, the environment variables its commands read, each declared by " +
380
+ "name with a description (its value goes in .secrets/.env, never in context.json; every one is required). " +
381
+ "Variables are edited in context.json by hand. Nothing is locked: each place installs the newest release a " +
382
+ "version allows when it first needs a package, and the image installs every package when it is built. Run in " +
383
+ "the agent directory (the current one). The first change adds mise to the agent's package.json (one optional " +
384
+ "package per platform; npm installs this machine's), so nothing has to be installed first.",
359
385
  subcommands: [
360
386
  {
361
- name: "run",
362
- summary: "run ONE routine's turn immediately, without waiting for a clock",
363
- description: "Run ONE routine's turn immediately (authoring loop, like invoke) — runs routines/<name>.ts now, " +
364
- "whether or not it declares a cron. Reply→stdout; does NOT advance its fire state.",
365
- args: [{ name: "<name>", description: "the routine name (routines/<name>.ts)" }, DIR_ARG],
366
- flags: [MODEL, NO_INPUT],
367
- examples: [{ cmd: "fastagent routine run daily-digest" }],
368
- run: async (args, f) => (await import("./commands/routine-run.js")).runRoutine(args[0], args[1], {
369
- model: f.model,
370
- input: f.input !== false,
387
+ name: "add",
388
+ summary: "add packages: installed here first, then declared",
389
+ args: [{ name: "<packages...>", description: "name[@version] (default latest), or apt:<name> for the image" }],
390
+ examples: [
391
+ { cmd: "fastagent env add gh@2", note: "a CLI from mise's registry" },
392
+ { cmd: "fastagent env add npm:prettier@3", note: "an npm package" },
393
+ { cmd: "fastagent env add python uv pypi:markitdown", note: "PyPI, with its runtime" },
394
+ { cmd: "fastagent env add apt:chromium", note: "installed by the image" },
395
+ ],
396
+ run: async (args) => (await import("./commands/env.js")).runEnvAdd(args[0]),
397
+ },
398
+ {
399
+ name: "remove",
400
+ summary: "remove packages, by the name they are declared with",
401
+ args: [{ name: "<packages...>", description: "a declared package, or apt:<name>" }],
402
+ examples: [{ cmd: "fastagent env remove gh apt:chromium" }],
403
+ run: async (args) => (await import("./commands/env.js")).runEnvRemove(args[0]),
404
+ },
405
+ {
406
+ name: "list",
407
+ summary: "the declared packages and their versions, the variables and whether each has a value",
408
+ flags: [{ flags: "--json", description: "the packages, apt packages and variables as JSON" }],
409
+ examples: [{ cmd: "fastagent env list" }, { cmd: "fastagent env list --json" }],
410
+ run: async (_args, f) => (await import("./commands/env.js")).runEnvList({ json: f.json === true }),
411
+ },
412
+ {
413
+ name: "install",
414
+ summary: "install what context.json declares here, at the newest release each version allows",
415
+ description: "Install the agent's mise (adding it to package.json when it is not there), then every package context.json " +
416
+ "declares, at the newest release its version allows: a newer one where one is out. Not needed day to day " +
417
+ "(`add` installs what it adds, and every start installs what is missing): it is for a newer release, and " +
418
+ "for a clone that has not installed its mise yet.",
419
+ examples: [{ cmd: "fastagent env install", note: "after a clone, or for newer releases" }],
420
+ run: async () => (await import("./commands/env.js")).runEnvInstall(),
421
+ },
422
+ {
423
+ name: "exec",
424
+ summary: "run a command in the environment, with the agent's .secrets/.env",
425
+ args: [{ name: "<command...>", description: "the command and its arguments, after --", verbatim: true }],
426
+ examples: [{ cmd: "fastagent env exec -- gh --version" }],
427
+ run: async (args) => (await import("./commands/env.js")).runEnvExec(args[0]),
428
+ },
429
+ ],
430
+ notes: "`dev`, `start` and `invoke` install the declared packages that have no install here yet, and " +
431
+ "put them first on the PATH of what the agent runs; one already installed is kept, so a start needs no network. " +
432
+ "`dev` restarts when context.json changes. Apt packages are installed in the image; on Debian or Ubuntu a start " +
433
+ "here names the missing ones.",
434
+ };
435
+ const content = {
436
+ name: "content",
437
+ summary: "list, add or remove what the agent works on and knows",
438
+ description: "Content is a directory the agent works on (or only knows, with --readonly): a GitHub repository declared " +
439
+ "by name in context.json, shared with the agent and cloned at content/<name>, or a directory of this " +
440
+ "machine bound in context.local.json, which never leaves it.",
441
+ subcommands: [
442
+ {
443
+ name: "list",
444
+ summary: "each content entry, where it is, and whether the agent works on it or only knows it",
445
+ args: [AGENT_ARG],
446
+ flags: [JSON_FLAG],
447
+ examples: [{ cmd: "fastagent content list" }],
448
+ run: async (args, f) => (await import("./commands/content.js")).runContentList(args[0], f.json === true),
449
+ },
450
+ {
451
+ name: "add",
452
+ summary: "add a GitHub repository, or bind a directory of this machine, as content",
453
+ args: [{ name: "<source>", description: "a directory, or github:owner/repo" }, AGENT_ARG],
454
+ flags: [
455
+ { flags: "--readonly", description: "the agent knows it and does not write it" },
456
+ { flags: "--ref <ref>", description: "a repository: the branch, tag or commit to clone" },
457
+ { flags: "--name <name>", description: "its name (default: the directory's or repository's)" },
458
+ { flags: "--description <text>", description: "one sentence for the agent: what it is, how to treat it" },
459
+ ],
460
+ examples: [
461
+ { cmd: "fastagent content add ~/code/app", note: "works on" },
462
+ { cmd: "fastagent content add ~/handbook --readonly", note: "knows" },
463
+ { cmd: "fastagent content add github:acme/docs --readonly", note: "knows a clone" },
464
+ ],
465
+ notes: "The root of a GitHub checkout is declared in context.json as that repository, and bound in " +
466
+ "context.local.json to the checkout, used as it is on this machine. github:owner/repo is cloned into " +
467
+ "content/<name> when the agent starts, and brought up to date in place at each start where git can do so " +
468
+ "without touching the agent's work; so is a declared repository on any machine with no checkout bound. " +
469
+ "Any other directory is bound in context.local.json only: a deployed instance works without it. A bound " +
470
+ "directory may not contain the agent directory, nor sit inside it.",
471
+ run: async (args, f) => (await import("./commands/content.js")).runContentAdd(args[0], args[1], {
472
+ readonly: f.readonly === true,
473
+ ...(typeof f.ref === "string" ? { ref: f.ref } : {}),
474
+ ...(typeof f.name === "string" ? { name: f.name } : {}),
475
+ ...(typeof f.description === "string" ? { description: f.description } : {}),
371
476
  }),
372
477
  },
373
478
  {
374
- name: "history",
375
- summary: "print the recent fires of a routine",
376
- description: "Print a routine's recent fires: when each fired, completed/failed/skipped/interrupted, and how long it " +
377
- 'took — the answer to "did last night\'s run silently fail?". What the run SAID is in its session, a ' +
378
- "JSON-lines journal under the state root's sessions/ — which this command points at. Read-only.",
379
- args: [{ name: "<name>", description: "the routine name" }, DIR_ARG],
380
- flags: [{ flags: "--json", description: "the full records" }],
381
- examples: [{ cmd: "fastagent routine history daily-digest" }],
382
- run: async (args, flags) => (await import("./commands/routine.js")).runRoutineHistory(args[0], args[1], flags.json === true),
479
+ name: "remove",
480
+ summary: "remove a content entry from both files (a bound directory, and a clone, are left as they are)",
481
+ args: [{ name: "<name>", description: "the entry's name" }, AGENT_ARG],
482
+ examples: [{ cmd: "fastagent content remove app" }],
483
+ run: async (args) => (await import("./commands/content.js")).runContentRemove(args[0], args[1]),
383
484
  },
485
+ ],
486
+ };
487
+ const schedules = {
488
+ name: "schedules",
489
+ summary: "what will wake this agent up: list, run a schedule now, cancel a wake-up",
490
+ subcommands: [
384
491
  {
385
492
  name: "list",
386
- summary: "every declared routine, and when (or whether) a clock fires it",
387
- description: "List the routines this definition declares: the next cron instant for each that has one, and " +
388
- '"on demand" for each that does not — those are reached by name (POST /run, `routine run`). The agent\'s ' +
389
- "own pending wake-ups are listed too, prefixed `wake`: a different owner (the STATE, not the " +
390
- "definition), and only the agent cancels them (the `unwake` tool). Read-only.",
391
- args: [DIR_ARG],
493
+ summary: "every schedule (src/schedules/<name>.ts) and wake-up, with when it runs next",
494
+ description: "List the schedules this definition declares (defineSchedule in src/schedules/<name>.ts): the next cron " +
495
+ "instant, how the last run ended and the session its runs continue. The agent's own pending wake-ups are listed too, prefixed " +
496
+ "`wake`: a different owner (the STATE, not the definition), cancelled by the agent's `unwake` tool or " +
497
+ "`schedules unwake`. --json adds each schedule's retained fire history. It changes no state; like every " +
498
+ "command that reads the definition, it regenerates .fastagent/.",
499
+ args: [AGENT_ARG],
392
500
  flags: [JSON_FLAG],
393
- examples: [{ cmd: "fastagent routine list" }],
394
- run: async (args, flags) => (await import("./commands/routine.js")).runRoutineList(args[0], flags.json === true),
501
+ examples: [{ cmd: "fastagent schedules list" }],
502
+ run: async (args, flags) => (await import("./commands/schedules.js")).runSchedulesList(args[0], flags.json === true),
503
+ },
504
+ {
505
+ name: "run",
506
+ summary: "fire one schedule now, as its clock would",
507
+ description: "Fire the schedule <name> now, the way its clock would: in its own session, with its claim and outcome " +
508
+ "recorded (`schedules list` shows them). The answer goes to stdout, the fire's log to stderr; it exits " +
509
+ "non-zero unless its message completed. It opens the instance's storage, so it is refused while `dev` or " +
510
+ "`start` serves this agent, and they are refused while it runs; it is refused too while the instance holds " +
511
+ "messages a stopped serve left unfinished, which it would run and cut off: serve them to their end first.",
512
+ args: [{ name: "<name>", description: "the schedule, as src/schedules/<name>.ts names it" }, AGENT_ARG],
513
+ flags: [
514
+ {
515
+ flags: MODEL.flags,
516
+ description: "the default model, as for dev: the schedule's session takes it at its first fire, and keeps the one " +
517
+ "it took after that",
518
+ },
519
+ NO_INPUT,
520
+ ],
521
+ examples: [{ cmd: "fastagent schedules run daily-digest" }],
522
+ run: async (args, f) => (await import("./commands/schedules.js")).runScheduleNow(args[0], args[1], {
523
+ model: f.model,
524
+ input: f.input !== false,
525
+ }),
526
+ },
527
+ {
528
+ name: "unwake",
529
+ summary: "cancel one of the agent's pending wake-ups",
530
+ description: "Cancel the pending wake-up <id> (`schedules list` shows the ids), whatever session set it: the way to " +
531
+ "one set where nobody can message the agent, such as a schedule's own session. It is refused while `dev` " +
532
+ "or `start` serves this agent, since a serve's clock writes the same store.",
533
+ args: [{ name: "<id>", description: "the wake-up's id" }, AGENT_ARG],
534
+ examples: [{ cmd: "fastagent schedules unwake 3f1c…" }],
535
+ run: async (args) => (await import("./commands/schedules.js")).runUnwake(args[0], args[1]),
395
536
  },
396
537
  ],
397
538
  };
398
539
  const destroy = {
399
540
  name: "destroy",
400
- summary: "delete every AWS resource `deploy agentcore` created for a workspace",
541
+ summary: "delete every AWS resource `deploy agentcore` created for an agent",
401
542
  description: "AgentCore only, and it exists because `aws cloudformation delete-stack` is not enough: the S3 " +
402
543
  "artifact bucket and the ECR repository have to exist BEFORE the stack that reads from them, BOTH " +
403
544
  "log groups (the forwarder's and the runtime's own stdout) are created by AWS on first write so no " +
404
- "template mentions them, and a wake alarm is minted at runtime by the container — a schedule that " +
405
- "keeps retrying into a deleted Lambda. " +
406
- "Derives the same names from dir that deploy did. Without --run it deletes nothing and reports what " +
545
+ "template mentions them, and the EventBridge schedules (one per schedule, one per pending wake-up) " +
546
+ "are minted at runtime by the container — left behind, they keep firing into a deleted Lambda. " +
547
+ "Derives the same names from the agent directory that deploy did. Without --run it deletes nothing and reports what " +
407
548
  "is out there.",
408
- args: [{ name: "<host>", description: "deployed host", choices: ["agentcore"] }, DIR_ARG],
549
+ args: [{ name: "<host>", description: "deployed host", choices: ["agentcore"] }, AGENT_ARG],
409
550
  flags: [{ flags: "--run", description: "actually delete. Without it, this is a read-only inventory" }],
410
551
  // The other hosts need no command of their own, and saying which one to use belongs where it can be READ:
411
552
  // `<host>` has `choices`, so a `destroy fly` never reaches the command body.
@@ -428,10 +569,10 @@ const destroy = {
428
569
  const logs = {
429
570
  name: "logs",
430
571
  summary: "find and tail a deployed host's application logs",
431
- description: "Find the CloudWatch log group for the AgentCore stack derived from dir, then run aws logs tail. " +
572
+ description: "Find the CloudWatch log group for the AgentCore stack derived from the agent directory, then run aws logs tail. " +
432
573
  "The default Runtime source shows the agent process's own stdout/stderr; the forwarder source shows " +
433
574
  "the Lambda ingress transport logs.",
434
- args: [{ name: "<host>", description: "deployed host", choices: ["agentcore"] }, DIR_ARG],
575
+ args: [{ name: "<host>", description: "deployed host", choices: ["agentcore"] }, AGENT_ARG],
435
576
  flags: [
436
577
  { flags: "--source <source>", description: "agentcore log source: runtime (default) or forwarder" },
437
578
  { flags: "--since <duration>", description: "history window accepted by AWS CLI (for example 30m or 2h)" },
@@ -441,7 +582,7 @@ const logs = {
441
582
  { cmd: "fastagent logs agentcore --follow", note: "the agent process" },
442
583
  { cmd: "fastagent logs agentcore --source forwarder --follow", note: "Lambda ingress" },
443
584
  ],
444
- notes: "Read-only. Run it against the same workspace passed to deploy so it derives the same CloudFormation " +
585
+ notes: "Read-only. Run it against the same agent directory passed to deploy so it derives the same CloudFormation " +
445
586
  "stack name. It never changes FASTAGENT_LOG_LEVEL: AgentCore keeps start's production default, and " +
446
587
  "setting that environment knob to debug exposes the existing detailed turn trace when needed.",
447
588
  run: async (args, f) => (await import("./commands/logs.js")).runLogs(args[0], args[1], {
@@ -450,26 +591,42 @@ const logs = {
450
591
  follow: f.follow === true,
451
592
  }),
452
593
  };
594
+ const GLOBAL_AUTH = {
595
+ flags: "-g, --global",
596
+ description: "the global ~/.fastagent/.secrets/auth.json, which every agent here reads for a provider it has no other credential for",
597
+ };
453
598
  const login = {
454
599
  name: "login",
455
- summary: "authenticate a model provider (subscription/OAuth or API key)",
456
- description: "Authenticate a model provider into the project-level <agent dir>/.secrets/auth.json (outside an " +
457
- "agent it writes the global ~/.fastagent/.secrets/auth.json, and says so): pick a method " +
458
- "(subscription/OAuth or API " +
459
- "key), then a provider that offers it (configured status shown). [provider] takes the method from " +
460
- "what that provider supports, asked only when both. An agent READS the global store for a provider it has " +
461
- "no other credential for (its own file, a models.json key, an env variable), so `-g` logs in once for every " +
462
- "agent on this machine; it warns when an env variable already authenticates the provider.",
463
- args: [{ name: "[provider]", description: "provider id (skip the provider menu)" }],
600
+ summary: "sign in to a model provider (an account or an API key)",
601
+ description: "Sign in to a model provider into the agent's <agent dir>/.secrets/auth.json (outside an agent it writes the " +
602
+ "global ~/.fastagent/.secrets/auth.json, and says so), as pi's /login does: how to sign in (an account or an API " +
603
+ "key), then the provider, each with what authenticates it now. [provider] (its id or name) skips the provider " +
604
+ "menu; how is asked only when it offers both. An agent READS the global store for a provider it has no other " +
605
+ "credential for (its own file, a provider in its config that authenticates itself, an env variable), so `-g` " +
606
+ "signs in once for every agent on this machine; it warns when an env variable already authenticates the " +
607
+ "provider. Without a terminal (or with --no-input or --json), for a script or a coding agent, nothing is asked " +
608
+ "and nothing waits: a provider or --method not given is answered with the choices and a command for each (exit " +
609
+ "2); an account's sign-in starts in a process of its own and the command returns its address and a ticket at " +
610
+ "once, for the person to sign in at and `login --check <ticket>` to follow; an API key is named, for the person " +
611
+ "to set in the agent's .secrets/.env themselves.",
612
+ args: [{ name: "[provider]", description: "provider id or name (skip the provider menu)" }],
464
613
  flags: [
614
+ GLOBAL_AUTH,
615
+ { flags: "--method <how>", description: "account or api-key, for a provider that offers both" },
616
+ { flags: "--json", description: "the outcome as one JSON object, with what to do next (agent_next_steps)" },
617
+ { flags: "--check <ticket>", description: "where a sign-in started without a terminal stands" },
465
618
  {
466
- flags: "-g, --global",
467
- description: `store in ~/.fastagent/.secrets/auth.json — every agent here reads it for a provider it has no other credential for`,
619
+ flags: "--code <address>",
620
+ description: "with --check: the address the browser ended on, when it could not reach this machine",
468
621
  },
469
622
  {
470
- flags: "--deployment [host]",
471
- description: "log in this agent's deployment instead, on the box itself (docker, fly, railway, agentcore); the host may be left out " +
472
- "when the agent dir holds one host's deploy artifacts",
623
+ flags: "--timeout <seconds>",
624
+ description: "how long the sign-in stays open (default 600 without a terminal)",
625
+ },
626
+ { flags: "--ticket <id>", description: "the process that runs a ticket's sign-in", hidden: true },
627
+ {
628
+ flags: "--deployment <host>",
629
+ description: "log in this agent's deployment on <host> instead, on the box itself (docker, fly, railway, agentcore)",
473
630
  },
474
631
  { flags: "--stdio", description: "the box's half of --deployment", hidden: true },
475
632
  { flags: "--if-missing", description: "with --stdio: keep a stored credential for the provider", hidden: true },
@@ -477,23 +634,78 @@ const login = {
477
634
  ],
478
635
  examples: [
479
636
  { cmd: "fastagent login" },
480
- { cmd: "fastagent login openai" },
481
- { cmd: "fastagent login openai -g" },
482
- { cmd: "fastagent login openai-codex --deployment fly", note: "on the box" },
637
+ { cmd: "fastagent login openai", note: "ChatGPT, or an API key" },
638
+ { cmd: "fastagent login openai -g", note: "for every agent here" },
639
+ { cmd: "fastagent login openai --method account --json", note: "an agent" },
640
+ { cmd: "fastagent login --check 3f9a0c1d2e4b5a67 --json", note: "then" },
641
+ { cmd: "fastagent login openai --deployment fly", note: "on the box" },
483
642
  ],
484
- notes: "The positional is the PROVIDER (not a dir) — `cd` into your agent before logging in. " +
643
+ notes: "The positional is the PROVIDER (not a dir) — `cd` into your agent before logging in. Exit status: 0 signed in " +
644
+ "or waiting on the person (need_user_action), 1 cancelled, failed or expired, 2 a provider or method not given. " +
485
645
  "--deployment runs the login on the deployed box through the host's own shell (docker compose exec, fly ssh, " +
486
646
  "railway ssh, AgentCore's command shell); this terminal shows it, opens the browser, and catches the browser's " +
487
647
  "return to localhost (or asks you to paste that address when its port is taken). The box keeps the credential, " +
488
- "so it is the only holder of that grant, and logging in again replaces it there.",
648
+ "so it is the only holder of that grant, and logging in again replaces it there. Without a terminal, an " +
649
+ "account's sign-in on the box returns a ticket as a local one does, its process holding the box's shell; an API " +
650
+ "key is named, for the person to set in .secrets/production/.env before the next deploy carries it.",
489
651
  run: async (args, f) => (await import("./commands/login.js")).runLogin(args[0], {
490
652
  global: f.global === true,
491
653
  input: f.input !== false,
654
+ json: f.json === true,
655
+ ...(f.method !== undefined ? { method: f.method } : {}),
656
+ ...(f.timeout !== undefined ? { timeout: f.timeout } : {}),
657
+ ...(f.check !== undefined ? { check: f.check } : {}),
658
+ ...(f.code !== undefined ? { code: f.code } : {}),
659
+ ...(f.ticket !== undefined ? { ticket: f.ticket } : {}),
492
660
  ...(f.deployment !== undefined ? { deployment: f.deployment } : {}),
493
661
  stdio: f.stdio === true,
494
662
  ifMissing: f.ifMissing === true,
495
663
  }),
496
664
  };
665
+ const logout = {
666
+ name: "logout",
667
+ summary: "remove a provider's stored credential",
668
+ description: "Remove the credential `login` stored for a provider, from the agent's <agent dir>/.secrets/auth.json (outside " +
669
+ "an agent, or with -g, the global file), as pi's /logout does: a menu of the providers stored there, or the one " +
670
+ "named. Environment variables, and the grant at the provider, are left as they are.",
671
+ args: [{ name: "[provider]", description: "provider id or name (required without a terminal)" }],
672
+ flags: [GLOBAL_AUTH, NO_INPUT],
673
+ examples: [{ cmd: "fastagent logout" }, { cmd: "fastagent logout openai-codex" }],
674
+ run: async (args, f) => (await import("./commands/logout.js")).runLogout(args[0], {
675
+ global: f.global === true,
676
+ input: f.input !== false,
677
+ }),
678
+ };
679
+ const auth = {
680
+ name: "auth",
681
+ summary: "check a model provider's credential (for scripts and agents)",
682
+ subcommands: [
683
+ {
684
+ name: "check",
685
+ summary: "is a provider ready: prints ready, not_ready or invalid",
686
+ description: "Check what authenticates a provider for the agent here (outside an agent, or with -g, for the global " +
687
+ "file), as pi's `auth check` does: prints ready, not_ready or invalid, and exits 0, 1 or 2. --model names " +
688
+ "the provider by a model of it; a login due a refresh is refreshed, as a message would. --json prints " +
689
+ "{status, provider, authType | reason, source, path}.",
690
+ flags: [
691
+ { flags: "--provider <id>", description: "the provider to check" },
692
+ { flags: "--model <provider/modelId>", description: "the provider of this model" },
693
+ GLOBAL_AUTH,
694
+ JSON_FLAG,
695
+ ],
696
+ examples: [
697
+ { cmd: "fastagent auth check --provider openai" },
698
+ { cmd: "fastagent auth check --model openai/gpt-5.5 --json" },
699
+ ],
700
+ run: async (_args, f) => (await import("./commands/auth.js")).runAuthCheck({
701
+ ...(f.provider !== undefined ? { provider: f.provider } : {}),
702
+ ...(f.model !== undefined ? { model: f.model } : {}),
703
+ global: f.global === true,
704
+ json: f.json === true,
705
+ }),
706
+ },
707
+ ],
708
+ };
497
709
  /**
498
710
  * Registration order = help order — the ORIGINAL usage wall's order, kept verbatim (this is a commander refactor of
499
711
  * the same CLI, not a redesign).
@@ -502,17 +714,19 @@ export const specs = [
502
714
  init,
503
715
  models,
504
716
  info,
505
- tool,
717
+ content,
718
+ env,
506
719
  invoke,
507
- routine,
720
+ schedules,
508
721
  dev,
509
- chat,
510
722
  start,
511
723
  add,
512
724
  deploy,
513
725
  logs,
514
726
  destroy,
515
727
  login,
728
+ logout,
729
+ auth,
516
730
  ];
517
731
  /** The production program assembly (specs + the top-level examples/docs). */
518
732
  export function buildCliProgram(overrides = {}) {
@@ -528,5 +742,9 @@ export function buildCliProgram(overrides = {}) {
528
742
  }
529
743
  /** Parse and run one CLI invocation (`argv` = process.argv). */
530
744
  export async function runCli(argv) {
745
+ // Before any command loads the storage: an older Bun fails that import with a message that says nothing of Bun.
746
+ const unsupported = unsupportedRuntime();
747
+ if (unsupported !== undefined)
748
+ failStartup(new Error(unsupported));
531
749
  await buildCliProgram({ version: await fastagentVersion() }).parseAsync([...argv]);
532
750
  }