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