@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,32 +0,0 @@
1
- /**
2
- * THE GATE: refuse to run while a declaration for what is ABOUT TO RUN has no value.
3
- *
4
- * `declared-secrets.ts` answers "which env vars did this code declare, and which have no value" —
5
- * a predicate. This module owns the three decisions that turn that predicate into a refusal, for all five call
6
- * sites (the agent opener, the scheduler start, channel loading, `fastagent tool`, `fastagent routine run`):
7
- *
8
- * 1. WHICH declarations gate this run. A serve mounts every tool, schedule and channel, so all of
9
- * them gate it; `fastagent tool <name>` / `fire <name>` run exactly one owner, and requiring the
10
- * credentials of the ones they are not running blocks a machine that is configured correctly for
11
- * the job at hand. That is why declarations travel keyed BY OWNER.
12
- * 2. ORDER against load failures. The refusal throws, and a caller that prints `failures` after it
13
- * gets a value back would lose them: a broken `tools/x.ts` beside an unset declaration would
14
- * stay invisible until the author fixed the environment and ran again. So the gate reports them
15
- * itself, on the refusal path, before throwing. A caller that also reports on its own success
16
- * path is correct; one that reports before gating merely repeats a line, which is cosmetic —
17
- * the signal cannot be lost either way.
18
- * 3. The failure SHAPE. This throws a plain `Error` (a user-fixable startup problem). CLI commands
19
- * whose call is synchronous route it through the process boundary with `gateSecretsOrExit`
20
- * (cli/fail.ts) so the author sees the one line naming the file, never a Node stack.
21
- */
22
- import { type DeclaredSecret } from "./declared-secrets.ts";
23
- import { type ModuleLoadFailure } from "./loader.ts";
24
- export declare function gateSecrets(input: {
25
- /** Owner (tool / schedule / channel name) → what it declared, as the loaders return it. */
26
- declared: ReadonlyMap<string, readonly DeclaredSecret[]>;
27
- /** What could not be loaded from the same directory — reported before any refusal (decision 2). */
28
- failures: readonly ModuleLoadFailure[];
29
- /** The ONE owner about to run; omitted means every one of them is about to run. */
30
- owner?: string;
31
- env?: NodeJS.ProcessEnv;
32
- }): void;
@@ -1,33 +0,0 @@
1
- /**
2
- * THE GATE: refuse to run while a declaration for what is ABOUT TO RUN has no value.
3
- *
4
- * `declared-secrets.ts` answers "which env vars did this code declare, and which have no value" —
5
- * a predicate. This module owns the three decisions that turn that predicate into a refusal, for all five call
6
- * sites (the agent opener, the scheduler start, channel loading, `fastagent tool`, `fastagent routine run`):
7
- *
8
- * 1. WHICH declarations gate this run. A serve mounts every tool, schedule and channel, so all of
9
- * them gate it; `fastagent tool <name>` / `fire <name>` run exactly one owner, and requiring the
10
- * credentials of the ones they are not running blocks a machine that is configured correctly for
11
- * the job at hand. That is why declarations travel keyed BY OWNER.
12
- * 2. ORDER against load failures. The refusal throws, and a caller that prints `failures` after it
13
- * gets a value back would lose them: a broken `tools/x.ts` beside an unset declaration would
14
- * stay invisible until the author fixed the environment and ran again. So the gate reports them
15
- * itself, on the refusal path, before throwing. A caller that also reports on its own success
16
- * path is correct; one that reports before gating merely repeats a line, which is cosmetic —
17
- * the signal cannot be lost either way.
18
- * 3. The failure SHAPE. This throws a plain `Error` (a user-fixable startup problem). CLI commands
19
- * whose call is synchronous route it through the process boundary with `gateSecretsOrExit`
20
- * (cli/fail.ts) so the author sees the one line naming the file, never a Node stack.
21
- */
22
- import { allSecrets, describeSecrets, missingSecrets } from "./declared-secrets.js";
23
- import { reportModuleLoadFailures } from "./loader.js";
24
- export function gateSecrets(input) {
25
- const scope = input.owner === undefined ? allSecrets(input.declared) : (input.declared.get(input.owner) ?? []);
26
- const missing = missingSecrets(scope, input.env);
27
- if (missing.length === 0)
28
- return;
29
- reportModuleLoadFailures(input.failures);
30
- throw new Error(`missing required secrets: ${describeSecrets(missing)} — set them in .secrets/.env (or the ` +
31
- `environment). Deployed, they travel as deploy secrets; a tool that should run WITHOUT the ` +
32
- `value must not declare it.`);
33
- }
@@ -1,47 +0,0 @@
1
- /** The remote `SessionControl` — the client half of the HTTP + SSE transport (docs/design/session-control.md §13). */
2
- import type { Agent } from "./agent.ts";
3
- import { type SessionControl } from "./session.ts";
4
- /** A control request the server answered with a non-2xx status. */
5
- export declare class ControlRequestError extends Error {
6
- readonly status: number;
7
- /**
8
- * The plane's own error code, when the reply carried one (`sessions()` is the only read that does today — design
9
- * §13).
10
- */
11
- readonly code?: string;
12
- /**
13
- * Whether re-sending is worth it, as the plane itself answered — the same question `SessionResult.retryable`
14
- * answers for a write, carried here because a throwing read has no result to put it in. Absent when the reply
15
- * declared no opinion; a caller then has only the status.
16
- */
17
- readonly retryable?: boolean;
18
- constructor(status: number, body: string, declared?: {
19
- code?: string;
20
- retryable?: boolean;
21
- });
22
- }
23
- /**
24
- * Connection parameters shared by BOTH remote planes (`connectSessionControl` and `connectAgent`) — plane-neutral on
25
- * purpose: one endpoint, two contracts.
26
- */
27
- export interface RemoteEndpointOptions {
28
- /**
29
- * Base URL of the serving process (e.g. `http://127.0.0.1:8787`). fastagent serves it unauthenticated — point this
30
- * at whatever fronts it (a gateway, an SSH tunnel, a private network address), not at a public port.
31
- */
32
- url: string;
33
- /**
34
- * The transport seam. fastagent authenticates nothing, so whatever fronts the serve is what a caller has to
35
- * satisfy: wrap `fetch` here to add a gateway credential, refresh it, sign the request, or pin a client
36
- * certificate — a static header cannot express the refresh an IdP proxy needs. Tests inject a fake through the
37
- * same seam.
38
- */
39
- fetchFn?: typeof fetch;
40
- }
41
- export declare function connectSessionControl(options: RemoteEndpointOptions): Promise<SessionControl>;
42
- /**
43
- * The remote DATA plane: an `Agent` whose `invoke` drives `POST /invoke` on a serving process. A real Agent,
44
- * failure discipline included — SPEC MUST 2 forbids iteration throws, so transport, protocol and precheck failures
45
- * all become `failed` events.
46
- */
47
- export declare function connectAgent(options: RemoteEndpointOptions): Agent;
@@ -1,460 +0,0 @@
1
- import { SSE_HEARTBEAT_MS } from "./channels/sse.js";
2
- import { abortFirstIterator } from "./collect.js";
3
- import { isAddressableSession, } from "./session.js";
4
- /**
5
- * Dead-connection watchdog for SSE reads: the server heartbeats every SSE_HEARTBEAT_MS, so a PENDING READ seeing no
6
- * bytes (of ANY kind — comments included) for this many missed beats means the connection is a black hole.
7
- */
8
- const SSE_IDLE_LIMIT_MS = 3 * SSE_HEARTBEAT_MS;
9
- /**
10
- * Every request carries a TIMEOUT: a client's reliability model counts failed rounds against a budget ("unreachable
11
- * for ~Ns"), which a black-hole endpoint (firewall drop, half-dead tunnel) would silently defeat — a hung
12
- * state()/entries(), or a stream that never finishes connecting, ticks nothing.
13
- */
14
- const REQUEST_TIMEOUT_MS = 10_000;
15
- /** The PAYLOAD-bearing calls get a longer budget than the black-hole detector's 10s. */
16
- const PAYLOAD_TIMEOUT_MS = 60_000;
17
- class StreamEnded extends Error {
18
- kind;
19
- constructor(kind, message) {
20
- super(message);
21
- this.name = "StreamEnded";
22
- this.kind = kind;
23
- }
24
- }
25
- /** The reason this connection was ended, when one was given — `undefined` for any other failure. */
26
- function endedBecause(signal) {
27
- return signal.reason instanceof StreamEnded ? signal.reason : undefined;
28
- }
29
- function readBudget(abort, what, connectMs) {
30
- let timer;
31
- let connected = false;
32
- const expire = () => abort.abort(connected
33
- ? new StreamEnded("idle", `${what}: no bytes for ${SSE_IDLE_LIMIT_MS / 1000}s (heartbeats absent) — dead connection`)
34
- : new StreamEnded("connect-timeout", `${what}: no usable response in ${connectMs / 1000}s — the endpoint accepted the connection and never completed one`));
35
- const disarm = () => {
36
- clearTimeout(timer);
37
- timer = undefined;
38
- };
39
- return {
40
- // `??=`: a nested arm does not restart the clock, so one long read cannot be extended by re-arming inside it.
41
- arm: () => {
42
- timer ??= setTimeout(expire, connected ? SSE_IDLE_LIMIT_MS : connectMs);
43
- },
44
- disarm,
45
- connected: () => {
46
- disarm();
47
- connected = true;
48
- },
49
- };
50
- }
51
- /**
52
- * Open a streaming response — the one connect sequence both wire planes perform, under one budget: the headers, the
53
- * error body of a non-2xx (a half-dead tunnel answering 4xx and then black-holing the body is the case that makes
54
- * this one phase rather than two), and the check that a body exists at all. It returns only once the connection is
55
- * something that can carry events, which is the moment the budget switches to the idle limit.
56
- */
57
- async function openStreamBody(options) {
58
- const { fetchFn, url, init, abort, budget, what } = options;
59
- budget.arm(); // the connect await is a pending read
60
- const res = await fetchFn(url, { ...init, signal: abort.signal });
61
- if (!res.ok)
62
- throw new ControlRequestError(res.status, await res.text());
63
- if (!res.body)
64
- throw new Error(`${what}: response has no body`);
65
- budget.connected();
66
- return res.body;
67
- }
68
- /** A control request the server answered with a non-2xx status. */
69
- export class ControlRequestError extends Error {
70
- status;
71
- /**
72
- * The plane's own error code, when the reply carried one (`sessions()` is the only read that does today — design
73
- * §13).
74
- */
75
- code;
76
- /**
77
- * Whether re-sending is worth it, as the plane itself answered — the same question `SessionResult.retryable`
78
- * answers for a write, carried here because a throwing read has no result to put it in. Absent when the reply
79
- * declared no opinion; a caller then has only the status.
80
- */
81
- retryable;
82
- constructor(status, body, declared) {
83
- super(`control request failed: ${status} ${body}`);
84
- this.status = status;
85
- if (declared?.code !== undefined)
86
- this.code = declared.code;
87
- if (declared?.retryable !== undefined)
88
- this.retryable = declared.retryable;
89
- }
90
- }
91
- /** A non-2xx reply as an error, carrying what the plane declared about it. */
92
- async function controlError(res) {
93
- const body = await res.text();
94
- if (!res.headers.get("content-type")?.includes("application/json"))
95
- return new ControlRequestError(res.status, body);
96
- let parsed;
97
- try {
98
- parsed = JSON.parse(body);
99
- }
100
- catch {
101
- // The reply declared JSON and is not — a protocol fault worth seeing, but not worth losing the status over.
102
- return new ControlRequestError(res.status, `${body} (declared application/json but did not parse)`);
103
- }
104
- return new ControlRequestError(res.status, body, {
105
- ...(typeof parsed?.code === "string" ? { code: parsed.code } : {}),
106
- ...(typeof parsed?.retryable === "boolean" ? { retryable: parsed.retryable } : {}),
107
- });
108
- }
109
- export async function connectSessionControl(options) {
110
- const { url, fetchFn = fetch } = options;
111
- const base = url.replace(/\/$/, "");
112
- const get = async (path, timeoutMs = REQUEST_TIMEOUT_MS) => {
113
- const res = await fetchFn(`${base}${path}`, { signal: AbortSignal.timeout(timeoutMs) });
114
- if (!res.ok)
115
- throw await controlError(res);
116
- return (await res.json());
117
- };
118
- const capabilities = await get("/control/capabilities");
119
- const eventsOf = (session) => {
120
- // The server subscribes BEFORE it writes the response headers (channels/sse.ts pulls the source once first), so
121
- // "headers arrived, 2xx" IS "this session's subscription exists" — the boundary a reconnecting client awaits
122
- // before reading history (session.ts, SessionEventStream).
123
- let subscribed;
124
- let unreachable;
125
- const ready = new Promise((resolve, reject) => {
126
- subscribed = resolve;
127
- unreachable = reject;
128
- });
129
- // A consumer that never awaits `ready` (it can iterate and let the stream report the same failure) would
130
- // otherwise take an unhandled rejection for a connection that legitimately failed. Awaiters still get it.
131
- ready.catch(() => { });
132
- // ONE CALL IS ONE SUBSCRIPTION — one connection, one readiness. A second iteration would open a second
133
- // connection and inherit this `ready`, reporting a boundary the first one crossed; it is refused instead, the
134
- // same way the local hub refuses it.
135
- const openStream = (abort) => (async function* iterate() {
136
- const budget = readBudget(abort, "control events", REQUEST_TIMEOUT_MS);
137
- try {
138
- let body;
139
- try {
140
- body = await openStreamBody({
141
- fetchFn,
142
- url: `${base}/control/sessions/${encodeURIComponent(session)}/events`,
143
- init: {},
144
- abort,
145
- budget,
146
- what: "control events",
147
- });
148
- }
149
- catch (error) {
150
- // The subscription was never established: the endpoint is unreachable or never completed a response, a
151
- // gateway in front refused it, the consumer cancelled first. Whoever ended it said why, and `fetch` rejected with
152
- // that very object. A waiter on `ready` must learn it instead of waiting out a stream that will never
153
- // carry anything — including the cancellation, which the ITERATION reports as a clean end (walking away
154
- // is not an error) while `ready` still has a promise it cannot keep.
155
- const failure = endedBecause(abort.signal) ?? error;
156
- unreachable(failure);
157
- throw failure;
158
- }
159
- subscribed();
160
- let nextSeq = 0;
161
- for await (const data of sseData(body, budget)) {
162
- // Parse discipline, same as the other two wire planes (dispatch parses, invoke classifies drift): a
163
- // non-JSON or non-envelope payload is PROTOCOL MISMATCH.
164
- let wire;
165
- try {
166
- // The ONE envelope type (control.ts's WireEvent) — an inline shape would let the envelope drift
167
- // server-side while this cast silently kept the old fields.
168
- wire = JSON.parse(data);
169
- }
170
- catch (parseError) {
171
- throw new Error(`control events: non-JSON data on the stream (${String(parseError)}) — protocol mismatch?`);
172
- }
173
- if (typeof wire !== "object" ||
174
- wire === null ||
175
- typeof wire.seq !== "number" ||
176
- typeof wire.event !== "object" ||
177
- wire.event === null ||
178
- typeof wire.event.type !== "string") {
179
- throw new Error("control events: malformed envelope — the endpoint does not speak this protocol version");
180
- }
181
- // Envelope checks — consumed HERE.
182
- if (wire.seq !== nextSeq) {
183
- throw new Error(`control events: sequence gap (expected ${nextSeq}, got ${wire.seq}) — events were lost in transit; resync via entries()`);
184
- }
185
- nextSeq = wire.seq + 1;
186
- yield wire.event;
187
- }
188
- }
189
- catch (error) {
190
- const ended = endedBecause(abort.signal);
191
- if (ended?.kind === "cancelled")
192
- return; // the consumer walked away — clean end, not an error
193
- throw ended ?? error;
194
- }
195
- finally {
196
- budget.disarm();
197
- abort.abort();
198
- }
199
- })();
200
- let iterated = false;
201
- return {
202
- ready,
203
- [Symbol.asyncIterator]() {
204
- if (iterated) {
205
- throw new Error("control events: this stream is one subscription — call events() again for another");
206
- }
207
- iterated = true;
208
- const abort = new AbortController();
209
- // Abort-first cancellation (see abortFirstIterator): aborting the connection unblocks a generator suspended
210
- // on a quiet stream read.
211
- return abortFirstIterator(openStream(abort), () => {
212
- const cancelled = new StreamEnded("cancelled", "control events: cancelled by the consumer");
213
- abort.abort(cancelled);
214
- // Said HERE as well as in the generator's catch, because a generator that was never pulled does not run its
215
- // body on `return()` — and then nothing else would ever settle `ready`. Rejecting an already-settled
216
- // promise is a no-op, so the connected case still reports whatever ended it.
217
- unreachable(cancelled);
218
- });
219
- },
220
- };
221
- };
222
- /**
223
- * A write that answers a `SessionResult`: the result rides HTTP 200 either way (`ok: false` is a protocol answer,
224
- * not a transport failure), so a non-2xx here is a REAL transport fault.
225
- */
226
- const write = async (path, method, body) => {
227
- // Always declared, body or not: the plane refuses a write it was not told is JSON (channels/body.ts), and an
228
- // empty `PATCH` is a legal no-op that still has to get through.
229
- const res = await fetchFn(`${base}${path}`, {
230
- method,
231
- headers: { "content-type": "application/json" },
232
- ...(body === undefined ? {} : { body: JSON.stringify(body) }),
233
- signal: AbortSignal.timeout(PAYLOAD_TIMEOUT_MS),
234
- });
235
- if (!res.ok)
236
- throw await controlError(res);
237
- return (await res.json());
238
- };
239
- const id = (session) => encodeURIComponent(session);
240
- return {
241
- capabilities: () => capabilities,
242
- // NOT prefetched like capabilities: a live definition can grow a skill between calls, so the list is fetched per
243
- // call.
244
- async commands() {
245
- try {
246
- return await get("/control/commands");
247
- }
248
- catch (error) {
249
- if (error instanceof ControlRequestError && error.status === 404) {
250
- throw new ControlRequestError(404, "this serve does not implement /control/commands (it predates the route)");
251
- }
252
- throw error;
253
- }
254
- },
255
- sessions: {
256
- // Rejects when the deployment cannot enumerate its store.
257
- list: () => get("/control/sessions", PAYLOAD_TIMEOUT_MS),
258
- // PUT: the fork is idempotent, and so is the request that carries it.
259
- fork: async ({ from, at, into }) => {
260
- if (!isAddressableSession(into)) {
261
- throw new Error(`session id ${JSON.stringify(into)} cannot travel as a URL path segment — this transport cannot address it`);
262
- }
263
- return write(`/control/sessions/${id(into)}`, "PUT", { from, at });
264
- },
265
- // The local hub's handle is a pure binding; so is this one — an id and the transport above it.
266
- get: (session) => {
267
- if (!isAddressableSession(session)) {
268
- throw new Error(`session id ${JSON.stringify(session)} cannot travel as a URL path segment — this transport cannot address it`);
269
- }
270
- return {
271
- id: session,
272
- state: () => get(`/control/sessions/${id(session)}`),
273
- entries: (options) => get(`/control/sessions/${id(session)}/entries${options?.since !== undefined ? `?since=${encodeURIComponent(options.since)}` : ""}`, PAYLOAD_TIMEOUT_MS),
274
- image: async (ref) => {
275
- const res = await fetchFn(`${base}/control/sessions/${id(session)}/image?ref=${encodeURIComponent(ref)}`, {
276
- signal: AbortSignal.timeout(PAYLOAD_TIMEOUT_MS),
277
- });
278
- if (!res.ok)
279
- throw await controlError(res);
280
- if (res.status === 204)
281
- return undefined;
282
- return {
283
- data: toBase64(new Uint8Array(await res.arrayBuffer())),
284
- mimeType: res.headers.get("content-type") ?? "application/octet-stream",
285
- };
286
- },
287
- events: () => eventsOf(session),
288
- update: (patch) => write(`/control/sessions/${id(session)}`, "PATCH", patch),
289
- steer: (prompt) => write(`/control/sessions/${id(session)}/actions`, "POST", { type: "steer", prompt }),
290
- followUp: (prompt) => write(`/control/sessions/${id(session)}/actions`, "POST", { type: "follow_up", prompt }),
291
- abort: () => write(`/control/sessions/${id(session)}/actions`, "POST", { type: "abort" }),
292
- compact: (options) => write(`/control/sessions/${id(session)}/actions`, "POST", {
293
- type: "compact",
294
- ...(options?.instructions !== undefined ? { instructions: options.instructions } : {}),
295
- }),
296
- delete: () => write(`/control/sessions/${id(session)}`, "DELETE"),
297
- };
298
- },
299
- },
300
- };
301
- }
302
- /**
303
- * The remote DATA plane: an `Agent` whose `invoke` drives `POST /invoke` on a serving process. A real Agent,
304
- * failure discipline included — SPEC MUST 2 forbids iteration throws, so transport, protocol and precheck failures
305
- * all become `failed` events.
306
- */
307
- export function connectAgent(options) {
308
- const { url, fetchFn = fetch } = options;
309
- const base = url.replace(/\/$/, "");
310
- const toFailed = (error) => {
311
- if (error instanceof ControlRequestError) {
312
- return { type: "failed", details: error.message, retryable: error.status === 429 || error.status >= 500 };
313
- }
314
- return { type: "failed", details: String(error), retryable: true }; // network-class: worth re-sending
315
- };
316
- // COMPILE-TIME drift guard (dispatch-wire parity): the invoke body carries exactly text (and rejects images
317
- // visibly).
318
- const _invokeDriftGuard = {};
319
- void _invokeDriftGuard;
320
- // Same guard for Scope: the body carries session + the lineage extension — a new Scope field must force a decision
321
- // (carry it or reject it), never vanish on the wire.
322
- const _scopeDriftGuard = {};
323
- void _scopeDriftGuard;
324
- return {
325
- invoke(scope, prompt) {
326
- const abort = new AbortController();
327
- const openStream = () => (async function* iterate() {
328
- if (prompt.images && prompt.images.length > 0) {
329
- yield {
330
- type: "failed",
331
- details: "remote invoke does not carry images yet — send text, or invoke in-process",
332
- retryable: false,
333
- };
334
- return;
335
- }
336
- // A terminal closes the stream. Cleanup errors must not append a second terminal.
337
- let terminalSeen = false;
338
- // The run's driver rides the same mechanism as the events plane, with the connect limit its own callers
339
- // need: a black-holed POST must not hang it, but a scale-to-zero host (fly `auto_start_machines`, a cold
340
- // AgentCore container) can legitimately hold this open for tens of seconds before the first header, and
341
- // that is a slow success, not a dead endpoint. A connect failure lands in the catch below, which is where
342
- // every non-terminal failure becomes the one `failed` event this stream owes its caller.
343
- const budget = readBudget(abort, "remote invoke", PAYLOAD_TIMEOUT_MS);
344
- try {
345
- const body = await openStreamBody({
346
- fetchFn,
347
- url: `${base}/invoke`,
348
- init: {
349
- method: "POST",
350
- headers: { "content-type": "application/json" },
351
- body: JSON.stringify({
352
- session: scope.session,
353
- text: prompt.text,
354
- // Lineage rides the wire so a remote thread scope inherits server-side; the server reads it on the
355
- // session-create path only, same as in-process.
356
- ...(scope.parentSession !== undefined ? { parentSession: scope.parentSession } : {}),
357
- ...(scope.branchHints !== undefined ? { branchHints: scope.branchHints } : {}),
358
- }),
359
- },
360
- abort,
361
- budget,
362
- what: "remote invoke",
363
- });
364
- for await (const data of sseData(body, budget)) {
365
- let event;
366
- try {
367
- event = JSON.parse(data);
368
- }
369
- catch (parseError) {
370
- yield {
371
- type: "failed",
372
- details: `remote invoke: unparseable event on the stream (${String(parseError)})`,
373
- retryable: false,
374
- };
375
- return;
376
- }
377
- // Shape check, same discipline as the events plane: `data: null` / `data: 42` is valid JSON but
378
- // protocol drift.
379
- if (typeof event !== "object" || event === null || typeof event.type !== "string") {
380
- yield {
381
- type: "failed",
382
- details: "remote invoke: non-event data on the stream — protocol mismatch?",
383
- retryable: false,
384
- };
385
- return;
386
- }
387
- terminalSeen = event.type === "completed" || event.type === "failed";
388
- yield event;
389
- if (terminalSeen)
390
- return;
391
- }
392
- yield { type: "failed", details: "remote invoke: stream ended without a terminal", retryable: true };
393
- }
394
- catch (error) {
395
- const ended = endedBecause(abort.signal);
396
- // Cancellation is the consumer's own doing — reporting it back would be news to nobody. Any other stated
397
- // reason is a connection that died under the run, and this stream still owes its caller a terminal —
398
- // unless one was already sent, since a second would describe the run rather than the connection.
399
- if (ended?.kind === "cancelled")
400
- return;
401
- if (!terminalSeen)
402
- yield ended ? { type: "failed", details: ended.message, retryable: true } : toFailed(error);
403
- }
404
- finally {
405
- budget.disarm();
406
- abort.abort();
407
- }
408
- })();
409
- // ONE stream per invoke, like a local async generator (which is its own iterator): a second iteration must
410
- // never re-POST.
411
- const iterator = abortFirstIterator(openStream(), () => abort.abort(new StreamEnded("cancelled", "remote invoke: cancelled by the consumer")));
412
- return {
413
- [Symbol.asyncIterator]() {
414
- return iterator;
415
- },
416
- };
417
- },
418
- };
419
- }
420
- /** Base64 without `Buffer` (this module runs in any Fetch runtime), in chunks: spreading megabytes of bytes into one
421
- * `String.fromCharCode` call overflows the argument limit. */
422
- function toBase64(bytes) {
423
- let binary = "";
424
- for (let i = 0; i < bytes.length; i += 0x8000)
425
- binary += String.fromCharCode(...bytes.subarray(i, i + 0x8000));
426
- return btoa(binary);
427
- }
428
- /** Minimal SSE reader: yields each `data:` payload; ignores comments (heartbeats) and other fields. */
429
- async function* sseData(body, watch) {
430
- const decoder = new TextDecoder();
431
- let buffer = "";
432
- const reader = body.getReader();
433
- try {
434
- for (;;) {
435
- watch?.arm(); // a read is pending — the idle clock may run
436
- const { done, value } = await reader.read();
437
- watch?.disarm(); // bytes (ANY bytes — heartbeats included) or a clean end arrived
438
- if (done)
439
- return;
440
- // SSE permits CRLF line endings (proxies/other servers may produce them).
441
- buffer = (buffer + decoder.decode(value, { stream: true })).replace(/\r\n/g, "\n");
442
- let sep = buffer.indexOf("\n\n");
443
- while (sep !== -1) {
444
- const block = buffer.slice(0, sep);
445
- buffer = buffer.slice(sep + 2);
446
- const data = block
447
- .split("\n")
448
- .filter((line) => line.startsWith("data:"))
449
- .map((line) => line.slice(5).trimStart())
450
- .join("\n");
451
- if (data !== "")
452
- yield data;
453
- sep = buffer.indexOf("\n\n");
454
- }
455
- }
456
- }
457
- finally {
458
- reader.releaseLock();
459
- }
460
- }