@fastagent-sh/fastagent 0.24.3 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (480) hide show
  1. package/README.md +53 -82
  2. package/dist/agent-api.d.ts +452 -0
  3. package/dist/agent-api.js +201 -0
  4. package/dist/answer-text.d.ts +8 -0
  5. package/dist/answer-text.js +18 -0
  6. package/dist/atomic-write.d.ts +2 -2
  7. package/dist/atomic-write.js +2 -2
  8. package/dist/authoring.d.ts +77 -0
  9. package/dist/authoring.js +238 -0
  10. package/dist/channel.d.ts +29 -15
  11. package/dist/channel.js +4 -1
  12. package/dist/channels/agentcore-protocol.d.ts +36 -50
  13. package/dist/channels/agentcore-protocol.js +3 -3
  14. package/dist/channels/agentcore-service.d.ts +8 -18
  15. package/dist/channels/agentcore-service.js +108 -127
  16. package/dist/channels/agentcore.d.ts +8 -24
  17. package/dist/channels/agentcore.js +32 -65
  18. package/dist/channels/body.d.ts +0 -16
  19. package/dist/channels/body.js +0 -25
  20. package/dist/channels/busy.js +6 -1
  21. package/dist/channels/context.d.ts +4 -0
  22. package/dist/channels/context.js +35 -0
  23. package/dist/channels/discover.d.ts +18 -20
  24. package/dist/channels/discover.js +41 -99
  25. package/dist/channels/feishu/feishu-api.d.ts +54 -4
  26. package/dist/channels/feishu/feishu-api.js +192 -149
  27. package/dist/channels/feishu/feishu.d.ts +3 -0
  28. package/dist/channels/feishu/feishu.js +117 -106
  29. package/dist/channels/feishu/history.d.ts +55 -0
  30. package/dist/channels/feishu/history.js +199 -0
  31. package/dist/channels/feishu/invoke-turn.d.ts +13 -11
  32. package/dist/channels/feishu/invoke-turn.js +9 -10
  33. package/dist/channels/feishu/model.d.ts +2 -1
  34. package/dist/channels/feishu/normalize.js +100 -0
  35. package/dist/channels/feishu/preview.d.ts +2 -2
  36. package/dist/channels/feishu/register-webhook.d.ts +1 -0
  37. package/dist/channels/feishu/register-webhook.js +3 -2
  38. package/dist/channels/feishu/scaffold/channel.ts +65 -46
  39. package/dist/channels/feishu/scaffold/feishu-send.ts +38 -33
  40. package/dist/channels/feishu/scaffold/feishu-threads.ts +25 -0
  41. package/dist/channels/feishu/setup-mode.d.ts +45 -25
  42. package/dist/channels/feishu/setup-mode.js +74 -23
  43. package/dist/channels/feishu/shared-api.d.ts +24 -6
  44. package/dist/channels/feishu/shared-api.js +30 -24
  45. package/dist/channels/kit/context-buffer.d.ts +11 -2
  46. package/dist/channels/kit/context-buffer.js +7 -4
  47. package/dist/channels/kit/delivery.d.ts +19 -3
  48. package/dist/channels/kit/delivery.js +74 -15
  49. package/dist/channels/kit/event-stream.js +2 -1
  50. package/dist/channels/kit/invoke-turn-kit.d.ts +41 -41
  51. package/dist/channels/kit/invoke-turn-kit.js +62 -71
  52. package/dist/channels/kit/place-history.d.ts +107 -0
  53. package/dist/channels/kit/place-history.js +182 -0
  54. package/dist/channels/kit/preview-kit.d.ts +9 -5
  55. package/dist/channels/kit/preview-kit.js +36 -15
  56. package/dist/channels/kit/room-threads.d.ts +46 -0
  57. package/dist/channels/kit/room-threads.js +81 -0
  58. package/dist/channels/kit/seen.js +1 -1
  59. package/dist/channels/kit/stop-command.d.ts +6 -3
  60. package/dist/channels/kit/stop-command.js +20 -18
  61. package/dist/channels/kit/thread-fork.d.ts +17 -0
  62. package/dist/channels/kit/thread-fork.js +43 -0
  63. package/dist/channels/kit/thread-participants.js +1 -1
  64. package/dist/channels/kit/transport.d.ts +5 -0
  65. package/dist/channels/kit/transport.js +5 -0
  66. package/dist/channels/kit/turn-runner.d.ts +10 -9
  67. package/dist/channels/kit/turn-runner.js +17 -19
  68. package/dist/channels/kit/turn-store.d.ts +5 -4
  69. package/dist/channels/kit/turn-store.js +5 -5
  70. package/dist/channels/lark/lark.d.ts +3 -0
  71. package/dist/channels/lark/lark.js +5 -0
  72. package/dist/channels/lark/onboard.d.ts +5 -3
  73. package/dist/channels/lark/onboard.js +14 -14
  74. package/dist/channels/lark/scaffold/channel.ts +67 -44
  75. package/dist/channels/lark/scaffold/lark-send.ts +38 -33
  76. package/dist/channels/lark/scaffold/lark-threads.ts +25 -0
  77. package/dist/channels/respond.d.ts +0 -4
  78. package/dist/channels/respond.js +1 -1
  79. package/dist/channels/router.d.ts +18 -0
  80. package/dist/channels/router.js +68 -0
  81. package/dist/channels/serve.d.ts +5 -70
  82. package/dist/channels/serve.js +105 -287
  83. package/dist/channels/slack/history.d.ts +42 -0
  84. package/dist/channels/slack/history.js +282 -0
  85. package/dist/channels/slack/invoke-turn.d.ts +12 -5
  86. package/dist/channels/slack/invoke-turn.js +7 -5
  87. package/dist/channels/slack/manifest.d.ts +1 -4
  88. package/dist/channels/slack/manifest.js +22 -10
  89. package/dist/channels/slack/model.d.ts +2 -1
  90. package/dist/channels/slack/onboard.d.ts +0 -2
  91. package/dist/channels/slack/onboard.js +2 -4
  92. package/dist/channels/slack/onboarding-state.d.ts +0 -2
  93. package/dist/channels/slack/onboarding-state.js +0 -1
  94. package/dist/channels/slack/parse.d.ts +0 -5
  95. package/dist/channels/slack/parse.js +1 -16
  96. package/dist/channels/slack/preview.d.ts +2 -3
  97. package/dist/channels/slack/preview.js +78 -52
  98. package/dist/channels/slack/register-webhook.d.ts +1 -0
  99. package/dist/channels/slack/register-webhook.js +6 -5
  100. package/dist/channels/slack/scaffold/channel.ts +23 -24
  101. package/dist/channels/slack/scaffold/slack-send.ts +50 -43
  102. package/dist/channels/slack/scaffold/slack-threads.ts +29 -0
  103. package/dist/channels/slack/setup-server.d.ts +19 -0
  104. package/dist/channels/slack/setup-server.js +113 -11
  105. package/dist/channels/slack/shared-api.d.ts +15 -4
  106. package/dist/channels/slack/shared-api.js +19 -14
  107. package/dist/channels/slack/slack-api.d.ts +61 -2
  108. package/dist/channels/slack/slack-api.js +28 -5
  109. package/dist/channels/slack/slack.js +97 -52
  110. package/dist/channels/slack/welcomed.js +1 -1
  111. package/dist/channels/telegram/context-buffer.d.ts +6 -1
  112. package/dist/channels/telegram/context-buffer.js +19 -0
  113. package/dist/channels/telegram/invoke-turn.d.ts +8 -4
  114. package/dist/channels/telegram/invoke-turn.js +7 -7
  115. package/dist/channels/telegram/parse.d.ts +7 -2
  116. package/dist/channels/telegram/parse.js +7 -0
  117. package/dist/channels/telegram/preview.d.ts +2 -2
  118. package/dist/channels/telegram/register-webhook.d.ts +1 -0
  119. package/dist/channels/telegram/register-webhook.js +3 -2
  120. package/dist/channels/telegram/scaffold/channel.ts +27 -28
  121. package/dist/channels/telegram/scaffold/telegram-send.ts +61 -108
  122. package/dist/channels/telegram/shared-api.d.ts +34 -0
  123. package/dist/channels/telegram/shared-api.js +79 -0
  124. package/dist/channels/telegram/telegram-api.d.ts +15 -5
  125. package/dist/channels/telegram/telegram-api.js +10 -6
  126. package/dist/channels/telegram/telegram.js +27 -21
  127. package/dist/channels/telegram/turn-store.js +1 -1
  128. package/dist/channels/{kit/turn-queue.d.ts → turn-queue.d.ts} +2 -2
  129. package/dist/channels/{kit/turn-queue.js → turn-queue.js} +10 -10
  130. package/dist/cli/add-feishu.d.ts +42 -12
  131. package/dist/cli/add-feishu.js +177 -124
  132. package/dist/cli/add-slack.d.ts +8 -3
  133. package/dist/cli/add-slack.js +115 -63
  134. package/dist/cli/auth-view.d.ts +10 -3
  135. package/dist/cli/auth-view.js +8 -6
  136. package/dist/cli/box-login.d.ts +17 -7
  137. package/dist/cli/box-login.js +46 -12
  138. package/dist/cli/commands/add.d.ts +15 -4
  139. package/dist/cli/commands/add.js +252 -143
  140. package/dist/cli/commands/auth.d.ts +6 -0
  141. package/dist/cli/commands/auth.js +50 -0
  142. package/dist/cli/commands/content.d.ts +6 -0
  143. package/dist/cli/commands/content.js +45 -0
  144. package/dist/cli/commands/deploy/agentcore.js +50 -77
  145. package/dist/cli/commands/deploy/docker.js +38 -39
  146. package/dist/cli/commands/deploy/fly.js +21 -18
  147. package/dist/cli/commands/deploy/host-login.d.ts +26 -0
  148. package/dist/cli/commands/deploy/host-login.js +90 -0
  149. package/dist/cli/commands/deploy/railway.js +21 -26
  150. package/dist/cli/commands/deploy/shared.d.ts +45 -17
  151. package/dist/cli/commands/deploy/shared.js +34 -15
  152. package/dist/cli/commands/deploy.d.ts +0 -4
  153. package/dist/cli/commands/deploy.js +237 -50
  154. package/dist/cli/commands/destroy.js +8 -6
  155. package/dist/cli/commands/dev.d.ts +0 -2
  156. package/dist/cli/commands/dev.js +20 -19
  157. package/dist/cli/commands/env.d.ts +12 -0
  158. package/dist/cli/commands/env.js +190 -0
  159. package/dist/cli/commands/info.js +95 -156
  160. package/dist/cli/commands/init.d.ts +2 -2
  161. package/dist/cli/commands/init.js +35 -33
  162. package/dist/cli/commands/invoke.d.ts +6 -0
  163. package/dist/cli/commands/invoke.js +131 -16
  164. package/dist/cli/commands/login.d.ts +31 -2
  165. package/dist/cli/commands/login.js +413 -64
  166. package/dist/cli/commands/logout.d.ts +4 -0
  167. package/dist/cli/commands/logout.js +53 -0
  168. package/dist/cli/commands/logs.js +8 -6
  169. package/dist/cli/commands/models.d.ts +2 -1
  170. package/dist/cli/commands/models.js +39 -37
  171. package/dist/cli/commands/schedules.d.ts +21 -0
  172. package/dist/cli/commands/schedules.js +143 -0
  173. package/dist/cli/commands/start.d.ts +11 -10
  174. package/dist/cli/commands/start.js +35 -62
  175. package/dist/cli/content-view.d.ts +9 -0
  176. package/dist/cli/content-view.js +26 -0
  177. package/dist/cli/fail.d.ts +9 -12
  178. package/dist/cli/fail.js +17 -14
  179. package/dist/cli/invoke-stream.d.ts +12 -3
  180. package/dist/cli/invoke-stream.js +85 -23
  181. package/dist/cli/kernel.d.ts +9 -2
  182. package/dist/cli/kernel.js +15 -6
  183. package/dist/cli/login-relay.d.ts +3 -2
  184. package/dist/cli/login-relay.js +18 -6
  185. package/dist/cli/models-view.d.ts +5 -1
  186. package/dist/cli/models-view.js +1 -1
  187. package/dist/cli/person.d.ts +10 -0
  188. package/dist/cli/person.js +23 -0
  189. package/dist/cli/program.js +421 -203
  190. package/dist/cli/serve.d.ts +13 -63
  191. package/dist/cli/serve.js +31 -121
  192. package/dist/cli/shared.d.ts +21 -48
  193. package/dist/cli/shared.js +68 -89
  194. package/dist/cli/ticket.d.ts +136 -0
  195. package/dist/cli/ticket.js +476 -0
  196. package/dist/client.d.ts +7 -0
  197. package/dist/client.js +2 -0
  198. package/dist/content/declare.d.ts +70 -0
  199. package/dist/content/declare.js +163 -0
  200. package/dist/content/file.d.ts +32 -0
  201. package/dist/content/file.js +119 -0
  202. package/dist/content/git.d.ts +41 -0
  203. package/dist/content/git.js +217 -0
  204. package/dist/content/mount.d.ts +2 -0
  205. package/dist/content/mount.js +15 -0
  206. package/dist/content/resolve.d.ts +52 -0
  207. package/dist/content/resolve.js +151 -0
  208. package/dist/content/source.d.ts +27 -0
  209. package/dist/content/source.js +53 -0
  210. package/dist/conversation-sessions.d.ts +26 -0
  211. package/dist/conversation-sessions.js +99 -0
  212. package/dist/declared-secrets.d.ts +19 -37
  213. package/dist/declared-secrets.js +16 -58
  214. package/dist/deploy/agentcore/destroy.d.ts +3 -3
  215. package/dist/deploy/agentcore/destroy.js +46 -28
  216. package/dist/deploy/agentcore/forwarder.js +105 -22
  217. package/dist/deploy/agentcore/logs.js +1 -1
  218. package/dist/deploy/agentcore/plan.d.ts +10 -24
  219. package/dist/deploy/agentcore/plan.js +31 -135
  220. package/dist/deploy/agentcore/run.d.ts +1 -1
  221. package/dist/deploy/agentcore/run.js +8 -5
  222. package/dist/deploy/agentcore/shell.d.ts +1 -1
  223. package/dist/deploy/agentcore/shell.js +5 -5
  224. package/dist/deploy/api.d.ts +34 -0
  225. package/dist/deploy/api.js +50 -0
  226. package/dist/deploy/box-shell.d.ts +6 -0
  227. package/dist/deploy/box-shell.js +7 -0
  228. package/dist/deploy/build-context.d.ts +7 -5
  229. package/dist/deploy/build-context.js +41 -35
  230. package/dist/deploy/channel-ingress.d.ts +6 -1
  231. package/dist/deploy/channel-ingress.js +18 -5
  232. package/dist/deploy/container.d.ts +22 -9
  233. package/dist/deploy/container.js +96 -55
  234. package/dist/deploy/docker/plan.d.ts +3 -2
  235. package/dist/deploy/docker/plan.js +13 -14
  236. package/dist/deploy/docker/run.d.ts +2 -2
  237. package/dist/deploy/docker/run.js +8 -4
  238. package/dist/deploy/fly/plan.d.ts +1 -1
  239. package/dist/deploy/fly/plan.js +12 -21
  240. package/dist/deploy/fly/run.d.ts +10 -6
  241. package/dist/deploy/fly/run.js +11 -6
  242. package/dist/deploy/hosts.d.ts +2 -1
  243. package/dist/deploy/hosts.js +2 -1
  244. package/dist/deploy/preflight.d.ts +21 -23
  245. package/dist/deploy/preflight.js +222 -201
  246. package/dist/deploy/railway/plan.d.ts +8 -6
  247. package/dist/deploy/railway/plan.js +15 -58
  248. package/dist/deploy/railway/run.d.ts +8 -3
  249. package/dist/deploy/railway/run.js +12 -8
  250. package/dist/deploy/residency.d.ts +5 -11
  251. package/dist/deploy/residency.js +0 -6
  252. package/dist/deploy/runner.d.ts +1 -1
  253. package/dist/deploy/runner.js +1 -1
  254. package/dist/deploy/secrets.d.ts +16 -2
  255. package/dist/deploy/secrets.js +33 -6
  256. package/dist/deploy/workspace.d.ts +11 -6
  257. package/dist/deploy/workspace.js +55 -38
  258. package/dist/dev-supervisor.d.ts +11 -2
  259. package/dist/dev-supervisor.js +51 -26
  260. package/dist/effect-port.d.ts +4 -4
  261. package/dist/effect-port.js +4 -4
  262. package/dist/environment/apt.d.ts +4 -0
  263. package/dist/environment/apt.js +32 -0
  264. package/dist/environment/declare.d.ts +59 -0
  265. package/dist/environment/declare.js +210 -0
  266. package/dist/environment/mise.d.ts +50 -0
  267. package/dist/environment/mise.js +268 -0
  268. package/dist/feishu.d.ts +2 -2
  269. package/dist/feishu.js +2 -2
  270. package/dist/git.d.ts +13 -0
  271. package/dist/git.js +55 -0
  272. package/dist/harnesses/models/catalog.d.ts +20 -0
  273. package/dist/harnesses/models/catalog.js +254 -0
  274. package/dist/{engines/pi/auth.d.ts → harnesses/models/credentials.d.ts} +3 -3
  275. package/dist/{engines/pi/auth.js → harnesses/models/credentials.js} +3 -3
  276. package/dist/harnesses/models/environment.d.ts +43 -0
  277. package/dist/harnesses/models/environment.js +82 -0
  278. package/dist/{engines/pi → harnesses/models}/login.d.ts +57 -26
  279. package/dist/{engines/pi → harnesses/models}/login.js +187 -79
  280. package/dist/harnesses/models/models.d.ts +83 -0
  281. package/dist/harnesses/models/models.js +158 -0
  282. package/dist/harnesses/pi-durable/agent.d.ts +42 -0
  283. package/dist/harnesses/pi-durable/agent.js +579 -0
  284. package/dist/harnesses/pi-durable/defaults.d.ts +28 -0
  285. package/dist/harnesses/pi-durable/defaults.js +26 -0
  286. package/dist/harnesses/pi-durable/define.d.ts +77 -0
  287. package/dist/harnesses/pi-durable/define.js +28 -0
  288. package/dist/harnesses/pi-durable/entries.d.ts +32 -0
  289. package/dist/harnesses/pi-durable/entries.js +126 -0
  290. package/dist/harnesses/pi-durable/events.d.ts +25 -0
  291. package/dist/harnesses/pi-durable/events.js +238 -0
  292. package/dist/harnesses/pi-durable/ids.d.ts +16 -0
  293. package/dist/harnesses/pi-durable/ids.js +55 -0
  294. package/dist/harnesses/pi-durable/messages.d.ts +41 -0
  295. package/dist/harnesses/pi-durable/messages.js +116 -0
  296. package/dist/harnesses/pi-durable/open.d.ts +88 -0
  297. package/dist/harnesses/pi-durable/open.js +329 -0
  298. package/dist/harnesses/pi-durable/reads.d.ts +30 -0
  299. package/dist/harnesses/pi-durable/reads.js +94 -0
  300. package/dist/harnesses/pi-durable/registry.d.ts +18 -0
  301. package/dist/harnesses/pi-durable/registry.js +56 -0
  302. package/dist/harnesses/pi-durable/release.d.ts +13 -0
  303. package/dist/harnesses/pi-durable/release.js +40 -0
  304. package/dist/harnesses/pi-durable/serve.d.ts +80 -0
  305. package/dist/harnesses/pi-durable/serve.js +156 -0
  306. package/dist/harnesses/pi-durable/sessions.d.ts +27 -0
  307. package/dist/harnesses/pi-durable/sessions.js +47 -0
  308. package/dist/harnesses/pi-durable/storage.d.ts +4 -0
  309. package/dist/harnesses/pi-durable/storage.js +49 -0
  310. package/dist/harnesses/pi-durable/stream.d.ts +20 -0
  311. package/dist/harnesses/pi-durable/stream.js +221 -0
  312. package/dist/harnesses/pi-durable/text.d.ts +30 -0
  313. package/dist/harnesses/pi-durable/text.js +292 -0
  314. package/dist/harnesses/pi-durable/wake.d.ts +4 -0
  315. package/dist/harnesses/pi-durable/wake.js +81 -0
  316. package/dist/http/client.d.ts +6 -0
  317. package/dist/http/client.js +256 -0
  318. package/dist/http/contract.d.ts +541 -0
  319. package/dist/http/contract.js +179 -0
  320. package/dist/http/server.d.ts +34 -0
  321. package/dist/http/server.js +194 -0
  322. package/dist/index.d.ts +17 -4
  323. package/dist/index.js +10 -5
  324. package/dist/lark.d.ts +2 -2
  325. package/dist/lark.js +2 -2
  326. package/dist/locked-file.d.ts +17 -0
  327. package/dist/{engines/pi/locked-file.js → locked-file.js} +16 -10
  328. package/dist/once.d.ts +6 -0
  329. package/dist/once.js +23 -0
  330. package/dist/paths.d.ts +36 -52
  331. package/dist/paths.js +66 -182
  332. package/dist/runtime.d.ts +25 -2
  333. package/dist/runtime.js +27 -0
  334. package/dist/scaffold/add-channel.d.ts +14 -27
  335. package/dist/scaffold/add-channel.js +82 -180
  336. package/dist/scaffold/init.d.ts +17 -18
  337. package/dist/scaffold/init.js +87 -99
  338. package/dist/scaffold/templates/SYSTEM.md +12 -0
  339. package/dist/scaffold/templates/env.example +4 -10
  340. package/dist/scaffold/templates/fastagent.config.ts +21 -33
  341. package/dist/scaffold/templates/gitignore +8 -1
  342. package/dist/scaffold/templates/skills/writing-great-skills/SKILL.md +1 -2
  343. package/dist/scaffold/templates.d.ts +9 -4
  344. package/dist/scaffold/templates.js +7 -5
  345. package/dist/scaffold/vendor-skill.d.ts +1 -4
  346. package/dist/scaffold/vendor-skill.js +5 -6
  347. package/dist/schedule/cron.d.ts +13 -0
  348. package/dist/schedule/cron.js +52 -0
  349. package/dist/schedule/eventbridge-cron.d.ts +17 -0
  350. package/dist/schedule/eventbridge-cron.js +88 -0
  351. package/dist/schedule/schedule.d.ts +23 -0
  352. package/dist/schedule/schedule.js +34 -0
  353. package/dist/schedule/scheduler.d.ts +34 -33
  354. package/dist/schedule/scheduler.js +251 -137
  355. package/dist/schedule/state.d.ts +4 -14
  356. package/dist/schedule/state.js +7 -7
  357. package/dist/schedule/wake-alarm.d.ts +22 -2
  358. package/dist/schedule/wake-alarm.js +66 -20
  359. package/dist/schedule/wakeups.d.ts +16 -15
  360. package/dist/schedule/wakeups.js +47 -45
  361. package/dist/service.d.ts +56 -169
  362. package/dist/service.js +91 -187
  363. package/dist/serving-command.d.ts +10 -0
  364. package/dist/serving-command.js +16 -0
  365. package/dist/slack.d.ts +1 -1
  366. package/dist/slack.js +1 -1
  367. package/dist/{channels/kit/state.js → state-file.js} +6 -6
  368. package/dist/telegram.d.ts +1 -0
  369. package/dist/telegram.js +1 -0
  370. package/dist/tunnel.d.ts +3 -0
  371. package/dist/tunnel.js +12 -4
  372. package/dist/value-file.d.ts +21 -0
  373. package/dist/value-file.js +108 -0
  374. package/dist/version.d.ts +5 -0
  375. package/dist/version.js +14 -1
  376. package/package.json +18 -28
  377. package/dist/agent.d.ts +0 -106
  378. package/dist/agent.js +0 -21
  379. package/dist/channels/control.d.ts +0 -31
  380. package/dist/channels/control.js +0 -329
  381. package/dist/channels/define-channel.d.ts +0 -39
  382. package/dist/channels/define-channel.js +0 -9
  383. package/dist/channels/feishu/context-buffer.d.ts +0 -35
  384. package/dist/channels/feishu/context-buffer.js +0 -65
  385. package/dist/channels/feishu/scaffold/channel.websocket.ts +0 -31
  386. package/dist/channels/http.d.ts +0 -23
  387. package/dist/channels/http.js +0 -57
  388. package/dist/channels/lark/scaffold/channel.websocket.ts +0 -31
  389. package/dist/channels/slack/context-buffer.d.ts +0 -23
  390. package/dist/channels/slack/context-buffer.js +0 -37
  391. package/dist/channels/sse.d.ts +0 -4
  392. package/dist/channels/sse.js +0 -66
  393. package/dist/cli/commands/chat.d.ts +0 -3
  394. package/dist/cli/commands/chat.js +0 -14
  395. package/dist/cli/commands/routine-run.d.ts +0 -6
  396. package/dist/cli/commands/routine-run.js +0 -46
  397. package/dist/cli/commands/routine.d.ts +0 -25
  398. package/dist/cli/commands/routine.js +0 -122
  399. package/dist/cli/commands/tool.d.ts +0 -1
  400. package/dist/cli/commands/tool.js +0 -57
  401. package/dist/collect.d.ts +0 -63
  402. package/dist/collect.js +0 -90
  403. package/dist/core.d.ts +0 -13
  404. package/dist/core.js +0 -15
  405. package/dist/engines/pi/agent-models.d.ts +0 -83
  406. package/dist/engines/pi/agent-models.js +0 -120
  407. package/dist/engines/pi/agent-session-factory.d.ts +0 -121
  408. package/dist/engines/pi/agent-session-factory.js +0 -517
  409. package/dist/engines/pi/chat.d.ts +0 -3
  410. package/dist/engines/pi/chat.js +0 -8
  411. package/dist/engines/pi/config.d.ts +0 -71
  412. package/dist/engines/pi/config.js +0 -199
  413. package/dist/engines/pi/create.d.ts +0 -170
  414. package/dist/engines/pi/create.js +0 -343
  415. package/dist/engines/pi/definition.d.ts +0 -74
  416. package/dist/engines/pi/definition.js +0 -236
  417. package/dist/engines/pi/entry-images.d.ts +0 -14
  418. package/dist/engines/pi/entry-images.js +0 -23
  419. package/dist/engines/pi/invoke-session.d.ts +0 -18
  420. package/dist/engines/pi/invoke-session.js +0 -403
  421. package/dist/engines/pi/locked-file.d.ts +0 -9
  422. package/dist/engines/pi/machine.d.ts +0 -53
  423. package/dist/engines/pi/machine.js +0 -137
  424. package/dist/engines/pi/models.d.ts +0 -200
  425. package/dist/engines/pi/models.js +0 -533
  426. package/dist/engines/pi/open.d.ts +0 -180
  427. package/dist/engines/pi/open.js +0 -270
  428. package/dist/engines/pi/openai-account-models.d.ts +0 -35
  429. package/dist/engines/pi/openai-account-models.js +0 -116
  430. package/dist/engines/pi/report.d.ts +0 -18
  431. package/dist/engines/pi/report.js +0 -59
  432. package/dist/engines/pi/retry-event.d.ts +0 -6
  433. package/dist/engines/pi/retry-event.js +0 -15
  434. package/dist/engines/pi/service.d.ts +0 -9
  435. package/dist/engines/pi/service.js +0 -14
  436. package/dist/engines/pi/session-builder.d.ts +0 -13
  437. package/dist/engines/pi/session-builder.js +0 -117
  438. package/dist/engines/pi/session-control.d.ts +0 -77
  439. package/dist/engines/pi/session-control.js +0 -908
  440. package/dist/engines/pi/session-effects.d.ts +0 -14
  441. package/dist/engines/pi/session-effects.js +0 -30
  442. package/dist/engines/pi/session-inheritance.d.ts +0 -21
  443. package/dist/engines/pi/session-inheritance.js +0 -204
  444. package/dist/engines/pi/session-markers.d.ts +0 -49
  445. package/dist/engines/pi/session-markers.js +0 -60
  446. package/dist/engines/pi/session-settings.d.ts +0 -67
  447. package/dist/engines/pi/session-settings.js +0 -119
  448. package/dist/engines/pi/session-store.d.ts +0 -69
  449. package/dist/engines/pi/session-store.js +0 -430
  450. package/dist/engines/pi/tool-context.d.ts +0 -45
  451. package/dist/engines/pi/tool-context.js +0 -31
  452. package/dist/engines/pi/tool.d.ts +0 -99
  453. package/dist/engines/pi/tool.js +0 -118
  454. package/dist/engines/pi/turn-kit.d.ts +0 -83
  455. package/dist/engines/pi/turn-kit.js +0 -275
  456. package/dist/engines/pi/wake-tool.d.ts +0 -9
  457. package/dist/engines/pi/wake-tool.js +0 -92
  458. package/dist/loader.d.ts +0 -41
  459. package/dist/loader.js +0 -116
  460. package/dist/node.d.ts +0 -3
  461. package/dist/node.js +0 -4
  462. package/dist/observe.d.ts +0 -6
  463. package/dist/observe.js +0 -47
  464. package/dist/pi.d.ts +0 -25
  465. package/dist/pi.js +0 -15
  466. package/dist/scaffold/templates/APPEND_SYSTEM.md +0 -12
  467. package/dist/scaffold/templates/tools/fetch-url.ts +0 -25
  468. package/dist/schedule/discover.d.ts +0 -17
  469. package/dist/schedule/discover.js +0 -61
  470. package/dist/schedule/routine.d.ts +0 -43
  471. package/dist/schedule/routine.js +0 -32
  472. package/dist/schedule/run.d.ts +0 -55
  473. package/dist/schedule/run.js +0 -146
  474. package/dist/secrets-gate.d.ts +0 -32
  475. package/dist/secrets-gate.js +0 -33
  476. package/dist/session-remote.d.ts +0 -47
  477. package/dist/session-remote.js +0 -460
  478. package/dist/session.d.ts +0 -466
  479. package/dist/session.js +0 -57
  480. /package/dist/{channels/kit/state.d.ts → state-file.d.ts} +0 -0
@@ -1,23 +0,0 @@
1
- /** A user prompt's and a tool result's images; no other message publishes any, so no ref can reach them. */
2
- function publishedImages(message) {
3
- if (message.role !== "user" && message.role !== "toolResult")
4
- return [];
5
- const content = message.content;
6
- return Array.isArray(content) ? content.filter((b) => b.type === "image") : [];
7
- }
8
- /** `data.images` of the entry `entryId` holding `message`, absent when it has none. */
9
- export function entryImages(entryId, message) {
10
- const images = publishedImages(message).map((b, i) => ({ ref: `${entryId}:${i}`, mimeType: b.mimeType }));
11
- return images.length > 0 ? { images } : {};
12
- }
13
- /** The image `ref` names in `record`, or undefined when it names none there. The inverse of `entryImages`. */
14
- export function imageAt(record, ref) {
15
- const at = ref.lastIndexOf(":");
16
- const index = ref.slice(at + 1);
17
- // Canonical digits only, so one image has one ref (`:00` is not `:0`).
18
- if (at <= 0 || !/^(0|[1-9]\d*)$/.test(index))
19
- return undefined;
20
- const entry = record.getEntry(ref.slice(0, at));
21
- const image = entry?.type === "message" ? publishedImages(entry.message)[Number(index)] : undefined;
22
- return image ? { data: image.data, mimeType: image.mimeType } : undefined;
23
- }
@@ -1,18 +0,0 @@
1
- /** Pi's per-invoke binding over a durable session record. */
2
- import type { AgentSession, AgentSessionEvent } from "@earendil-works/pi-coding-agent";
3
- import { type Agent } from "../../agent.ts";
4
- import type { SessionEvent } from "../../session.ts";
5
- import type { SessionInheritance } from "./session-inheritance.ts";
6
- import { type Lease, type SessionObserver } from "./turn-kit.ts";
7
- /** Open or create a record and bind a session. */
8
- export type PiAgentSessionFactory = (sessionId: string, inherit?: SessionInheritance) => Promise<AgentSession>;
9
- export interface CreatePiAgentFromSessionOptions {
10
- sessionFactory: PiAgentSessionFactory;
11
- /** Shared with control-plane writes; admission is synchronous and fail-fast. */
12
- lease?: Lease;
13
- /** Trusted observation tap; controls arrive with run_started, before session binding. */
14
- observer?: SessionObserver;
15
- }
16
- /** pi's session event as the observation plane's, or null for one it does not publish. Exported for tests only. */
17
- export declare function toSessionEvent(event: AgentSessionEvent, runId: string): SessionEvent | null;
18
- export declare function createPiAgentFromSession(options: CreatePiAgentFromSessionOptions): Agent;
@@ -1,403 +0,0 @@
1
- import { contentText } from "@earendil-works/pi-ai";
2
- import * as Deferred from "effect/Deferred";
3
- import * as Effect from "effect/Effect";
4
- import * as Fiber from "effect/Fiber";
5
- import * as Queue from "effect/Queue";
6
- import { ABORTED_CODE, MISSING_MODEL_CODE, SESSION_BUSY_CODE, } from "../../agent.js";
7
- import { entryImages } from "./entry-images.js";
8
- import { cancellableStream } from "../../collect.js";
9
- import { log } from "../../log.js";
10
- import { toRetryScheduledEvent } from "./retry-event.js";
11
- import { PortFailure, port, portAbort, portCleanup, portError } from "../../effect-port.js";
12
- import { SessionBusy, acquireSession, acquireSessionLease } from "./session-effects.js";
13
- import { MissingModel } from "./session-settings.js";
14
- import { errorToTerminal, inProcessLease, agentEventProjection, answerOutcome, streamsThinkingDelta, asksToEndRun, toPiPromptOptions, toTerminal, } from "./turn-kit.js";
15
- // Structured output is for scripts. Observation publishes Pi's display result, including bounded nested traces.
16
- function displayToolResult(result) {
17
- const { structuredContent: _internal, ...display } = result;
18
- return display;
19
- }
20
- /** pi's session event as the observation plane's, or null for one it does not publish. Exported for tests only. */
21
- export function toSessionEvent(event, runId) {
22
- const at = Date.now();
23
- switch (event.type) {
24
- case "message_start":
25
- if (event.message.role !== "assistant")
26
- return null;
27
- return { type: "message_started", timestamp: at, runId, data: {} };
28
- case "message_update": {
29
- const ev = event.assistantMessageEvent;
30
- if (ev.type === "text_delta" || ev.type === "thinking_delta") {
31
- // Empty deltas must not spend the silent window in which a provider retry is safe. A redacted block's
32
- // placeholder is not reasoning, and its entry will not carry it either (turn-kit.ts answerThinking).
33
- return ev.delta === "" || (ev.type === "thinking_delta" && !streamsThinkingDelta(ev))
34
- ? null
35
- : {
36
- type: "message_delta",
37
- timestamp: at,
38
- runId,
39
- data: { channel: ev.type === "text_delta" ? "text" : "thinking", delta: ev.delta },
40
- };
41
- }
42
- return null;
43
- }
44
- case "message_end": {
45
- if (event.message.role !== "assistant")
46
- return null;
47
- const outcome = answerOutcome(event.message);
48
- return { type: "message_finished", timestamp: at, runId, data: outcome ? { outcome } : {} };
49
- }
50
- case "tool_execution_start":
51
- return {
52
- type: "tool_started",
53
- timestamp: at,
54
- runId,
55
- data: {
56
- id: event.toolCallId,
57
- name: event.toolName,
58
- args: event.args,
59
- ...(event.parentToolCallId ? { parentToolCallId: event.parentToolCallId } : {}),
60
- },
61
- };
62
- case "tool_execution_update":
63
- return {
64
- type: "tool_progress",
65
- timestamp: at,
66
- runId,
67
- data: {
68
- id: event.toolCallId,
69
- name: event.toolName,
70
- partialResult: displayToolResult(event.partialResult),
71
- ...(event.parentToolCallId ? { parentToolCallId: event.parentToolCallId } : {}),
72
- },
73
- };
74
- case "tool_execution_end":
75
- return {
76
- type: "tool_finished",
77
- timestamp: at,
78
- runId,
79
- data: {
80
- id: event.toolCallId,
81
- isError: event.isError,
82
- content: displayToolResult(event.result),
83
- ...(event.parentToolCallId ? { parentToolCallId: event.parentToolCallId } : {}),
84
- ...(asksToEndRun(event) ? { terminate: true } : {}),
85
- },
86
- };
87
- case "queue_update":
88
- return {
89
- type: "queue_changed",
90
- timestamp: at,
91
- runId,
92
- data: { steering: [...event.steering], followUp: [...event.followUp] },
93
- };
94
- case "auto_retry_start":
95
- case "summarization_retry_scheduled":
96
- return toRetryScheduledEvent(event, runId);
97
- default:
98
- return null;
99
- }
100
- }
101
- /** pi's error-channel events for work an invoke owes its caller: the command it ran, and the turns it started. */
102
- const OWED_BY_THE_RUN = new Set(["command", "send_user_message", "send_message"]);
103
- /**
104
- * The turns extensions start on this session and have not finished. `pi.sendUserMessage` and `pi.sendMessage` reach
105
- * these two session methods, and pi discards the promise; wrapping the methods keeps it. The session is this run's
106
- * alone, so the wrap never outlives the run.
107
- */
108
- function trackExtensionTurns(session) {
109
- const pending = new Set();
110
- const track = (sent) => {
111
- pending.add(sent);
112
- const done = () => void pending.delete(sent);
113
- sent.then(done, done); // pi's own `.catch` on `sent` reports the failure
114
- return sent;
115
- };
116
- const sendUserMessage = session.sendUserMessage.bind(session);
117
- const sendCustomMessage = session.sendCustomMessage.bind(session);
118
- session.sendUserMessage = (...args) => track(sendUserMessage(...args));
119
- session.sendCustomMessage = (...args) => track(sendCustomMessage(...args));
120
- return pending;
121
- }
122
- /**
123
- * Report each user message when it is WRITTEN, which is later than pi announces it: pi awaits extension `message_end`
124
- * handlers before it appends. Emitting from the write is what makes `user_message.entryId` readable through
125
- * `entries()` by the time the event arrives, so a reconnecting client's backfill cannot miss a message whose event
126
- * fired before it subscribed. pi's agent awaits each listener before the next event, so the message still reports
127
- * before the answer to it. The in-memory store reuses one record across runs, so the release restores the method.
128
- */
129
- function reportUserMessages(session, report) {
130
- const record = session.sessionManager;
131
- const append = record.appendMessage;
132
- return Effect.acquireRelease(Effect.sync(() => {
133
- record.appendMessage = (message) => {
134
- const entryId = append.call(record, message);
135
- // The same text and images `entries()` publishes for this entry (session-control.ts toSessionEntry).
136
- if (message.role === "user") {
137
- report({ entryId, text: contentText(message.content, ""), ...entryImages(entryId, message) });
138
- }
139
- return entryId;
140
- };
141
- }), () => Effect.sync(() => {
142
- record.appendMessage = append;
143
- }));
144
- }
145
- export function createPiAgentFromSession(options) {
146
- const { sessionFactory, lease = inProcessLease(), observer } = options;
147
- async function* turn(scope, prompt, { onCancelReady, wasCancelled }) {
148
- const queue = Effect.runSync(Queue.unbounded());
149
- const consumed = Deferred.makeUnsafe();
150
- const bound = Deferred.makeUnsafe();
151
- const abort = new AbortController();
152
- onCancelReady(() => abort.abort());
153
- const runId = crypto.randomUUID();
154
- const project = agentEventProjection();
155
- /**
156
- * Each call's `tool_progress` still waiting in the queue. A newer status replaces its text instead of queuing
157
- * behind it, so the queue holds at most one per running call, and a consumer that falls behind (a slow `/invoke`
158
- * client) gets the latest status, not every snapshot in between: pi's bash reports every 100 ms, and a single
159
- * growing line is up to 50 KB each time. The replaced event keeps its place, which moves a status earlier, never
160
- * past its own call's `tool_ended`: pi takes no progress from a call once it has returned.
161
- */
162
- const unreadProgress = new Map();
163
- let settled = false;
164
- let outcome;
165
- let abortsInFlight = 0;
166
- let abortSucceeded = false;
167
- /**
168
- * An abort is owed to every model request this invoke makes, including one not yet started. pi's `abort()` stops
169
- * only an agent run or a compaction already in flight: one that lands while `prompt()` prepares (input handlers,
170
- * the auth check, `before_agent_start`) finds nothing to stop, and `_runAgentPrompt` then clears pi's own flag.
171
- * So the run remembers it and aborts each agent run and automatic compaction as it starts (`agent_start`,
172
- * `compaction_start`: both emitted once pi's controller for it exists).
173
- */
174
- let abortRequested = false;
175
- const observe = (event, run) => {
176
- if (!event || !observer)
177
- return;
178
- try {
179
- observer(scope.session, event, run);
180
- }
181
- catch (error) {
182
- log.warn(`[fastagent] session observer threw (event ${event.type}): ${String(error)}`);
183
- }
184
- };
185
- const ready = Deferred.await(bound);
186
- /**
187
- * Every control command obeys one admission rule: wait for this run's binding, then refuse once it has settled.
188
- * Kept in one place so a fourth command cannot arrive with a fifth spelling of it.
189
- */
190
- const alreadySettled = () => new PortFailure(new Error("run already settled; the command cannot take effect"));
191
- const command = (run) => Effect.runPromise(Effect.gen(function* () {
192
- const session = yield* ready;
193
- if (settled)
194
- return yield* Effect.fail(alreadySettled());
195
- return yield* run(session);
196
- }));
197
- // Prompt preparation stays OUTSIDE admission: pi accepts a message for a finished run without complaint
198
- // (`_steeringMessages.push`), so a run that ends between the settled check and the enqueue drops the command while
199
- // it reports success. Image resizing would be such a gap, hundreds of milliseconds of dynamic import and Photon
200
- // work, and doing it here also keeps it overlapping session acquisition. pi has a gap of its own: it awaits the
201
- // definition's `input` handlers before it queues, so a `queued` answer is checked against settlement once more.
202
- // A `handled` one stands either way: the handler took the prompt whatever became of the run.
203
- const enqueue = async (p, kind) => {
204
- const opts = await toPiPromptOptions(p, "queued");
205
- return command((session) => Effect.gen(function* () {
206
- const disposition = yield* port(() => session[kind](p.text, opts?.images));
207
- if (disposition === "queued" && settled) {
208
- // pi has queued it, and announced it (`queue_update`), on a run that takes nothing in any more. Emptying
209
- // the queue tells the observation plane so, which would otherwise report the refused prompt pending.
210
- session.clearQueue();
211
- return yield* Effect.fail(alreadySettled());
212
- }
213
- return disposition;
214
- }));
215
- };
216
- const controls = {
217
- steer: (p) => enqueue(p, "steer"),
218
- followUp: (p) => enqueue(p, "followUp"),
219
- abort: () => command((session) => Effect.gen(function* () {
220
- abortsInFlight++;
221
- abortRequested = true;
222
- yield* port(() => session.abort()).pipe(Effect.tap(() => Effect.sync(() => {
223
- abortSucceeded = true;
224
- })), Effect.ensuring(Effect.sync(() => {
225
- abortsInFlight--;
226
- })));
227
- })),
228
- };
229
- const execute = Effect.gen(function* () {
230
- yield* acquireSessionLease(lease, scope.session);
231
- yield* Effect.addFinalizer(() => Effect.sync(() => {
232
- settled = true;
233
- observe({ type: "run_settled", timestamp: Date.now(), runId, data: outcome ?? { status: "aborted" } });
234
- }));
235
- // Admission precedes binding so a racing control command waits on this run's readiness gate.
236
- observe({ type: "run_started", timestamp: Date.now(), runId, data: {} }, controls);
237
- const session = yield* acquireSession(sessionFactory, scope.session, scope.parentSession === undefined
238
- ? undefined
239
- : {
240
- parentSession: scope.parentSession,
241
- ...(scope.branchHints !== undefined ? { branchHints: scope.branchHints } : {}),
242
- });
243
- let finalAssistant;
244
- let runStarted = false;
245
- let extensionFailure;
246
- let streamedAnswer = false;
247
- let retriedAfterAnswer;
248
- let eventFailure;
249
- const abortWith = (operation) => {
250
- void Effect.runPromise(portCleanup(operation, () => session.abort()));
251
- };
252
- const stop = () => abortWith("event-fault abort");
253
- yield* Effect.acquireRelease(Effect.try({
254
- try: () => session.subscribe((event) => {
255
- if (retriedAfterAnswer !== undefined || eventFailure)
256
- return;
257
- try {
258
- if (event.type === "agent_start")
259
- runStarted = true;
260
- if ((event.type === "agent_start" || event.type === "compaction_start") && abortRequested)
261
- abortWith("requested abort");
262
- // Compaction rewrites session history; the event's assistant message is the turn's fact.
263
- if (event.type === "message_end" && event.message.role === "assistant") {
264
- finalAssistant = event.message;
265
- for (const diagnostic of finalAssistant.diagnostics ?? []) {
266
- log.warn(`[fastagent] provider diagnostic ${diagnostic.type} (${finalAssistant.provider}/${finalAssistant.model}, session ${scope.session}, run ${runId})`);
267
- }
268
- }
269
- if (event.type === "compaction_end" && event.reason !== "manual") {
270
- const status = event.aborted ? "aborted" : event.errorMessage ? "failed" : "completed";
271
- const emit = event.errorMessage && !event.aborted ? log.warn : log.debug;
272
- emit(`[fastagent] automatic compaction ${event.reason} (session ${scope.session}, run ${runId}): ${status}`);
273
- }
274
- if (event.type === "auto_retry_start" && streamedAnswer) {
275
- retriedAfterAnswer = event.errorMessage;
276
- // Pi installs the retry controller after emitting this event.
277
- queueMicrotask(stop);
278
- return;
279
- }
280
- const rich = toSessionEvent(event, runId);
281
- observe(rich);
282
- if (!rich)
283
- return;
284
- const projected = project(rich);
285
- if (!projected)
286
- return;
287
- if (projected.type === "text" || projected.type === "thinking")
288
- streamedAnswer = true;
289
- if (projected.type === "tool_progress") {
290
- const unread = unreadProgress.get(projected.id);
291
- if (unread) {
292
- unread.text = projected.text;
293
- return;
294
- }
295
- unreadProgress.set(projected.id, projected);
296
- }
297
- Queue.offerUnsafe(queue, projected);
298
- }
299
- catch (error) {
300
- eventFailure = new PortFailure(error);
301
- queueMicrotask(stop);
302
- }
303
- }),
304
- catch: (error) => new PortFailure(error),
305
- }), (unsubscribe) => portCleanup("unsubscribe", unsubscribe));
306
- // pi swallows a failing extension command, and a turn an extension failed to start, into its error channel;
307
- // both are work this run owes its caller, so the run reports them.
308
- yield* Effect.acquireRelease(Effect.sync(() => session.extensionRunner.onError((error) => {
309
- if (OWED_BY_THE_RUN.has(error.event))
310
- extensionFailure ??= `${error.event} failed (${error.extensionPath}): ${error.error}`;
311
- })), (unsubscribe) => Effect.sync(unsubscribe));
312
- yield* reportUserMessages(session, (data) => observe({ type: "user_message", timestamp: Date.now(), runId, data }));
313
- const extensionTurns = trackExtensionTurns(session);
314
- // Completing the gate can run waiting controls synchronously; their queue events must be observed.
315
- yield* Deferred.succeed(bound, session);
316
- const promptOptions = yield* port(() => toPiPromptOptions(prompt, "prompt"));
317
- if (eventFailure)
318
- return yield* Effect.fail(eventFailure);
319
- // Whether an extension could take this input instead of the model (a command, or an `input` handler): only
320
- // then may a prompt settle with no model run and still have done its job.
321
- const extensionMayTakeInput = session.extensionRunner.getRegisteredCommands().length > 0 || session.extensionRunner.hasHandlers("input");
322
- yield* portAbort("prompt", async () => {
323
- await session.prompt(prompt.text, promptOptions);
324
- // An extension command returns from `prompt()` as soon as its handler does, and a turn it started may not
325
- // have begun yet, so idleness alone proves nothing. This run owns those turns until they settle, and any
326
- // turn they start in turn.
327
- do {
328
- await Promise.allSettled([...extensionTurns]);
329
- await session.waitForIdle();
330
- } while (extensionTurns.size > 0);
331
- }, () => session.abort());
332
- if (eventFailure)
333
- return yield* Effect.fail(eventFailure);
334
- if (extensionFailure !== undefined)
335
- return { type: "failed", details: extensionFailure, retryable: false };
336
- if (retriedAfterAnswer !== undefined)
337
- return { type: "failed", details: retriedAfterAnswer, retryable: true };
338
- if (finalAssistant)
339
- return toTerminal(finalAssistant);
340
- // No model run at all: an extension took the input (a command, or an `input` handler) and did its work.
341
- if (!runStarted && extensionMayTakeInput)
342
- return { type: "completed" };
343
- return {
344
- type: "failed",
345
- details: "the engine settled the run without ending an assistant message",
346
- retryable: false,
347
- };
348
- }).pipe(Effect.onError((cause) => Deferred.failCause(bound, cause)));
349
- const work = Effect.runFork(Effect.scoped(Effect.gen(function* () {
350
- const terminal = yield* execute.pipe(Effect.catchCause((cause) => {
351
- const error = portError(cause);
352
- return Effect.succeed(error instanceof SessionBusy
353
- ? {
354
- type: "failed",
355
- details: "session busy: a turn is already in flight for this session",
356
- retryable: true,
357
- code: SESSION_BUSY_CODE,
358
- }
359
- : error instanceof MissingModel
360
- ? { type: "failed", details: error.message, retryable: false, code: MISSING_MODEL_CODE }
361
- : errorToTerminal(error));
362
- }));
363
- settled = true;
364
- Queue.offerUnsafe(queue, terminal.type === "failed" && (abortSucceeded || abortsInFlight > 0)
365
- ? { ...terminal, retryable: false, code: ABORTED_CODE }
366
- : terminal);
367
- Queue.endUnsafe(queue);
368
- // Producer completion is earlier than consumer completion.
369
- yield* Deferred.await(consumed);
370
- })).pipe(Effect.ensuring(Effect.sync(() => {
371
- Queue.endUnsafe(queue);
372
- }))), { signal: abort.signal });
373
- const read = Queue.takeAll(queue).pipe(Effect.catchTag("Done", () => Effect.succeed([])));
374
- try {
375
- for (;;) {
376
- const events = await Effect.runPromise(read);
377
- if (events.length === 0)
378
- return;
379
- for (const event of events) {
380
- if (wasCancelled())
381
- return;
382
- if (event.type === "failed") {
383
- outcome =
384
- event.code === ABORTED_CODE
385
- ? { status: "aborted", error: { message: event.details, retryable: false } }
386
- : { status: "failed", error: { code: event.code, message: event.details, retryable: event.retryable } };
387
- }
388
- else if (event.type === "completed")
389
- outcome = { status: "completed" };
390
- // Handed over: the consumer owns it now, and the next status queues afresh.
391
- if (event.type === "tool_progress")
392
- unreadProgress.delete(event.id);
393
- yield event;
394
- }
395
- }
396
- }
397
- finally {
398
- Deferred.doneUnsafe(consumed, Effect.void);
399
- await Effect.runPromise(Fiber.await(work));
400
- }
401
- }
402
- return { invoke: (scope, prompt) => cancellableStream((hooks) => turn(scope, prompt, hooks)) };
403
- }
@@ -1,9 +0,0 @@
1
- export interface LockResult<T> {
2
- result: T;
3
- /** New file content to persist under the lock; undefined = no write. */
4
- next?: string;
5
- }
6
- /** Serialized cross-process read-modify-write of one file, replaced whole so its readers need no lock. */
7
- export declare function withLockedFile<T>(path: string, fn: (current: string | undefined) => Promise<LockResult<T>>, options?: {
8
- signal?: AbortSignal;
9
- }): Promise<T>;
@@ -1,53 +0,0 @@
1
- /**
2
- * THE MACHINE an agent runs on, as fastagent inherits it: the skills and prompt templates this box provides — found
3
- * by pi's own Agent Skills discovery, installed pi packages included — and pi's engine settings.
4
- *
5
- * An agent inherits its machine the way it already inherits the `PATH`: `bash` runs whatever is installed, and a
6
- * skill in `~/.pi/agent/skills` is available the same way. Deploying ships the project scope — the workspace — and
7
- * nothing here is compared against a deployment, the same way nobody is told their local `ffmpeg` is not in the image.
8
- *
9
- * READ ONCE per process, like the environment it is. The definition is what stays live (`dev` re-reads it per turn,
10
- * because it is what an author edits); a skill installed after boot arrives on the next start.
11
- */
12
- import { DefaultResourceLoader, SettingsManager } from "@earendil-works/pi-coding-agent";
13
- /** pi's own shapes, taken from its loader rather than re-declared. */
14
- export type MachineSkill = ReturnType<DefaultResourceLoader["getSkills"]>["skills"][number];
15
- export type MachinePrompt = ReturnType<DefaultResourceLoader["getPrompts"]>["prompts"][number];
16
- /** The Pi built-in extensions a definition loads, each unless the machine's settings disable it. */
17
- export declare const BUILTIN_EXTENSIONS: readonly ["codemode", "tool-search"];
18
- /**
19
- * The way in for an authored tool the model is not given up front, by its exposure: the built-in extension that
20
- * provides it and the tool that extension registers. A `codemode` tool is called from codemode scripts, a `deferred`
21
- * one is loaded by tool_search — the rule Pi's MCP extension applies to its own tools (`ensureDiscoveryActive`).
22
- * Without that extension the tool has no way in at all.
23
- */
24
- export declare const DISCOVERY: {
25
- readonly codemode: {
26
- readonly extension: "codemode";
27
- readonly tool: "codemode";
28
- };
29
- readonly deferred: {
30
- readonly extension: "tool-search";
31
- readonly tool: "tool_search";
32
- };
33
- };
34
- /** What this box lends an agent. */
35
- export interface Machine {
36
- skills: MachineSkill[];
37
- prompts: MachinePrompt[];
38
- /**
39
- * The {@link BUILTIN_EXTENSIONS} left enabled, by Pi's own rule: `"extensions": ["-builtin:codemode"]` in the user
40
- * settings disables one, and the workspace's `.pi/settings.json` overrides that either way.
41
- */
42
- builtinExtensions: string[];
43
- /** pi's engine settings (retry, compaction, cache warming, …) as read at boot — a fresh manager per caller. */
44
- settingsManager(): SettingsManager;
45
- }
46
- /** This process's one read of the machine, shared by the run plane and `commands()` so the two cannot disagree. */
47
- export declare function readMachine(workspace: string): Promise<Machine>;
48
- /** The definition's names win: vendoring a skill into `skills/` is how an author overrides the machine's. */
49
- export declare function withMachine<Own extends {
50
- name: string;
51
- }, Lent extends {
52
- name: string;
53
- }>(own: readonly Own[], lent: readonly Lent[]): (Own | Lent)[];
@@ -1,137 +0,0 @@
1
- /**
2
- * THE MACHINE an agent runs on, as fastagent inherits it: the skills and prompt templates this box provides — found
3
- * by pi's own Agent Skills discovery, installed pi packages included — and pi's engine settings.
4
- *
5
- * An agent inherits its machine the way it already inherits the `PATH`: `bash` runs whatever is installed, and a
6
- * skill in `~/.pi/agent/skills` is available the same way. Deploying ships the project scope — the workspace — and
7
- * nothing here is compared against a deployment, the same way nobody is told their local `ffmpeg` is not in the image.
8
- *
9
- * READ ONCE per process, like the environment it is. The definition is what stays live (`dev` re-reads it per turn,
10
- * because it is what an author edits); a skill installed after boot arrives on the next start.
11
- */
12
- import { DefaultPackageManager, DefaultResourceLoader, SettingsManager, getAgentDir, } from "@earendil-works/pi-coding-agent";
13
- import { log } from "../../log.js";
14
- /** The Pi built-in extensions a definition loads, each unless the machine's settings disable it. */
15
- // Not `mcp`: its server connections live as long as a session, and a served session lives one turn, so every turn
16
- // would start every configured server.
17
- export const BUILTIN_EXTENSIONS = ["codemode", "tool-search"];
18
- /**
19
- * The way in for an authored tool the model is not given up front, by its exposure: the built-in extension that
20
- * provides it and the tool that extension registers. A `codemode` tool is called from codemode scripts, a `deferred`
21
- * one is loaded by tool_search — the rule Pi's MCP extension applies to its own tools (`ensureDiscoveryActive`).
22
- * Without that extension the tool has no way in at all.
23
- */
24
- export const DISCOVERY = {
25
- codemode: { extension: "codemode", tool: "codemode" },
26
- deferred: { extension: "tool-search", tool: "tool_search" },
27
- };
28
- /** Keyed by the two places it reads: the workspace (project scope) and pi's own directory (user scope). */
29
- const reads = new Map();
30
- /** This process's one read of the machine, shared by the run plane and `commands()` so the two cannot disagree. */
31
- export function readMachine(workspace) {
32
- // pi's own answer for where its user-level resources live — asked, not spelled, since `PI_CODING_AGENT_DIR` moves it.
33
- const agentDir = getAgentDir();
34
- const key = `${workspace}\u0000${agentDir}`;
35
- const cached = reads.get(key);
36
- if (cached)
37
- return cached;
38
- const reading = read(workspace, agentDir);
39
- reads.set(key, reading);
40
- return reading;
41
- }
42
- async function read(workspace, agentDir) {
43
- const files = SettingsManager.create(workspace, agentDir);
44
- // pi reads an unparseable or locked settings file as `{}` and keeps the error for whoever asks. Nobody did, so a
45
- // trailing comma in `~/.pi/agent/settings.json` — or pi's own TUI holding the lock at that moment — left this whole
46
- // process on pi's defaults, silently: the read happens once.
47
- for (const { scope, path, error } of files.drainErrors()) {
48
- log.warn(`[fastagent] pi ${scope} settings${path ? ` (${path})` : ""} could not be read, so pi's defaults apply: ${error.message}`);
49
- }
50
- // INSTALLED PACKAGES, NEVER AN INSTALL. pi's loader resolves `packages` itself and installs a missing one
51
- // (`npm install`, `git clone`), throwing out of `reload()` when that fails — measured. So fastagent resolves them
52
- // here, telling pi to skip what is absent, and hands the loader a packageless copy of the settings so its own
53
- // resolve has nothing to do.
54
- const manager = new DefaultPackageManager({
55
- cwd: workspace,
56
- agentDir,
57
- settingsManager: files,
58
- builtinExtensions: [...BUILTIN_EXTENSIONS],
59
- });
60
- const packages = await manager.resolve(async () => "skip");
61
- // A package skipped is said, once: its skills would otherwise just not be there. Asked of the configured list, not
62
- // of `onMissing` — pi never calls that under `PI_OFFLINE`, so the warning would vanish exactly when offline.
63
- for (const { source } of manager.listConfiguredPackages().filter((configured) => !configured.installedPath)) {
64
- log.warn(`[fastagent] pi package ${source} is not installed, so its skills and prompts are not loaded`);
65
- }
66
- const settings = {
67
- global: withoutPackages(files.getGlobalSettings()),
68
- project: withoutPackages(files.getProjectSettings()),
69
- };
70
- const loader = new DefaultResourceLoader({
71
- cwd: workspace,
72
- agentDir,
73
- settingsManager: scopedSettings(settings),
74
- additionalSkillPaths: fromPackages(packages.skills),
75
- additionalPromptTemplatePaths: fromPackages(packages.prompts),
76
- // The machine's extensions are its owner's setup, not this agent's (agent-session-factory.ts loads only the
77
- // definition's own); context files are fastagent's own (segment ②).
78
- noExtensions: true,
79
- noContextFiles: true,
80
- });
81
- await loader.reload();
82
- const { skills, diagnostics: skillDiagnostics } = loader.getSkills();
83
- const { prompts, diagnostics: promptDiagnostics } = loader.getPrompts();
84
- // Said once — this is the process's only read. A `SKILL.md` with no description, or a prompt template whose
85
- // frontmatter does not parse, is otherwise simply absent.
86
- for (const [kind, diagnostics] of [
87
- ["skill", skillDiagnostics],
88
- ["prompt template", promptDiagnostics],
89
- ]) {
90
- for (const diagnostic of diagnostics) {
91
- log.warn(`[fastagent] ${kind} ${diagnostic.type}: ${diagnostic.message}${diagnostic.path ? ` (${diagnostic.path})` : ""}`);
92
- }
93
- }
94
- // A `/` in a skill's name names the context it comes from (definition.ts), and pi only warns about one. The
95
- // machine's own skill spelled that way is left out rather than let collide with a context's.
96
- const lent = skills.filter((skill) => {
97
- if (!skill.name.includes("/"))
98
- return true;
99
- log.warn(`[fastagent] machine skill "${skill.name}" (${skill.filePath}) is not loaded: a skill's name may not contain "/", ` +
100
- `which names the context a skill comes from`);
101
- return false;
102
- });
103
- const builtinExtensions = packages.extensions
104
- .filter((resource) => resource.enabled && resource.metadata.source === "builtin")
105
- .map((resource) => resource.path.slice("builtin:".length));
106
- return { skills: lent, prompts, builtinExtensions, settingsManager: () => scopedSettings(settings) };
107
- }
108
- /** A package's enabled resources; the loader discovers the top-level ones itself. */
109
- function fromPackages(resources) {
110
- return resources.filter((r) => r.enabled && r.metadata.origin === "package").map((r) => r.path);
111
- }
112
- function withoutPackages({ packages: _, ...rest }) {
113
- return rest;
114
- }
115
- /**
116
- * A SettingsManager over the boot snapshot. TWO scopes, not `SettingsManager.inMemory`'s one: pi deep-merges the
117
- * project file over the global one (a project `retry.enabled` keeps the global `retry.maxRetries`), and flattening
118
- * them first would change that. A write stays in memory — a served turn never edits the operator's files.
119
- */
120
- function scopedSettings(snapshot) {
121
- const stored = {
122
- global: JSON.stringify(snapshot.global),
123
- project: JSON.stringify(snapshot.project),
124
- };
125
- return SettingsManager.fromStorage({
126
- withLock(scope, fn) {
127
- const next = fn(stored[scope]);
128
- if (next !== undefined)
129
- stored[scope] = next;
130
- },
131
- });
132
- }
133
- /** The definition's names win: vendoring a skill into `skills/` is how an author overrides the machine's. */
134
- export function withMachine(own, lent) {
135
- const names = new Set(own.map((item) => item.name));
136
- return [...own, ...lent.filter((item) => !names.has(item.name))];
137
- }