@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,73 +1,42 @@
1
1
  /**
2
- * The `fastagent dev` process supervisor: re-spawn the CLI as a worker (`FASTAGENT_DEV_WORKER=1`) and
3
- * restart it on debounced edits to the agent's CODE inputs. Each restart is a fresh process
4
- * (always-latest, no stale module cache). The supervisor never exits on a bad edit — the worker fails
5
- * loudly and it waits for the next save.
6
- *
7
- * Watch scope is deliberately narrow: only inputs whose changes REQUIRE a new process — imported
8
- * code (tools/, channels/), fastagent.config.*, package.json, .env. The definition (AGENTS.md,
9
- * persona.md, skills/) is re-read per invoke by the directory rung, so its edits go live on the next turn with no
10
- * restart — and, critically, an agent that writes files into its own workspace (its normal work
11
- * product, including editing its own AGENTS.md) never has its in-flight turn killed by the watcher.
2
+ * The `fastagent dev` process supervisor: re-spawn the CLI as a worker (`FASTAGENT_DEV_WORKER=1`) and restart it on
3
+ * debounced edits to the agent's CODE inputs.
12
4
  */
13
5
  import { spawn } from "node:child_process";
14
6
  import { relative, sep } from "node:path";
15
7
  import { watch as watchTree } from "chokidar";
16
- import { AGENT_CONFIG_NAMES, AGENT_MODELS_FILE, resolveStateRoot, isUnderDir, } from "./paths.js";
8
+ import { AGENT_CONFIG_FILE, AGENT_MODELS_FILE, resolveStateRoot, isUnderDir } from "./paths.js";
17
9
  import { dotEnvPath } from "./env.js";
18
10
  import { log } from "./log.js";
19
- import { installProxyFetch } from "./proxy.js";
20
11
  import { openExternalUrl } from "./open-url.js";
21
12
  import { declaredChannels } from "./channels/discover.js";
22
13
  import { announceWebhooks, startCloudflareTunnel } from "./tunnel.js";
23
14
  /** What the dev watcher restarts on (agent-dir-relative): the process-bound code inputs only. */
24
- /**
25
- * The agent-dir directories loaded ONCE per worker: a restart is their only re-read. One list, so
26
- * the watcher and the line printed at startup cannot disagree — a directory watched but unannounced
27
- * looks broken, and one announced but unwatched silently strands the author mid-edit.
28
- */
29
- const CODE_INPUT_DIRS = ["tools", "channels", "schedules", "extensions"];
30
- const WATCHED_HINT = `${CODE_INPUT_DIRS.map((dir) => `${dir}/`).join(", ")}, package.json, fastagent.config.*, models.json, .secrets/.env`;
31
- /**
32
- * chokidar `ignored` matcher for the narrow watch scope (true = ignore), rooted at the AGENT DIR. When
33
- * the agent sits INSIDE the workspace that means the surrounding tree never triggers a restart at all;
34
- * when the agent IS the workspace the root is that tree, and the allowlist below is what keeps the
35
- * author's own files out of scope. Ignoring a directory prunes the whole subtree, so everything outside it —
36
- * `.state/` machine state, node_modules, .git, and any file/dir the agent writes as work product —
37
- * costs no watchers and triggers no restarts. Helper code imported from OUTSIDE tools//channels/ is
38
- * out of scope by design (keep it under tools/, or restart manually) — the startup log names the set.
39
- */
15
+ /** The agent-dir directories loaded ONCE per worker: a restart is their only re-read. */
16
+ const CODE_INPUT_DIRS = ["tools", "channels", "routines", "extensions"];
17
+ const WATCHED_HINT = `${CODE_INPUT_DIRS.map((dir) => `${dir}/`).join(", ")}, package.json, fastagent.config.ts, models.json, .secrets/.env`;
18
+ /** chokidar `ignored` matcher for the narrow watch scope (true = ignore), rooted at the AGENT DIR. */
40
19
  export function devWatchIgnored(root, envFile) {
41
- // The `.env` is allow-listed by its RESOLVED path, not by the `.secrets` name: FASTAGENT_SECRETS_DIR
42
- // can put it in an in-agent directory called anything, and a name-based rule would prune the very
43
- // file the worker loads (a credential edit would then silently never restart it).
20
+ // The `.env` is allow-listed by its RESOLVED path, not by the `.secrets` name.
44
21
  const envRel = relative(root, envFile).split(sep);
45
22
  return (path) => {
46
23
  if (path === root)
47
24
  return false; // the root itself must not be pruned
48
25
  const rel = relative(root, path);
49
- // Code inputs at the agent dir root: config, package.json, and the dirs loaded once per worker
50
- // (a restart is their only re-read). Everything else (skills/, persona.md, AGENTS.md) is
51
- // live-read — pruned, no restart.
52
- // The config NAMES come from paths.ts, not a regex spelled here: adding a name there must not
53
- // silently stop `dev` restarting on edits to it.
54
- if (AGENT_CONFIG_NAMES.includes(rel))
26
+ // Code inputs at the agent dir root: config, package.json, and the dirs loaded once per worker (a restart is
27
+ // their only re-read).
28
+ if (rel === AGENT_CONFIG_FILE)
55
29
  return false;
56
30
  if (rel === "package.json")
57
31
  return false;
58
- // models.json is read ONCE per worker (the model hub is built during assembly), so an edit needs a
59
- // restart like any other code input. It is also the one input whose breakage KILLS the worker — a
60
- // malformed file fails assembly — so leaving it unwatched would strand the author: the fix that
61
- // repairs it would not be the edit that restarts.
32
+ // models.json is read ONCE per worker (the model hub is built during assembly), so an edit needs a restart like
33
+ // any other code input.
62
34
  if (rel === AGENT_MODELS_FILE)
63
35
  return false;
64
36
  const segments = rel.split(sep);
65
37
  if (CODE_INPUT_DIRS.includes(segments[0]))
66
38
  return false;
67
- // The `.env` restarts too (credentials are process-bound). Keep it AND its ancestor directories
68
- // un-pruned so chokidar can descend to it; every sibling inside them (auth.json, .env.example)
69
- // prunes normally. An out-of-agent `.env` yields a `..`-prefixed envRel that matches nothing here
70
- // — the supervisor warns about that case instead of pretending to watch it.
39
+ // The `.env` restarts too (credentials are process-bound).
71
40
  if (segments.length <= envRel.length && segments.every((seg, i) => seg === envRel[i]))
72
41
  return false;
73
42
  return true;
@@ -75,22 +44,14 @@ export function devWatchIgnored(root, envFile) {
75
44
  }
76
45
  /** Spawn the dev worker and restart it on agent-dir edits; supervise its lifecycle until the process exits. */
77
46
  export async function runDevSupervisor(placement, options = {}) {
78
- // The placement arrives RESOLVED from the command (which already routed its refusal through
79
- // failStartup): re-resolving here would duplicate the rule and surface the same user-fixable
80
- // refusal as a raw stack. The watch root is the AGENT DIR — every restart-relevant code input lives
81
- // under it, so the surrounding workspace costs no watchers at all. Placement is assumed STATIC for
82
- // the session (creating/removing `fastagent/` mid-session is out of scope for watch re-sync).
47
+ // The placement arrives RESOLVED from the command (which already routed its refusal through failStartup).
83
48
  let worker;
84
49
  let reloadPending = false;
85
50
  let everServed = false; // has any worker successfully bound (sent `ready`) yet?
86
51
  let timer;
87
- // The supervisor owns the tunnel so the public URL survives worker reloads (a fresh tunnel per save
88
- // would mean a new URL + re-registering the webhook on every edit).
52
+ // The supervisor owns the tunnel so the public URL survives worker reloads (a fresh tunnel per save would mean a
53
+ // new URL + re-registering the webhook on every edit).
89
54
  let tunnel;
90
- // The supervisor itself calls the channel webhook APIs (setWebhook) when announcing the tunnel, so
91
- // it needs the proxy too (workers install their own). A region-blocked api.telegram.org fails otherwise.
92
- if (options.tunnel)
93
- installProxyFetch();
94
55
  const spawnWorker = () => {
95
56
  // ipc fd so the worker can signal readiness once it binds; stdio otherwise inherited.
96
57
  // biome-ignore lint/style/noNonNullAssertion: argv[1] is always the script path under a node entry
@@ -125,9 +86,8 @@ export async function runDevSupervisor(placement, options = {}) {
125
86
  spawnWorker(); // restart requested: the old worker has exited, so the port is free
126
87
  }
127
88
  else if (!everServed) {
128
- // Failed BEFORE ever serving — a non-editable startup failure (bad flag, EADDRINUSE, broken
129
- // initial workspace) that saving cannot fix. Propagate the exit code (the worker already
130
- // printed the error via inherited stdio).
89
+ // Failed BEFORE ever serving — a non-editable startup failure (bad flag, EADDRINUSE, broken initial
90
+ // workspace) that saving cannot fix.
131
91
  process.exit(code ?? 1);
132
92
  }
133
93
  else {
@@ -146,8 +106,7 @@ export async function runDevSupervisor(placement, options = {}) {
146
106
  spawnWorker(); // worker was down (broken edit) — retry now
147
107
  }
148
108
  };
149
- // chokidar gives reliable cross-platform recursion + structural ignore that native fs.watch
150
- // cannot; devWatchIgnored (above) narrows the scope to the process-bound code inputs.
109
+ // chokidar gives reliable cross-platform recursion + structural ignore that native fs.watch cannot.
151
110
  const watcher = watchTree(placement.agentDir, {
152
111
  ignoreInitial: true, // the startup scan is not a change
153
112
  ignored: devWatchIgnored(placement.agentDir, dotEnvPath(placement.agentDir)),
@@ -158,9 +117,7 @@ export async function runDevSupervisor(placement, options = {}) {
158
117
  });
159
118
  watcher.on("error", (error) => log.warn(`[fastagent] file watching error (${error.message}); some edits may need a manual restart`));
160
119
  log.info(`[fastagent] watching ${WATCHED_HINT} — code edits restart the dev worker (--no-watch to disable); AGENTS.md/persona.md/skills edits go live next turn without a restart`);
161
- // FASTAGENT_SECRETS_DIR can move the `.env` OUT of the agent dir entirely; the watcher follows it
162
- // anywhere inside (the resolved path is allow-listed above), but outside the watch root the worker
163
- // would load a file no watcher sees. Say so once instead of leaving the hint above lying.
120
+ // FASTAGENT_SECRETS_DIR can move the `.env` OUT of the agent dir entirely.
164
121
  if (!isUnderDir(dotEnvPath(placement.agentDir), placement.agentDir)) {
165
122
  log.warn(`[fastagent] .env lives outside the agent dir (FASTAGENT_SECRETS_DIR → ${dotEnvPath(placement.agentDir)}) — it is NOT watched; restart dev after editing it`);
166
123
  }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * The ONE crossing between this codebase's Promise-shaped ports and Effect execution.
3
+ *
4
+ * The ports are everywhere and none of them are ours to change: the SPEC fixes `Agent.invoke` as an
5
+ * AsyncIterable and `SessionControl` as Promises, pi's SDK is Promise-based, every platform client
6
+ * is `fetch`, and so is the filesystem. Two properties have to hold at each crossing:
7
+ *
8
+ * 1. INTERRUPTION MUST JOIN. A Promise exposes no abort hook, so cancelling the fiber that awaits
9
+ * one does not stop the work behind it. Releasing its resources anyway is how a disposed session
10
+ * gets written to, or a lease is handed to the next turn while the previous one is still
11
+ * running. {@link portJoin}, {@link portAbort} and {@link portRequest} therefore wait for the
12
+ * pending promise to settle before releasing, and abort first when the port gives us a door.
13
+ * {@link port} is the explicit opt-out, for work a caller may walk away from — so a call site
14
+ * holding a lease, a session or any other resource must not reach for it.
15
+ * 2. THE CAUSE SURVIVES. Retry classification (`turn-kit.classifyRetryable`), the channels'
16
+ * platform error types and every operator-facing message read the ORIGINAL error, so the
17
+ * wrapper carries it verbatim and {@link portError} is how a caller gets it back.
18
+ *
19
+ * The channel kit, the pi engine, the AgentCore runtime and the scheduler all cross through here, so each rule is
20
+ * written once.
21
+ *
22
+ * What is NOT here is a policy: whether a failure rejects a request, is logged, or ends a turn stays
23
+ * with the caller that knows. The only opinion this module holds is the one above.
24
+ */
25
+ import * as Cause from "effect/Cause";
26
+ import * as Effect from "effect/Effect";
27
+ /** A Promise port's failure, carrying the original error as `cause`. One tag, because every caller
28
+ * that discriminates does so on WHAT FAILED (its own control flow), never on which module wrapped it. */
29
+ export declare class PortFailure extends Error {
30
+ readonly _tag = "PortFailure";
31
+ constructor(cause: unknown);
32
+ }
33
+ /** The original error behind a failed port, for classification and messages. */
34
+ export declare function portError(cause: Cause.Cause<unknown>): unknown;
35
+ /** A Promise port whose work is abandonable: interruption does not wait for it. Use for reads and
36
+ * for writes a caller is free to walk away from; anything holding a resource wants {@link portJoin}. */
37
+ export declare function port<A>(run: () => Promise<A>): Effect.Effect<A, PortFailure>;
38
+ /** A Promise port with no abort hook: interruption joins the issued work before releasing. */
39
+ export declare function portJoin<A>(run: () => Promise<A>): Effect.Effect<A, PortFailure>;
40
+ /** A Promise port WITH an abort hook: interruption stops the work, then joins it. The hook runs only
41
+ * on interruption — a settled operation must not be told to abort (`session.abort()` on a finished
42
+ * run would reach the next one). A failing hook is diagnosed, never rethrown, under `label`: the
43
+ * tag is one thing, but a serve running an invoke and a manual compaction at once needs the warn to
44
+ * say WHICH abort could not be delivered. */
45
+ export declare function portAbort<A>(label: string, run: () => Promise<A>, abort: () => void | Promise<void>): Effect.Effect<A, PortFailure>;
46
+ /** A request with a deadline: the signal is closed on EVERY exit (it owns the response body, which a
47
+ * settled call has to release too), and the real request is joined before ownership is given up. */
48
+ export declare function portRequest<A>(run: (signal: AbortSignal) => Promise<A>, timeoutMs: number): Effect.Effect<A, PortFailure>;
49
+ /** Cleanup anomalies are diagnostic: they cannot change an already-published outcome. */
50
+ export declare function portCleanup(operation: string, run: () => void | Promise<void>): Effect.Effect<void>;
@@ -0,0 +1,77 @@
1
+ /**
2
+ * The ONE crossing between this codebase's Promise-shaped ports and Effect execution.
3
+ *
4
+ * The ports are everywhere and none of them are ours to change: the SPEC fixes `Agent.invoke` as an
5
+ * AsyncIterable and `SessionControl` as Promises, pi's SDK is Promise-based, every platform client
6
+ * is `fetch`, and so is the filesystem. Two properties have to hold at each crossing:
7
+ *
8
+ * 1. INTERRUPTION MUST JOIN. A Promise exposes no abort hook, so cancelling the fiber that awaits
9
+ * one does not stop the work behind it. Releasing its resources anyway is how a disposed session
10
+ * gets written to, or a lease is handed to the next turn while the previous one is still
11
+ * running. {@link portJoin}, {@link portAbort} and {@link portRequest} therefore wait for the
12
+ * pending promise to settle before releasing, and abort first when the port gives us a door.
13
+ * {@link port} is the explicit opt-out, for work a caller may walk away from — so a call site
14
+ * holding a lease, a session or any other resource must not reach for it.
15
+ * 2. THE CAUSE SURVIVES. Retry classification (`turn-kit.classifyRetryable`), the channels'
16
+ * platform error types and every operator-facing message read the ORIGINAL error, so the
17
+ * wrapper carries it verbatim and {@link portError} is how a caller gets it back.
18
+ *
19
+ * The channel kit, the pi engine, the AgentCore runtime and the scheduler all cross through here, so each rule is
20
+ * written once.
21
+ *
22
+ * What is NOT here is a policy: whether a failure rejects a request, is logged, or ends a turn stays
23
+ * with the caller that knows. The only opinion this module holds is the one above.
24
+ */
25
+ import * as Cause from "effect/Cause";
26
+ import * as Effect from "effect/Effect";
27
+ import * as Exit from "effect/Exit";
28
+ import { log } from "./log.js";
29
+ /** A Promise port's failure, carrying the original error as `cause`. One tag, because every caller
30
+ * that discriminates does so on WHAT FAILED (its own control flow), never on which module wrapped it. */
31
+ export class PortFailure extends Error {
32
+ _tag = "PortFailure";
33
+ constructor(cause) {
34
+ super(cause instanceof Error ? cause.message : String(cause), { cause });
35
+ }
36
+ }
37
+ /** The original error behind a failed port, for classification and messages. */
38
+ export function portError(cause) {
39
+ const error = Cause.squash(cause);
40
+ return error instanceof PortFailure ? error.cause : error;
41
+ }
42
+ /** Await a promise we already own, as a typed failure. */
43
+ const wait = (pending) => Effect.tryPromise({ try: () => pending, catch: (cause) => new PortFailure(cause) });
44
+ /** A Promise port whose work is abandonable: interruption does not wait for it. Use for reads and
45
+ * for writes a caller is free to walk away from; anything holding a resource wants {@link portJoin}. */
46
+ export function port(run) {
47
+ return Effect.tryPromise({ try: run, catch: (cause) => new PortFailure(cause) });
48
+ }
49
+ /** A Promise port with no abort hook: interruption joins the issued work before releasing. */
50
+ export function portJoin(run) {
51
+ return Effect.acquireUseRelease(Effect.try({ try: run, catch: (cause) => new PortFailure(cause) }), wait, (pending, exit) => (Exit.hasInterrupts(exit) ? Effect.exit(wait(pending)) : Effect.void));
52
+ }
53
+ /** A Promise port WITH an abort hook: interruption stops the work, then joins it. The hook runs only
54
+ * on interruption — a settled operation must not be told to abort (`session.abort()` on a finished
55
+ * run would reach the next one). A failing hook is diagnosed, never rethrown, under `label`: the
56
+ * tag is one thing, but a serve running an invoke and a manual compaction at once needs the warn to
57
+ * say WHICH abort could not be delivered. */
58
+ export function portAbort(label, run, abort) {
59
+ return Effect.acquireUseRelease(Effect.try({ try: run, catch: (cause) => new PortFailure(cause) }), wait, (pending, exit) => Exit.hasInterrupts(exit)
60
+ ? portCleanup(`${label} abort`, abort).pipe(
61
+ // Cancellation silences the port's result, but its work must settle before release.
62
+ Effect.andThen(Effect.exit(wait(pending))))
63
+ : Effect.void);
64
+ }
65
+ /** A request with a deadline: the signal is closed on EVERY exit (it owns the response body, which a
66
+ * settled call has to release too), and the real request is joined before ownership is given up. */
67
+ export function portRequest(run, timeoutMs) {
68
+ return Effect.acquireUseRelease(Effect.sync(() => {
69
+ const controller = new AbortController();
70
+ // Publish the controller before entering foreign code, including a synchronous fetch throw.
71
+ return { controller, pending: Promise.resolve().then(() => run(controller.signal)) };
72
+ }), ({ pending }) => wait(pending).pipe(Effect.timeout(timeoutMs), Effect.mapError((error) => (error instanceof PortFailure ? error : new PortFailure(error)))), ({ controller, pending }) => Effect.sync(() => controller.abort()).pipe(Effect.andThen(Effect.exit(wait(pending)))));
73
+ }
74
+ /** Cleanup anomalies are diagnostic: they cannot change an already-published outcome. */
75
+ export function portCleanup(operation, run) {
76
+ return port(async () => run()).pipe(Effect.catchCause((cause) => Effect.sync(() => log.warn(`[fastagent] ${operation} failed during cleanup: ${String(portError(cause))}`))));
77
+ }
@@ -1,5 +1,6 @@
1
+ import { type Machine } from "./machine.ts";
1
2
  import type { Skill, ThinkingLevel } from "@earendil-works/pi-agent-core";
2
- import { type AgentSessionServices, type CreateAgentSessionServicesOptions, type ModelRuntime, type SessionManager, createAgentSessionFromServices } from "@earendil-works/pi-coding-agent";
3
+ import { type AgentSession, type AgentSessionServices, type CompactionResult, type CreateAgentSessionServicesOptions, type ModelRuntime, type ResolvedCommand, SessionManager, createAgentSessionFromServices } from "@earendil-works/pi-coding-agent";
3
4
  import type { PiAgentSessionFactory } from "./invoke-session.ts";
4
5
  import type { PiSessionRecordStore } from "./session-store.ts";
5
6
  import { type MountedTool } from "./tool.ts";
@@ -9,16 +10,9 @@ interface PiSessionDefinition {
9
10
  skills: Skill[];
10
11
  }
11
12
  export interface PiAgentSessionFactoryOptions {
12
- /** Where conversations live. Continuity = same store + same session id. */
13
+ /** Where conversations live. */
13
14
  sessions: PiSessionRecordStore;
14
- /**
15
- * The model to run and the hub that authenticates it, resolved on FIRST USE and kept.
16
- *
17
- * A thunk because building a `ModelRuntime` is async while assembling an agent is not: the L1
18
- * surface hands back an `Agent` synchronously, so the credential read that a runtime performs
19
- * belongs on the first turn rather than in the caller's constructor. The two travel together
20
- * because a model must be resolved against the runtime that holds its provider's auth.
21
- */
15
+ /** The model to run and the hub that authenticates it, resolved on FIRST USE and kept. */
22
16
  engine: () => Promise<{
23
17
  modelRuntime: ModelRuntime;
24
18
  model: AnyModel;
@@ -29,34 +23,7 @@ export interface PiAgentSessionFactoryOptions {
29
23
  readDefinition: () => PiSessionDefinition | Promise<PiSessionDefinition>;
30
24
  /** The agent's working directory — what fastagent-defined tools see as `cwd`. */
31
25
  cwd: string;
32
- /**
33
- * Where pi looks for ITS settings (retry budget, compaction thresholds, default thinking level).
34
- *
35
- * Deliberately NOT pi's machine-global `~/.pi/agent`: a served agent must behave the same on the
36
- * author's laptop and in a container, and reading the operator's personal pi configuration is the
37
- * artifact losing to the machine. Point it at a definition-scoped path; a missing directory simply
38
- * means pi's own defaults, which is the intended baseline.
39
- */
40
- agentDir?: string;
41
- /**
42
- * The definition's own extension entry points, for ANNOUNCING that serving does not run them.
43
- *
44
- * pi's extension machinery is built for one process serving one session: `bindCore()` copies the
45
- * session's actions into a runtime the pi source itself calls "the shared runtime", extension
46
- * modules are cached per assembly, and `session_start`/`session_shutdown` are a matched pair.
47
- * Serving breaks every one of those assumptions — concurrent turns for unrelated conversations —
48
- * and the failure is silent cross-talk: with two turns in flight, an extension calling
49
- * `pi.sendMessage()` can deliver into the other conversation.
50
- *
51
- * Loading them anyway would be a correctness bug dressed as a feature, so serving does not, and
52
- * warns when a definition ships some. `chat` runs them fully: one session, one runtime, which is
53
- * exactly the shape pi is built for.
54
- *
55
- * Isolating them per session is mechanically possible — pi's uncached loader path builds a fresh
56
- * module (jiti with `moduleCache: false`) and takes the runtime as an argument — but that function
57
- * is not exported and the deep path is blocked by the package's `exports`. Reopening this needs
58
- * that entry point upstream, not a workaround here.
59
- */
26
+ /** The definition's own extension entry points, loaded fresh for every bound session. */
60
27
  extensionPaths?: string[];
61
28
  /** Built-ins omitted by an explicit lower-level tool list. */
62
29
  excludedToolNames?: readonly string[];
@@ -73,52 +40,66 @@ export interface BindPiSessionOptions {
73
40
  cwd: string;
74
41
  /** Built-ins omitted by an explicit lower-level tool list. */
75
42
  excludedToolNames?: readonly string[];
76
- /** The CALLER's session id — what a tool asking which conversation it is in hears. Defaults to
77
- * pi's own id, which is right where the caller has none (chat). */
43
+ /** The CALLER's session id — what a tool asking which conversation it is in hears. */
78
44
  sessionId?: string;
79
- /** Record each discovered activation on the session, so the next bind restores it. Off for chat:
80
- * pi's own session has nowhere to put one, so a resumed chat re-discovers. */
45
+ /** Record each discovered activation on the session, so the next bind restores it. */
81
46
  recordActivations: boolean;
82
47
  }
83
48
  /**
84
- * Bind ONE pi session to a record: the definition's tools as pi definitions over one turn context,
85
- * pi's own tool copies kept off, and deferral applied. The per-invoke factory and the resident chat
86
- * runtime both bind here — they differ in what they hand in (a shared vs a per-session `services`,
87
- * record-resolved vs configured settings) and in whether a discovered activation has a record to
88
- * land in, and in nothing else. Two copies of this drifted once (the tool adapter and the deferral
89
- * narrowing each existed twice, identical but for those parameters).
49
+ * Bind ONE pi session to a record: the definition's tools as pi definitions over one turn context, pi's own tool
50
+ * copies kept off, and deferral applied.
90
51
  */
91
52
  export declare function bindPiSession(options: BindPiSessionOptions): ReturnType<typeof createAgentSessionFromServices>;
92
53
  /**
93
- * Announce extensions pi failed to load. pi collects them into `LoadExtensionsResult.errors` and
94
- * carries on with the rest — sound for a TUI that shows them, silent for a server that never looks.
95
- * A definition running without the extension it ships is exactly the "quietly missing" failure this
96
- * exists to remove. CHAT calls it, once per built services — serving does not load extensions at
97
- * all, and announces that instead (see PiAgentSessionFactoryOptions.extensionPaths).
54
+ * Announce extensions pi failed to load. pi collects them into `LoadExtensionsResult.errors` and carries on with the
55
+ * rest.
98
56
  */
99
57
  export declare function reportExtensionErrors(services: AgentSessionServices): void;
100
58
  /** What pi is allowed to discover, minus the parts each assembly fills in itself. */
101
59
  type DefinitionLoaderOptions = NonNullable<CreateAgentSessionServicesOptions["resourceLoaderOptions"]>;
102
- /**
103
- * The resource posture a fastagent definition asks pi for — ONE definition of it, for both
104
- * assemblies. Serving (`piAgentSessionFactory`) and chat (`buildAgentSessionRuntime`) build
105
- * different sessions on top, but what pi is allowed to DISCOVER is not one of the differences:
106
- * everything comes from the definition, nothing from the machine that happens to be running it.
107
- *
108
- * Two copies of this drifted once already: `additionalExtensionPaths` was added to both, and only
109
- * one of them also passed the resulting tool names through pi's `tools` allowlist — so extensions
110
- * worked when served and vanished in chat. A difference between the two has to be visible AS a
111
- * difference, which is what the parameters are for: serving reads a prompt and skills that change
112
- * per turn and passes NO extension paths (it does not run them — see
113
- * {@link PiAgentSessionFactoryOptions.extensionPaths}); chat reads a fixed assembly and passes its
114
- * own. Both are arguments now, rather than two files that happen to disagree.
115
- */
60
+ /** The resource posture a fastagent definition asks pi for — ONE definition of it, for both assemblies. */
116
61
  export declare function definitionResourceLoaderOptions(source: {
117
62
  systemPrompt: () => string | undefined;
118
63
  skills: () => Skill[];
119
- /** Omitted by serving, which does not run them. */
64
+ /** {@link readMachine} for this workspace — resolved by the caller, because this function is synchronous. */
65
+ machine: Machine;
120
66
  extensionPaths?: readonly string[];
121
67
  }): DefinitionLoaderOptions;
122
- /** Open-or-create the record, then bind a fresh session to it. One call per invoke. */
68
+ /** Tell a waiting {@link startCompaction} that pi admitted the compaction on this record. */
69
+ export declare function admitCompaction(record: SessionManager): void;
70
+ /** What pi decided before its model call: go ahead, nothing to do, or a failure of its own (in `refused`). */
71
+ export type CompactAdmission = "admitted" | "nothing_to_compact" | {
72
+ refused: unknown;
73
+ };
74
+ /**
75
+ * Start pi's manual compaction on a bound session. `onAdmitted` runs INSIDE pi's admission event, so everything it
76
+ * publishes precedes anything pi does next (the model call, its retries). `admission` settles before the model call.
77
+ * pi's own pre-admission failures come back as `refused` rather than a rejection: the caller answers them to its
78
+ * Caller as a result. `done` is the compaction itself.
79
+ */
80
+ export declare function startCompaction(session: AgentSession, instructions: string | undefined, onAdmitted: () => void): {
81
+ admission: Promise<CompactAdmission>;
82
+ done: Promise<CompactionResult>;
83
+ };
84
+ /**
85
+ * The `/name` commands a served session dispatches, named the way pi resolves them (a name two extensions share gets
86
+ * a `:N` suffix). Loaded through the same {@link servingServices} a turn binds, so the menu and the dispatch cannot
87
+ * disagree. Loading runs the extensions' factories; no session opens, so `session_start` does not fire, and the
88
+ * instances are never bound (any action they call throws).
89
+ */
90
+ export declare function servedExtensionCommands(options: {
91
+ cwd: string;
92
+ modelRuntime: ModelRuntime;
93
+ extensionPaths: readonly string[];
94
+ }): Promise<ResolvedCommand[]>;
95
+ /**
96
+ * Open-or-create the record, then bind a fresh session to it — on a fresh resource loader.
97
+ *
98
+ * ONE LOADER PER SESSION, because pi's extension runtime belongs to its loader: a loader shared across concurrent
99
+ * turns would let one conversation's extension act on another's session. It also makes the definition live with no
100
+ * bookkeeping: every bind reads the prompt and skills this invoke read. The machine's half is the process's one read
101
+ * (machine.ts). Extension CODE is imported once per process, so an edit to `extensions/` needs a restart, which is
102
+ * what `dev` does on one.
103
+ */
123
104
  export declare function piAgentSessionFactory(options: PiAgentSessionFactoryOptions): PiAgentSessionFactory;
124
105
  export {};