@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,81 +1,31 @@
1
- import type { Agent } from "../agent.ts";
2
- import type { ChannelHandler } from "../channel.ts";
3
- import { type AgentService, type MountableAgent, type MountAgentServiceOptions } from "../service.ts";
1
+ import type { ServedAgent, ServeOptions, Service } from "../service.ts";
2
+ import type { AgentConfig } from "../harnesses/pi-durable/define.ts";
4
3
  /** Refuse `--tunnel` with a `--bind` that cloudflared cannot reach. */
5
4
  export declare function assertTunnelBindable(host: string | undefined, tunnel: boolean): void;
6
5
  /**
7
- * Apply the flags that override what the definition said, for THIS run only.
8
- *
9
- * ONE place, because `dev` and `start` both do it and a mapping two call sites must each remember is one a third
10
- * will not.
11
- *
12
- * `--no-invoke` outranks `http.invoke`: a config value travels into a deployed image, so "do not publish a turn
13
- * endpoint on this tunnel" has to be sayable without editing the definition.
14
- *
15
- * It takes `POST /run` WITH it, including over a definition that said `http.run: true`. Both routes start a
16
- * turn for an anonymous caller, and the flag's whole reason for existing is the case where the definition cannot be
17
- * edited — `dev --tunnel --no-invoke` leaving the other one published at the tunnel URL would be the flag failing at
18
- * exactly the job it was added for.
6
+ * What the CLI adds to the assembly: its shutdown grace, exit on a connection that drops, and the API's keys, none
7
+ * when the definition turns the API off, whatever key the environment holds (a host's from an earlier deploy).
19
8
  */
20
- export declare function withRunOverrides<T extends MountableAgent>(opened: T, run: {
21
- invoke?: boolean;
22
- }): T;
23
- /** What the CLI adds to the assembly: its shutdown grace, and exit on a connection that drops. */
24
- export declare function cliMountOptions(wrapAgent: (agent: Agent) => Agent): MountAgentServiceOptions;
9
+ export declare function cliMountOptions(config: AgentConfig): ServeOptions;
25
10
  /**
26
- * Bind, report, announce the control plane, open the tunnel, and close in order on a signal — the tail dev's worker
27
- * and start share once the service is assembled.
11
+ * Bind, report, warn about reach, open the tunnel, and close in order on a signal — the tail dev's worker and start
12
+ * share once the service is assembled.
28
13
  */
29
- export declare function serveService(service: AgentService, bind: {
14
+ export declare function serveService(service: ServedAgent, bind: {
30
15
  port: number;
31
16
  host?: string;
32
17
  }, posture: {
33
18
  tunnel: boolean;
34
19
  agentDir: string;
35
20
  stateRoot: string;
21
+ config: AgentConfig;
36
22
  }): void;
37
23
  /** The "we are serving" report: the supervisor message `dev`'s watcher waits for, the addresses, and what mounted. */
38
- export declare function reportServing(service: AgentService, host: string | undefined, boundPort: number): void;
24
+ export declare function reportServing(service: ServedAgent, host: string | undefined, boundPort: number, config: AgentConfig): void;
39
25
  /** The line that names WHERE the serve is — every posture reports it, including AgentCore's own surface. */
40
26
  export declare function bindLine(host: string | undefined, boundPort: number): string;
41
- /**
42
- * The startup lines for a serve of OUR surface: the bind report, and the curl the reader copies.
43
- *
44
- * `servesInvoke` is `AgentService.unverifiedRoutes`, never a guess from the route table: `http.invoke: false` leaves no
45
- * `/invoke` to curl, and a channel may serve that path with a protocol of its own — both would turn this line into
46
- * a copyable request that fails.
47
- */
48
- export declare function readyAddressLines(host: string | undefined, boundPort: number, servesInvoke: boolean): string[];
49
- /**
50
- * Say what this port exposes and how far it reaches.
51
- *
52
- * NOTHING fastagent serves is authenticated — authentication belongs to the deployment (a gateway, a private
53
- * network, AgentCore's IAM, an embedder's middleware). Two of the three warnings fire at a REACH the operator did
54
- * not get by default: a bind off this machine, and `--tunnel`'s public URL.
55
- *
56
- * The cross-origin one is UNCONDITIONAL, including on a loopback `dev`, because the grant is. `*` is the default
57
- * (`channels/serve.ts`), so a page the developer merely visits can drive this port from their browser and read the
58
- * reply, loopback bind or not. Nobody opts into a default, so the one posture the decision costs is the one that
59
- * has to hear about it.
60
- *
61
- * WHAT IS EXPOSED is read off `AgentService.unverifiedRoutes`, never assumed and never guessed from the route table.
62
- * `POST /invoke` is on most serves but not all: AgentCore answers the Runtime's `/invocations` behind IAM,
63
- * `http.invoke: false` withholds it, and a channel may serve that path itself — in which case the caller it is
64
- * open to is the platform that signs its requests, not anyone at all. A warning naming an endpoint this process
65
- * does not serve is how an operator learns to skim past all of them — the same reason `preflightDeploy` takes
66
- * `publicUrl`.
67
- */
68
- export declare function announceControl(service: Pick<AgentService, "controlPrefix" | "unverifiedRoutes" | "corsOrigins">, bind: {
69
- host?: string;
70
- tunnel: boolean;
71
- }): void;
72
- /** Bind HTTP and report ready — but only once the SERVICE is, which is not the same moment. */
73
- export declare function serve(handler: ChannelHandler, bind: {
27
+ /** Listen, and report ready — but only once the SERVICE is, which is not the same moment — until a signal closes it. */
28
+ export declare function serve(service: Service, bind: {
74
29
  port: number;
75
30
  host?: string;
76
- }, hooks?: {
77
- /** Awaited before anything is reported ready — see the listening handler. */
78
- ready?: Promise<void>;
79
- onListening?: (boundPort: number) => void;
80
- onShutdown?: () => Promise<void> | void;
81
- }): void;
31
+ }, onListening?: (boundPort: number) => void): void;
package/dist/cli/serve.js CHANGED
@@ -1,8 +1,7 @@
1
1
  /** What `dev` (its worker) and `start` need beyond the service itself. */
2
- import { INVOKE_EXAMPLE_BODY } from "../channels/http.js";
3
- import { answersLocalhost, bindLabel, classifyBind, clientHost } from "../bind.js";
4
- import { describeAnonymousSurface, } from "../service.js";
5
- import { serveNode } from "../channels/serve.js";
2
+ import { answersLocalhost, bindLabel, classifyBind } from "../bind.js";
3
+ import { API_PREFIX } from "../http/contract.js";
4
+ import { API_KEY_VARIABLE, API_TURNED_OFF, apiKeysFrom, apiTurnedOff } from "../http/server.js";
6
5
  import { log } from "../log.js";
7
6
  import { openExternalUrl } from "../open-url.js";
8
7
  import { declaredChannels } from "../channels/discover.js";
@@ -15,54 +14,36 @@ export function assertTunnelBindable(host, tunnel) {
15
14
  failUsage(`--tunnel reaches the serve by dialing localhost, which the bind address ${host} does not answer — bind 0.0.0.0 (or 127.0.0.1), or drop --tunnel`);
16
15
  }
17
16
  /**
18
- * Apply the flags that override what the definition said, for THIS run only.
19
- *
20
- * ONE place, because `dev` and `start` both do it and a mapping two call sites must each remember is one a third
21
- * will not.
22
- *
23
- * `--no-invoke` outranks `http.invoke`: a config value travels into a deployed image, so "do not publish a turn
24
- * endpoint on this tunnel" has to be sayable without editing the definition.
25
- *
26
- * It takes `POST /run` WITH it, including over a definition that said `http.run: true`. Both routes start a
27
- * turn for an anonymous caller, and the flag's whole reason for existing is the case where the definition cannot be
28
- * edited — `dev --tunnel --no-invoke` leaving the other one published at the tunnel URL would be the flag failing at
29
- * exactly the job it was added for.
17
+ * What the CLI adds to the assembly: its shutdown grace, exit on a connection that drops, and the API's keys, none
18
+ * when the definition turns the API off, whatever key the environment holds (a host's from an earlier deploy).
30
19
  */
31
- export function withRunOverrides(opened, run) {
32
- return run.invoke === false ? { ...opened, http: { ...opened.http, invoke: false, run: false } } : opened;
33
- }
34
- /** What the CLI adds to the assembly: its shutdown grace, and exit on a connection that drops. */
35
- export function cliMountOptions(wrapAgent) {
20
+ export function cliMountOptions(config) {
36
21
  return {
37
- wrapAgent,
22
+ apiKeys: apiTurnedOff(config) ? [] : apiKeysFrom(process.env[API_KEY_VARIABLE]),
38
23
  closeTimeoutMs: SHUTDOWN_GRACE_MS,
39
24
  onChannelClosed: (name, error) => failStartup(new Error(`${name} ${error === undefined ? "closed unexpectedly" : `failed: ${String(error)}`}`)),
40
25
  };
41
26
  }
42
27
  /**
43
- * Bind, report, announce the control plane, open the tunnel, and close in order on a signal — the tail dev's worker
44
- * and start share once the service is assembled.
28
+ * Bind, report, warn about reach, open the tunnel, and close in order on a signal — the tail dev's worker and start
29
+ * share once the service is assembled.
45
30
  */
46
31
  export function serveService(service, bind, posture) {
47
32
  const { host } = bind;
48
- const { tunnel, agentDir, stateRoot } = posture;
49
- serve(service.handler, bind, {
50
- ready: service.ready,
51
- onListening: (p) => {
52
- reportServing(service, host, p);
53
- announceControl(service, { host, tunnel });
54
- maybeTunnel(agentDir, service.channels.routes, p, tunnel, stateRoot);
55
- },
56
- onShutdown: () => service.close(),
33
+ const { tunnel, agentDir, stateRoot, config } = posture;
34
+ serve(service, bind, (p) => {
35
+ reportServing(service, host, p, config);
36
+ maybeTunnel(agentDir, service.channels.routes, p, tunnel, stateRoot);
57
37
  });
58
38
  }
59
39
  /** The "we are serving" report: the supervisor message `dev`'s watcher waits for, the addresses, and what mounted. */
60
- export function reportServing(service, host, boundPort) {
40
+ export function reportServing(service, host, boundPort, config) {
61
41
  process.send?.({ type: "ready", port: boundPort, routeChannels: service.channels.routes });
62
- for (const line of readyAddressLines(host, boundPort, service.unverifiedRoutes.includes("POST /invoke"))) {
63
- log.info(line);
64
- }
42
+ log.info(bindLine(host, boundPort));
65
43
  log.info(`[fastagent] routes: ${Object.keys(service.routes).join(", ") || "(none)"}`);
44
+ log.info(service.api
45
+ ? `[fastagent] Agent API: ${API_PREFIX} (keys from ${API_KEY_VARIABLE})`
46
+ : `[fastagent] Agent API: not served — ${apiTurnedOff(config) ? API_TURNED_OFF : `set ${API_KEY_VARIABLE} to serve it under ${API_PREFIX}`}`);
66
47
  if (service.channels.longConnections.length > 0) {
67
48
  log.info(`[fastagent] long connections: ${service.channels.longConnections.join(", ")}`);
68
49
  }
@@ -72,79 +53,14 @@ export function bindLine(host, boundPort) {
72
53
  return `[fastagent] http host on ${classifyBind(host) === "wildcard" ? `:${boundPort} (all interfaces)` : bindLabel(host, boundPort)}`;
73
54
  }
74
55
  /**
75
- * The startup lines for a serve of OUR surface: the bind report, and the curl the reader copies.
76
- *
77
- * `servesInvoke` is `AgentService.unverifiedRoutes`, never a guess from the route table: `http.invoke: false` leaves no
78
- * `/invoke` to curl, and a channel may serve that path with a protocol of its own — both would turn this line into
79
- * a copyable request that fails.
80
- */
81
- export function readyAddressLines(host, boundPort, servesInvoke) {
82
- const dial = `${clientHost(host)}:${boundPort}`;
83
- return [
84
- bindLine(host, boundPort),
85
- ...(servesInvoke
86
- ? [
87
- `[fastagent] try it: curl -s ${dial}/invoke -X POST -H 'content-type: application/json' -d '${INVOKE_EXAMPLE_BODY}'`,
88
- ]
89
- : []),
90
- ];
91
- }
92
- /**
93
- * Say what this port exposes and how far it reaches.
94
- *
95
- * NOTHING fastagent serves is authenticated — authentication belongs to the deployment (a gateway, a private
96
- * network, AgentCore's IAM, an embedder's middleware). Two of the three warnings fire at a REACH the operator did
97
- * not get by default: a bind off this machine, and `--tunnel`'s public URL.
98
- *
99
- * The cross-origin one is UNCONDITIONAL, including on a loopback `dev`, because the grant is. `*` is the default
100
- * (`channels/serve.ts`), so a page the developer merely visits can drive this port from their browser and read the
101
- * reply, loopback bind or not. Nobody opts into a default, so the one posture the decision costs is the one that
102
- * has to hear about it.
103
- *
104
- * WHAT IS EXPOSED is read off `AgentService.unverifiedRoutes`, never assumed and never guessed from the route table.
105
- * `POST /invoke` is on most serves but not all: AgentCore answers the Runtime's `/invocations` behind IAM,
106
- * `http.invoke: false` withholds it, and a channel may serve that path itself — in which case the caller it is
107
- * open to is the platform that signs its requests, not anyone at all. A warning naming an endpoint this process
108
- * does not serve is how an operator learns to skim past all of them — the same reason `preflightDeploy` takes
109
- * `publicUrl`.
56
+ * What the CLI gives a long connection to stop in, and the hard exit that follows the whole close: the server's own
57
+ * grace for requests in flight (500 ms, channels/serve.ts), then the channels'.
110
58
  */
111
- export function announceControl(service, bind) {
112
- const { controlPrefix, corsOrigins } = service;
113
- if (controlPrefix)
114
- log.info(`[fastagent] session control on ${controlPrefix}/*`);
115
- // What an unauthenticated caller of this port can do, worst first. From `unverifiedRoutes`, so a channel that serves
116
- // `/invoke` itself is not described as our unauthenticated data plane — it has its own signature check.
117
- const exposed = describeAnonymousSurface({
118
- invoke: service.unverifiedRoutes.includes("POST /invoke"),
119
- run: service.unverifiedRoutes.includes("POST /run"),
120
- ...(controlPrefix ? { controlPrefix } : {}),
121
- });
122
- if (exposed.length === 0)
123
- return; // nothing of ours answers here (the AgentCore adapter's surface)
124
- const what = `${exposed.join(" and ")} ${exposed.length > 1 ? "answer" : "answers"}`;
125
- if (corsOrigins === undefined || corsOrigins.includes("*")) {
126
- log.warn(`[fastagent] any web page your browser visits can call this serve cross-origin and read the reply: ${what} ` +
127
- "with no credential. That is the default (`*`); pin the origins you actually use with http.cors " +
128
- "(docs/design/session-control.md §14)");
129
- }
130
- const reach = classifyBind(bind.host);
131
- if (reach !== "loopback") {
132
- log.warn(`[fastagent] the port binds ${reach === "wildcard" ? "all interfaces" : `${bind.host} (off this machine)`}: ` +
133
- `${what} UNAUTHENTICATED to anyone who can reach it — bind loopback (--bind 127.0.0.1), ` +
134
- "firewall the port, or front it with a gateway (docs/design/session-control.md §14)");
135
- }
136
- if (bind.tunnel) {
137
- log.warn(`[fastagent] --tunnel publishes this port at a public URL with NO authentication: ${what} to anyone with ` +
138
- "that URL — put real auth in front before sharing it (docs/design/session-control.md §14)");
139
- }
140
- }
141
- /** What the CLI gives a service to stop in, and the hard exit that follows it. */
142
59
  const SHUTDOWN_GRACE_MS = 800;
143
60
  const FORCED_EXIT_MS = 1_500;
144
- /** Bind HTTP and report ready — but only once the SERVICE is, which is not the same moment. */
145
- export function serve(handler, bind, hooks = {}) {
61
+ /** Listen, and report ready — but only once the SERVICE is, which is not the same moment — until a signal closes it. */
62
+ export function serve(service, bind, onListening) {
146
63
  const { port, host } = bind;
147
- const hosted = serveNode(handler, { port, host });
148
64
  let stopping = false;
149
65
  const stop = (exitCode) => {
150
66
  if (stopping)
@@ -155,33 +71,27 @@ export function serve(handler, bind, hooks = {}) {
155
71
  log.error(`[fastagent] shutdown did not finish within ${FORCED_EXIT_MS}ms; exiting`);
156
72
  process.exit(1);
157
73
  }, FORCED_EXIT_MS);
158
- // Stop accepting FIRST, before anything is awaited.
159
- const closingServer = hosted.close();
160
- hosted.closeAllConnections();
161
74
  // A cleanup that failed is not a clean exit.
162
- void Promise.allSettled([closingServer, Promise.resolve(hooks.onShutdown?.())]).then((outcomes) => {
163
- let code = exitCode;
164
- for (const outcome of outcomes) {
165
- if (outcome.status === "rejected") {
166
- log.error(`[fastagent] shutdown failed: ${String(outcome.reason)}`);
167
- code = 1;
168
- }
169
- }
75
+ void service.close().then(() => {
76
+ clearTimeout(deadline);
77
+ process.exit(exitCode);
78
+ }, (error) => {
79
+ log.error(`[fastagent] shutdown failed: ${String(error)}`);
170
80
  clearTimeout(deadline);
171
- process.exit(code);
81
+ process.exit(1);
172
82
  });
173
83
  };
174
84
  process.once("SIGINT", () => stop(0));
175
85
  process.once("SIGTERM", () => stop(0));
176
- hosted.listening.then(async (boundPort) => {
86
+ service.listen(port, host).then(async (boundPort) => {
177
87
  try {
178
88
  // A bound socket is NOT a serving agent: a declared socket-mode channel still has to come up, and reporting
179
89
  // ready before it does tells the supervisor (and --tunnel, and the operator) that a surface is live while a
180
90
  // channel is dead.
181
- await hooks.ready;
91
+ await service.ready;
182
92
  if (stopping)
183
93
  return;
184
- hooks.onListening?.(boundPort);
94
+ onListening?.(boundPort);
185
95
  }
186
96
  catch (error) {
187
97
  failStartup(error);
@@ -1,61 +1,32 @@
1
- import { type LoginIO } from "../engines/pi/login.ts";
2
- import { type AgentModels } from "../engines/pi/agent-models.ts";
3
- import { type IndirectTool } from "../engines/pi/create.ts";
4
- import type { LoadedDefinition } from "../engines/pi/definition.ts";
5
- import type { ToolCollision } from "../engines/pi/tool.ts";
6
- import { type ResolvedPlacement } from "../paths.ts";
1
+ import { type LoginIO } from "../harnesses/models/login.ts";
2
+ import { type ModelEnvironment } from "../harnesses/models/environment.ts";
3
+ import type { OpenedServing } from "../harnesses/pi-durable/serve.ts";
4
+ /** An agent directory a command entered, and the default model that then resolves, if any. */
5
+ export interface EnteredAgent {
6
+ agentDir: string;
7
+ modelSpec?: string;
8
+ }
7
9
  /**
8
- * How a command enters its agent directory, in the one order that works: placement, the agent's environment, then the
9
- * first-run model picker. Returns the default model that then resolves, if any. `deploy` uses this directly: it gates
10
- * a missing model itself, by what will ship.
10
+ * How a command enters its agent directory, in the one order that works: the directory, the agent's environment, then
11
+ * the first-run model picker. Returns the default model that then resolves, if any. `deploy` uses this directly: it
12
+ * gates a missing model itself, by what will ship. `before`: what the command checks of the directory before a model
13
+ * is asked for (`schedules run`: that the schedule it names exists).
11
14
  */
12
15
  export declare function enterAgentDirectory(dirArg: string, opts: {
13
16
  model?: string;
14
17
  input?: boolean;
15
- }): Promise<ResolvedPlacement & {
16
- modelSpec?: string;
17
- }>;
18
+ }, before?: (agentDir: string) => Promise<void>): Promise<EnteredAgent>;
18
19
  /**
19
- * How every command that RUNS the agent on this machine enters it (dev, start, invoke, routine run, chat):
20
+ * How every command that RUNS the agent on this machine enters it (dev, start, invoke, schedules run):
20
21
  * {@link enterAgentDirectory}, plus a default model. The agent opens without one, but a process here would then fail
21
- * every new conversation, so it stops at startup with {@link missingDefaultModel} instead.
22
+ * every new conversation, so it stops at startup instead: exit 2, the choice a terminal's picker would have asked for.
22
23
  */
23
24
  export declare function enterAgentCommand(dirArg: string, opts: {
24
25
  model?: string;
25
26
  input?: boolean;
26
- }): Promise<ResolvedPlacement & {
27
- modelSpec: string;
28
- }>;
29
- /**
30
- * The startup half of {@link enterAgentCommand}, for the one command that checks something of its own in between:
31
- * `routine run`, whose unknown name or unset secret is the more basic fault and is reported first.
32
- */
33
- export declare function requireDefaultModel(placement: ResolvedPlacement & {
34
- modelSpec?: string;
35
- }): ResolvedPlacement & {
36
- modelSpec: string;
37
- };
38
- /** What the startup report reads off an opened directory. */
39
- export interface ReportableAssembly {
40
- agentDir: string;
41
- workspace: string;
42
- modelSpec: string;
43
- models: AgentModels;
44
- config: {
45
- thinkingLevel?: string;
46
- };
47
- definition: LoadedDefinition;
48
- toolNames: string[];
49
- indirectTools: IndirectTool[];
50
- toolCollisions: ToolCollision[];
51
- }
52
- /** What `dev` and `start` say about the directory they just opened, in the order they say it. */
53
- export declare function reportAssembly(a: ReportableAssembly, extras?: {
54
- /** Printed between `workspace:` and `model:` (`dev` names the config file here). */
55
- beforeModel?: [label: string, value: string][];
56
- /** Printed after the tool lines, before findings (`start` names state + sessions here). */
57
- afterTools?: [label: string, value: string][];
58
- }): Promise<void>;
27
+ }, before?: (agentDir: string) => Promise<void>): Promise<Required<EnteredAgent>>;
28
+ /** What `dev` and `start` say about the agent they just opened, in the order they say it. */
29
+ export declare function reportAssembly(opened: OpenedServing, modelSpec: string, extras?: [label: string, value: string][]): Promise<void>;
59
30
  /** Both stdin and stdout are a terminal — the precondition for an interactive prompt. */
60
31
  export declare function isInteractive(): boolean;
61
32
  /** Parse + range-check a port string (CLI flag or env). */
@@ -66,6 +37,8 @@ export declare function parsePort(value: string | undefined, source: string, fro
66
37
  */
67
38
  export declare function parseBind(value: string | undefined): string | undefined;
68
39
  /** Report which source provides the model's credentials, surfacing a remediation hint at startup. */
69
- export declare function reportAuth(models: AgentModels, modelSpec: string): Promise<void>;
40
+ export declare function reportAuth(models: ModelEnvironment, modelSpec: string, agentDir: string): Promise<void>;
70
41
  /** Login terminal IO via @clack/prompts: a searchable list once long, a hidden prompt for keys. */
71
42
  export declare function terminalLoginIO(): LoginIO;
43
+ /** A copy/paste-safe POSIX shell argument for a command the CLI prints. */
44
+ export declare function shellArg(value: string): string;
@@ -2,79 +2,68 @@
2
2
  * Helpers shared across command modules: interactivity gates, port parsing, the startup auth report, first-run model
3
3
  * resolution, and the login terminal IO.
4
4
  */
5
- import { readFile, writeFile } from "node:fs/promises";
6
- import { relative, resolve } from "node:path";
5
+ import { resolve } from "node:path";
7
6
  import { autocomplete, isCancel, log as clackLog, password, select, text as clackText } from "@clack/prompts";
8
7
  import { buildModelPickerOptions } from "./models-view.js";
9
- import { isValidPort, listModels, loadConfig, missingDefaultModel, providerOf, resolveModelSpec, rewriteConfigModel, } from "../engines/pi/config.js";
10
- import { LoginCancelled, loginFlow } from "../engines/pi/login.js";
11
- import { readMachine, withMachine } from "../engines/pi/machine.js";
12
- import { providerAuthStatuses } from "../engines/pi/models.js";
13
- import { agentModels } from "../engines/pi/agent-models.js";
8
+ import { LoginCancelled, loginFlow } from "../harnesses/models/login.js";
9
+ import { modelEnvironment } from "../harnesses/models/environment.js";
10
+ import { listModels, providerAuthStatuses, providerOf } from "../harnesses/models/models.js";
11
+ import { definitionProviders, loadConfig, modelSpecFor } from "../harnesses/pi-durable/open.js";
14
12
  import { formatAuthReport } from "./auth-view.js";
15
- import { CODING_TOOL_NAMES } from "../engines/pi/create.js";
16
- import { describeIndirectTools, describePrompt, reportFindingsIfChanged, reportToolCollisions, } from "../engines/pi/report.js";
17
- import { isDeployedWorkspace } from "../paths.js";
13
+ import { contentLines } from "./content-view.js";
14
+ import { deployedHost, isDeployedWorkspace } from "../paths.js";
18
15
  import { log } from "../log.js";
19
- import { enterAgentEnv } from "../env.js";
16
+ import { dotEnvPath, enterAgentEnv } from "../env.js";
20
17
  import { openExternalUrl } from "../open-url.js";
21
18
  import { bindAddress, isBindAddress } from "../bind.js";
22
- import { failStartup, failUsage, placementOrExit } from "./fail.js";
19
+ import { agentDirOrExit, failStartup, failUsage } from "./fail.js";
23
20
  /**
24
- * How a command enters its agent directory, in the one order that works: placement, the agent's environment, then the
25
- * first-run model picker. Returns the default model that then resolves, if any. `deploy` uses this directly: it gates
26
- * a missing model itself, by what will ship.
21
+ * How a command enters its agent directory, in the one order that works: the directory, the agent's environment, then
22
+ * the first-run model picker. Returns the default model that then resolves, if any. `deploy` uses this directly: it
23
+ * gates a missing model itself, by what will ship. `before`: what the command checks of the directory before a model
24
+ * is asked for (`schedules run`: that the schedule it names exists).
27
25
  */
28
- export async function enterAgentDirectory(dirArg, opts) {
29
- const placement = placementOrExit(resolve(dirArg));
30
- enterAgentEnv(placement.agentDir);
31
- const modelSpec = await resolveFirstRunModel(placement, opts);
32
- return { ...placement, ...(modelSpec ? { modelSpec } : {}) };
26
+ export async function enterAgentDirectory(dirArg, opts, before) {
27
+ const agentDir = agentDirOrExit(resolve(dirArg));
28
+ enterAgentEnv(agentDir);
29
+ await before?.(agentDir);
30
+ const modelSpec = await resolveFirstRunModel(agentDir, opts);
31
+ return { agentDir, ...(modelSpec ? { modelSpec } : {}) };
33
32
  }
34
33
  /**
35
- * How every command that RUNS the agent on this machine enters it (dev, start, invoke, routine run, chat):
34
+ * How every command that RUNS the agent on this machine enters it (dev, start, invoke, schedules run):
36
35
  * {@link enterAgentDirectory}, plus a default model. The agent opens without one, but a process here would then fail
37
- * every new conversation, so it stops at startup with {@link missingDefaultModel} instead.
36
+ * every new conversation, so it stops at startup instead: exit 2, the choice a terminal's picker would have asked for.
38
37
  */
39
- export async function enterAgentCommand(dirArg, opts) {
40
- return requireDefaultModel(await enterAgentDirectory(dirArg, opts));
41
- }
42
- /**
43
- * The startup half of {@link enterAgentCommand}, for the one command that checks something of its own in between:
44
- * `routine run`, whose unknown name or unset secret is the more basic fault and is reported first.
45
- */
46
- export function requireDefaultModel(placement) {
47
- const { modelSpec } = placement;
48
- if (!modelSpec)
49
- failStartup(missingDefaultModel());
50
- return { ...placement, modelSpec };
38
+ export async function enterAgentCommand(dirArg, opts, before) {
39
+ const entered = await enterAgentDirectory(dirArg, opts, before);
40
+ const { modelSpec } = entered;
41
+ if (!modelSpec) {
42
+ failUsage(`missing model: set --model, "model" in fastagent.config.ts, or FASTAGENT_MODEL (e.g. "openai/gpt-5.5"; ` +
43
+ "`fastagent models` lists them)");
44
+ }
45
+ return { ...entered, modelSpec };
51
46
  }
52
47
  /** The padded label writer for the STARTUP report (`dev`/`start`, stderr via the log level). */
53
48
  function reportLine(label, value) {
54
49
  log.info(`[fastagent] ${`${label}:`.padEnd(13)}${value}`);
55
50
  }
56
- /** What `dev` and `start` say about the directory they just opened, in the order they say it. */
57
- export async function reportAssembly(a, extras = {}) {
58
- reportLine("agent", a.agentDir);
59
- reportLine("workspace", a.workspace);
60
- for (const [label, value] of extras.beforeModel ?? [])
51
+ /** What `dev` and `start` say about the agent they just opened, in the order they say it. */
52
+ export async function reportAssembly(opened, modelSpec, extras = []) {
53
+ const { definition, code, models, agentDir, stateRoot } = opened;
54
+ reportLine("agent", `${definition.name} — ${agentDir}`);
55
+ for (const [label, value] of contentLines(opened.content))
61
56
  reportLine(label, value);
62
- reportLine("model", `${a.modelSpec}${a.config.thinkingLevel ? ` (thinking: ${a.config.thinkingLevel})` : ""}`);
63
- await reportAuth(a.models, a.modelSpec);
64
- reportLine("context", a.definition.contextFiles.map((f) => f.path).join(", ") || "(none)");
65
- reportLine("prompt", describePrompt(a.definition));
66
- // What this agent HAS — the definition's skills and the ones its machine lends (machine.ts).
67
- const skills = withMachine(a.definition.skills, (await readMachine(a.workspace)).skills);
68
- reportLine("skills", skills.map((s) => s.name).join(", ") || "(none)");
69
- reportLine("codingTools", CODING_TOOL_NAMES.join(", "));
70
- if (a.toolNames.length > 0)
71
- reportLine("tools", a.toolNames.join(", "));
72
- if (a.indirectTools.length > 0)
73
- reportLine("indirect", describeIndirectTools(a.indirectTools));
74
- reportToolCollisions(a.toolCollisions);
75
- for (const [label, value] of extras.afterTools ?? [])
57
+ reportLine("model", `${modelSpec}${definition.config.thinkingLevel ? ` (thinking: ${definition.config.thinkingLevel})` : ""}`);
58
+ await reportAuth(models, modelSpec, agentDir);
59
+ const names = (list) => list.map(({ name }) => name).join(", ") || "(none)";
60
+ reportLine("tools", names(code.tools));
61
+ if (code.extensions.length > 0)
62
+ reportLine("extensions", names(code.extensions));
63
+ reportLine("commands", (await opened.agent.info()).commands.map(({ name }) => `/${name}`).join(", ") || "(none)");
64
+ reportLine("state", stateRoot);
65
+ for (const [label, value] of extras)
76
66
  reportLine(label, value);
77
- reportFindingsIfChanged(a.definition.dir, a.definition);
78
67
  }
79
68
  /** Both stdin and stdout are a terminal — the precondition for an interactive prompt. */
80
69
  export function isInteractive() {
@@ -87,7 +76,7 @@ export function parsePort(value, source, from) {
87
76
  const trimmed = value.trim();
88
77
  if (trimmed === "")
89
78
  return undefined;
90
- if (!/^\d+$/.test(trimmed) || !isValidPort(Number(trimmed))) {
79
+ if (!/^\d+$/.test(trimmed) || Number(trimmed) > 65535) {
91
80
  const message = `invalid ${source} "${value}": must be an integer 0-65535`;
92
81
  if (from === "flag")
93
82
  failUsage(message);
@@ -108,7 +97,7 @@ export function parseBind(value) {
108
97
  return bindAddress(trimmed); // a name never travels past this point — see bind.ts
109
98
  }
110
99
  /** Report which source provides the model's credentials, surfacing a remediation hint at startup. */
111
- export async function reportAuth(models, modelSpec) {
100
+ export async function reportAuth(models, modelSpec, agentDir) {
112
101
  const provider = providerOf(modelSpec);
113
102
  // No files: the opener was handed a credential store, which is its caller's to describe.
114
103
  if (models.auth === undefined) {
@@ -119,36 +108,42 @@ export async function reportAuth(models, modelSpec) {
119
108
  // line cannot name a file, or a source, other than the ones the runtime uses.
120
109
  const modelId = modelSpec.slice(provider.length + 1);
121
110
  const status = await models.authStatus(provider, modelId).catch(failStartup);
122
- const report = formatAuthReport({ provider, path: models.auth.path, ...status, deployed: isDeployedWorkspace() });
111
+ const report = formatAuthReport({
112
+ provider,
113
+ path: models.auth.path,
114
+ ...status,
115
+ ...(isDeployedWorkspace()
116
+ ? { deployed: { host: deployedHost() } }
117
+ : { local: { authPath: models.auth.path, valueFile: dotEnvPath(agentDir) } }),
118
+ });
123
119
  log.info(`[fastagent] ${report.line}`);
124
120
  if (report.warn)
125
121
  log.warn(`[fastagent] ${report.warn}`);
126
122
  }
127
123
  /**
128
- * First-run model resolution for every assembly command (dev/start/invoke/fire/chat/deploy): ONE funnel, no dead ends.
124
+ * The default model, for every command that runs the agent: `--model` > `FASTAGENT_MODEL` > `fastagent.config.ts`. With
125
+ * none and a terminal, the first-run picker chooses one for this run (and logs in to its provider when needed).
129
126
  */
130
- async function resolveFirstRunModel({ agentDir, workspace }, options = {}) {
131
- const { config, path: configPath } = await loadConfig(agentDir).catch(failStartup);
132
- const configured = resolveModelSpec(options.model, config);
127
+ async function resolveFirstRunModel(agentDir, options = {}) {
128
+ const config = await loadConfig(agentDir).catch(failStartup);
129
+ const configured = modelSpecFor(config, options.model);
133
130
  if (configured)
134
- return configured; // already set (flag > FASTAGENT_MODEL > config)
131
+ return configured;
135
132
  if (options.input === false)
136
133
  return undefined; // --no-input: never prompt (clig) — the caller decides what's missing
137
134
  if (!isInteractive())
138
135
  return undefined; // CI/deploy: the caller raises the actionable missing-model error
139
- const environment = agentModels(agentDir, {}, { cwd: workspace });
140
- // The picker lists the AGENT's surface: built-ins plus whatever its models.json declares, so a self-hosted endpoint
141
- // is pickable on first run instead of being invisible until hand-set.
142
- const models = await environment.runtime().catch(failStartup);
143
- const chosen = await pickWithCredentials(models, environment.auth.path, agentDir);
136
+ const providers = await definitionProviders(agentDir).catch(failStartup);
137
+ const environment = await modelEnvironment(agentDir, {}, providers);
138
+ const chosen = await pickWithCredentials(environment.models, environment.auth?.path, providers);
144
139
  if (chosen === undefined)
145
140
  return undefined; // cancelled (or auth probe failed): the caller raises its clear error
146
141
  process.env.FASTAGENT_MODEL = chosen; // this process + any spawned dev worker inherits it
147
- await persistModelChoice(agentDir, configPath, chosen);
142
+ console.error(`[fastagent] picked ${chosen} — set \`model: ${JSON.stringify(chosen)}\` in fastagent.config.ts to keep it`);
148
143
  return chosen;
149
144
  }
150
145
  /** The credential-aware pick: full catalog annotated per provider, then the post-pick auth policy. */
151
- async function pickWithCredentials(models, authPath, agentDir) {
146
+ async function pickWithCredentials(models, authPath, providers) {
152
147
  let statuses;
153
148
  try {
154
149
  statuses = await providerAuthStatuses(models);
@@ -181,7 +176,7 @@ async function pickWithCredentials(models, authPath, agentDir) {
181
176
  }
182
177
  try {
183
178
  // Verified on this agent's registry, against the chosen model: the request the agent is about to make.
184
- await loginFlow(terminalLoginIO(), { provider, authPath, agentDir, verifyWith: chosen });
179
+ await loginFlow(terminalLoginIO(), { provider, authPath, providers, verifyWith: chosen });
185
180
  console.error(`[fastagent] logged in to ${provider} — saved to ${authPath}`);
186
181
  }
187
182
  catch (error) {
@@ -210,23 +205,7 @@ export function terminalLoginIO() {
210
205
  openUrl: openExternalUrl,
211
206
  };
212
207
  }
213
- /** Best-effort persist the picked model so the next run does not prompt. */
214
- async function persistModelChoice(agentDir, configPath, spec) {
215
- const hint = (why = "") => console.error(
216
- // The pick lives in THIS process's environment only, so it serves this run and nothing that outlives it: a
217
- // deployment resolves in the environment being deployed, where this machine's variables do not exist.
218
- `[fastagent] picked ${spec} — set \`model: ${JSON.stringify(spec)}\` in your config to persist${why}`);
219
- if (!configPath)
220
- return hint();
221
- try {
222
- const replaced = rewriteConfigModel(await readFile(configPath, "utf8"), spec);
223
- if (!replaced)
224
- return hint();
225
- await writeFile(configPath, replaced);
226
- console.error(`[fastagent] saved model ${JSON.stringify(spec)} to ${relative(agentDir, configPath)}`);
227
- }
228
- catch (error) {
229
- // The run goes on with the pick either way; the reason the file was not written is what the author needs to fix.
230
- hint(` (could not write ${configPath}: ${error.message})`);
231
- }
208
+ /** A copy/paste-safe POSIX shell argument for a command the CLI prints. */
209
+ export function shellArg(value) {
210
+ return /^[A-Za-z0-9_./:@%+=,-]+$/.test(value) ? value : `'${value.replaceAll("'", `'"'"'`)}'`;
232
211
  }