@fastagent-sh/fastagent 0.24.4 → 0.26.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 (487) hide show
  1. package/README.md +54 -82
  2. package/dist/agent-api.d.ts +460 -0
  3. package/dist/agent-api.js +209 -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 +81 -0
  9. package/dist/authoring.js +245 -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 +116 -64
  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 +18 -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 +253 -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 +191 -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 +132 -16
  164. package/dist/cli/commands/login.d.ts +31 -2
  165. package/dist/cli/commands/login.js +416 -65
  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 +6 -4
  184. package/dist/cli/login-relay.js +19 -7
  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 +70 -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 +220 -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 +223 -202
  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 +52 -27
  260. package/dist/effect-port.d.ts +4 -4
  261. package/dist/effect-port.js +4 -4
  262. package/dist/env.d.ts +0 -13
  263. package/dist/env.js +1 -44
  264. package/dist/environment/apt.d.ts +4 -0
  265. package/dist/environment/apt.js +32 -0
  266. package/dist/environment/declare.d.ts +59 -0
  267. package/dist/environment/declare.js +210 -0
  268. package/dist/environment/mise.d.ts +51 -0
  269. package/dist/environment/mise.js +272 -0
  270. package/dist/feishu.d.ts +2 -2
  271. package/dist/feishu.js +2 -2
  272. package/dist/git.d.ts +13 -0
  273. package/dist/git.js +55 -0
  274. package/dist/harnesses/models/catalog.d.ts +20 -0
  275. package/dist/harnesses/models/catalog.js +254 -0
  276. package/dist/{engines/pi/auth.d.ts → harnesses/models/credentials.d.ts} +3 -3
  277. package/dist/{engines/pi/auth.js → harnesses/models/credentials.js} +3 -3
  278. package/dist/harnesses/models/environment.d.ts +48 -0
  279. package/dist/harnesses/models/environment.js +88 -0
  280. package/dist/harnesses/models/host.d.ts +30 -0
  281. package/dist/harnesses/models/host.js +97 -0
  282. package/dist/{engines/pi → harnesses/models}/login.d.ts +66 -70
  283. package/dist/harnesses/models/login.js +439 -0
  284. package/dist/harnesses/models/models.d.ts +84 -0
  285. package/dist/harnesses/models/models.js +197 -0
  286. package/dist/harnesses/pi-durable/agent.d.ts +42 -0
  287. package/dist/harnesses/pi-durable/agent.js +581 -0
  288. package/dist/harnesses/pi-durable/defaults.d.ts +28 -0
  289. package/dist/harnesses/pi-durable/defaults.js +26 -0
  290. package/dist/harnesses/pi-durable/define.d.ts +77 -0
  291. package/dist/harnesses/pi-durable/define.js +28 -0
  292. package/dist/harnesses/pi-durable/entries.d.ts +32 -0
  293. package/dist/harnesses/pi-durable/entries.js +126 -0
  294. package/dist/harnesses/pi-durable/events.d.ts +25 -0
  295. package/dist/harnesses/pi-durable/events.js +238 -0
  296. package/dist/harnesses/pi-durable/ids.d.ts +16 -0
  297. package/dist/harnesses/pi-durable/ids.js +55 -0
  298. package/dist/harnesses/pi-durable/messages.d.ts +41 -0
  299. package/dist/harnesses/pi-durable/messages.js +116 -0
  300. package/dist/harnesses/pi-durable/open.d.ts +95 -0
  301. package/dist/harnesses/pi-durable/open.js +330 -0
  302. package/dist/harnesses/pi-durable/reads.d.ts +30 -0
  303. package/dist/harnesses/pi-durable/reads.js +94 -0
  304. package/dist/harnesses/pi-durable/registry.d.ts +18 -0
  305. package/dist/harnesses/pi-durable/registry.js +56 -0
  306. package/dist/harnesses/pi-durable/release.d.ts +13 -0
  307. package/dist/harnesses/pi-durable/release.js +40 -0
  308. package/dist/harnesses/pi-durable/serve.d.ts +90 -0
  309. package/dist/harnesses/pi-durable/serve.js +186 -0
  310. package/dist/harnesses/pi-durable/sessions.d.ts +27 -0
  311. package/dist/harnesses/pi-durable/sessions.js +47 -0
  312. package/dist/harnesses/pi-durable/storage.d.ts +4 -0
  313. package/dist/harnesses/pi-durable/storage.js +49 -0
  314. package/dist/harnesses/pi-durable/stream.d.ts +20 -0
  315. package/dist/harnesses/pi-durable/stream.js +221 -0
  316. package/dist/harnesses/pi-durable/text.d.ts +30 -0
  317. package/dist/harnesses/pi-durable/text.js +292 -0
  318. package/dist/harnesses/pi-durable/wake.d.ts +11 -0
  319. package/dist/harnesses/pi-durable/wake.js +90 -0
  320. package/dist/http/client.d.ts +6 -0
  321. package/dist/http/client.js +256 -0
  322. package/dist/http/contract.d.ts +541 -0
  323. package/dist/http/contract.js +179 -0
  324. package/dist/http/server.d.ts +34 -0
  325. package/dist/http/server.js +194 -0
  326. package/dist/index.d.ts +19 -4
  327. package/dist/index.js +13 -5
  328. package/dist/lark.d.ts +2 -2
  329. package/dist/lark.js +2 -2
  330. package/dist/locked-file.d.ts +17 -0
  331. package/dist/{engines/pi/locked-file.js → locked-file.js} +16 -10
  332. package/dist/once.d.ts +6 -0
  333. package/dist/once.js +23 -0
  334. package/dist/paths.d.ts +36 -52
  335. package/dist/paths.js +66 -182
  336. package/dist/runtime.d.ts +25 -2
  337. package/dist/runtime.js +27 -0
  338. package/dist/scaffold/add-channel.d.ts +14 -27
  339. package/dist/scaffold/add-channel.js +82 -180
  340. package/dist/scaffold/init.d.ts +17 -18
  341. package/dist/scaffold/init.js +87 -99
  342. package/dist/scaffold/templates/SYSTEM.md +12 -0
  343. package/dist/scaffold/templates/env.example +4 -10
  344. package/dist/scaffold/templates/fastagent.config.ts +21 -33
  345. package/dist/scaffold/templates/gitignore +8 -1
  346. package/dist/scaffold/templates/skills/writing-great-skills/SKILL.md +1 -2
  347. package/dist/scaffold/templates.d.ts +9 -4
  348. package/dist/scaffold/templates.js +7 -5
  349. package/dist/scaffold/vendor-skill.d.ts +1 -4
  350. package/dist/scaffold/vendor-skill.js +5 -6
  351. package/dist/schedule/cron.d.ts +13 -0
  352. package/dist/schedule/cron.js +52 -0
  353. package/dist/schedule/eventbridge-cron.d.ts +17 -0
  354. package/dist/schedule/eventbridge-cron.js +88 -0
  355. package/dist/schedule/schedule.d.ts +23 -0
  356. package/dist/schedule/schedule.js +34 -0
  357. package/dist/schedule/scheduler.d.ts +34 -33
  358. package/dist/schedule/scheduler.js +251 -137
  359. package/dist/schedule/state.d.ts +4 -14
  360. package/dist/schedule/state.js +7 -7
  361. package/dist/schedule/wake-alarm.d.ts +22 -2
  362. package/dist/schedule/wake-alarm.js +66 -20
  363. package/dist/schedule/wakeups.d.ts +16 -15
  364. package/dist/schedule/wakeups.js +47 -45
  365. package/dist/service.d.ts +56 -169
  366. package/dist/service.js +91 -187
  367. package/dist/serving-command.d.ts +10 -0
  368. package/dist/serving-command.js +16 -0
  369. package/dist/sign-in-api.d.ts +147 -0
  370. package/dist/sign-in-api.js +9 -0
  371. package/dist/slack.d.ts +1 -1
  372. package/dist/slack.js +1 -1
  373. package/dist/{channels/kit/state.js → state-file.js} +6 -6
  374. package/dist/telegram.d.ts +1 -0
  375. package/dist/telegram.js +1 -0
  376. package/dist/tunnel.d.ts +3 -0
  377. package/dist/tunnel.js +14 -5
  378. package/dist/value-file.d.ts +40 -0
  379. package/dist/value-file.js +164 -0
  380. package/dist/version.d.ts +5 -0
  381. package/dist/version.js +14 -1
  382. package/package.json +18 -28
  383. package/dist/agent.d.ts +0 -106
  384. package/dist/agent.js +0 -21
  385. package/dist/channels/control.d.ts +0 -31
  386. package/dist/channels/control.js +0 -329
  387. package/dist/channels/define-channel.d.ts +0 -39
  388. package/dist/channels/define-channel.js +0 -9
  389. package/dist/channels/feishu/context-buffer.d.ts +0 -35
  390. package/dist/channels/feishu/context-buffer.js +0 -65
  391. package/dist/channels/feishu/scaffold/channel.websocket.ts +0 -31
  392. package/dist/channels/http.d.ts +0 -23
  393. package/dist/channels/http.js +0 -57
  394. package/dist/channels/lark/scaffold/channel.websocket.ts +0 -31
  395. package/dist/channels/slack/context-buffer.d.ts +0 -23
  396. package/dist/channels/slack/context-buffer.js +0 -37
  397. package/dist/channels/sse.d.ts +0 -4
  398. package/dist/channels/sse.js +0 -66
  399. package/dist/cli/commands/chat.d.ts +0 -3
  400. package/dist/cli/commands/chat.js +0 -14
  401. package/dist/cli/commands/routine-run.d.ts +0 -6
  402. package/dist/cli/commands/routine-run.js +0 -46
  403. package/dist/cli/commands/routine.d.ts +0 -25
  404. package/dist/cli/commands/routine.js +0 -122
  405. package/dist/cli/commands/tool.d.ts +0 -1
  406. package/dist/cli/commands/tool.js +0 -57
  407. package/dist/collect.d.ts +0 -63
  408. package/dist/collect.js +0 -90
  409. package/dist/core.d.ts +0 -13
  410. package/dist/core.js +0 -15
  411. package/dist/engines/pi/agent-models.d.ts +0 -83
  412. package/dist/engines/pi/agent-models.js +0 -120
  413. package/dist/engines/pi/agent-session-factory.d.ts +0 -121
  414. package/dist/engines/pi/agent-session-factory.js +0 -535
  415. package/dist/engines/pi/chat.d.ts +0 -3
  416. package/dist/engines/pi/chat.js +0 -8
  417. package/dist/engines/pi/config.d.ts +0 -71
  418. package/dist/engines/pi/config.js +0 -199
  419. package/dist/engines/pi/create.d.ts +0 -170
  420. package/dist/engines/pi/create.js +0 -343
  421. package/dist/engines/pi/definition.d.ts +0 -74
  422. package/dist/engines/pi/definition.js +0 -236
  423. package/dist/engines/pi/entry-images.d.ts +0 -14
  424. package/dist/engines/pi/entry-images.js +0 -23
  425. package/dist/engines/pi/invoke-session.d.ts +0 -18
  426. package/dist/engines/pi/invoke-session.js +0 -403
  427. package/dist/engines/pi/locked-file.d.ts +0 -9
  428. package/dist/engines/pi/login.js +0 -331
  429. package/dist/engines/pi/machine.d.ts +0 -53
  430. package/dist/engines/pi/machine.js +0 -137
  431. package/dist/engines/pi/models.d.ts +0 -200
  432. package/dist/engines/pi/models.js +0 -533
  433. package/dist/engines/pi/open.d.ts +0 -180
  434. package/dist/engines/pi/open.js +0 -270
  435. package/dist/engines/pi/openai-account-models.d.ts +0 -35
  436. package/dist/engines/pi/openai-account-models.js +0 -116
  437. package/dist/engines/pi/report.d.ts +0 -18
  438. package/dist/engines/pi/report.js +0 -59
  439. package/dist/engines/pi/retry-event.d.ts +0 -6
  440. package/dist/engines/pi/retry-event.js +0 -15
  441. package/dist/engines/pi/service.d.ts +0 -9
  442. package/dist/engines/pi/service.js +0 -14
  443. package/dist/engines/pi/session-builder.d.ts +0 -13
  444. package/dist/engines/pi/session-builder.js +0 -117
  445. package/dist/engines/pi/session-control.d.ts +0 -77
  446. package/dist/engines/pi/session-control.js +0 -908
  447. package/dist/engines/pi/session-effects.d.ts +0 -14
  448. package/dist/engines/pi/session-effects.js +0 -30
  449. package/dist/engines/pi/session-inheritance.d.ts +0 -21
  450. package/dist/engines/pi/session-inheritance.js +0 -204
  451. package/dist/engines/pi/session-markers.d.ts +0 -49
  452. package/dist/engines/pi/session-markers.js +0 -60
  453. package/dist/engines/pi/session-settings.d.ts +0 -67
  454. package/dist/engines/pi/session-settings.js +0 -119
  455. package/dist/engines/pi/session-store.d.ts +0 -69
  456. package/dist/engines/pi/session-store.js +0 -430
  457. package/dist/engines/pi/tool-context.d.ts +0 -45
  458. package/dist/engines/pi/tool-context.js +0 -31
  459. package/dist/engines/pi/tool.d.ts +0 -99
  460. package/dist/engines/pi/tool.js +0 -118
  461. package/dist/engines/pi/turn-kit.d.ts +0 -92
  462. package/dist/engines/pi/turn-kit.js +0 -288
  463. package/dist/engines/pi/wake-tool.d.ts +0 -9
  464. package/dist/engines/pi/wake-tool.js +0 -92
  465. package/dist/loader.d.ts +0 -41
  466. package/dist/loader.js +0 -116
  467. package/dist/node.d.ts +0 -3
  468. package/dist/node.js +0 -4
  469. package/dist/observe.d.ts +0 -6
  470. package/dist/observe.js +0 -47
  471. package/dist/pi.d.ts +0 -25
  472. package/dist/pi.js +0 -15
  473. package/dist/scaffold/templates/APPEND_SYSTEM.md +0 -12
  474. package/dist/scaffold/templates/tools/fetch-url.ts +0 -25
  475. package/dist/schedule/discover.d.ts +0 -17
  476. package/dist/schedule/discover.js +0 -61
  477. package/dist/schedule/routine.d.ts +0 -43
  478. package/dist/schedule/routine.js +0 -32
  479. package/dist/schedule/run.d.ts +0 -55
  480. package/dist/schedule/run.js +0 -146
  481. package/dist/secrets-gate.d.ts +0 -32
  482. package/dist/secrets-gate.js +0 -33
  483. package/dist/session-remote.d.ts +0 -47
  484. package/dist/session-remote.js +0 -460
  485. package/dist/session.d.ts +0 -466
  486. package/dist/session.js +0 -57
  487. /package/dist/{channels/kit/state.d.ts → state-file.d.ts} +0 -0
@@ -1,343 +0,0 @@
1
- /**
2
- * Agent assembly (configuration-time): the engine assets (tools, prompt) plus the reusable ladder that puts a pi agent
3
- * together.
4
- */
5
- import { toUSVString } from "node:util";
6
- import { NodeExecutionEnv } from "@earendil-works/pi-agent-core/node";
7
- import { createCodingTools, createPowerShellTool, createReadOnlyTools, } from "@earendil-works/pi-coding-agent";
8
- import { resolveModel } from "./config.js";
9
- import { isAgentcoreRuntime, isDeployedWorkspace } from "../../paths.js";
10
- import { loadAgentDefinition } from "./definition.js";
11
- import { reportFindingsIfChanged } from "./report.js";
12
- import { log } from "../../log.js";
13
- import { BUILTIN_EXTENSIONS, DISCOVERY, readMachine } from "./machine.js";
14
- import { loadTools, mergeDiscoveredTools } from "./tool.js";
15
- import { readSecretDeclaration } from "../../declared-secrets.js";
16
- import { createPiAgentFromSession } from "./invoke-session.js";
17
- import { piAgentSessionFactory } from "./agent-session-factory.js";
18
- import { DEFAULT_THINKING_LEVEL } from "./models.js";
19
- import { agentModels } from "./agent-models.js";
20
- import { piInMemorySessionRecordStore } from "./session-store.js";
21
- import { inProcessLease } from "./turn-kit.js";
22
- // ── §1 tools ─────────────────────────────────────────────────────────────────
23
- //
24
- // A directory agent gets every pi coding tool.
25
- /**
26
- * Every pi coding tool, in canonical order, rooted at the workspace it operates in. pi ships two overlapping groupings
27
- * and neither is the whole set.
28
- */
29
- export const CODING_TOOL_NAMES = ["read", "grep", "find", "ls", "bash", "edit", "write"];
30
- export function piAllCodingTools(cwd) {
31
- const mutating = createCodingTools(cwd, {
32
- bash: {
33
- spawnHook(context) {
34
- const { env } = context;
35
- const id = env.PI_SESSION_ID;
36
- delete env.PI_SESSION_ID_ENCODING;
37
- // OS environment strings cannot preserve NUL or unpaired UTF-16 surrogates.
38
- if (id !== undefined && (id.includes("\u0000") || toUSVString(id) !== id)) {
39
- env.PI_SESSION_ID = JSON.stringify(id);
40
- env.PI_SESSION_ID_ENCODING = "json";
41
- }
42
- return context;
43
- },
44
- },
45
- }).filter((tool) => tool.name !== "read");
46
- return [...createReadOnlyTools(cwd), ...mutating];
47
- }
48
- /** Every tool an `AgentSession` registers on its own, whether or not a directory agent mounts it. */
49
- function piRegisteredToolNames(cwd) {
50
- return [
51
- ...createReadOnlyTools(cwd).map((tool) => tool.name),
52
- ...createCodingTools(cwd).map((tool) => tool.name),
53
- createPowerShellTool(cwd).name,
54
- ];
55
- }
56
- /** Built-ins omitted by an explicit lower-level tool list. */
57
- function omittedBuiltinNames(mounted, cwd) {
58
- const mountedNames = new Set(mounted.map((tool) => tool.name));
59
- return [...new Set(piRegisteredToolNames(cwd))].filter((name) => !mountedNames.has(name));
60
- }
61
- function isDefaultActiveTool(tool) {
62
- return ((!tool.exposure || tool.exposure === "direct" || tool.exposure === "model-only") && tool.defaultActive !== false);
63
- }
64
- /** The built-in extension a `codemode`/`deferred` tool is reached through ({@link DISCOVERY}). */
65
- function wayIn(tool) {
66
- return tool.exposure === "codemode" || tool.exposure === "deferred" ? DISCOVERY[tool.exposure].extension : undefined;
67
- }
68
- /** Whether this machine leaves the tool's way in enabled (a tool that needs none always has one). */
69
- function hasWayIn(tool, builtinExtensions) {
70
- const extension = wayIn(tool);
71
- return extension === undefined || builtinExtensions.includes(extension);
72
- }
73
- function indirectReach(tool, builtinExtensions) {
74
- if (isDefaultActiveTool(tool))
75
- return undefined;
76
- if (!hasWayIn(tool, builtinExtensions))
77
- return "unreachable";
78
- if (tool.exposure === "deferred")
79
- return "tool_search";
80
- if (tool.exposure === "codemode")
81
- return "codemode";
82
- if (tool.exposure === "hidden")
83
- return "hidden";
84
- // `defaultActive: false`: only an authored loader (`ToolContext.tools.activate`) brings it in.
85
- return "inactive";
86
- }
87
- /**
88
- * The full directory-agent tool set: all pi coding tools + `config.tools` + discovered `tools/` (deduped, existing
89
- * win), plus the authored names and collisions to report.
90
- */
91
- export async function resolveAgentTools(config, agentDir, cwd) {
92
- // Discovered `tools/` come from `agentDir` (the agent's own surface); the coding tools are rooted at `cwd`, the
93
- // WORKSPACE.
94
- const discovered = await loadTools(agentDir);
95
- const configured = piAllCodingTools(cwd);
96
- const configuredNames = new Set(configured.map((tool) => tool.name));
97
- const configuredCollisions = [];
98
- // The config.tools that actually MOUNT — collected here rather than re-derived from `config.tools`
99
- // afterwards, so a tool dropped for sharing a coding tool's name cannot contribute a declaration
100
- // (its body never runs, and gating a start on its secret would refuse to serve for nothing).
101
- const mountedConfigTools = [];
102
- for (const tool of config.tools ?? []) {
103
- if (configuredNames.has(tool.name)) {
104
- configuredCollisions.push({ name: tool.name, source: "config.tools" });
105
- continue;
106
- }
107
- configuredNames.add(tool.name);
108
- configured.push(tool);
109
- mountedConfigTools.push(tool);
110
- }
111
- const merged = mergeDiscoveredTools(configured, discovered.tools);
112
- const tools = merged.tools;
113
- const toolCollisions = [...discovered.collisions, ...configuredCollisions, ...merged.collisions];
114
- // `toolNames` is the AUTHOR's active-by-default surface (config.tools + tools/).
115
- // The discovered tools that were DROPPED (a coding tool or config.tools already owns the name):
116
- // asking the mounted set instead would read the winner's name as proof the loser is mounted.
117
- const shadowed = new Set(merged.collisions.map((c) => c.name));
118
- const { builtinExtensions } = await readMachine(cwd);
119
- const defaultNames = new Set(CODING_TOOL_NAMES);
120
- const toolNames = tools.filter((t) => !defaultNames.has(t.name) && isDefaultActiveTool(t)).map((t) => t.name);
121
- return {
122
- tools,
123
- toolNames,
124
- indirectTools: tools.flatMap((t) => {
125
- const reach = defaultNames.has(t.name) ? undefined : indirectReach(t, builtinExtensions);
126
- return reach ? [{ name: t.name, reach }] : [];
127
- }),
128
- toolCollisions,
129
- toolFailures: discovered.failures,
130
- // Mounted only, and config.tools are FastagentTools too, so a programmatic tool declares the
131
- // same way a file does.
132
- toolSecrets: new Map([
133
- ...[...discovered.secrets].filter(([name]) => !shadowed.has(name)),
134
- // A programmatic tool declares the same way a file does. The source names the ENTRY, not just
135
- // the list: `source` has to point at something the author can find, and "config.tools" alone
136
- // locates nothing when the list has several tools. The shape was already refused by config
137
- // validation (config.ts), so a throw here means a FastagentConfig assembled in code bypassed
138
- // it — still the caller's own object, so it fails loudly rather than being isolated.
139
- ...mountedConfigTools.map((tool) => {
140
- const declaration = readSecretDeclaration(tool, `config.tools "${tool.name}"`);
141
- if (declaration.error !== undefined)
142
- throw new Error(declaration.error);
143
- return [tool.name, declaration.secrets];
144
- }),
145
- ]),
146
- };
147
- }
148
- // pi builds the prompt (its default, or SYSTEM.md in its place); FastAgent adds its own named sections after it.
149
- /** The tools pi's default prompt says the agent has ("reading files, executing commands, editing code"). */
150
- const CODING_IDENTITY_TOOLS = ["read", "bash", "edit", "write"];
151
- /**
152
- * Refuse a prompt that would claim tools the agent does not have: pi's default says the agent reads files, runs
153
- * commands and edits code, which an embedder that replaced the coding tools made false. A prompt of the agent's own
154
- * (`base`, or `SYSTEM.md`) describes it instead. Checked at assembly and on every turn, since `SYSTEM.md` is re-read
155
- * per turn and an agent may delete it.
156
- */
157
- function refuseDefaultPromptOverReplacedTools(tools, hasOwnPrompt) {
158
- if (hasOwnPrompt)
159
- return;
160
- const mounted = new Set(tools.map((tool) => tool.name));
161
- const missing = CODING_IDENTITY_TOOLS.filter((name) => !mounted.has(name));
162
- if (missing.length === 0)
163
- return;
164
- throw new Error(`the coding tools were replaced (${missing.join(", ")} not mounted), so pi's default prompt, which says the agent ` +
165
- `reads files, runs commands and edits code, does not describe this agent: pass \`base\` or write SYSTEM.md`);
166
- }
167
- /**
168
- * FastAgent's own prompt sections (docs/design/agent-model.md §2): what pi's prompt cannot know. Each is a named
169
- * section pi renders after its own, so it holds whoever wrote the rest of the prompt.
170
- */
171
- export function fastagentPromptSections(options) {
172
- const sections = {};
173
- const mountedNames = new Set(options.tools.map((tool) => tool.name));
174
- // Only `deferred` tools are tool_search's to load (the session activates it for them); `codemode` ones are listed
175
- // in codemode's own description, and an inactive direct tool is reached only through an authored activation.
176
- // A disabled tool-search leaves them no way in, and naming tool_search would invite calls to a tool that is not there.
177
- const deferredCount = options.tools.filter((tool) => tool.exposure === "deferred" && hasWayIn(tool, options.builtinExtensions)).length;
178
- if (deferredCount > 0) {
179
- sections.deferred_tools = `${deferredCount} additional tool(s) are registered but not loaded — use tool_search to find and load them before concluding a capability is missing.`;
180
- }
181
- // What takes effect when, and the agent's own path to a new capability, are the same on every host; only how long
182
- // the storage lives differs, below. The skill it writes lives in the definition directory, which the next
183
- // deployment replaces (or, on AgentCore, erases with everything else) — so the sentence says so, and where a skill
184
- // that should outlast it has to go. A skill outside the definition would survive, but it is machine state, read
185
- // once per process (machine.ts), so it would not be live.
186
- const runtimeChanges = ` Markdown definition files are read each turn; changes to tools, channels or configuration take effect when the service restarts. To give yourself a new capability now, write a skill — a SKILL.md in your definition's skills/ directory, with any script it needs run through bash. It lasts until the next deployment replaces that directory, so a capability that should outlast it belongs in the author's release: propose it to them.${
187
- // Named only when mounted (a serve; not a one-shot invoke), like the deferred tools above: naming a tool the model
188
- // does not have invites calls to it.
189
- mountedNames.has("wake") ? " To schedule your own follow-up work, use the wake tool." : ""}`;
190
- // How long the storage lives is the HOST's answer, not a deployment-wide one: AgentCore's managed mount is reset by
191
- // every deploy, so telling that agent to keep work "outside the definition" would name a location its next deploy
192
- // erases.
193
- if (isDeployedWorkspace()) {
194
- sections.self_change = isAgentcoreRuntime()
195
- ? `Your workspace survives restarts, including uncommitted work; /tmp does not. Every deployment of a new version resets this host's storage entirely, so anything that must outlive a deployment belongs in an external system (a git remote, an issue tracker, a database).${runtimeChanges}`
196
- : `Your workspace survives restarts and deployments, including uncommitted work; /tmp does not. A new deployment replaces your definition directory with the author's release, so keep ongoing project work outside it.${runtimeChanges}`;
197
- }
198
- return sections;
199
- }
200
- /** Shared low-level wiring: resolve the model spec against the collection, default the K ports, build the parts. */
201
- function assemblePi(opts) {
202
- const cwd = opts.cwd ?? opts.env?.cwd ?? process.cwd();
203
- // Materialized here (not defaulted inside the L0) so the value carries the SAME lease instance the agent runs under
204
- // — boundary mutations must contend on it.
205
- const lease = opts.lease ?? inProcessLease();
206
- const sessions = opts.sessions ?? piInMemorySessionRecordStore({ cwd });
207
- const createModelRuntime = opts.models;
208
- let registry;
209
- const modelRuntime = () => {
210
- registry ??= opts.catalog();
211
- return registry;
212
- };
213
- let engine;
214
- const resolveEngine = () => {
215
- const spec = opts.model;
216
- engine ??= modelRuntime().then((runtime) => ({
217
- modelRuntime: runtime,
218
- ...(spec ? { model: resolveModel(runtime, spec) } : {}),
219
- }));
220
- return engine;
221
- };
222
- // Deny omitted coding names so discovery cannot reintroduce tools a lower-level caller excluded.
223
- const excludedToolNames = omittedBuiltinNames(opts.tools ?? [], cwd);
224
- const sessionFactory = piAgentSessionFactory({
225
- sessions,
226
- engine: async () => ({ modelRuntime: await createModelRuntime() }),
227
- ...(opts.model ? { modelSpec: opts.model } : {}),
228
- thinkingLevel: opts.thinkingLevel,
229
- tools: opts.tools,
230
- readDefinition: opts.readDefinition,
231
- cwd,
232
- ...(opts.extensionPaths ? { extensionPaths: opts.extensionPaths } : {}),
233
- excludedToolNames,
234
- });
235
- return {
236
- lease,
237
- sessionFactory,
238
- modelRuntime,
239
- createModelRuntime,
240
- engine: resolveEngine,
241
- thinkingLevel: opts.thinkingLevel ?? DEFAULT_THINKING_LEVEL,
242
- tools: opts.tools ?? [],
243
- excludedToolNames,
244
- readDefinition: opts.readDefinition,
245
- extensionPaths: opts.extensionPaths ?? [],
246
- };
247
- }
248
- /** The agent an assembly runs as: the L0 over its lease and session factory. */
249
- export function agentOf(assembly, observer) {
250
- return createPiAgentFromSession({ lease: assembly.lease, observer, sessionFactory: assembly.sessionFactory });
251
- }
252
- /** L1: assemble from typed parts. */
253
- export function createPiAgent(options) {
254
- const { instructions, skills = [] } = options;
255
- const models = agentModels(undefined, options, { providers: options.providers });
256
- return agentOf(assemblePi({
257
- model: options.model,
258
- thinkingLevel: options.thinkingLevel,
259
- models: models.createRuntime,
260
- catalog: models.runtime,
261
- // No instructions is an empty prompt, not pi's default: this path takes the prompt whole.
262
- readDefinition: () => ({
263
- systemPrompt: (typeof instructions === "function" ? instructions() : instructions) || " ",
264
- skills,
265
- }),
266
- tools: options.tools,
267
- sessions: options.sessions,
268
- env: options.env,
269
- lease: options.lease,
270
- }), options.observer);
271
- }
272
- /**
273
- * L2, as the value: load the directory (base + AGENTS.md + skills + env) and assemble. `models` is the directory's
274
- * model environment when the caller already built it (the opener, whose report must describe what runs); otherwise it
275
- * is built here from the credential options.
276
- */
277
- export async function assemblePiFromDefinition(dir, options) {
278
- // `dir` = the agent-definition dir; `cwd` (default = dir) is the run root where tools operate and whose ancestors are
279
- // walked for project context.
280
- const cwd = options.cwd ?? dir;
281
- const env = options.env ?? new NodeExecutionEnv({ cwd });
282
- // Boot-time load: fail-visibly at startup on a broken directory, and give callers the snapshot to report
283
- // (skills/diagnostics/collisions).
284
- const definition = await loadAgentDefinition(dir, { cwd, env });
285
- const tools = options.tools ?? piAllCodingTools(cwd);
286
- // Boot findings go through the SAME memoized reporter every later reader uses (report.ts, keyed by the resolved
287
- // dir).
288
- reportFindingsIfChanged(definition.dir, definition);
289
- // pi treats an empty prompt as none and builds its default, so a blank `base` would look like a prompt of the
290
- // caller's own while being nothing.
291
- if (options.base !== undefined && options.base.trim() === "") {
292
- throw new Error("`base` is empty: pass the prompt the agent should use, or leave `base` out for pi's default");
293
- }
294
- refuseDefaultPromptOverReplacedTools(tools, options.base !== undefined || definition.systemPrompt !== undefined);
295
- const { providers } = options;
296
- const models = options.models ?? agentModels(dir, options, { cwd, env, ...(providers ? { providers } : {}) });
297
- // Built at boot, so a malformed models.json fails the assembly rather than its first turn. The directory's own
298
- // models.json is what a turn resolves against, layered over the machine's (models.ts).
299
- await models.runtime();
300
- const { builtinExtensions } = await readMachine(cwd);
301
- const unreachable = tools.filter((tool) => !hasWayIn(tool, builtinExtensions));
302
- // Said once per assembly: the model cannot call these at all, while the tools themselves loaded fine.
303
- for (const tool of unreachable) {
304
- log.warn(`[fastagent] tool "${tool.name}" (exposure: ${tool.exposure}) cannot be reached: pi's settings disable ` +
305
- `builtin:${wayIn(tool)}, its only way in`);
306
- }
307
- const assembly = assemblePi({
308
- model: options.model,
309
- thinkingLevel: options.thinkingLevel,
310
- models: models.createRuntime,
311
- catalog: models.runtime,
312
- // The directory is the agent, LIVE: re-read the definition on every invoke, so AGENTS.md/skills edits (the
313
- // author's, or the agent's own self-modification) take effect on the next turn with no process restart — restarts
314
- // are reserved for code (tools/channels/config, module cache).
315
- readDefinition: async () => {
316
- const def = await loadAgentDefinition(dir, { cwd, env });
317
- reportFindingsIfChanged(def.dir, def);
318
- const systemPrompt = options.base ?? def.systemPrompt?.content;
319
- refuseDefaultPromptOverReplacedTools(tools, systemPrompt !== undefined);
320
- return {
321
- ...(systemPrompt !== undefined ? { systemPrompt } : {}),
322
- ...(def.appendSystemPrompt ? { appendSystemPrompt: def.appendSystemPrompt.content } : {}),
323
- contextFiles: def.contextFiles,
324
- sections: fastagentPromptSections({ tools, builtinExtensions }),
325
- skills: def.skills,
326
- prompts: def.prompts,
327
- };
328
- },
329
- tools,
330
- sessions: options.sessions,
331
- // The catalog's own discovery: the models it registered and the extensions sessions load are one list.
332
- extensionPaths: [...(await models.extensionPaths())],
333
- cwd,
334
- env,
335
- lease: options.lease,
336
- });
337
- return { assembly, definition };
338
- }
339
- /** L2: "point at a directory → agent": {@link assemblePiFromDefinition} under the L0. */
340
- export async function createPiAgentFromDefinition(dir, options) {
341
- const { assembly, definition } = await assemblePiFromDefinition(dir, options);
342
- return { agent: agentOf(assembly, options.observer), definition };
343
- }
@@ -1,74 +0,0 @@
1
- import { type ExecutionEnv, type PromptTemplateDiagnostic, type Skill, type SkillDiagnostic } from "@earendil-works/pi-agent-core";
2
- /** A same-name skill collision (the discarded side). */
3
- export interface SkillCollision {
4
- name: string;
5
- winnerPath: string;
6
- loserPath: string;
7
- }
8
- /**
9
- * Two places in the definition holding the same thing: `SYSTEM.md` and `.pi/SYSTEM.md`, or one prompt template in
10
- * `prompts/` and `.pi/prompts/`. The first is used; the other is reported, because it is a file the author wrote that
11
- * does nothing.
12
- */
13
- export interface DefinitionShadow {
14
- what: string;
15
- winnerPath: string;
16
- loserPath: string;
17
- }
18
- /** A file the definition holds verbatim, with where it came from. */
19
- export interface DefinitionFile {
20
- path: string;
21
- content: string;
22
- }
23
- /** A prompt template of the definition's own (`prompts/`, `.pi/prompts/`). */
24
- export interface DefinitionPrompt {
25
- name: string;
26
- description?: string;
27
- content: string;
28
- filePath: string;
29
- }
30
- export type DefinitionDiagnostic = SkillDiagnostic | PromptTemplateDiagnostic;
31
- /** Result of loading a definition directory. */
32
- export interface LoadedDefinition {
33
- /** Project-context files (AGENTS.md), sourced via pi's `loadProjectContextFiles`; pi renders them. */
34
- contextFiles: Array<{
35
- path: string;
36
- content: string;
37
- }>;
38
- /** `SYSTEM.md`, else `.pi/SYSTEM.md`: replaces pi's default prompt. Absent → pi builds its default. */
39
- systemPrompt?: DefinitionFile;
40
- /** `APPEND_SYSTEM.md`, else `.pi/APPEND_SYSTEM.md`: added after the prompt, whichever it is. */
41
- appendSystemPrompt?: DefinitionFile;
42
- skills: Skill[];
43
- prompts: DefinitionPrompt[];
44
- /** Non-fatal per-file problems reported by pi's skill and prompt-template loaders. */
45
- diagnostics: DefinitionDiagnostic[];
46
- /** Same-name skill conflicts across the definition's skill directories (first wins). */
47
- collisions: SkillCollision[];
48
- /** Same-name files and prompt templates across the definition's locations (first wins). */
49
- shadowed: DefinitionShadow[];
50
- /** Paths that exist in the definition and are deliberately not loaded, each with why. */
51
- ignored: Array<{
52
- path: string;
53
- reason: string;
54
- }>;
55
- /** Absolute agent-definition directory path. */
56
- dir: string;
57
- }
58
- export interface LoadAgentDefinitionOptions {
59
- /** Working directory whose ancestors are walked for context files. */
60
- cwd?: string;
61
- env?: ExecutionEnv;
62
- }
63
- /**
64
- * Read an agent definition: its prompt files, skills and prompt templates from `agentDir`; the project context from
65
- * pi's loadProjectContextFiles({ cwd, agentDir }).
66
- */
67
- export declare function loadAgentDefinition(agentDir: string, options?: LoadAgentDefinitionOptions): Promise<LoadedDefinition>;
68
- /** Extension entry-point FILES under `<agentDir>/extensions/`, empty when there are none. */
69
- export declare function loadExtensionPaths(agentDir: string, options?: {
70
- cwd?: string;
71
- env?: ExecutionEnv;
72
- }): Promise<string[]>;
73
- /** Resolve to a canonical (symlink-free) absolute path so comparisons match `process.cwd()`'s realpath. */
74
- export declare function canonicalPath(p: string): string;
@@ -1,236 +0,0 @@
1
- /**
2
- * Definition domain: read an agent definition directory into memory — its system prompt files, its skills and prompt
3
- * templates (each from the agent directory's root spelling first, then pi's `.pi/` and the standard `.agents/` ones),
4
- * and, until contexts exist, the AGENTS.md project context. docs/design/agent-model.md §2 is the rule this follows.
5
- */
6
- import { realpathSync } from "node:fs";
7
- import { join, resolve } from "node:path";
8
- import { BACKGROUND_CONTEXT, loadPromptTemplates, loadSkills, } from "@earendil-works/pi-agent-core";
9
- import { NodeExecutionEnv } from "@earendil-works/pi-agent-core/node";
10
- import { loadProjectContextFiles } from "@earendil-works/pi-coding-agent";
11
- import { log } from "../../log.js";
12
- import { assertInsideAgentDir } from "../../paths.js";
13
- /** Where each resource is read from, in order: the root spelling first, then pi's, then the standard one. */
14
- const SYSTEM_PROMPT_FILES = ["SYSTEM.md", ".pi/SYSTEM.md"];
15
- const APPEND_SYSTEM_PROMPT_FILES = ["APPEND_SYSTEM.md", ".pi/APPEND_SYSTEM.md"];
16
- const SKILL_DIRS = ["skills", ".pi/skills", ".agents/skills"];
17
- const PROMPT_DIRS = ["prompts", ".pi/prompts"];
18
- /** The file `SYSTEM.md` and `APPEND_SYSTEM.md` replaced. Refused rather than ignored: its text would do nothing. */
19
- const RETIRED_PERSONA = "persona.md";
20
- /**
21
- * Read an agent definition: its prompt files, skills and prompt templates from `agentDir`; the project context from
22
- * pi's loadProjectContextFiles({ cwd, agentDir }).
23
- */
24
- export async function loadAgentDefinition(agentDir, options = {}) {
25
- // One resolved default for the working directory (env cwd AND the context-walk start), so they can never diverge if
26
- // a caller passes a relative agentDir.
27
- const cwd = options.cwd ?? agentDir;
28
- const e = options.env ?? new NodeExecutionEnv({ cwd });
29
- const rootResult = await e.absolutePath(agentDir, BACKGROUND_CONTEXT);
30
- if (!rootResult.ok) {
31
- throw new Error(`cannot resolve agent dir "${agentDir}": ${rootResult.error.message}`);
32
- }
33
- const root = rootResult.value;
34
- await refuseRetiredPersona(e, root);
35
- // Project context, following pi: the agentDir's own AGENTS.md + every AGENTS.md walking cwd up to root
36
- // (loadProjectContextFiles).
37
- const contextFiles = loadProjectContextFiles({ cwd, agentDir: root });
38
- const shadowed = [];
39
- const ignored = [];
40
- const systemPrompt = await readFirstFile(e, root, SYSTEM_PROMPT_FILES, "system prompt", shadowed, ignored);
41
- const appendSystemPrompt = await readFirstFile(e, root, APPEND_SYSTEM_PROMPT_FILES, "appended prompt", shadowed, ignored);
42
- const { skills, diagnostics: skillDiagnostics, collisions } = await readSkills(e, root);
43
- const { prompts, diagnostics: promptDiagnostics } = await readPrompts(e, root, shadowed);
44
- ignored.push(...(await ignoredPaths(e, root)));
45
- return {
46
- contextFiles,
47
- ...(systemPrompt ? { systemPrompt } : {}),
48
- ...(appendSystemPrompt ? { appendSystemPrompt } : {}),
49
- skills,
50
- prompts,
51
- diagnostics: [...skillDiagnostics, ...promptDiagnostics],
52
- collisions,
53
- shadowed,
54
- ignored,
55
- dir: root,
56
- };
57
- }
58
- async function exists(e, path) {
59
- const info = await e.fileInfo(path, BACKGROUND_CONTEXT);
60
- if (info.ok)
61
- return true;
62
- if (info.error.code === "not_found")
63
- return false;
64
- throw new Error(`cannot read ${path}: ${info.error.message}`);
65
- }
66
- async function refuseRetiredPersona(e, root) {
67
- const path = join(root, RETIRED_PERSONA);
68
- if (!(await exists(e, path)))
69
- return;
70
- throw new Error(`${path} is no longer read. Move its text to SYSTEM.md to replace pi's default prompt with an identity of the ` +
71
- `agent's own, or to APPEND_SYSTEM.md to add standing instructions to pi's default prompt, which already says ` +
72
- `who the agent is (pi's coding assistant) — an identity written there gives the model two`);
73
- }
74
- /**
75
- * The first of `names` that exists, read; every later one that also exists is shadowed by it. A blank file counts as
76
- * absent and is reported: pi treats an empty prompt as none, so it would change nothing while looking like a prompt
77
- * of the agent's own.
78
- */
79
- async function readFirstFile(e, root, names, what, shadowed, ignored) {
80
- let found;
81
- for (const name of names) {
82
- const path = join(root, name);
83
- const read = await e.readTextFile(path, BACKGROUND_CONTEXT);
84
- if (!read.ok) {
85
- if (read.error.code === "not_found")
86
- continue;
87
- throw new Error(`cannot read ${path}: ${read.error.message}`);
88
- }
89
- if (read.value.trim() === "") {
90
- ignored.push({ path, reason: `empty, so it is not used as the ${what}` });
91
- continue;
92
- }
93
- if (found)
94
- shadowed.push({ what, winnerPath: found.path, loserPath: path });
95
- else
96
- found = { path, content: read.value };
97
- }
98
- return found;
99
- }
100
- /** `.pi/extensions/` is pi's place for project extensions; a definition's are `extensions/`, and only those load. */
101
- async function ignoredPaths(e, root) {
102
- const path = join(root, ".pi", "extensions");
103
- return (await exists(e, path)) ? [{ path, reason: "not loaded: a definition's extensions live in extensions/" }] : [];
104
- }
105
- /** Extension entry-point FILES under `<agentDir>/extensions/`, empty when there are none. */
106
- export async function loadExtensionPaths(agentDir, options = {}) {
107
- const cwd = options.cwd ?? agentDir;
108
- const e = options.env ?? new NodeExecutionEnv({ cwd });
109
- const rootResult = await e.absolutePath(agentDir, BACKGROUND_CONTEXT);
110
- if (!rootResult.ok)
111
- throw new Error(`cannot resolve agent dir "${agentDir}": ${rootResult.error.message}`);
112
- const root = rootResult.value;
113
- await assertInsideAgentDir(root, "extensions");
114
- const dir = join(root, "extensions");
115
- const listed = await e.listDir(dir, BACKGROUND_CONTEXT);
116
- if (!listed.ok) {
117
- if (listed.error.code === "not_found")
118
- return [];
119
- throw new Error(`cannot read ${dir}: ${listed.error.message}`);
120
- }
121
- const paths = [];
122
- for (const entry of listed.value) {
123
- if (entry.kind === "symlink") {
124
- // EVERY symlink here is announced, without guessing whether it meant to be an extension.
125
- warnSymlinkRefused(entry.path);
126
- continue;
127
- }
128
- if (entry.name.endsWith(".ts") || entry.name.endsWith(".js")) {
129
- if (entry.kind === "file")
130
- paths.push(entry.path);
131
- continue;
132
- }
133
- if (entry.kind === "file")
134
- continue; // a README, a .json — not an extension, not a problem
135
- const index = await firstRealFile(e, [join(entry.path, "index.ts"), join(entry.path, "index.js")]);
136
- if (index.path) {
137
- paths.push(index.path);
138
- }
139
- else if (!index.refused) {
140
- // Silent when the index WAS found and refused for being a symlink.
141
- log.warn(`[fastagent] ${entry.path} is not a loadable extension: expected index.ts or index.js ` +
142
- `(pi's package.json "pi" manifest form is not supported here) — it will not be loaded`);
143
- }
144
- }
145
- return paths.sort();
146
- }
147
- /** The first candidate that is a REAL file, and whether one was found but REFUSED as a symlink. */
148
- async function firstRealFile(e, candidates) {
149
- let refused = false;
150
- for (const candidate of candidates) {
151
- const info = await e.fileInfo(candidate, BACKGROUND_CONTEXT);
152
- if (!info.ok) {
153
- if (info.error.code === "not_found")
154
- continue;
155
- throw new Error(`cannot read ${candidate}: ${info.error.message}`);
156
- }
157
- if (info.value.kind === "file")
158
- return { path: candidate, refused };
159
- if (info.value.kind === "symlink") {
160
- warnSymlinkRefused(candidate);
161
- refused = true;
162
- }
163
- }
164
- return { refused };
165
- }
166
- function warnSymlinkRefused(path) {
167
- log.warn(`[fastagent] ${path} is a symlink and will not be loaded: an extension must be a real file inside ` +
168
- `the definition so it travels with the artifact — move it in. (If it is not an extension, ` +
169
- `keep it outside extensions/ to silence this.)`);
170
- }
171
- /** The skills half of {@link loadAgentDefinition}. */
172
- async function readSkills(e, root) {
173
- // The definition's OWN skills — its half of the answer, from every place it may keep one, the root spelling first.
174
- // The machine's half is machine.ts's, and `withMachine` decides a name collision in this half's favour.
175
- for (const dir of SKILL_DIRS)
176
- await assertInsideAgentDir(root, dir);
177
- const { skills: raw, diagnostics } = await loadSkills(e, SKILL_DIRS.map((dir) => join(root, dir)), BACKGROUND_CONTEXT);
178
- const byName = new Map();
179
- const collisions = [];
180
- for (const skill of raw) {
181
- // pi only warns about a `/` in a skill name, and loads it. The slash names the context a skill comes from, so a
182
- // definition's own skill spelled that way could collide with a context's and is refused here.
183
- if (skill.name.includes("/")) {
184
- throw new Error(`skill "${skill.name}" (${skill.filePath}): a skill's name may not contain "/", which names the context a ` +
185
- `skill comes from — rename it`);
186
- }
187
- const existing = byName.get(skill.name);
188
- if (existing) {
189
- collisions.push({ name: skill.name, winnerPath: existing.filePath, loserPath: skill.filePath });
190
- }
191
- else {
192
- byName.set(skill.name, skill);
193
- }
194
- }
195
- return { skills: [...byName.values()], diagnostics, collisions };
196
- }
197
- /** The prompt-template half: `prompts/`, then `.pi/prompts/`, first wins. */
198
- async function readPrompts(e, root, shadowed) {
199
- const byName = new Map();
200
- const diagnostics = [];
201
- for (const dir of PROMPT_DIRS) {
202
- await assertInsideAgentDir(root, dir);
203
- const loaded = await loadPromptTemplates(e, join(root, dir), BACKGROUND_CONTEXT);
204
- diagnostics.push(...loaded.diagnostics);
205
- for (const template of loaded.promptTemplates) {
206
- // pi's loader names a template after its file and reads direct children only, so this is its file.
207
- const filePath = join(root, dir, `${template.name}.md`);
208
- const existing = byName.get(template.name);
209
- if (existing) {
210
- shadowed.push({
211
- what: `prompt template "${template.name}"`,
212
- winnerPath: existing.filePath,
213
- loserPath: filePath,
214
- });
215
- continue;
216
- }
217
- byName.set(template.name, {
218
- name: template.name,
219
- ...(template.description ? { description: template.description } : {}),
220
- content: template.content,
221
- filePath,
222
- });
223
- }
224
- }
225
- return { prompts: [...byName.values()], diagnostics };
226
- }
227
- /** Resolve to a canonical (symlink-free) absolute path so comparisons match `process.cwd()`'s realpath. */
228
- export function canonicalPath(p) {
229
- const resolved = resolve(p);
230
- try {
231
- return realpathSync(resolved);
232
- }
233
- catch {
234
- return resolved;
235
- }
236
- }
@@ -1,14 +0,0 @@
1
- import type { SessionManager } from "@earendil-works/pi-coding-agent";
2
- import type { ImageRef } from "../../agent.ts";
3
- import type { EntryImage } from "../../session.ts";
4
- type Message = {
5
- role: string;
6
- content?: unknown;
7
- };
8
- /** `data.images` of the entry `entryId` holding `message`, absent when it has none. */
9
- export declare function entryImages(entryId: string, message: Message): {
10
- images?: EntryImage[];
11
- };
12
- /** The image `ref` names in `record`, or undefined when it names none there. The inverse of `entryImages`. */
13
- export declare function imageAt(record: SessionManager, ref: string): ImageRef | undefined;
14
- export {};