@fastagent-sh/fastagent 0.24.4 → 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 -535
  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 -92
  455. package/dist/engines/pi/turn-kit.js +0 -288
  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,32 +1,35 @@
1
- /**
2
- * `fastagent login [provider]`: authenticate a model provider into the project-level auth file
3
- * (`<agentDir>/.secrets/auth.json`) by default, or `FASTAGENT_AUTH_PATH`. `--deployment` runs the same login on this
4
- * workspace's deployed box instead (box-login.ts); `--stdio` is the box's half of that.
5
- */
6
- import { existsSync } from "node:fs";
7
- import { join } from "node:path";
8
- import { enterAgentEnv } from "../../env.js";
9
- import { GLOBAL_AUTH_PATH, resolveAuthPath } from "../../engines/pi/auth.js";
10
- import { agentModels } from "../../engines/pi/agent-models.js";
1
+ import { enterAgentEnv, dotEnvPath } from "../../env.js";
2
+ import { GLOBAL_AUTH_PATH, resolveAuthPath, } from "../../harnesses/models/credentials.js";
3
+ import { modelEnvironment } from "../../harnesses/models/environment.js";
11
4
  import { DEPLOY_HOSTS } from "../../deploy/hosts.js";
12
- import { findAgentDir, globalHome, placementDeadEnd, resolvePlacement } from "../../paths.js";
13
- import { LoginCancelled, loginFlow } from "../../engines/pi/login.js";
14
- import { environmentAuthSource } from "../../engines/pi/models.js";
15
- import { loginOnBox } from "../box-login.js";
16
- import { failStartup, failUsage, placementOrExit } from "../fail.js";
5
+ import { findAgentDir, globalHome, selectAgentEnvironment } from "../../paths.js";
6
+ import { LoginCancelled, LoginRefused, PI_DEFAULT_MODELS, chooseLogin, loginFlow, loginOptionsOver, loginOver, loginStatusText, } from "../../harnesses/models/login.js";
7
+ import { environmentAuth, keyVariables, loginProviders } from "../../harnesses/models/models.js";
8
+ import { definitionProviders, loadConfig, modelSpecFor } from "../../harnesses/pi-durable/open.js";
9
+ import { loginOnBox, ticketLoginIO } from "../box-login.js";
10
+ import { deploymentLoginCommand } from "../../deploy/box-shell.js";
11
+ import { agentDirOrExit, failStartup, failUsage, optionalAgentDirOrExit } from "../fail.js";
12
+ import { printReport, refusedCheck, checkTicket, runTicket, startTicket, ticketExitCode, ticketReport, } from "../ticket.js";
17
13
  import { stdioLoginIO } from "../login-relay.js";
18
14
  import { isInteractive, terminalLoginIO } from "../shared.js";
19
15
  import { HOSTS } from "./deploy.js";
16
+ /** The command that reads a sign-in's ticket, as every such ticket records it. */
17
+ const LOGIN_CHECK = "fastagent login --check";
18
+ /** Without a terminal, how long a sign-in stays open for the person to finish it. */
19
+ const UNATTENDED_TIMEOUT_SECONDS = 600;
20
20
  export async function runLogin(provider, opts) {
21
21
  if (opts.stdio)
22
22
  return runStdioLogin(provider, opts);
23
23
  if (opts.deployment !== undefined)
24
24
  return runDeploymentLogin(provider, opts);
25
- const cwd = process.cwd();
26
- const agentDir = findAgentDir(cwd);
27
- // "Outside an agent" must mean exactly that.
28
- if (!agentDir && placementDeadEnd(cwd))
29
- placementOrExit(cwd);
25
+ if (opts.check !== undefined)
26
+ return runCheck(opts.check, opts);
27
+ if (opts.code !== undefined)
28
+ failUsage("--code hands an address to a sign-in: pass --check <ticket> too");
29
+ const method = opts.method === undefined ? undefined : methodOf(opts.method);
30
+ const givenTimeout = opts.timeout === undefined ? undefined : secondsOf(opts.timeout);
31
+ // "Outside an agent" must mean exactly that: inside one is refused (findAgentDir), never a global login.
32
+ const agentDir = optionalAgentDirOrExit(process.cwd());
30
33
  // Outside any agent the target is the user-global machinery home — handed over explicitly, so the path resolvers
31
34
  // need no "is this $HOME?" special case to infer it.
32
35
  const loginDir = agentDir ?? globalHome();
@@ -41,86 +44,425 @@ export async function runLogin(provider, opts) {
41
44
  // exactly where the operator said, or a second `login` for a provider they already have globally would silently
42
45
  // rewrite the global credential instead of creating the project-level override they asked for.
43
46
  const authPath = opts.global ? GLOBAL_AUTH_PATH : resolveAuthPath(loginDir);
47
+ const ownAgent = opts.global ? undefined : agentDir;
48
+ // The definition's providers too: a gateway's key is verified against the gateway, not a built-in's endpoint. Not for
49
+ // `-g`: the global file serves every agent on this machine, so no one agent's providers decide what it holds.
50
+ const providersOf = () => (ownAgent ? definitionProviders(ownAgent) : Promise.resolve([]));
51
+ if (opts.ticket !== undefined) {
52
+ // The process `startTicket` started: it takes the ticket before loading the definition, then signs in.
53
+ await runTicket(opts.ticket, async (step) => {
54
+ const providers = await providersOf();
55
+ const interaction = signInInteraction(step, provider);
56
+ await loginOver({ provider: provider, method: "oauth", authPath, interaction }, { providers });
57
+ const model = ownAgent ? await defaultModelHint(ownAgent, provider) : undefined;
58
+ const name = loginProviders(providers).find((p) => p.id === provider)?.name ?? provider;
59
+ return { provider, path: authPath, ...(model === undefined ? {} : { model, name }) };
60
+ });
61
+ process.exit(0);
62
+ }
63
+ const providers = await providersOf().catch(failStartup);
44
64
  // Announce when the FALLBACK is what decided the target: outside an agent with no explicit path, the credential
45
65
  // lands somewhere no agent will read.
46
66
  if (!agentDir && !opts.global && !process.env.FASTAGENT_AUTH_PATH) {
47
- console.error(`[fastagent] no agent here (no fastagent.config.ts, here or one level inside) — ` +
67
+ console.error(`[fastagent] no agent here (no fastagent.config.ts) — ` +
48
68
  `logging in GLOBALLY (${authPath}). An agent on this machine uses this file for a provider it has no ` +
49
- `credential of its own for (no entry in its .secrets/auth.json, no apiKey in its models.json, no env ` +
50
- `variable), so this is usually what you want; \`cd\` into an agent to give that one its own account instead.`);
69
+ `credential of its own for (no entry in its .secrets/auth.json, no env variable), so this is usually what ` +
70
+ `you want; \`cd\` into an agent to give that one its own account instead.`);
51
71
  }
52
- // login is inherently interactive — loginFlow renders provider/method menus and opens a browser (or prompts for a
53
- // key).
54
- if (opts.input === false || !isInteractive()) {
55
- failStartup(new Error(`login is interactive (it shows a menu and opens a browser) — run it in a terminal, not a pipe/CI`));
72
+ // What the agent reads, its file over the global one, is what authenticates each provider for it now.
73
+ const statusFrom = ownAgent
74
+ ? (await modelEnvironment(ownAgent, {}, providers)).credentials
75
+ : authPath;
76
+ if (opts.input === false || opts.json === true || !isInteractive()) {
77
+ const offered = await loginOptionsOver(statusFrom, providers);
78
+ return requestLogin(offered, { provider, method }, opts, {
79
+ authPath,
80
+ providers,
81
+ valueFile: ownAgent === undefined ? undefined : dotEnvPath(ownAgent),
82
+ heldIn: async (id) => (typeof statusFrom === "string" ? statusFrom : statusFrom.layerOf(id)),
83
+ timeoutSeconds: givenTimeout ?? UNATTENDED_TIMEOUT_SECONDS,
84
+ });
56
85
  }
86
+ const timeout = givenTimeout === undefined ? undefined : AbortSignal.timeout(givenTimeout * 1000);
57
87
  // An entered API key is verified with one minimal request (login.ts); a rejected one is asked for again.
58
- // Inside an agent, the key is checked on that agent's registry: its models.json may point a provider at a gateway.
59
- // Not with `-g`: the global file serves every agent on the machine, so no one agent's routing may judge its key.
60
88
  const result = await loginFlow(terminalLoginIO(), {
61
89
  authPath,
90
+ providers,
91
+ statusFrom: typeof statusFrom === "string" ? undefined : statusFrom,
62
92
  ...(provider ? { provider } : {}),
63
- ...(agentDir && !opts.global ? { agentDir } : {}),
93
+ ...(method ? { method } : {}),
94
+ ...(timeout ? { signal: timeout } : {}),
64
95
  }).catch((error) => {
96
+ if (timeout?.aborted)
97
+ failStartup(new Error(`login timed out after ${givenTimeout}s (--timeout)`));
65
98
  if (error instanceof LoginCancelled) {
66
99
  // A decision, not a failure — neutral wording; non-zero exit because no credential was stored.
67
100
  console.error(`[fastagent] login cancelled`);
68
101
  process.exit(1);
69
102
  }
103
+ if (error instanceof LoginRefused)
104
+ failUsage(error.message);
70
105
  failStartup(error);
71
106
  });
72
- console.error(`[fastagent] logged in to ${result.provider} (${result.method}) — saved to ${authPath}`);
107
+ const name = loginProviders(providers).find((p) => p.id === result.provider)?.name ?? result.provider;
108
+ console.error(result.method === "oauth"
109
+ ? `[fastagent] logged in to ${name} — saved to ${authPath}`
110
+ : `[fastagent] saved the API key for ${name} to ${authPath}`);
111
+ const model = ownAgent ? await defaultModelHint(ownAgent, result.provider) : undefined;
112
+ if (model !== undefined)
113
+ console.error(`[fastagent] ${modelHint(model, name)}`);
73
114
  // The environment outranks the global file for every agent, so a global login it shadows would sit unused while
74
115
  // agents run on, say, an API key billed per request, with only a startup line to show it.
75
- const shadowedBy = authPath === GLOBAL_AUTH_PATH ? await environmentAuthSource(result.provider, shellEnv) : undefined;
116
+ const shadowedBy = authPath === GLOBAL_AUTH_PATH ? (await environmentAuth(result.provider, shellEnv))?.source : undefined;
76
117
  if (shadowedBy !== undefined) {
77
118
  console.error(`[fastagent] warning: ${result.provider} is also authenticated by ${shadowedBy} in your shell environment, which ` +
78
119
  `agents use before the global file, so this login is not used while it is set. Unset it to use this login.`);
79
120
  }
80
121
  process.exit(0); // the undici proxy agent's keep-alive sockets would otherwise hold the event loop open
81
122
  }
123
+ const modelHint = (model, name) => `this agent has no model: \`model: "${model}"\` in fastagent.config.ts uses ${name}'s default`;
124
+ /** `--method`'s words, pi's: an account (OAuth) or an API key. */
125
+ function methodOf(value) {
126
+ if (value === "account")
127
+ return "oauth";
128
+ if (value === "api-key")
129
+ return "api_key";
130
+ return failUsage(`--method must be account or api-key, not "${value}"`);
131
+ }
132
+ const methodWord = (method) => (method === "oauth" ? "account" : "api-key");
133
+ function secondsOf(value) {
134
+ const seconds = Number(value);
135
+ if (!Number.isInteger(seconds) || seconds <= 0)
136
+ failUsage(`--timeout must be a whole number of seconds, not "${value}"`);
137
+ return seconds;
138
+ }
139
+ /**
140
+ * pi's default model for `provider`, when the agent in `agentDir` has no model of its own: what pi starts on after a
141
+ * sign-in. Printed, never written: the model belongs in the author's own config.
142
+ */
143
+ async function defaultModelHint(agentDir, provider) {
144
+ const config = await loadConfig(agentDir).catch(failStartup);
145
+ if (modelSpecFor(config, undefined) !== undefined)
146
+ return undefined;
147
+ const modelId = PI_DEFAULT_MODELS[provider];
148
+ return modelId === undefined ? undefined : `${provider}/${modelId}`;
149
+ }
82
150
  /**
83
- * `--deployment [host]`: the host is named, or the one whose generated artifact is in the agent dir. Several is a
84
- * question only the operator can answer, so it is asked back rather than guessed.
151
+ * Login with no one at a terminal to ask, as Netlify's `login --request` and Dosu's tickets have it: a choice not
152
+ * given is named with a command for each way (`need_choice`, exit 2); an account sign-in starts in a process of its
153
+ * own and returns its address with a ticket (`need_user_action`, exit 0); an API key is the person's to set where the
154
+ * agent reads it, never handed through the agent (`need_user_action` naming the variables).
155
+ */
156
+ async function requestLogin(offered, given, opts, target) {
157
+ const global = opts.global ? " -g" : "";
158
+ let choice;
159
+ try {
160
+ choice = await chooseLogin(offered, given, undefined);
161
+ }
162
+ catch (error) {
163
+ if (!(error instanceof LoginRefused))
164
+ throw error;
165
+ return choiceNotGiven(error, opts, { flags: global, statuses: true });
166
+ }
167
+ if (choice.method === "api_key")
168
+ return keyNeeded(choice, opts, target);
169
+ const ticket = await startTicket({
170
+ // One subject per provider, here or on a deployment: they hold the same callback port on this machine.
171
+ subject: `login:${choice.provider}`,
172
+ fields: { provider: choice.provider, method: "account" },
173
+ action: `sign in to ${choice.name}`,
174
+ check: LOGIN_CHECK,
175
+ restart: `fastagent login ${choice.provider} --method account${global}`,
176
+ timeoutSeconds: target.timeoutSeconds,
177
+ waitsFirst: true,
178
+ whenRunning: "replace",
179
+ command: {
180
+ file: process.execPath,
181
+ args: [
182
+ ...process.execArgv,
183
+ process.argv[1],
184
+ "login",
185
+ choice.provider,
186
+ "--method",
187
+ "account",
188
+ ...(opts.global ? ["-g"] : []),
189
+ ],
190
+ cwd: process.cwd(),
191
+ },
192
+ });
193
+ // No browser is opened: the agent hands the address to its person, who may be on another machine.
194
+ reportTicket(ticket, opts, "started");
195
+ process.exit(ticketExitCode(ticket));
196
+ }
197
+ /**
198
+ * An API key with no terminal to type it in: the variables the person sets themselves where the agent reads them, and
199
+ * how to tell it worked. With no agent's value file to name (`-g`, or no agent here), the person signs in at a terminal
200
+ * of their own, which keeps the key in the global file `auth check -g` reads: the agent's environment was fixed when it
201
+ * started, so a variable set now would never reach it.
202
+ */
203
+ async function keyNeeded(choice, opts, target) {
204
+ const base = { provider: choice.provider, method: "api-key" };
205
+ if (choice.status?.type === "api_key") {
206
+ printReport(opts.json, { status: "ready", ...base, source: choice.status.source }, [
207
+ `ready: ${choice.name} is authenticated by ${choice.status.source}`,
208
+ ]);
209
+ return;
210
+ }
211
+ const check = `fastagent auth check --provider ${choice.provider}${target.valueFile === undefined ? " -g" : ""}`;
212
+ if (target.valueFile === undefined) {
213
+ const terminal = `fastagent login ${choice.provider} --method api-key -g`;
214
+ printReport(opts.json, {
215
+ status: "need_user_action",
216
+ ...base,
217
+ terminal_command: terminal,
218
+ check_command: `${check} --json`,
219
+ agent_next_steps: "Ask the user to run terminal_command in a terminal of their own: it asks for the key there, not in this " +
220
+ "conversation, and keeps it in the global credentials file. Once they say they have, run check_command.",
221
+ }, [`need_user_action: run in a terminal of your own: ${terminal}`, `then run: ${check}`]);
222
+ return;
223
+ }
224
+ // A stored account sign-in outranks any key in the environment: it goes first, or the key set now is never used.
225
+ const outranking = choice.status?.source === "OAuth" ? await target.heldIn(choice.provider) : undefined;
226
+ const logout = outranking === undefined
227
+ ? undefined
228
+ : `fastagent logout ${choice.provider}${outranking === GLOBAL_AUTH_PATH ? " -g" : ""}`;
229
+ const { variables, what } = await keyToSet(choice, target.providers);
230
+ const first = logout === undefined
231
+ ? ""
232
+ : `${choice.name} is signed in with an account in ${outranking}, which outranks a key in the environment: ` +
233
+ "run logout_command first (with the user's agreement: it removes that sign-in). Then ";
234
+ printReport(opts.json, {
235
+ status: "need_user_action",
236
+ ...base,
237
+ variables,
238
+ value_file: target.valueFile,
239
+ ...(logout === undefined ? {} : { logout_command: logout }),
240
+ check_command: `${check} --json`,
241
+ agent_next_steps: `${first}${first ? "ask" : "Ask"} the user to set ${what} in ${target.valueFile} themselves, not in this ` +
242
+ "conversation. Once they say they have, run check_command.",
243
+ }, [
244
+ ...(logout === undefined ? [] : [`first, to replace the account sign-in in ${outranking}: ${logout}`]),
245
+ `need_user_action: set ${what} in ${target.valueFile}`,
246
+ `then run: ${check}`,
247
+ ]);
248
+ }
249
+ /**
250
+ * A sign-in not chosen with no one to ask (exit 2): with `--json`, the choices and the command for each, `flags`
251
+ * added to it. `statuses`: what authenticates each provider here is worth showing (it is not, for a deployment).
252
+ */
253
+ function choiceNotGiven(error, opts, how) {
254
+ if (opts.json) {
255
+ const choices = error.choices.map((o) => ({
256
+ provider: o.provider,
257
+ name: o.name,
258
+ method: methodWord(o.method),
259
+ label: o.label,
260
+ ...(how.statuses ? { status: loginStatusText(o) } : {}),
261
+ command: `fastagent login ${o.provider} --method ${methodWord(o.method)}${how.flags} --json`,
262
+ }));
263
+ printReport(true, {
264
+ status: "need_choice",
265
+ message: error.message,
266
+ choices,
267
+ agent_next_steps: "Ask the user which of these to sign in with, then run that choice's command.",
268
+ }, []);
269
+ }
270
+ return failUsage(error.message);
271
+ }
272
+ /** The variables `choice`'s key is read from, and how to tell the person to set it. */
273
+ async function keyToSet(choice, providers) {
274
+ const provider = loginProviders(providers).find((p) => p.id === choice.provider);
275
+ const variables = provider ? await keyVariables(provider) : [];
276
+ const what = variables.length === 0
277
+ ? `its key as ${choice.name}'s own documentation says`
278
+ : variables.length === 1
279
+ ? `${variables[0]}=<their ${choice.name} key>`
280
+ : `the variables ${choice.name} reads its key from (${variables.join(", ")})`;
281
+ return { variables, what };
282
+ }
283
+ /** `login --check <ticket> [--code <address>]`. */
284
+ async function runCheck(id, opts) {
285
+ const refused = refusedCheck(id, LOGIN_CHECK);
286
+ if (refused !== undefined)
287
+ failUsage(refused);
288
+ // There: refusedCheck read it, and a ticket is pruned only a day after it ends.
289
+ const ticket = (await checkTicket(id, opts.code));
290
+ reportTicket(ticket, opts, "checked");
291
+ process.exit(ticketExitCode(ticket));
292
+ }
293
+ /** A sign-in's ticket for whoever started or checked it: the shared report, and what a finished sign-in adds. */
294
+ function reportTicket(ticket, opts, when) {
295
+ const deployment = ticket.fields?.deployment;
296
+ const { json, text } = ticketReport(ticket, when, (result) => {
297
+ if (deployment !== undefined) {
298
+ return { fields: {}, text: [`signed in on the ${deployment} deployment`], next: "Signed in on the deployment." };
299
+ }
300
+ const hint = typeof result.model === "string" ? modelHint(result.model, String(result.name)) : undefined;
301
+ return {
302
+ fields: { path: result.path, ...(result.model ? { model: result.model } : {}) },
303
+ text: [`saved to ${String(result.path)}`, ...(hint === undefined ? [] : [hint])],
304
+ next: hint === undefined ? "Signed in." : `Signed in. Tell the user: ${hint}.`,
305
+ };
306
+ });
307
+ printReport(opts.json, json, text);
308
+ }
309
+ /**
310
+ * pi-ai's account sign-in, run by a ticket's process with no one to answer it. A choice takes its first option, pi's
311
+ * default (the browser sign-in); a text question is left blank, the one pi-ai's account sign-ins ask being Copilot's
312
+ * optional Enterprise domain (a required one fails in the provider's own flow, which the ticket reports); a secret it
313
+ * cannot take; the code or address a browser ends on comes from `login --check --code`, unless the provider's callback
314
+ * brings it first. Not public: a test seam.
315
+ */
316
+ export function signInInteraction(step, provider) {
317
+ return {
318
+ signal: step.signal,
319
+ prompt: async (prompt) => {
320
+ if (prompt.type === "select")
321
+ return prompt.options[0].id;
322
+ if (prompt.type === "text")
323
+ return "";
324
+ if (prompt.type === "secret") {
325
+ throw new Error(`the sign-in asks "${prompt.message}", which only a terminal can answer: run \`fastagent login ${provider}\` ` +
326
+ "in one");
327
+ }
328
+ return step.address(prompt.signal ? AbortSignal.any([prompt.signal, step.signal]) : step.signal);
329
+ },
330
+ notify: (event) => {
331
+ if (event.type === "auth_url") {
332
+ step.waits({
333
+ url: event.url,
334
+ takesAddress: true,
335
+ ...(event.instructions ? { instructions: event.instructions } : {}),
336
+ });
337
+ }
338
+ else if (event.type === "device_code") {
339
+ step.waits({ url: event.verificationUri, code: event.userCode });
340
+ }
341
+ console.error(`[fastagent] ${event.type}: ${"message" in event ? event.message : ""}`);
342
+ },
343
+ };
344
+ }
345
+ /**
346
+ * `--deployment <host>`: always named. The agent directory cannot answer which host it means: a Railway deploy leaves
347
+ * no file of its own there, and a directory can hold several hosts' files, so a guess could log a different box in
348
+ * than the one that asked. Every command fastagent prints names it (`deploymentLoginCommand`, `deployedHost`).
85
349
  */
86
350
  async function runDeploymentLogin(provider, opts) {
87
351
  if (opts.global)
88
352
  failUsage("--deployment logs the deployment in; -g names this machine's global file — pick one");
89
- const placement = placementOrExit(process.cwd());
90
- // The host's CLI must reach the account/region/proxy the deploy used, and those may be definition-local.
91
- enterAgentEnv(placement.agentDir);
92
- let host;
93
- if (typeof opts.deployment === "string") {
94
- if (!DEPLOY_HOSTS.includes(opts.deployment)) {
95
- failUsage(`--deployment takes a host (${DEPLOY_HOSTS.join(", ")}), not "${opts.deployment}" — to name a provider too: ` +
96
- `fastagent login <provider> --deployment <host>`);
97
- }
98
- host = opts.deployment;
99
- }
100
- else {
101
- const found = DEPLOY_HOSTS.filter((h) => existsSync(join(placement.agentDir, HOSTS[h].artifact)));
102
- if (found.length !== 1) {
103
- failUsage(found.length === 0
104
- ? `no deployment artifacts in ${placement.agentDir} — name the host: --deployment <${DEPLOY_HOSTS.join("|")}>`
105
- : `this agent deploys to ${found.join(" and ")} — name one: --deployment <${found.join("|")}>`);
106
- }
107
- host = found[0];
353
+ // A ticket is read on its own: with --deployment, this would start another sign-in and replace the one it names.
354
+ if (opts.check !== undefined || opts.code !== undefined) {
355
+ failUsage("--check reads a sign-in's ticket by itself: run `fastagent login --check <ticket>`, without --deployment");
356
+ }
357
+ const agentDir = agentDirOrExit(process.cwd());
358
+ selectAgentEnvironment("production");
359
+ enterAgentEnv(agentDir);
360
+ if (!DEPLOY_HOSTS.includes(opts.deployment)) {
361
+ failUsage(`--deployment takes a host (${DEPLOY_HOSTS.join(", ")}), not "${opts.deployment}" — to name a provider too: ` +
362
+ `fastagent login <provider> --deployment <host>`);
363
+ }
364
+ const host = opts.deployment;
365
+ const method = opts.method === undefined ? undefined : methodOf(opts.method);
366
+ if (opts.ticket !== undefined) {
367
+ // The process `startTicket` started: it holds the box's shell while the person signs in.
368
+ const retry = deploymentLoginCommand(host, provider);
369
+ await runTicket(opts.ticket, async (step) => {
370
+ const io = ticketLoginIO(step, retry);
371
+ const failed = await loginOnBox({
372
+ host,
373
+ shell: await HOSTS[host].shell(agentDir),
374
+ provider: provider,
375
+ method: "oauth",
376
+ input: true,
377
+ io,
378
+ });
379
+ if (failed)
380
+ throw new Error(io.refusal() ?? failed);
381
+ return { provider, deployment: host };
382
+ });
383
+ process.exit(0);
108
384
  }
109
- const input = opts.input !== false && isInteractive();
110
- if (!input) {
111
- failStartup(new Error(`login is interactive (it shows a menu and opens a browser) — run it in a terminal`));
385
+ if (opts.input === false || opts.json === true || !isInteractive()) {
386
+ const timeout = opts.timeout === undefined ? UNATTENDED_TIMEOUT_SECONDS : secondsOf(opts.timeout);
387
+ return requestDeploymentLogin(agentDir, host, { provider, method }, opts, timeout);
112
388
  }
113
389
  const failed = await loginOnBox({
114
390
  host,
115
- shell: await HOSTS[host].shell(placement).catch(failStartup),
116
- placement,
391
+ shell: await HOSTS[host].shell(agentDir).catch(failStartup),
117
392
  ...(provider ? { provider } : {}),
118
- input,
393
+ ...(method ? { method } : {}),
394
+ input: true,
119
395
  });
120
396
  if (failed)
121
397
  failStartup(new Error(failed));
122
398
  process.exit(0);
123
399
  }
400
+ /**
401
+ * `login --deployment <host>` with no one at a terminal. The sign-in is chosen here, from the definition the box
402
+ * serves; what this machine holds says nothing of the box, so no status is shown. An account sign-in runs on the box
403
+ * through a ticket whose process holds the box's shell (box-login.ts `ticketLoginIO`). An API key reaches a box only
404
+ * as a variable its deploy carries, so the person sets it in the production value file and the agent deploys again.
405
+ */
406
+ async function requestDeploymentLogin(agentDir, host, given, opts, timeoutSeconds) {
407
+ const providers = await definitionProviders(agentDir).catch(failStartup);
408
+ const offered = await loginOptionsOver(resolveAuthPath(agentDir), providers);
409
+ let choice;
410
+ try {
411
+ choice = await chooseLogin(offered, given, undefined);
412
+ }
413
+ catch (error) {
414
+ if (!(error instanceof LoginRefused))
415
+ throw error;
416
+ return choiceNotGiven(error, opts, { flags: ` --deployment ${host}`, statuses: false });
417
+ }
418
+ if (choice.method === "api_key") {
419
+ const valueFile = dotEnvPath(agentDir);
420
+ const { variables, what } = await keyToSet(choice, providers);
421
+ const deploy = `fastagent deploy ${host} --run`;
422
+ printReport(opts.json, {
423
+ status: "need_user_action",
424
+ provider: choice.provider,
425
+ method: "api-key",
426
+ deployment: host,
427
+ variables,
428
+ value_file: valueFile,
429
+ check_command: deploy,
430
+ agent_next_steps: `Ask the user to set ${what} in ${valueFile} themselves, not in this conversation. A key reaches the ` +
431
+ `${host} deployment with its next deploy: once they say they have, run check_command.`,
432
+ }, [
433
+ `need_user_action: set ${what} in ${valueFile}`,
434
+ `then run: ${deploy} # the key reaches the deployment with its deploy`,
435
+ ]);
436
+ process.exit(0);
437
+ }
438
+ const ticket = await startTicket({
439
+ subject: `login:${choice.provider}`,
440
+ fields: { provider: choice.provider, method: "account", deployment: host },
441
+ action: `sign in to ${choice.name} for the ${host} deployment`,
442
+ check: LOGIN_CHECK,
443
+ restart: `fastagent login ${choice.provider} --method account --deployment ${host}`,
444
+ timeoutSeconds,
445
+ // Reaching the box comes first, and can take a while (a host's shell, an idle runtime woken).
446
+ waitsFirst: false,
447
+ whenRunning: "replace",
448
+ command: {
449
+ file: process.execPath,
450
+ args: [
451
+ ...process.execArgv,
452
+ process.argv[1],
453
+ "login",
454
+ choice.provider,
455
+ "--method",
456
+ "account",
457
+ "--deployment",
458
+ host,
459
+ ],
460
+ cwd: process.cwd(),
461
+ },
462
+ });
463
+ reportTicket(ticket, opts, "started");
464
+ process.exit(ticketExitCode(ticket));
465
+ }
124
466
  /**
125
467
  * `--stdio`: the box's half of `--deployment`. Runs where the server runs; everything it would show or ask travels as
126
468
  * the relay wire, and it ends with exactly one result line. Never started by hand: the credential path is the one the
@@ -146,10 +488,11 @@ async function stdioLogin(io, provider, opts) {
146
488
  // proxy they name. AgentCore's command shell hands down none of the runtime's, so a proxy carried there in
147
489
  // FASTAGENT_ENV does not reach the login (docs/deploy.md).
148
490
  enterAgentEnv(agentDir);
149
- // The model environment the serving runtime reads (createPiAgentFromDir), so "logged in" means what the server will
150
- // use.
151
- const models = agentModels(agentDir, {}, { cwd: resolvePlacement(agentDir).workspace });
152
- const { auth } = models;
491
+ // The model environment the serving Agent reads (openServing), its definition's providers included, so "logged in"
492
+ // means what the server will use, and a provider only the definition declares can be signed in to.
493
+ const providers = await definitionProviders(agentDir);
494
+ const models = await modelEnvironment(agentDir, {}, providers);
495
+ const auth = models.auth;
153
496
  if (opts.ifMissing && provider) {
154
497
  // The server's own answer (`authStatus`), the one its startup report prints. Known ceiling: nothing is asked of
155
498
  // the provider beyond a due refresh, so a revoked grant whose access token has not expired yet, or a revoked API
@@ -169,6 +512,12 @@ async function stdioLogin(io, provider, opts) {
169
512
  if (opts.input === false) {
170
513
  return { ok: false, reason: "missing", message: `no ${provider ?? "model"} credential in ${auth.path}` };
171
514
  }
172
- const result = await loginFlow(io, { authPath: auth.path, ...(provider ? { provider } : {}), agentDir });
515
+ const method = opts.method === undefined ? undefined : methodOf(opts.method);
516
+ const result = await loginFlow(io, {
517
+ authPath: auth.path,
518
+ providers,
519
+ ...(provider ? { provider } : {}),
520
+ ...(method ? { method } : {}),
521
+ });
173
522
  return { ok: true, provider: result.provider, method: result.method, path: auth.path };
174
523
  }
@@ -0,0 +1,4 @@
1
+ export declare function runLogout(provider: string | undefined, opts: {
2
+ global?: boolean;
3
+ input?: boolean;
4
+ }): Promise<void>;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * `fastagent logout [provider]`: remove the credential `login` stored for a provider, as pi's `/logout` does, from the
3
+ * file `login` writes (the agent's, or with `-g` or outside an agent the global one). Environment variables and the
4
+ * grant at the provider are left as they are.
5
+ */
6
+ import { enterAgentEnv } from "../../env.js";
7
+ import { GLOBAL_AUTH_PATH, fastagentCredentialStore, resolveAuthPath } from "../../harnesses/models/credentials.js";
8
+ import { loginProviders } from "../../harnesses/models/models.js";
9
+ import { definitionProviders } from "../../harnesses/pi-durable/open.js";
10
+ import { globalHome } from "../../paths.js";
11
+ import { failStartup, failUsage, optionalAgentDirOrExit } from "../fail.js";
12
+ import { isInteractive, terminalLoginIO } from "../shared.js";
13
+ export async function runLogout(provider, opts) {
14
+ const agentDir = opts.global ? undefined : optionalAgentDirOrExit(process.cwd());
15
+ enterAgentEnv(agentDir ?? globalHome());
16
+ const authPath = opts.global ? GLOBAL_AUTH_PATH : resolveAuthPath(agentDir ?? globalHome());
17
+ const store = fastagentCredentialStore(authPath);
18
+ const known = loginProviders(agentDir ? await definitionProviders(agentDir).catch(failStartup) : []);
19
+ const stored = (await store.list())
20
+ .map(({ providerId, type }) => ({
21
+ id: providerId,
22
+ type,
23
+ name: known.find((p) => p.id === providerId)?.name ?? providerId,
24
+ }))
25
+ .sort((a, b) => a.name.localeCompare(b.name));
26
+ const held = stored.length === 0 ? "it holds none" : `it holds ${stored.map(({ id }) => id).join(", ")}`;
27
+ let chosen;
28
+ if (provider !== undefined) {
29
+ const named = provider.trim().toLowerCase();
30
+ chosen = stored.find(({ id, name }) => id.toLowerCase() === named || name.toLowerCase() === named);
31
+ if (chosen === undefined)
32
+ failStartup(new Error(`no credential for "${provider}" is stored in ${authPath}: ${held}`));
33
+ }
34
+ else if (stored.length === 0) {
35
+ console.error(`[fastagent] no credential is stored in ${authPath}; environment variables are not login's to remove`);
36
+ return;
37
+ }
38
+ else if (opts.input === false || !isInteractive()) {
39
+ failUsage(`name the provider to log out of: ${held} (${authPath})`);
40
+ }
41
+ else {
42
+ const value = await terminalLoginIO().select("Select provider to logout:", stored.map(({ id, name, type }) => ({ value: id, label: name, hint: type === "oauth" ? "account" : "API key" })));
43
+ chosen = stored.find(({ id }) => id === value);
44
+ if (chosen === undefined) {
45
+ console.error("[fastagent] logout cancelled");
46
+ process.exit(1);
47
+ }
48
+ }
49
+ await store.delete(chosen.id);
50
+ console.error(chosen.type === "oauth"
51
+ ? `[fastagent] logged out of ${chosen.name} — removed from ${authPath}`
52
+ : `[fastagent] removed the stored API key for ${chosen.name} from ${authPath}; environment variables are unchanged`);
53
+ }
@@ -1,26 +1,28 @@
1
- /** `fastagent logs agentcore [dir]`: discover and tail the deployed AgentCore CloudWatch logs. */
1
+ /** `fastagent logs agentcore [agent]`: discover and tail the deployed AgentCore CloudWatch logs. */
2
2
  import { basename, resolve } from "node:path";
3
3
  import { agentcoreName } from "../../deploy/agentcore/plan.js";
4
4
  import { tailAgentcoreLogs } from "../../deploy/agentcore/logs.js";
5
5
  import { awsRunner } from "../../deploy/runner.js";
6
6
  import { enterAgentEnv } from "../../env.js";
7
- import { failStartup, failUsage, placementOrExit } from "../fail.js";
7
+ import { selectAgentEnvironment } from "../../paths.js";
8
+ import { agentDirOrExit, failStartup, failUsage } from "../fail.js";
8
9
  export async function runLogs(host, dirArg, opts) {
9
10
  // The host argument is DISPATCHED here, as in runDeploy.
10
11
  if (host !== "agentcore")
11
12
  failUsage(`logs: unsupported host "${host}" — only agentcore has remote logs`);
12
- const placement = placementOrExit(resolve(dirArg));
13
- enterAgentEnv(placement.agentDir); // AWS_PROFILE/region/proxy may be definition-local, as on deploy
13
+ const agentDir = agentDirOrExit(resolve(dirArg));
14
+ selectAgentEnvironment("production");
15
+ enterAgentEnv(agentDir);
14
16
  const source = opts.source ?? "runtime";
15
17
  if (source !== "runtime" && source !== "forwarder") {
16
18
  failUsage(`logs: --source must be "runtime" or "forwarder"`);
17
19
  }
18
20
  const outcome = await tailAgentcoreLogs({
19
- name: agentcoreName(basename(placement.workspace)),
21
+ name: agentcoreName(basename(agentDir)),
20
22
  source: source,
21
23
  since: opts.since,
22
24
  follow: opts.follow === true,
23
- }, awsRunner(placement.workspace), (message) => console.error(`[fastagent] logs: ${message}`));
25
+ }, awsRunner(agentDir), (message) => console.error(`[fastagent] logs: ${message}`));
24
26
  if (!outcome.ok)
25
27
  failStartup(new Error(`logs stopped: ${outcome.gate}`));
26
28
  }