@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,118 +0,0 @@
1
- /** Tool authoring: `defineTool` (the authoring surface) and `loadTools` (filesystem discovery). */
2
- import { join } from "node:path";
3
- import { assertInsideAgentDir } from "../../paths.js";
4
- import { z } from "zod";
5
- import { loadModuleDir } from "../../loader.js";
6
- import { readSecretDeclaration, secretValues } from "../../declared-secrets.js";
7
- import { turnContext } from "./tool-context.js";
8
- /**
9
- * Ask the provider to constrain sampling to the tool's schema, the posture pi's own built-ins take. `"prefer"`
10
- * rather than `"require"`: a schema pi cannot express strictly, one using a keyword the provider's strict mode rejects
11
- * (Anthropic: numeric bounds, which every `z.number().int()` carries), or a provider without strict mode silently
12
- * falls back to an ordinary function tool instead of failing the turn.
13
- *
14
- * Nothing here has to undo pi's strict rewrite. To express "optional" strictly, pi marks every property required and
15
- * unions the optional ones with `null`, so a constrained model emits `null` where it would have omitted the key — and
16
- * pi-ai's `validateToolArguments` drops those nulls (`normalizeOptionalNulls`) before `execute` is called. It drops
17
- * one only where the author's OWN schema rejects null, so any nullable property keeps its `null`, and a
18
- * `.nullable().optional()` property can no longer distinguish "absent" from "null" — the one place this changes
19
- * what an author's `execute` receives.
20
- */
21
- const CONSTRAINED_SAMPLING = { type: "json_schema", strict: "prefer" };
22
- /** Wrap a plain return value into pi's tool-result shape; pass a full result through unchanged. */
23
- function wrapResult(value, output) {
24
- if (value && typeof value === "object" && Array.isArray(value.content)) {
25
- return value;
26
- }
27
- const structuredContent = output ? output.parse(value) : undefined;
28
- const text = typeof value === "string" ? value : JSON.stringify(value ?? null);
29
- return { content: [{ type: "text", text }], details: value, ...(output ? { structuredContent } : {}) };
30
- }
31
- // `S` defaults to the EMPTY tuple, not `readonly string[]`: a tool that declares nothing then gets
32
- // `ctx.secrets` with no keys, so `ctx.secrets.X_API_KEY` fails to compile instead of type-checking as
33
- // a `string` that is `undefined` at run time. "A typo is a compile error" has to hold for the tool
34
- // that forgot to declare, which is the one making the mistake.
35
- export function defineTool(options) {
36
- const { $schema: _drop, ...parameters } = z.toJSONSchema(options.input);
37
- const tool = {
38
- name: options.name ?? "",
39
- label: options.name ?? "",
40
- description: options.description,
41
- parameters,
42
- constrainedSampling: CONSTRAINED_SAMPLING,
43
- ...(options.exposure ? { exposure: options.exposure } : {}),
44
- ...(options.defaultActive !== undefined ? { defaultActive: options.defaultActive } : {}),
45
- ...(options.annotations ? { annotations: options.annotations } : {}),
46
- ...(options.namespace ? { namespace: options.namespace } : {}),
47
- ...(options.output ? { outputSchema: z.toJSONSchema(options.output) } : {}),
48
- ...(options.executionMode ? { executionMode: options.executionMode } : {}),
49
- ...(options.secrets?.length ? { secrets: options.secrets } : {}),
50
- async execute(_toolCallId, rawParams, signal, onUpdate, context) {
51
- const parsed = options.input.safeParse(rawParams);
52
- if (!parsed.success) {
53
- // Validation failure is reported TO THE MODEL (it can correct and retry), not thrown.
54
- const detail = parsed.error.issues.map((i) => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ");
55
- return {
56
- content: [{ type: "text", text: `Invalid arguments: ${detail}` }],
57
- details: { error: detail },
58
- isError: true,
59
- };
60
- }
61
- const store = turnContext.getStore();
62
- return wrapResult(await options.execute(parsed.data, {
63
- cwd: store?.cwd ?? process.cwd(),
64
- signal,
65
- sessionManager: store?.sessionManager,
66
- tools: store?.tools,
67
- // Per CALL, not per turn: pi binds `executeTool` to this call's id, the parent of what it runs.
68
- executeTool: context?.executeTool,
69
- onUpdate: onUpdate && ((partial) => onUpdate(wrapResult(partial))),
70
- secrets: secretValues(options.secrets),
71
- }), options.output);
72
- },
73
- };
74
- return tool;
75
- }
76
- /** Discover code tools in `<dir>/tools/`: each `*.ts|.js|.mjs` default-exports a tool, named from its filename. */
77
- export async function loadTools(dir) {
78
- // The same containment guard channels/routines/skills get.
79
- await assertInsideAgentDir(dir, "tools");
80
- const { modules, failures } = await loadModuleDir(join(dir, "tools"));
81
- const byName = new Map();
82
- const collisions = [];
83
- const secrets = new Map();
84
- for (const { name, label, file, mod } of modules) {
85
- const tool = mod.default;
86
- if (!tool || typeof tool.execute !== "function") {
87
- failures.push({ label, file, message: `${label} must default-export defineTool({...})` });
88
- continue;
89
- }
90
- const declaration = readSecretDeclaration(tool, label);
91
- if (declaration.error !== undefined) {
92
- failures.push({ label, file, message: declaration.error });
93
- continue;
94
- }
95
- if (byName.has(name)) {
96
- collisions.push({ name, source: label });
97
- continue;
98
- }
99
- byName.set(name, { ...tool, name });
100
- secrets.set(name, declaration.secrets);
101
- }
102
- return { tools: [...byName.values()], secrets, collisions, failures };
103
- }
104
- /** Merge resolved tools (pi coding tools + `config.tools`) with discovered `tools/`, deduped by name. */
105
- export function mergeDiscoveredTools(existing, discovered) {
106
- const names = new Set(existing.map((t) => t.name));
107
- const tools = [...existing];
108
- const collisions = [];
109
- for (const tool of discovered) {
110
- if (names.has(tool.name)) {
111
- collisions.push({ name: tool.name, source: `tools/${tool.name}` });
112
- continue;
113
- }
114
- names.add(tool.name);
115
- tools.push(tool);
116
- }
117
- return { tools, collisions };
118
- }
@@ -1,83 +0,0 @@
1
- import { type AssistantMessage, type ImageContent, type ToolResultMessage } from "@earendil-works/pi-ai";
2
- import { type AgentEvent, type Prompt } from "../../agent.ts";
3
- import type { AnswerOutcome, PromptDisposition, SessionEvent } from "../../session.ts";
4
- export type Release = () => void;
5
- export interface Lease {
6
- /** Try to acquire exclusive write access for the session (fail-fast). */
7
- tryAcquire(session: string): Release | null;
8
- }
9
- export declare function inProcessLease(): Lease;
10
- /** Classify `retryable`: structured status/code first, message prose only as the last-resort ceiling. */
11
- export declare function classifyRetryable(details: string, signal: {
12
- status?: number;
13
- code?: unknown;
14
- }): boolean;
15
- /**
16
- * How an answer ended, read off the stopReason pi records on the message. The ONE reading: `message_finished`,
17
- * the `assistant` entry `entries()` publishes, and the invoke terminal all derive from it, so the live outcome and
18
- * the recorded one cannot disagree.
19
- */
20
- export declare function answerOutcome(message: AssistantMessage): AnswerOutcome | undefined;
21
- /**
22
- * An answer's recorded thinking: its published thinking blocks, in order, joined with nothing between them, exactly as
23
- * their live deltas add up (the stream marks no block boundary, and the answer's `text` is joined the same way).
24
- * Undefined when it has none.
25
- */
26
- export declare function answerThinking(message: AssistantMessage): string | undefined;
27
- /** Whether a live thinking delta is streamed: the block it extends is one {@link answerThinking} will publish. */
28
- export declare function streamsThinkingDelta(event: {
29
- contentIndex: number;
30
- partial: AssistantMessage;
31
- }): boolean;
32
- /**
33
- * Whether a finished tool call asked to end its run (pi's `terminate`: returned by the tool, or set by a `tool_call`
34
- * hook that blocks it; pi 0.99.2's `tool_result` hook cannot set it). After a batch whose EVERY result asks it, pi
35
- * makes no further model call for that batch, so unless a queued steer or follow-up continues the run, it completes on
36
- * `tool` entries with no answer after them: the same shape a process killed after its tools leaves. A call made from
37
- * inside another tool (`parentToolCallId`, a codemode script) is not in the batch and does not count.
38
- * The ONE reading: the live `tool_finished` and the flag {@link markEndsRun} records both come from it.
39
- */
40
- export declare function asksToEndRun(event: {
41
- result?: unknown;
42
- parentToolCallId?: string;
43
- }): boolean;
44
- /**
45
- * The tool result message as pi then records it, carrying the request: pi's `createToolResultMessage` drops
46
- * `terminate` (as of pi 0.99.2), so without this nothing in the record says the run ended on purpose.
47
- */
48
- export declare function markEndsRun(message: ToolResultMessage): ToolResultMessage;
49
- /** Whether a recorded tool result carries {@link markEndsRun}'s flag. */
50
- export declare function endsRun(message: ToolResultMessage): boolean;
51
- /**
52
- * Terminal mapping, decided by the resolved message's outcome: pi's `prompt()` RESOLVES a message with stopReason
53
- * "error"/"aborted" rather than throwing, so relying on catch alone would miss that whole failure class and violate
54
- * SPEC MUST 1. A truncated final answer still completes the run.
55
- */
56
- export declare function toTerminal(message: AssistantMessage): AgentEvent;
57
- export declare function errorToTerminal(error: unknown): Extract<AgentEvent, {
58
- type: "failed";
59
- }>;
60
- /**
61
- * Map prompt images to pi ImageContent. `prompt()` normalizes its images itself, with the bound model's resize
62
- * profile (`inputLimits.images.resize`) and format conversion, so a `"prompt"` delivery hands them over as-is.
63
- * `steer`/`followUp` do not, so a `"queued"` delivery resizes here with pi's default profile: the model is not known
64
- * yet when a queued message is prepared. pi's resizer is lazy-imported so the no-image path never loads its module
65
- * graph.
66
- */
67
- export declare function toPiPromptOptions(prompt: Prompt, delivery: "prompt" | "queued"): Promise<{
68
- images?: ImageContent[];
69
- } | undefined>;
70
- /** Live modulation handles for one active run — what the control plane's `dispatch` routes to. */
71
- export interface RunControls {
72
- steer(prompt: Prompt): Promise<PromptDisposition>;
73
- followUp(prompt: Prompt): Promise<PromptDisposition>;
74
- abort(): Promise<void>;
75
- }
76
- /** The DATA-plane observation seam: every rich event of every run, pushed as it happens. */
77
- export type SessionObserver = (session: string, event: SessionEvent, run?: RunControls) => void;
78
- /**
79
- * The SPEC projection of ONE run's rich stream. Stateful only for `tool_progress`, the one event that is a status
80
- * rather than a fact: an outer call's status line is sent when it changes, and a call that call makes, at any depth,
81
- * is its status. Nested calls are otherwise the observation plane's alone.
82
- */
83
- export declare function agentEventProjection(): (se: SessionEvent) => AgentEvent | null;
@@ -1,275 +0,0 @@
1
- /** The turn mechanism's ENGINE-agnostic half: the parts that describe a turn rather than pi. */
2
- import { stripVTControlCharacters } from "node:util";
3
- import { contentText, } from "@earendil-works/pi-ai";
4
- import { ABORTED_CODE } from "../../agent.js";
5
- import { log } from "../../log.js";
6
- export function inProcessLease() {
7
- const busy = new Set();
8
- return {
9
- tryAcquire(session) {
10
- if (busy.has(session))
11
- return null;
12
- busy.add(session);
13
- let released = false;
14
- return () => {
15
- if (released)
16
- return;
17
- released = true;
18
- busy.delete(session);
19
- };
20
- },
21
- };
22
- }
23
- /** Clearly-transient network error codes (Node/undici), decisive on their own. */
24
- const RETRYABLE_CODES = new Set([
25
- "ECONNRESET",
26
- "ETIMEDOUT",
27
- "ENETUNREACH",
28
- "ENETDOWN",
29
- "EAI_AGAIN",
30
- "EPIPE",
31
- "UND_ERR_CONNECT_TIMEOUT",
32
- "UND_ERR_SOCKET",
33
- ]);
34
- /** 429 (rate limit) and 5xx (server) are worth retrying; other statuses are decisive NON-retryable. */
35
- const statusIsRetryable = (status) => status === 429 || (status >= 500 && status < 600);
36
- /** Last-resort prose match, used only when no structured status/code is available. */
37
- const RETRYABLE_MESSAGE = /\b(429|5\d\d|timeout|timed out|rate.?limit|overloaded|ECONNRESET|ETIMEDOUT|ENETUNREACH|EAI_AGAIN|socket hang up)\b/i;
38
- /** A structured status/code decision, or `null` when the signal is absent/undecisive → fall to prose. */
39
- function retryableFromSignal(signal) {
40
- if (typeof signal.status === "number")
41
- return statusIsRetryable(signal.status);
42
- const { code } = signal;
43
- if (typeof code === "number")
44
- return statusIsRetryable(code);
45
- if (typeof code === "string") {
46
- if (RETRYABLE_CODES.has(code))
47
- return true;
48
- if (/^\d{3}$/.test(code))
49
- return statusIsRetryable(Number(code)); // a status carried as a string
50
- }
51
- return null; // no code, or an unknown one — not decisive on its own
52
- }
53
- /** Classify `retryable`: structured status/code first, message prose only as the last-resort ceiling. */
54
- export function classifyRetryable(details, signal) {
55
- return retryableFromSignal(signal) ?? RETRYABLE_MESSAGE.test(details);
56
- }
57
- /** Pull a structured status/code off a thrown error (HTTP status or a network code, incl. its cause). */
58
- function errorSignal(error) {
59
- if (!error || typeof error !== "object")
60
- return {};
61
- const e = error;
62
- const status = typeof e.status === "number" ? e.status : typeof e.statusCode === "number" ? e.statusCode : undefined;
63
- const causeCode = e.cause && typeof e.cause === "object" ? e.cause.code : undefined;
64
- return { status, code: e.code ?? causeCode };
65
- }
66
- /** Pull the structured error `code` pi records on a failed message's diagnostics. */
67
- function messageSignal(message) {
68
- const diagnostics = message.diagnostics ?? [];
69
- for (let i = diagnostics.length - 1; i >= 0; i--) {
70
- const code = diagnostics[i]?.error?.code;
71
- if (code !== undefined)
72
- return { code };
73
- }
74
- return {};
75
- }
76
- /**
77
- * How an answer ended, read off the stopReason pi records on the message. The ONE reading: `message_finished`,
78
- * the `assistant` entry `entries()` publishes, and the invoke terminal all derive from it, so the live outcome and
79
- * the recorded one cannot disagree.
80
- */
81
- export function answerOutcome(message) {
82
- const error = message.errorMessage ? { error: { message: message.errorMessage } } : {};
83
- switch (message.stopReason) {
84
- case "error":
85
- return { status: "failed", ...error };
86
- case "aborted":
87
- return { status: "aborted", ...error };
88
- case "length":
89
- return { status: "truncated" };
90
- default:
91
- return undefined;
92
- }
93
- }
94
- /**
95
- * Whether a thinking block is PUBLISHED: readable reasoning. A redacted one holds a provider's opaque payload and a
96
- * placeholder (pi writes "[Reasoning redacted]" for it), not reasoning anyone can read, so it is neither streamed nor
97
- * read back. The ONE rule: the live `message_delta { channel: "thinking" }` ({@link streamsThinkingDelta}) and the
98
- * `assistant` entry's `thinking` ({@link answerThinking}) both apply it, so a client reads the same text either way.
99
- *
100
- * One exception, by when the flag is read: live reads it as each delta arrives, the record as the answer ended. pi's
101
- * Bedrock path flags a block redacted when its first encrypted chunk arrives, and its readable text and its encrypted
102
- * chunks are separate fields, so a block that streamed readable text BEFORE turning redacted had that text streamed
103
- * and is then not read back. Not separable after the fact: the record keeps one flag and one string per block, with
104
- * pi's placeholder appended. Whether a Bedrock model sends both in one block is unverified.
105
- */
106
- function isPublishedThinking(block) {
107
- return block?.type === "thinking" && block.redacted !== true;
108
- }
109
- /**
110
- * An answer's recorded thinking: its published thinking blocks, in order, joined with nothing between them, exactly as
111
- * their live deltas add up (the stream marks no block boundary, and the answer's `text` is joined the same way).
112
- * Undefined when it has none.
113
- */
114
- export function answerThinking(message) {
115
- const text = message.content
116
- .filter(isPublishedThinking)
117
- .map((block) => block.thinking)
118
- .join("");
119
- return text === "" ? undefined : text;
120
- }
121
- /** Whether a live thinking delta is streamed: the block it extends is one {@link answerThinking} will publish. */
122
- export function streamsThinkingDelta(event) {
123
- return isPublishedThinking(event.partial.content[event.contentIndex]);
124
- }
125
- /**
126
- * Whether a finished tool call asked to end its run (pi's `terminate`: returned by the tool, or set by a `tool_call`
127
- * hook that blocks it; pi 0.99.2's `tool_result` hook cannot set it). After a batch whose EVERY result asks it, pi
128
- * makes no further model call for that batch, so unless a queued steer or follow-up continues the run, it completes on
129
- * `tool` entries with no answer after them: the same shape a process killed after its tools leaves. A call made from
130
- * inside another tool (`parentToolCallId`, a codemode script) is not in the batch and does not count.
131
- * The ONE reading: the live `tool_finished` and the flag {@link markEndsRun} records both come from it.
132
- */
133
- export function asksToEndRun(event) {
134
- return !event.parentToolCallId && event.result?.terminate === true;
135
- }
136
- /**
137
- * The tool result message as pi then records it, carrying the request: pi's `createToolResultMessage` drops
138
- * `terminate` (as of pi 0.99.2), so without this nothing in the record says the run ended on purpose.
139
- */
140
- export function markEndsRun(message) {
141
- return { ...message, terminate: true };
142
- }
143
- /** Whether a recorded tool result carries {@link markEndsRun}'s flag. */
144
- export function endsRun(message) {
145
- return message.terminate === true;
146
- }
147
- /**
148
- * Terminal mapping, decided by the resolved message's outcome: pi's `prompt()` RESOLVES a message with stopReason
149
- * "error"/"aborted" rather than throwing, so relying on catch alone would miss that whole failure class and violate
150
- * SPEC MUST 1. A truncated final answer still completes the run.
151
- */
152
- export function toTerminal(message) {
153
- const outcome = answerOutcome(message);
154
- if (outcome?.status === "aborted") {
155
- // A deliberate stop (a control-plane or consumer abort), not an error — see {@link ABORTED_CODE} for the consumer
156
- // contract (design §6).
157
- const details = outcome.error?.message ?? "run aborted";
158
- return { type: "failed", details, retryable: false, code: ABORTED_CODE };
159
- }
160
- if (outcome?.status === "failed") {
161
- const details = outcome.error?.message ?? "model stopped: error";
162
- return { type: "failed", details, retryable: classifyRetryable(details, messageSignal(message)) };
163
- }
164
- return { type: "completed" };
165
- }
166
- export function errorToTerminal(error) {
167
- const details = error instanceof Error ? error.message : String(error);
168
- return { type: "failed", details, retryable: classifyRetryable(details, errorSignal(error)) };
169
- }
170
- /**
171
- * Map prompt images to pi ImageContent. `prompt()` normalizes its images itself, with the bound model's resize
172
- * profile (`inputLimits.images.resize`) and format conversion, so a `"prompt"` delivery hands them over as-is.
173
- * `steer`/`followUp` do not, so a `"queued"` delivery resizes here with pi's default profile: the model is not known
174
- * yet when a queued message is prepared. pi's resizer is lazy-imported so the no-image path never loads its module
175
- * graph.
176
- */
177
- export async function toPiPromptOptions(prompt, delivery) {
178
- if (!prompt.images || prompt.images.length === 0)
179
- return undefined;
180
- if (delivery === "prompt") {
181
- return { images: prompt.images.map((img) => ({ type: "image", data: img.data, mimeType: img.mimeType })) };
182
- }
183
- const { resizeImage } = await import("@earendil-works/pi-coding-agent");
184
- const images = await Promise.all(prompt.images.map(async (img, i) => {
185
- const resized = await resizeImage(Buffer.from(img.data, "base64"), img.mimeType);
186
- if (resized)
187
- return { type: "image", data: resized.data, mimeType: resized.mimeType };
188
- // `null` covers an image it cannot decode or shrink under the limit AND an image backend that did not load,
189
- // and does not say which. pi's own tool-result path keeps the original in that case rather than drop what the
190
- // sender attached, and so does this; a provider that refuses it fails the turn with its own message.
191
- log.warn(`[fastagent] queued image ${i + 1} (${img.mimeType}) could not be resized; sending it as given — ` +
192
- "the provider may refuse it");
193
- return { type: "image", data: img.data, mimeType: img.mimeType };
194
- }));
195
- return { images };
196
- }
197
- /**
198
- * The SPEC projection of ONE run's rich stream. Stateful only for `tool_progress`, the one event that is a status
199
- * rather than a fact: an outer call's status line is sent when it changes, and a call that call makes, at any depth,
200
- * is its status. Nested calls are otherwise the observation plane's alone.
201
- */
202
- export function agentEventProjection() {
203
- /** Each nested call's outer call, the one the stream announced with `tool_started`. */
204
- const outerOf = new Map();
205
- /** The status line each outer call last reported. */
206
- const shown = new Map();
207
- const progress = (id, text) => {
208
- if (text === undefined || shown.get(id) === text)
209
- return null;
210
- shown.set(id, text);
211
- return { type: "tool_progress", id, text };
212
- };
213
- return (se) => {
214
- switch (se.type) {
215
- case "message_delta": {
216
- const d = se.data;
217
- return d.channel === "text" ? { type: "text", delta: d.delta } : { type: "thinking", delta: d.delta };
218
- }
219
- case "tool_started": {
220
- const d = se.data;
221
- if (!d.parentToolCallId)
222
- return { type: "tool_started", id: d.id, name: d.name, args: d.args };
223
- const outer = outerOf.get(d.parentToolCallId) ?? d.parentToolCallId;
224
- outerOf.set(d.id, outer);
225
- return progress(outer, callLine(d.name, d.args));
226
- }
227
- case "tool_progress": {
228
- const d = se.data;
229
- // A nested call's own output is not its caller's status; the nested call starting is (above).
230
- if (d.parentToolCallId || !Array.isArray(d.partialResult.content))
231
- return null;
232
- return progress(d.id, lastLine(contentText(d.partialResult.content, "\n")));
233
- }
234
- case "tool_finished": {
235
- const d = se.data;
236
- if (d.parentToolCallId)
237
- return null;
238
- return { type: "tool_ended", id: d.id, isError: d.isError, content: d.content };
239
- }
240
- case "retry_scheduled": {
241
- // `operation` (compaction | branch_summary) stays session-plane vocabulary.
242
- const d = se.data;
243
- return {
244
- type: "retrying",
245
- attempt: d.attempt,
246
- maxAttempts: d.maxAttempts,
247
- delayMs: d.delayMs,
248
- reason: d.error,
249
- };
250
- }
251
- default:
252
- return null;
253
- }
254
- };
255
- }
256
- /**
257
- * The line a terminal shows last: control sequences removed, and a bare `\r`, a progress bar redrawing in place, ends a
258
- * line like `\n` does. Undefined when there is no visible text yet (a shell that has printed nothing).
259
- */
260
- function lastLine(text) {
261
- const lines = stripVTControlCharacters(text).split(/\r\n|\r|\n/);
262
- for (let i = lines.length - 1; i >= 0; i--) {
263
- const line = lines[i]?.trim();
264
- if (line)
265
- return line;
266
- }
267
- return undefined;
268
- }
269
- /** A nested call as its caller's status: the tool and its first plain argument, on one line (`weather London`). */
270
- function callLine(name, args) {
271
- const first = args !== null && typeof args === "object" && !Array.isArray(args)
272
- ? Object.values(args).find((value) => typeof value === "string" || typeof value === "number")
273
- : undefined;
274
- return first === undefined ? name : `${name} ${String(first).replace(/\s+/g, " ").trim()}`.trim();
275
- }
@@ -1,9 +0,0 @@
1
- import { type MountedTool } from "./tool.ts";
2
- /**
3
- * Parse a delay to milliseconds: a number is SECONDS; a string MUST carry a unit — `"<n><s|m|h|d>"` ("30m", "2h",
4
- * "1d").
5
- */
6
- export declare function parseDelayMs(input: string | number): number | undefined;
7
- export declare function withWakeTool(tools: MountedTool[], stateRoot: string, enabled: boolean): MountedTool[];
8
- /** Build the `wake` tool bound to `stateRoot` (where wake-ups persist). */
9
- export declare function makeWakeTool(stateRoot: string, now?: () => Date): MountedTool;
@@ -1,92 +0,0 @@
1
- /** The built-in `wake` tool: the agent's self-scheduling surface. */
2
- import { z } from "zod";
3
- import { addWakeup, removeWakeup } from "../../schedule/wakeups.js";
4
- import { defineTool } from "./tool.js";
5
- /**
6
- * Parse a delay to milliseconds: a number is SECONDS; a string MUST carry a unit — `"<n><s|m|h|d>"` ("30m", "2h",
7
- * "1d").
8
- */
9
- export function parseDelayMs(input) {
10
- if (typeof input === "number")
11
- return Number.isFinite(input) && input > 0 ? input * 1000 : undefined;
12
- const m = input.trim().match(/^(\d+(?:\.\d+)?)\s*(s|m|h|d)$/i); // unit REQUIRED on a string
13
- if (!m)
14
- return undefined;
15
- const mult = { s: 1_000, m: 60_000, h: 3_600_000, d: 86_400_000 }[m[2].toLowerCase()];
16
- return Number(m[1]) * mult;
17
- }
18
- export function withWakeTool(tools, stateRoot, enabled) {
19
- if (!enabled)
20
- return tools;
21
- // wake/unwake are a PAIR over one store: if the workspace defines EITHER name, mount NEITHER built-in.
22
- if (tools.some((t) => t.name === "wake" || t.name === "unwake"))
23
- return tools;
24
- return [...tools, makeWakeTool(stateRoot), makeUnwakeTool(stateRoot)];
25
- }
26
- /** Build the `wake` tool bound to `stateRoot` (where wake-ups persist). */
27
- export function makeWakeTool(stateRoot, now = () => new Date()) {
28
- return defineTool({
29
- name: "wake",
30
- description: "Schedule yourself to wake up later and continue in THIS conversation. ONE-SHOT: pass `in` — a " +
31
- 'duration string with a unit ("30m", "2h", "1d") or a number of seconds — to resume a task after a ' +
32
- "delay. RECURRING: pass `cron` (5-field, optional `tz`) to wake repeatedly — use sparingly, and " +
33
- "`unwake` with the returned id when the job is done. Exactly one of `in`/`cron`. When the time " +
34
- "comes, a new turn runs in this same session with `prompt` as its instruction (tagged with the wake-up's " +
35
- "id so you can tell it from a user message) — you keep the full context of this conversation. IMPORTANT: the woken turn's plain reply is NOT delivered to anyone — " +
36
- "to reach the user it must call a delivery tool (e.g. a channel's send tool), exactly as a scheduled " +
37
- "job would.",
38
- input: z.object({
39
- in: z
40
- .union([z.string(), z.number()])
41
- .optional()
42
- .describe('one-shot delay: a duration string with a unit ("30m" / "2h" / "1d"), or a number of seconds'),
43
- cron: z.string().optional().describe('recurring: a 5-field cron expression (e.g. "0 9 * * *")'),
44
- tz: z.string().optional().describe('IANA timezone for `cron` (default "UTC")'),
45
- prompt: z.string().min(1).describe("the instruction for the woken turn (runs in this same conversation)"),
46
- }),
47
- execute(input, ctx) {
48
- const session = ctx.sessionManager?.getSessionId();
49
- if (!session)
50
- return "wake is only available inside a conversation (there is no session to resume).";
51
- if ((input.in === undefined) === (input.cron === undefined)) {
52
- return "pass exactly one of `in` (one-shot) or `cron` (recurring).";
53
- }
54
- if (input.cron !== undefined) {
55
- // addWakeup validates the cron and DERIVES the first instant itself — one computation, one truth.
56
- const r = addWakeup(stateRoot, { session, prompt: input.prompt, cron: input.cron, tz: input.tz }, now());
57
- if (!r.ok)
58
- return r.error; // guardrail message the model can act on
59
- return `OK — recurring wake ${r.id} (cron "${input.cron}"${input.tz ? ` ${input.tz}` : ""}), first at ${r.fireAt}: ${input.prompt}. Use unwake({ id: "${r.id}" }) to stop it.`;
60
- }
61
- const ms = parseDelayMs(input.in);
62
- if (ms === undefined) {
63
- return `couldn't parse "in" (${JSON.stringify(input.in)}) — use a unit like "30m" / "2h" / "1d", or a number of seconds (a bare number as text like "120" is rejected).`;
64
- }
65
- const at = new Date(now().getTime() + ms);
66
- const r = addWakeup(stateRoot, { session, prompt: input.prompt, fireAt: at }, now());
67
- if (!r.ok)
68
- return r.error; // guardrail message the model can act on
69
- return `OK — I'll wake up at ${r.fireAt} (id ${r.id}) to: ${input.prompt}. Use unwake({ id: "${r.id}" }) if it becomes unnecessary.`;
70
- },
71
- });
72
- }
73
- /**
74
- * Build the `unwake` tool: cancel one of THIS conversation's pending wake-ups by id (a wake/recurring that is no
75
- * longer needed).
76
- */
77
- function makeUnwakeTool(stateRoot) {
78
- return defineTool({
79
- name: "unwake",
80
- description: "Cancel one of YOUR pending wake-ups (one-shot or recurring) by the id `wake` returned. Use it when " +
81
- "a scheduled follow-up is no longer needed — especially to stop a recurring wake once its job is done.",
82
- input: z.object({ id: z.string().min(1).describe("the wake-up id (returned by `wake`)") }),
83
- execute(input, ctx) {
84
- const session = ctx.sessionManager?.getSessionId();
85
- if (!session)
86
- return "unwake is only available inside a conversation.";
87
- return removeWakeup(stateRoot, input.id, session)
88
- ? `OK — wake-up ${input.id} cancelled.`
89
- : `no pending wake-up ${input.id} in this conversation (already fired, or not yours).`;
90
- },
91
- });
92
- }
package/dist/loader.d.ts DELETED
@@ -1,41 +0,0 @@
1
- export interface DiscoveredModule {
2
- /** Basename without extension — the authoritative name for tools/channels. */
3
- name: string;
4
- /** "tools/foo.ts"-style label for errors and collisions. */
5
- label: string;
6
- file: string;
7
- mod: {
8
- default?: unknown;
9
- };
10
- }
11
- /** An agent module that failed to load, surfaced as data so its caller can report the exact file. */
12
- export interface ModuleLoadFailure {
13
- /** "tools/foo.ts"-style label. */
14
- label: string;
15
- file: string;
16
- /** The failure message (an import error carries {@link moduleLoadHint}). */
17
- message: string;
18
- }
19
- /** A module the loader skipped, said once, the same way for tools, channels and routines. */
20
- export declare function reportModuleLoadFailures(failures: readonly ModuleLoadFailure[]): void;
21
- /**
22
- * THE REFUSAL every path that is about to RUN the agent shares: an enabled file under `tools/`, `channels/` or
23
- * `routines/` is a declaration, so one that cannot load means the agent is missing something its author said it
24
- * has. Starting anyway announces a ready service over an absent capability — a schedule that never fires, a tool the
25
- * model simply never gets — with nothing but one warning to find it by. Every failure is reported before this
26
- * throws, so a boot fixes all of them at once rather than one per restart.
27
- *
28
- * Inspecting a definition (`info`, `fastagent tool`) is NOT this path: it must survive a broken file in order to
29
- * report it.
30
- */
31
- export declare function refuseBrokenDeclarations(failures: readonly ModuleLoadFailure[]): void;
32
- /** Import every module the directory declares ({@link moduleInventory}). */
33
- export declare function loadModuleDir(subDir: string): Promise<{
34
- modules: DiscoveredModule[];
35
- failures: ModuleLoadFailure[];
36
- }>;
37
- /**
38
- * A hint for the two common dynamic-import failures — an uninstalled dependency or a non-ESM package — and empty
39
- * otherwise, so an unrelated error is reported on its own.
40
- */
41
- export declare function moduleLoadHint(error: NodeJS.ErrnoException): string;