@fastagent-sh/fastagent 0.21.0 → 0.22.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 (388) hide show
  1. package/README.md +9 -12
  2. package/dist/agent.d.ts +24 -37
  3. package/dist/agent.js +7 -15
  4. package/dist/atomic-write.d.ts +13 -17
  5. package/dist/atomic-write.js +18 -29
  6. package/dist/bind.d.ts +12 -22
  7. package/dist/bind.js +18 -27
  8. package/dist/channel.d.ts +11 -33
  9. package/dist/channels/agentcore-limits.d.ts +2 -13
  10. package/dist/channels/agentcore-limits.js +2 -13
  11. package/dist/channels/agentcore-protocol.d.ts +67 -58
  12. package/dist/channels/agentcore-protocol.js +23 -15
  13. package/dist/channels/agentcore-service.d.ts +19 -33
  14. package/dist/channels/agentcore-service.js +176 -59
  15. package/dist/channels/agentcore.d.ts +39 -33
  16. package/dist/channels/agentcore.js +90 -224
  17. package/dist/channels/body.d.ts +15 -2
  18. package/dist/channels/body.js +24 -2
  19. package/dist/channels/busy.d.ts +1 -21
  20. package/dist/channels/busy.js +2 -39
  21. package/dist/channels/control.d.ts +17 -62
  22. package/dist/channels/control.js +74 -182
  23. package/dist/channels/define-channel.d.ts +39 -0
  24. package/dist/channels/define-channel.js +9 -0
  25. package/dist/channels/discover.d.ts +10 -31
  26. package/dist/channels/discover.js +37 -31
  27. package/dist/channels/feishu/bootstrap-token.d.ts +1 -8
  28. package/dist/channels/feishu/bootstrap-token.js +7 -23
  29. package/dist/channels/feishu/card.d.ts +14 -28
  30. package/dist/channels/feishu/card.js +16 -30
  31. package/dist/channels/feishu/cloud.d.ts +1 -5
  32. package/dist/channels/feishu/context-buffer.d.ts +4 -23
  33. package/dist/channels/feishu/context-buffer.js +8 -31
  34. package/dist/channels/feishu/crypto.d.ts +10 -5
  35. package/dist/channels/feishu/crypto.js +12 -19
  36. package/dist/channels/feishu/feishu-api.d.ts +2 -1
  37. package/dist/channels/feishu/feishu-api.js +5 -4
  38. package/dist/channels/feishu/feishu.d.ts +4 -10
  39. package/dist/channels/feishu/feishu.js +113 -227
  40. package/dist/channels/feishu/invoke-turn.d.ts +5 -4
  41. package/dist/channels/feishu/invoke-turn.js +36 -54
  42. package/dist/channels/feishu/model.d.ts +4 -21
  43. package/dist/channels/feishu/model.js +1 -8
  44. package/dist/channels/feishu/normalize.d.ts +2 -10
  45. package/dist/channels/feishu/normalize.js +7 -42
  46. package/dist/channels/feishu/parse.d.ts +9 -29
  47. package/dist/channels/feishu/parse.js +8 -26
  48. package/dist/channels/feishu/preview.d.ts +12 -14
  49. package/dist/channels/feishu/preview.js +108 -207
  50. package/dist/channels/feishu/register-app.d.ts +8 -23
  51. package/dist/channels/feishu/register-app.js +7 -20
  52. package/dist/channels/feishu/register-webhook.d.ts +2 -9
  53. package/dist/channels/feishu/register-webhook.js +9 -33
  54. package/dist/channels/feishu/scaffold/channel.ts +27 -19
  55. package/dist/channels/feishu/scaffold/channel.websocket.ts +31 -0
  56. package/dist/channels/feishu/setup-mode.d.ts +11 -36
  57. package/dist/channels/feishu/setup-mode.js +7 -26
  58. package/dist/channels/feishu/ws-ingress.d.ts +1 -2
  59. package/dist/channels/feishu/ws-ingress.js +6 -8
  60. package/dist/channels/http.d.ts +15 -15
  61. package/dist/channels/http.js +19 -9
  62. package/dist/channels/kit/attachment-path.d.ts +4 -5
  63. package/dist/channels/kit/attachment-path.js +10 -34
  64. package/dist/channels/kit/context-buffer.d.ts +14 -21
  65. package/dist/channels/kit/context-buffer.js +25 -38
  66. package/dist/channels/kit/delivery.d.ts +35 -0
  67. package/dist/channels/kit/delivery.js +129 -0
  68. package/dist/channels/kit/event-stream.d.ts +5 -0
  69. package/dist/channels/kit/event-stream.js +29 -0
  70. package/dist/channels/kit/invoke-turn-kit.d.ts +53 -26
  71. package/dist/channels/kit/invoke-turn-kit.js +89 -32
  72. package/dist/channels/kit/preview-kit.d.ts +18 -72
  73. package/dist/channels/kit/preview-kit.js +22 -88
  74. package/dist/channels/kit/signature.d.ts +3 -9
  75. package/dist/channels/kit/signature.js +3 -9
  76. package/dist/channels/kit/state.d.ts +1 -2
  77. package/dist/channels/kit/state.js +5 -14
  78. package/dist/channels/kit/stop-command.d.ts +1 -2
  79. package/dist/channels/kit/stop-command.js +6 -9
  80. package/dist/channels/kit/tasks.d.ts +1 -1
  81. package/dist/channels/kit/tasks.js +8 -21
  82. package/dist/channels/kit/text.d.ts +2 -16
  83. package/dist/channels/kit/text.js +23 -31
  84. package/dist/channels/kit/thread-participants.d.ts +4 -17
  85. package/dist/channels/kit/thread-participants.js +8 -55
  86. package/dist/channels/kit/transport.d.ts +26 -0
  87. package/dist/channels/kit/transport.js +20 -0
  88. package/dist/channels/kit/turn-queue.d.ts +7 -11
  89. package/dist/channels/kit/turn-queue.js +21 -39
  90. package/dist/channels/kit/turn-runner.d.ts +32 -18
  91. package/dist/channels/kit/turn-runner.js +98 -53
  92. package/dist/channels/kit/turn-store.d.ts +32 -32
  93. package/dist/channels/kit/turn-store.js +45 -88
  94. package/dist/channels/lark/lark.d.ts +1 -5
  95. package/dist/channels/lark/onboard.d.ts +3 -12
  96. package/dist/channels/lark/onboard.js +3 -13
  97. package/dist/channels/lark/scaffold/channel.ts +27 -19
  98. package/dist/channels/lark/scaffold/channel.websocket.ts +31 -0
  99. package/dist/channels/registration.d.ts +9 -35
  100. package/dist/channels/registration.js +6 -37
  101. package/dist/channels/secret.js +2 -5
  102. package/dist/channels/serve.d.ts +47 -44
  103. package/dist/channels/serve.js +165 -101
  104. package/dist/channels/slack/config-api.d.ts +4 -27
  105. package/dist/channels/slack/config-api.js +5 -34
  106. package/dist/channels/slack/context-buffer.d.ts +2 -3
  107. package/dist/channels/slack/context-buffer.js +5 -5
  108. package/dist/channels/slack/invoke-turn.d.ts +3 -1
  109. package/dist/channels/slack/invoke-turn.js +25 -34
  110. package/dist/channels/slack/manifest.js +1 -3
  111. package/dist/channels/slack/model.d.ts +1 -2
  112. package/dist/channels/slack/model.js +1 -1
  113. package/dist/channels/slack/onboard.d.ts +4 -3
  114. package/dist/channels/slack/onboard.js +8 -11
  115. package/dist/channels/slack/onboarding-state.d.ts +3 -5
  116. package/dist/channels/slack/onboarding-state.js +9 -6
  117. package/dist/channels/slack/parse.d.ts +4 -13
  118. package/dist/channels/slack/parse.js +7 -28
  119. package/dist/channels/slack/preview.d.ts +12 -2
  120. package/dist/channels/slack/preview.js +292 -269
  121. package/dist/channels/slack/reaction.d.ts +11 -3
  122. package/dist/channels/slack/reaction.js +19 -8
  123. package/dist/channels/slack/register-webhook.js +4 -7
  124. package/dist/channels/slack/scaffold/channel.ts +20 -13
  125. package/dist/channels/slack/scaffold/slack-send.ts +2 -2
  126. package/dist/channels/slack/setup-server.d.ts +1 -5
  127. package/dist/channels/slack/setup-server.js +1 -5
  128. package/dist/channels/slack/shared-api.d.ts +1 -4
  129. package/dist/channels/slack/shared-api.js +2 -13
  130. package/dist/channels/slack/slack-api.d.ts +2 -1
  131. package/dist/channels/slack/slack-api.js +6 -4
  132. package/dist/channels/slack/slack.d.ts +11 -14
  133. package/dist/channels/slack/slack.js +121 -122
  134. package/dist/channels/sse.d.ts +1 -1
  135. package/dist/channels/sse.js +1 -1
  136. package/dist/channels/telegram/context-buffer.d.ts +7 -22
  137. package/dist/channels/telegram/context-buffer.js +6 -23
  138. package/dist/channels/telegram/invoke-turn.d.ts +7 -7
  139. package/dist/channels/telegram/invoke-turn.js +24 -43
  140. package/dist/channels/telegram/parse.d.ts +24 -51
  141. package/dist/channels/telegram/parse.js +32 -84
  142. package/dist/channels/telegram/preview.d.ts +10 -1
  143. package/dist/channels/telegram/preview.js +79 -100
  144. package/dist/channels/telegram/register-webhook.js +5 -23
  145. package/dist/channels/telegram/scaffold/channel.ts +25 -18
  146. package/dist/channels/telegram/scaffold/telegram-send.ts +6 -4
  147. package/dist/channels/telegram/telegram-api.d.ts +4 -3
  148. package/dist/channels/telegram/telegram-api.js +9 -7
  149. package/dist/channels/telegram/telegram.d.ts +4 -18
  150. package/dist/channels/telegram/telegram.js +38 -94
  151. package/dist/channels/telegram/turn-store.d.ts +11 -14
  152. package/dist/channels/telegram/turn-store.js +8 -6
  153. package/dist/channels/wait-health.d.ts +4 -6
  154. package/dist/channels/wait-health.js +10 -14
  155. package/dist/cli/add-feishu.d.ts +2 -12
  156. package/dist/cli/add-feishu.js +24 -71
  157. package/dist/cli/add-slack.d.ts +5 -3
  158. package/dist/cli/add-slack.js +53 -76
  159. package/dist/cli/auth-view.d.ts +2 -16
  160. package/dist/cli/auth-view.js +2 -16
  161. package/dist/cli/commands/add.js +25 -43
  162. package/dist/cli/commands/chat.d.ts +0 -1
  163. package/dist/cli/commands/chat.js +5 -6
  164. package/dist/cli/commands/deploy/agentcore.js +60 -65
  165. package/dist/cli/commands/deploy/docker.js +50 -23
  166. package/dist/cli/commands/deploy/fly.js +23 -61
  167. package/dist/cli/commands/deploy/railway.js +23 -18
  168. package/dist/cli/commands/deploy/shared.d.ts +38 -57
  169. package/dist/cli/commands/deploy/shared.js +40 -59
  170. package/dist/cli/commands/deploy.d.ts +10 -27
  171. package/dist/cli/commands/deploy.js +38 -60
  172. package/dist/cli/commands/destroy.d.ts +4 -0
  173. package/dist/cli/commands/destroy.js +56 -0
  174. package/dist/cli/commands/dev.d.ts +2 -1
  175. package/dist/cli/commands/dev.js +20 -23
  176. package/dist/cli/commands/info.d.ts +0 -2
  177. package/dist/cli/commands/info.js +83 -49
  178. package/dist/cli/commands/init.d.ts +1 -2
  179. package/dist/cli/commands/init.js +16 -55
  180. package/dist/cli/commands/invoke.d.ts +0 -1
  181. package/dist/cli/commands/invoke.js +5 -7
  182. package/dist/cli/commands/login.d.ts +2 -1
  183. package/dist/cli/commands/login.js +33 -38
  184. package/dist/cli/commands/logs.js +3 -4
  185. package/dist/cli/commands/models.js +1 -5
  186. package/dist/cli/commands/routine-run.d.ts +6 -0
  187. package/dist/cli/commands/routine-run.js +47 -0
  188. package/dist/cli/commands/routine.d.ts +25 -0
  189. package/dist/cli/commands/routine.js +122 -0
  190. package/dist/cli/commands/start.d.ts +31 -3
  191. package/dist/cli/commands/start.js +131 -81
  192. package/dist/cli/commands/tool.js +26 -12
  193. package/dist/cli/fail.d.ts +13 -23
  194. package/dist/cli/fail.js +20 -23
  195. package/dist/cli/invoke-stream.d.ts +1 -8
  196. package/dist/cli/kernel.d.ts +6 -38
  197. package/dist/cli/kernel.js +14 -77
  198. package/dist/cli/models-view.d.ts +1 -9
  199. package/dist/cli/models-view.js +11 -22
  200. package/dist/cli/program.d.ts +5 -6
  201. package/dist/cli/program.js +120 -157
  202. package/dist/cli/serve.d.ts +57 -41
  203. package/dist/cli/serve.js +94 -121
  204. package/dist/cli/shared.d.ts +15 -61
  205. package/dist/cli/shared.js +55 -181
  206. package/dist/cli.js +1 -8
  207. package/dist/collect.d.ts +6 -0
  208. package/dist/collect.js +6 -0
  209. package/dist/core.d.ts +4 -1
  210. package/dist/core.js +9 -7
  211. package/dist/declared-secrets.d.ts +55 -0
  212. package/dist/declared-secrets.js +88 -0
  213. package/dist/deploy/agentcore/aws-cli.d.ts +91 -0
  214. package/dist/deploy/agentcore/aws-cli.js +64 -0
  215. package/dist/deploy/agentcore/destroy.d.ts +51 -0
  216. package/dist/deploy/agentcore/destroy.js +273 -0
  217. package/dist/deploy/agentcore/forwarder.js +28 -79
  218. package/dist/deploy/agentcore/logs.d.ts +2 -18
  219. package/dist/deploy/agentcore/logs.js +27 -51
  220. package/dist/deploy/agentcore/plan.d.ts +85 -105
  221. package/dist/deploy/agentcore/plan.js +152 -314
  222. package/dist/deploy/agentcore/run.d.ts +28 -28
  223. package/dist/deploy/agentcore/run.js +227 -306
  224. package/dist/deploy/agentcore/zip.d.ts +2 -15
  225. package/dist/deploy/agentcore/zip.js +3 -17
  226. package/dist/deploy/build-context.d.ts +21 -0
  227. package/dist/deploy/build-context.js +137 -0
  228. package/dist/deploy/channel-ingress.d.ts +26 -39
  229. package/dist/deploy/channel-ingress.js +57 -28
  230. package/dist/deploy/container.d.ts +20 -34
  231. package/dist/deploy/container.js +49 -100
  232. package/dist/deploy/docker/plan.d.ts +12 -11
  233. package/dist/deploy/docker/plan.js +43 -24
  234. package/dist/deploy/docker/run.d.ts +22 -25
  235. package/dist/deploy/docker/run.js +39 -37
  236. package/dist/deploy/fly/plan.d.ts +15 -44
  237. package/dist/deploy/fly/plan.js +41 -73
  238. package/dist/deploy/fly/run.d.ts +16 -51
  239. package/dist/deploy/fly/run.js +42 -95
  240. package/dist/deploy/hosts.d.ts +24 -3
  241. package/dist/deploy/hosts.js +24 -3
  242. package/dist/deploy/preflight.d.ts +47 -41
  243. package/dist/deploy/preflight.js +282 -383
  244. package/dist/deploy/railway/plan.d.ts +16 -42
  245. package/dist/deploy/railway/plan.js +42 -60
  246. package/dist/deploy/railway/run.d.ts +30 -68
  247. package/dist/deploy/railway/run.js +86 -100
  248. package/dist/deploy/registration-gate.d.ts +6 -13
  249. package/dist/deploy/residency.d.ts +37 -0
  250. package/dist/deploy/residency.js +24 -0
  251. package/dist/deploy/runner.d.ts +10 -9
  252. package/dist/deploy/runner.js +7 -18
  253. package/dist/deploy/secrets.d.ts +40 -41
  254. package/dist/deploy/secrets.js +117 -103
  255. package/dist/deploy/workspace.d.ts +50 -0
  256. package/dist/deploy/workspace.js +197 -0
  257. package/dist/dev-supervisor.d.ts +1 -9
  258. package/dist/dev-supervisor.js +21 -64
  259. package/dist/effect-port.d.ts +50 -0
  260. package/dist/effect-port.js +77 -0
  261. package/dist/engines/pi/agent-session-factory.d.ts +50 -69
  262. package/dist/engines/pi/agent-session-factory.js +249 -146
  263. package/dist/engines/pi/auth.d.ts +15 -11
  264. package/dist/engines/pi/auth.js +96 -99
  265. package/dist/engines/pi/chat.d.ts +1 -5
  266. package/dist/engines/pi/chat.js +2 -14
  267. package/dist/engines/pi/config.d.ts +53 -51
  268. package/dist/engines/pi/config.js +83 -92
  269. package/dist/engines/pi/create.d.ts +60 -75
  270. package/dist/engines/pi/create.js +108 -141
  271. package/dist/engines/pi/definition.d.ts +14 -58
  272. package/dist/engines/pi/definition.js +21 -85
  273. package/dist/engines/pi/invoke-session.d.ts +5 -25
  274. package/dist/engines/pi/invoke-session.js +209 -244
  275. package/dist/engines/pi/login.d.ts +95 -35
  276. package/dist/engines/pi/login.js +259 -107
  277. package/dist/engines/pi/machine.d.ts +31 -0
  278. package/dist/engines/pi/machine.js +106 -0
  279. package/dist/engines/pi/models.d.ts +70 -89
  280. package/dist/engines/pi/models.js +188 -81
  281. package/dist/engines/pi/open.d.ts +65 -53
  282. package/dist/engines/pi/open.js +129 -69
  283. package/dist/engines/pi/report.d.ts +3 -12
  284. package/dist/engines/pi/report.js +2 -16
  285. package/dist/engines/pi/search-tools.d.ts +1 -9
  286. package/dist/engines/pi/search-tools.js +26 -57
  287. package/dist/engines/pi/service.d.ts +2 -16
  288. package/dist/engines/pi/service.js +2 -16
  289. package/dist/engines/pi/session-builder.d.ts +5 -9
  290. package/dist/engines/pi/session-builder.js +44 -82
  291. package/dist/engines/pi/session-control.js +286 -269
  292. package/dist/engines/pi/session-effects.d.ts +14 -0
  293. package/dist/engines/pi/session-effects.js +30 -0
  294. package/dist/engines/pi/session-inheritance.d.ts +9 -18
  295. package/dist/engines/pi/session-inheritance.js +103 -160
  296. package/dist/engines/pi/session-markers.d.ts +31 -30
  297. package/dist/engines/pi/session-markers.js +26 -25
  298. package/dist/engines/pi/session-settings.d.ts +6 -22
  299. package/dist/engines/pi/session-settings.js +10 -21
  300. package/dist/engines/pi/session-store.d.ts +26 -92
  301. package/dist/engines/pi/session-store.js +96 -310
  302. package/dist/engines/pi/tool-context.d.ts +17 -45
  303. package/dist/engines/pi/tool-context.js +7 -26
  304. package/dist/engines/pi/tool.d.ts +45 -36
  305. package/dist/engines/pi/tool.js +43 -57
  306. package/dist/engines/pi/turn-kit.d.ts +14 -52
  307. package/dist/engines/pi/turn-kit.js +18 -67
  308. package/dist/engines/pi/wake-tool.d.ts +2 -10
  309. package/dist/engines/pi/wake-tool.js +7 -27
  310. package/dist/env.d.ts +27 -28
  311. package/dist/env.js +45 -50
  312. package/dist/index.js +0 -2
  313. package/dist/lark.d.ts +1 -2
  314. package/dist/lark.js +1 -2
  315. package/dist/loader.d.ts +14 -55
  316. package/dist/loader.js +24 -43
  317. package/dist/log.d.ts +2 -12
  318. package/dist/log.js +3 -24
  319. package/dist/node.d.ts +2 -15
  320. package/dist/node.js +2 -18
  321. package/dist/observe.d.ts +2 -8
  322. package/dist/open-url.d.ts +1 -1
  323. package/dist/open-url.js +1 -1
  324. package/dist/paths.d.ts +70 -134
  325. package/dist/paths.js +165 -232
  326. package/dist/pi.d.ts +4 -6
  327. package/dist/pi.js +3 -3
  328. package/dist/proxy.d.ts +16 -6
  329. package/dist/proxy.js +52 -16
  330. package/dist/runtime.d.ts +18 -12
  331. package/dist/runtime.js +18 -11
  332. package/dist/scaffold/add-channel.d.ts +14 -31
  333. package/dist/scaffold/add-channel.js +48 -112
  334. package/dist/scaffold/init.d.ts +9 -31
  335. package/dist/scaffold/init.js +45 -138
  336. package/dist/scaffold/templates/env.example +6 -4
  337. package/dist/scaffold/templates/fastagent.config.ts +36 -0
  338. package/dist/scaffold/templates.d.ts +3 -3
  339. package/dist/scaffold/templates.js +5 -8
  340. package/dist/scaffold/vendor-skill.d.ts +2 -5
  341. package/dist/scaffold/vendor-skill.js +19 -29
  342. package/dist/schedule/cron.d.ts +9 -5
  343. package/dist/schedule/cron.js +9 -11
  344. package/dist/schedule/discover.d.ts +12 -12
  345. package/dist/schedule/discover.js +43 -34
  346. package/dist/schedule/routine.d.ts +43 -0
  347. package/dist/schedule/routine.js +32 -0
  348. package/dist/schedule/run.d.ts +55 -0
  349. package/dist/schedule/run.js +146 -0
  350. package/dist/schedule/scheduler.d.ts +44 -55
  351. package/dist/schedule/scheduler.js +291 -265
  352. package/dist/schedule/state.d.ts +105 -10
  353. package/dist/schedule/state.js +293 -19
  354. package/dist/schedule/wake-alarm.d.ts +10 -23
  355. package/dist/schedule/wake-alarm.js +91 -121
  356. package/dist/schedule/wakeups.d.ts +23 -39
  357. package/dist/schedule/wakeups.js +33 -75
  358. package/dist/secrets-gate.d.ts +32 -0
  359. package/dist/secrets-gate.js +33 -0
  360. package/dist/service.d.ts +137 -98
  361. package/dist/service.js +250 -252
  362. package/dist/session-remote.d.ts +33 -44
  363. package/dist/session-remote.js +203 -192
  364. package/dist/session.d.ts +153 -228
  365. package/dist/session.js +33 -55
  366. package/dist/tunnel.d.ts +8 -36
  367. package/dist/tunnel.js +24 -65
  368. package/dist/version.d.ts +2 -2
  369. package/dist/version.js +2 -2
  370. package/package.json +10 -16
  371. package/dist/channels/agentcore-state.d.ts +0 -77
  372. package/dist/channels/agentcore-state.js +0 -276
  373. package/dist/channels/github/github.d.ts +0 -31
  374. package/dist/channels/github/github.js +0 -89
  375. package/dist/channels/github/scaffold/channel.ts +0 -25
  376. package/dist/cli/commands/attach.d.ts +0 -108
  377. package/dist/cli/commands/attach.js +0 -637
  378. package/dist/cli/commands/fire.d.ts +0 -7
  379. package/dist/cli/commands/fire.js +0 -38
  380. package/dist/cli/commands/schedule.d.ts +0 -12
  381. package/dist/cli/commands/schedule.js +0 -87
  382. package/dist/github.d.ts +0 -3
  383. package/dist/github.js +0 -2
  384. package/dist/scaffold/templates/fastagent.config.mjs +0 -23
  385. package/dist/schedule/audit.d.ts +0 -18
  386. package/dist/schedule/audit.js +0 -57
  387. package/dist/schedule/schedule.d.ts +0 -35
  388. package/dist/schedule/schedule.js +0 -23
@@ -1,108 +1,226 @@
1
1
  /**
2
- * The pi `Models` collection — the single hub that owns BOTH model resolution (provider/modelId
3
- * lookup) AND auth (per-request credential resolution). fastagent builds one per opener and threads
4
- * it into the engine alongside the selected `model`; the two must come from the same collection so
5
- * the model's provider auth is in scope.
2
+ * The pi `Models` collection — the single hub that owns BOTH model resolution (provider/modelId lookup) AND auth
3
+ * (per-request credential resolution). fastagent builds one per opener and threads it into the engine alongside the
4
+ * selected `model`; the two must come from the same collection so the model's provider auth is in scope.
6
5
  */
6
+ import { createHash } from "node:crypto";
7
+ import { existsSync } from "node:fs";
8
+ import { readFile } from "node:fs/promises";
9
+ import { homedir } from "node:os";
7
10
  import { join } from "node:path";
8
- import { defaultProviderAuthContext } from "@earendil-works/pi-ai";
9
- import { builtinModels } from "@earendil-works/pi-ai/providers/all";
11
+ import { InMemoryCredentialStore, defaultProviderAuthContext, } from "@earendil-works/pi-ai";
12
+ import { builtinModels, builtinProviders } from "@earendil-works/pi-ai/providers/all";
10
13
  import { ModelRuntime } from "@earendil-works/pi-coding-agent";
11
14
  import { fastagentCredentialStore } from "./auth.js";
12
15
  import { providerOf } from "./config.js";
13
- import { interactiveLoginKind } from "./login.js";
14
- import { AGENT_MODELS_FILE, resolveStateRoot } from "../../paths.js";
15
- /**
16
- * A `Models` with every built-in pi provider, wired to fastagent's auth: stored credentials from the
17
- * {@link CreatePiModelsOptions.authPath} file (via {@link fastagentCredentialStore}; the global
18
- * `~/.fastagent/.secrets/auth.json` unless the opener passes a project-level path), then ambient env vars. A
19
- * stored credential owns the provider; env is consulted only when nothing is stored (resolution order
20
- * is upstream-owned).
21
- */
16
+ import { AGENT_MODELS_FILE, GLOBAL_HOME_DIR, resolveOverridePath, resolveStateRoot } from "../../paths.js";
17
+ import { writeFileAtomic } from "../../atomic-write.js";
18
+ /** A `Models` with every built-in pi provider, wired to fastagent's auth. */
22
19
  export function createPiModels(options = {}) {
23
- const models = builtinModels({
24
- credentials: fastagentCredentialStore(options.authPath, { warn: options.warn }),
25
- authContext: defaultProviderAuthContext(),
26
- });
27
- for (const provider of options.providers ?? [])
20
+ return piModelsOver(fastagentCredentialStore(options.authPath, { warn: options.warn }), options.providers);
21
+ }
22
+ /** The built-ins plus `providers` (a same id replaces a built-in), over any credential store. */
23
+ export function piModelsOver(credentials, providers = []) {
24
+ const models = builtinModels({ credentials, authContext: defaultProviderAuthContext() });
25
+ for (const provider of providers)
28
26
  models.setProvider(provider);
29
27
  return models;
30
28
  }
29
+ /** The serving default for reasoning effort, pinned to what pi's TUI defaults to (its own DEFAULT_THINKING_LEVEL). */
30
+ export const DEFAULT_THINKING_LEVEL = "medium";
31
31
  /**
32
- * The serving default for reasoning effort, pinned to what pi's TUI defaults to (its own
33
- * DEFAULT_THINKING_LEVEL) — NOT inherited from the engine, whose fallback is "off": an author vibes
34
- * at "medium" in pi and must get "medium" when served (fidelity), and pinning the value here means
35
- * an upstream default change in either place cannot silently alter deployments. Models that do not
36
- * support a level are clamped by pi per model.
32
+ * The MACHINE's custom-endpoint file, in the same schema as an agent's own: endpoints a person set up for this machine
33
+ * (a local Ollama, a company gateway), which every agent here inherits the way it inherits the machine's skills.
34
+ * `FASTAGENT_MODELS_PATH` moves it. It never ships: a deployed agent has only its definition's file.
37
35
  */
38
- export const DEFAULT_THINKING_LEVEL = "medium";
36
+ export function machineModelsPath(env = process.env) {
37
+ return resolveOverridePath(env.FASTAGENT_MODELS_PATH) ?? join(homedir(), GLOBAL_HOME_DIR, AGENT_MODELS_FILE);
38
+ }
39
+ /** A custom-endpoint file's providers by id, or undefined when there is no file. Strict JSON: see {@link modelLayers}. */
40
+ async function readProviders(path) {
41
+ let raw;
42
+ try {
43
+ raw = await readFile(path, "utf8");
44
+ }
45
+ catch (error) {
46
+ if (error.code === "ENOENT")
47
+ return undefined;
48
+ throw new Error(`could not read ${path}: ${error.message}`);
49
+ }
50
+ let parsed;
51
+ try {
52
+ parsed = JSON.parse(raw.replace(/^\uFEFF/, ""));
53
+ }
54
+ catch (error) {
55
+ throw new Error(`${path} is not valid JSON: ${error.message}`);
56
+ }
57
+ const providers = parsed?.providers;
58
+ if (typeof providers !== "object" || providers === null || Array.isArray(providers)) {
59
+ throw new Error(`${path} must hold { "providers": { ... } }`);
60
+ }
61
+ return providers;
62
+ }
39
63
  /**
40
- * The `ModelRuntime`-shaped sibling of {@link createPiModels} — the SAME hub semantics (built-in
41
- * providers + fastagent's credential store at `authPath`) in the type pi's session services require
42
- * (`createAgentSessionServices({ modelRuntime })`). Built-ins PLUS the agent's own
43
- * {@link AGENT_MODELS_FILE} when `agentDir` is given (a dir-less caller gets built-ins only), and no
44
- * availability network, so the model surface equals serving's.
64
+ * The two custom-endpoint layers of an agent, read ONCE for every reader: the file pi loads and the report of where a
65
+ * provider came from both come from this, so what runs and what `info`/`deploy` say cannot disagree. Undefined when
66
+ * the machine has no file: then the agent's own file goes to pi untouched.
45
67
  *
46
- * `ModelRuntime` also takes `Provider` INSTANCES via `registerNativeProvider` (pi 0.83); the
47
- * declarative file is what this rung wires because it is data that travels with the definition.
68
+ * Read here rather than by pi, because pi loads exactly one path and its comment stripping is not reachable: while a
69
+ * machine file exists, both files must be plain JSON.
70
+ */
71
+ async function modelLayers(agentDir) {
72
+ const machinePath = machineModelsPath();
73
+ const machine = await readProviders(machinePath);
74
+ if (!machine)
75
+ return undefined;
76
+ return { machinePath, machine, own: (await readProviders(join(agentDir, AGENT_MODELS_FILE))) ?? {} };
77
+ }
78
+ /**
79
+ * The models.json pi loads for an agent: its own file, layered over the machine's. The agent's file wins a provider id
80
+ * outright, as a definition's skill wins a name: an agent that pins an endpoint keeps it.
81
+ *
82
+ * The merge is a SNAPSHOT named by its content, in fastagent's own home: not in the agent (so `info` writes nothing
83
+ * there), and not in a shared temp dir, which the OS clears while a long-running process still re-reads it (pi
84
+ * reloads `modelsPath` on every refresh). Content addressing is what lets every process share the directory: a
85
+ * snapshot is never rewritten, so no process can change what another's refresh reads. The price is that a running
86
+ * process keeps the snapshot it started with; an edit to either file takes effect on the next start.
87
+ *
88
+ * ponytail: snapshots are never pruned (one per distinct content, a few KB each) because a running process may still
89
+ * read an old one; delete the directory while no fastagent process runs if it ever matters.
90
+ */
91
+ async function modelsFileFor(agentDir) {
92
+ const definition = join(agentDir, AGENT_MODELS_FILE);
93
+ const layers = await modelLayers(agentDir);
94
+ if (!layers)
95
+ return { path: definition };
96
+ const content = JSON.stringify({ providers: { ...layers.machine, ...layers.own } }, null, 2);
97
+ const hash = createHash("sha256").update(content).digest("hex").slice(0, 32);
98
+ const path = join(homedir(), GLOBAL_HOME_DIR, ".cache", "models", `${hash}.json`);
99
+ // 0600: it may carry literal keys. Several processes may create the same snapshot at once.
100
+ if (!existsSync(path))
101
+ writeFileAtomic(path, content, 0o600, true);
102
+ return { path, merged: { machine: layers.machinePath, definition } };
103
+ }
104
+ /**
105
+ * Where an agent's custom endpoints come from, for a report: the machine file, the providers the agent inherits from
106
+ * it, and the ones its own file overrides. Undefined when the machine has no file.
48
107
  */
108
+ export async function machineModels(agentDir) {
109
+ const layers = await modelLayers(agentDir);
110
+ if (!layers)
111
+ return undefined;
112
+ const ids = Object.keys(layers.machine).sort();
113
+ return {
114
+ path: layers.machinePath,
115
+ inherited: ids.filter((id) => !(id in layers.own)),
116
+ overridden: ids.filter((id) => id in layers.own),
117
+ };
118
+ }
119
+ /** Whether pi ships this provider id itself, so an agent resolves it without any models.json entry. */
120
+ export function isBuiltinProvider(providerId) {
121
+ return builtinProviders().some((provider) => provider.id === providerId);
122
+ }
123
+ /** The `ModelRuntime`-shaped sibling of {@link createPiModels}. */
49
124
  export async function createPiModelRuntime(options = {}) {
50
125
  const { agentDir } = options;
126
+ const models = !agentDir
127
+ ? undefined
128
+ : options.machineLayer === false
129
+ ? { path: join(agentDir, AGENT_MODELS_FILE) }
130
+ : await modelsFileFor(agentDir);
51
131
  const runtime = await ModelRuntime.create({
52
- credentials: fastagentCredentialStore(options.authPath, { warn: options.warn }),
53
- modelsPath: agentDir ? join(agentDir, AGENT_MODELS_FILE) : null,
54
- // MUST be set whenever modelsPath is: pi defaults this to `<dirname(modelsPath)>/models-store.json`,
55
- // which would write a generated cache INTO the author's agent dir — and `deploy` bakes the whole
56
- // tree, so it would travel into the image as stale state. Machinery belongs under the state root.
132
+ credentials: options.credentials ??
133
+ fastagentCredentialStore(options.auth?.path, { warn: options.warn, fallbackPath: options.auth?.fallback }),
134
+ modelsPath: models?.path ?? null,
135
+ // MUST be set whenever modelsPath is: pi defaults this to `<dirname(modelsPath)>/models-store.json`, which would
136
+ // write a generated cache INTO the author's agent dir.
57
137
  ...(agentDir
58
138
  ? { modelsStorePath: join(options.stateRoot ?? resolveStateRoot(agentDir), "models-store.json") }
59
139
  : {}),
60
140
  allowModelNetwork: false,
61
141
  });
62
- // A malformed models.json does NOT throw upstream — `create` resolves with the built-ins and parks the
63
- // reason in getError(). Left unread, a typo'd endpoint would silently degrade to "provider not in
64
- // registry" at model-resolution time, i.e. the silent fallback this codebase forbids. The upstream
65
- // message already names both the reason and the file, so it is surfaced verbatim.
142
+ // A malformed models.json does NOT throw upstream — `create` resolves with the built-ins and parks the reason in
143
+ // getError().
66
144
  const error = runtime.getError();
67
- if (error)
68
- throw new Error(error);
145
+ if (error) {
146
+ const origin = models?.merged
147
+ ? `\n\nThat file merges ${models.merged.machine} with ${models.merged.definition} (the agent's own wins a provider id).`
148
+ : "";
149
+ throw new Error(`${error}${origin}`);
150
+ }
69
151
  for (const provider of options.providers ?? [])
70
152
  runtime.registerNativeProvider(provider);
71
153
  return runtime;
72
154
  }
73
- /**
74
- * How a model's credential will REACH a deployed agent — the question `deploy` asks, which
75
- * {@link probeAuthSource} cannot answer: it flattens every models.json endpoint to the display label
76
- * "configured API key", so a self-hosted endpoint looks credential-less to the deploy gate even when
77
- * its key is sitting in an env var.
78
- *
79
- * - `envVar`: an environment variable backs it, BY NAME — the shape `deploy` already understands, so
80
- * the value carries as a host secret with no extra declaration from the author.
81
- * - `inDefinition`: the definition itself carries it (a literal `apiKey`, or a `!command` run on the
82
- * host). Nothing for `deploy` to carry — and nothing to gate on either, which is the point: the
83
- * `fastagent login` remedy is meaningless for a provider login cannot serve.
84
- *
85
- * Neither set = a stored credential or nothing at all; the existing auth.json / gate paths decide.
86
- */
155
+ /** How a model's credential will REACH a deployed agent. */
87
156
  export function modelCredentialCarry(runtime, spec) {
88
157
  const status = runtime.getProviderAuthStatus(providerOf(spec));
89
158
  if (!status.configured)
90
159
  return { inDefinition: false };
91
- // An env-var name is only useful downstream if it IS one: `"${A}_${B}"` interpolation resolves from
92
- // the environment but has no single name to carry, so it falls through to the definition-carried
93
- // branch, where the author's `deploy.secrets` is the mechanism.
160
+ // An env-var name is only useful downstream if it IS one.
94
161
  if (status.source === "environment" && status.label && /^[A-Z][A-Z0-9_]*$/.test(status.label)) {
95
162
  return { envVar: status.label, inDefinition: false };
96
163
  }
97
164
  return { inDefinition: status.source !== "stored" };
98
165
  }
99
166
  /**
100
- * Probe every provider's auth once (auth is provider-scoped, so any of its models works as the probe)
101
- * — the status map behind the first-run model picker (`fastagent dev`/`start`/`invoke` with no model
102
- * set). The picker shows the FULL catalog annotated with these statuses, so "what fastagent supports"
103
- * and "what is authenticated on this machine" stay distinguishable; a needs-login choice triggers an
104
- * inline `loginFlow`. Providers with no models are omitted (nothing to pick).
167
+ * EVERY provider whose `models.json` entry writes its key as a LITERAL rather than a `"$NAME"` reference or a
168
+ * `"!cmd"`. The file ships inside the image, so a literal there is a credential in a readable layer.
169
+ *
170
+ * Read from the FILE, not from `getProviderAuthStatus`: that answers "what satisfies this provider right now" and
171
+ * returns `stored` first, so a provider that has both an `auth.json` entry and a literal in the file would report
172
+ * `stored` and the literal would go unreported. The question is what the definition DECLARES, and only the file
173
+ * answers it. The three-way split mirrors pi's `configuredRequestAuthStatus`, which is not exported.
174
+ *
175
+ * The caller WARNS on this; it does not refuse. Whether a given string is a credential is the author's knowledge,
176
+ * not the framework's — pi's own docs prescribe `"apiKey": "ollama"` for a keyless local server, and no static rule
177
+ * separates that from a leaked key (an endpoint's reachability is not decidable from its URL either). FastAgent
178
+ * gates what IT causes; what the author wrote into their own committed file, it reports.
179
+ */
180
+ export async function literalKeyProviders(agentDir) {
181
+ const file = join(agentDir, AGENT_MODELS_FILE);
182
+ let raw;
183
+ try {
184
+ raw = await readFile(file, "utf8");
185
+ }
186
+ catch (error) {
187
+ // No custom endpoints is the normal case; anything else (unreadable, a directory) is the caller's problem.
188
+ if (error.code === "ENOENT")
189
+ return [];
190
+ throw error;
191
+ }
192
+ // Malformed JSON already threw out of createPiModelRuntime before this runs, so a parse failure here would be a
193
+ // genuine surprise and must not be swallowed.
194
+ const providers = JSON.parse(raw).providers ?? {};
195
+ return Object.entries(providers)
196
+ .filter(([, provider]) => isLiteralKey(provider?.apiKey))
197
+ .map(([id]) => id);
198
+ }
199
+ /**
200
+ * `!cmd` runs on the box; `$NAME` / `${NAME}` reads the environment; anything else is the key itself.
201
+ *
202
+ * `$$` is pi's escape for a literal `$`, so it is removed BEFORE looking for a reference — otherwise `"sk$$abc"`
203
+ * (which resolves to the literal `sk$abc`) would read as a reference and go unmentioned.
105
204
  */
205
+ function isLiteralKey(apiKey) {
206
+ if (typeof apiKey !== "string" || apiKey === "" || apiKey.startsWith("!"))
207
+ return false;
208
+ return !/\$\{?[A-Za-z_]/.test(apiKey.replaceAll("$$", ""));
209
+ }
210
+ export function interactiveLoginKind(p) {
211
+ if (interactiveAuth(p, "oauth"))
212
+ return "oauth";
213
+ return interactiveAuth(p, "api_key") ? "api_key" : "none";
214
+ }
215
+ /** THE rule for "can this method be signed in to interactively": the auth to run for it, or undefined. */
216
+ export function interactiveAuth(provider, method) {
217
+ return method === "oauth" ? provider.auth.oauth : provider.auth.apiKey?.login ? provider.auth.apiKey : undefined;
218
+ }
219
+ /** The providers a sign-in can target: pi's built-ins plus `extra`, composed exactly as {@link createPiModels} does. */
220
+ export function loginProviders(extra) {
221
+ return piModelsOver(new InMemoryCredentialStore(), extra).getProviders();
222
+ }
223
+ /** Probe every provider's auth once (auth is provider-scoped, so any of its models works as the probe). */
106
224
  export async function providerAuthStatuses(models) {
107
225
  const statuses = new Map();
108
226
  for (const provider of models.getProviders()) {
@@ -120,12 +238,7 @@ export async function providerAuthStatuses(models) {
120
238
  }
121
239
  return statuses;
122
240
  }
123
- /**
124
- * Which source currently satisfies auth for `spec` — a startup diagnostic. Returns the upstream
125
- * `AuthResult.source` label: `"OAuth"` for a stored OAuth credential (e.g. a logged-in openai-codex),
126
- * `"stored credential"` for a stored API key, an env-var name like `"ANTHROPIC_API_KEY"` for env, or
127
- * undefined when unconfigured. Reporting-only; never throws.
128
- */
241
+ /** Which source currently satisfies auth for `spec` — a startup diagnostic. */
129
242
  export async function probeAuthSource(models, spec) {
130
243
  const slash = spec.indexOf("/");
131
244
  if (slash < 1)
@@ -136,15 +249,8 @@ export async function probeAuthSource(models, spec) {
136
249
  const auth = await models.getAuth(model).catch(() => undefined);
137
250
  return auth?.source;
138
251
  }
139
- /**
140
- * Quick-fail probe for a just-stored API key: one minimal real request through the standard auth
141
- * resolution path (the same path invokes take), so a mistyped key surfaces at login time, not at the
142
- * first turn. `complete` reports provider errors as `stopReason: "error"` rather than throwing; the
143
- * HTTP status arrives via `onResponse` — when a provider path never calls it (SDK transports), fall
144
- * back to a conservative "401" match in the error text. Short timeout, no retries: feedback speed
145
- * over transient-failure tolerance (a transient lands on `unknown`, which keeps the key).
146
- */
147
- export async function probeApiKey(models, model) {
252
+ /** Quick-fail probe for a just-stored API key. */
253
+ export async function probeApiKey(models, model, signal) {
148
254
  let status;
149
255
  let reply;
150
256
  try {
@@ -152,6 +258,7 @@ export async function probeApiKey(models, model) {
152
258
  maxTokens: 16,
153
259
  timeoutMs: 15_000,
154
260
  maxRetries: 0,
261
+ ...(signal ? { signal } : {}),
155
262
  onResponse: (r) => {
156
263
  status = r.status;
157
264
  },
@@ -1,54 +1,58 @@
1
1
  import type { Agent } from "../../agent.ts";
2
- import { type FastagentConfig } from "./config.ts";
3
- import type { SessionControl } from "../../session.ts";
2
+ import { type AuthLayers, type FastagentConfig } from "./config.ts";
3
+ import type { AgentCommand, SessionControl } from "../../session.ts";
4
4
  import type { SessionObserver } from "./turn-kit.ts";
5
- import type { ModuleLoadFailure } from "../../loader.ts";
6
5
  import { type LoadedDefinition } from "./definition.ts";
6
+ import type { ModelRuntime } from "@earendil-works/pi-coding-agent";
7
+ import type { FastagentAuthOptions } from "./auth.ts";
7
8
  import { type PiSessionRecordStore } from "./session-store.ts";
8
9
  import type { ToolCollision, MountedTool } from "./tool.ts";
10
+ import type { DeclaredSecret } from "../../declared-secrets.ts";
11
+ import type { HttpSurface } from "../../service.ts";
12
+ /**
13
+ * The names a `/` composer completes: this agent's skills — the definition's, plus the ones its machine lends
14
+ * (machine.ts) —, the commands its `extensions/` register, and the machine's prompt templates.
15
+ *
16
+ * `source` says how a name is INVOKED, which is the one thing a client needs from it: a `skill` is sent as
17
+ * `/skill:<name>`, an `extension` command and a `prompt` as `/<name>` (docs/design/session-control.md §5.1.1).
18
+ *
19
+ * The definition is read live, like every turn reads it; the machine is the process's one read, the same snapshot a
20
+ * bound session runs on, so the menu cannot offer a name the next prompt would not expand. The same holds for
21
+ * extensions: `served` is what sessions load — the assembly's entry points, discovered once, and the runtime turns run
22
+ * on (asked only when there are extensions) — never a fresh scan of `extensions/`.
23
+ */
24
+ export declare function agentCommands(agentDir: string, workspace: string, served: {
25
+ extensionPaths: readonly string[];
26
+ modelRuntime: () => Promise<ModelRuntime>;
27
+ }): Promise<AgentCommand[]>;
9
28
  export interface CreatePiAgentFromDirOptions {
10
- /** Model spec override (e.g. the CLI --model flag). Precedence: this > FASTAGENT_MODEL > config.model. */
29
+ /** Model spec override (e.g. the CLI --model flag). */
11
30
  model?: string;
12
31
  /**
13
- * Session store directory. Default `<agentDir>/.state/sessions` (machine state). `start`
14
- * overrides it (--sessions-dir / FASTAGENT_SESSIONS_DIR / a mounted volume) so production continuity
15
- * survives redeploys.
32
+ * Where conversations are stored, for an EMBEDDER that puts them somewhere the state root does not cover. There is
33
+ * no env or flag spelling of it: sessions are machine state, and the one knob that moves machine state is
34
+ * `FASTAGENT_STATE_DIR` (see {@link resolveSessionsDir}).
16
35
  */
17
36
  sessionsDir?: string;
18
- /**
19
- * Credentials file override. Default `<agentDir>/.secrets/auth.json` (project-level, under the
20
- * `.secrets/`). Override via --auth-path / FASTAGENT_AUTH_PATH; point it at
21
- * the global `~/.fastagent/.secrets/auth.json` to share one credential across projects.
22
- */
37
+ /** Credentials file override. */
23
38
  authPath?: string;
24
39
  /**
25
- * This is a long-running SERVE (`dev`/`start`), where the scheduler poller runs — so a self-scheduled
26
- * wake-up is actually honored. One-shot entries (`invoke`/`fire`) leave it off (they exit after the turn
27
- * and never poll). The built-in `wake` tool mounts only when this is set AND `config.selfSchedule` is on.
40
+ * This is a long-running SERVE (`dev`/`start`), where the scheduler poller runs — so a self-scheduled wake-up is
41
+ * actually honored.
28
42
  */
29
43
  serving?: boolean;
30
- /** Assemble the session control plane over this agent's session store and return it as
31
- * {@link sessionControl} — the store is created inside this opener, so the hub must be wired
32
- * here too (an external `createPiSessionControl` cannot exist before the store does).
33
- * Default: `config.sessionControl` AND {@link serving} — the config key means "serve the control
34
- * plane", so one-shot commands (invoke/fire) do not assemble an unused hub. Pass explicitly to
35
- * override either way. */
44
+ /**
45
+ * Wire the control plane's BOUNDARY (model changes, fork, delete) and publish it. A serve always gets the hub
46
+ * itself — stopping the running turn is a chat command, not a management endpoint — so this is the answer to
47
+ * "may a remote caller steer and rewrite this deployment", nothing else. Defaults to `config.sessionControl`.
48
+ */
36
49
  sessionControl?: boolean;
37
- /** Additional raw tap with the FULL vocabulary: run events composed after the
38
- * {@link sessionControl} hub's observer, plus the hub's own boundary-mutation events
39
- * (`state_changed`/`compaction_*`) via the hub's tap. TRUSTED seam: an observer receives each
40
- * run's live modulation handles (see `SessionObserver`) — for read-only consumers
41
- * use the hub's `events()` stream instead. */
50
+ /** Additional raw tap with the FULL vocabulary. */
42
51
  observer?: SessionObserver;
43
52
  }
44
53
  /**
45
- * The agent assembly FRONT HALF — everything that is independent of how pi consumes the
46
- * definition (a per-invoke session for serving vs a resident one for chat):
47
- * placement resolution → config → model spec → the full tool surface ({@link resolveAgentTools} — the
48
- * ONE place it is computed) → state root → auth path. Both {@link createPiAgentFromDir} and the
49
- * session builder (session-builder.ts) consume this, so THESE inputs cannot drift between the two
50
- * consumption shapes. (Definition loading and prompt assembly stay per-consumer: serving re-reads
51
- * them live per invoke, the session builder snapshots at startup and lets pi append skills/env.)
54
+ * The agent assembly FRONT HALF — everything that is independent of how pi consumes the definition (a per-invoke
55
+ * session for serving vs a resident one for chat).
52
56
  */
53
57
  export interface AgentAssembly {
54
58
  config: FastagentConfig;
@@ -57,29 +61,39 @@ export interface AgentAssembly {
57
61
  modelSpec: string;
58
62
  /** Absolute agent dir — definition + config + machinery live here (resolvePlacement().agentDir). */
59
63
  agentDir: string;
60
- /** Absolute workspace — the agent's cwd and the start of the ②-context walk: the agent dir's parent
61
- * when the agent sits inside it, the agent dir ITSELF when you point at the agent. */
64
+ /** Absolute workspace — the agent's cwd and the start of the ②-context walk. */
62
65
  workspace: string;
63
66
  /** Absolute state root (FASTAGENT_STATE_DIR > <agentDir>/.state). */
64
67
  stateRoot: string;
65
- /** Absolute credentials file (--auth-path/authPath option > FASTAGENT_AUTH_PATH > <agentDir>/.secrets/auth.json). */
66
- authPath: string;
68
+ /** The credentials files it reads ({@link resolveAuthLayers}). */
69
+ auth: AuthLayers;
67
70
  /** The full mounted tool surface (all coding tools + config.tools + discovered tools/, search_tools applied). */
68
71
  tools: MountedTool[];
69
72
  toolNames: string[];
70
73
  deferredToolNames: string[];
71
74
  toolCollisions: ToolCollision[];
72
- toolFailures: ModuleLoadFailure[];
75
+ /** Env vars the mounted tools declared, by tool name — already asserted present by this function. */
76
+ toolSecrets: Map<string, DeclaredSecret[]>;
73
77
  }
74
78
  export declare function resolveAgentAssembly(dir: string, options?: {
75
79
  model?: string;
76
80
  authPath?: string;
77
81
  }): Promise<AgentAssembly>;
78
82
  /**
79
- * "Point at a directory → agent": resolve the placement (`dir` may be either end — the workspace or
80
- * the agent dir itself), load the config, resolve model and tools, then L2. Throws a clear error when
81
- * no model source is set (fail visibly at startup). Returns everything an entry point needs to report
82
- * what it assembled.
83
+ * The model specs `createPiAgentFromDir(dir, { authPath })` could run now: the agent's registry (pi's built-ins plus
84
+ * its `models.json`) filtered to the providers whose credentials are configured, sorted. The directory needs no model
85
+ * set, and the same placement and credential layers as the opener apply, so a listed spec authenticates there.
86
+ * Configuration is checked, not validity: no OAuth token is refreshed and no provider is called.
87
+ *
88
+ * `warn` reaches the credential store. An unreadable or corrupt credentials file otherwise reads as "nothing
89
+ * configured", so a client that must not show that as an empty list passes a sink that throws.
90
+ */
91
+ export declare function availableModelsFromDir(dir: string, options?: FastagentAuthOptions & {
92
+ authPath?: string;
93
+ }): Promise<string[]>;
94
+ /**
95
+ * "Point at a directory → agent": resolve the placement (`dir` may be either end — the workspace or the agent dir
96
+ * itself), load the config, resolve model and tools, then L2.
83
97
  */
84
98
  export declare function createPiAgentFromDir(dir: string, options?: CreatePiAgentFromDirOptions): Promise<{
85
99
  agent: Agent;
@@ -96,21 +110,19 @@ export declare function createPiAgentFromDir(dir: string, options?: CreatePiAgen
96
110
  stateRoot: string;
97
111
  /** Absolute session store directory in use (for the startup report). */
98
112
  sessionsDir: string;
99
- /** Absolute credentials file in use (for the startup report). */
100
- authPath: string;
101
- /** The session store in use. */
113
+ /** The credentials files in use — the startup report names whichever layer the credential came from. */
114
+ auth: AuthLayers;
102
115
  sessions: PiSessionRecordStore;
103
- /** The observation plane over this agent's sessions; present iff `options.sessionControl`. */
116
+ /** The observation plane over this agent's sessions; present on every serve (a channel's stop command reaches the
117
+ * live run through it). Its boundary is wired only when {@link publishControl}. */
104
118
  sessionControl?: SessionControl;
105
- /** Whether the agent schedules its own follow-up turns — read from the config, so a caller
106
- * assembling a service does not have to reach back into it (MountableAgent). */
107
- selfSchedule: boolean;
108
- /** Non-default, active-by-default tool names in effect: config.tools + discovered tools/. Each name
109
- * lives in exactly one report slot — deferred names are in {@link deferredToolNames} instead. */
119
+ /** Whether that plane is also served as `/control/*` — `config.sessionControl`. */
120
+ publishControl: boolean;
121
+ /** What the serve publishes — `config.http`, handed to the assembly as-is (MountableAgent). */
122
+ http?: HttpSurface;
123
+ /** Non-default, active-by-default tool names in effect: config.tools + discovered tools/. */
110
124
  toolNames: string[];
111
125
  /** Tools registered but not initially active (deferred) — activated via search_tools. */
112
126
  deferredToolNames: string[];
113
127
  toolCollisions: ToolCollision[];
114
- /** `tools/` files that failed to import — skipped, reported by the caller, never fatal. */
115
- toolFailures: ModuleLoadFailure[];
116
128
  }>;