experimental-a2 0.16.1 → 0.18.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 (406) hide show
  1. package/CHANGELOG.md +373 -0
  2. package/README.md +1 -1
  3. package/dist/{actor-ohPC-81x.d.ts → actor-Bjce9_5U.d.ts} +21 -11
  4. package/dist/actor-Bjce9_5U.d.ts.map +1 -0
  5. package/dist/actor-client.d.ts +2 -5
  6. package/dist/actor-client.d.ts.map +1 -1
  7. package/dist/actor-client.js +13 -4
  8. package/dist/actor-client.js.map +1 -1
  9. package/dist/actor-react.d.ts +5 -3
  10. package/dist/actor-react.d.ts.map +1 -1
  11. package/dist/actor-react.js +20 -10
  12. package/dist/actor-react.js.map +1 -1
  13. package/dist/{actor-shared-B5tJfzt-.js → actor-shared-t7w8xIKP.js} +12 -7
  14. package/dist/actor-shared-t7w8xIKP.js.map +1 -0
  15. package/dist/actor.d.ts +1 -1
  16. package/dist/actor.js +42 -23
  17. package/dist/actor.js.map +1 -1
  18. package/dist/{ai-DgOBltJ_.js → ai-BpOGm-zB.js} +621 -216
  19. package/dist/ai-BpOGm-zB.js.map +1 -0
  20. package/dist/{ai-CrEf6p_W.d.ts → ai-DrUaMyRt.d.ts} +114 -100
  21. package/dist/ai-DrUaMyRt.d.ts.map +1 -0
  22. package/dist/ai-client.d.ts +27 -0
  23. package/dist/ai-client.d.ts.map +1 -0
  24. package/dist/ai-client.js +29 -0
  25. package/dist/ai-client.js.map +1 -0
  26. package/dist/ai-fx.browser.d.ts +1 -0
  27. package/dist/ai-fx.browser.js +6 -0
  28. package/dist/ai-fx.browser.js.map +1 -0
  29. package/dist/ai-fx.d.ts +10 -0
  30. package/dist/ai-fx.d.ts.map +1 -0
  31. package/dist/ai-fx.js +634 -0
  32. package/dist/ai-fx.js.map +1 -0
  33. package/dist/ai-harness-BuLh_EYi.js +273 -0
  34. package/dist/ai-harness-BuLh_EYi.js.map +1 -0
  35. package/dist/ai-harness-DvsPeJeB.d.ts +26 -0
  36. package/dist/ai-harness-DvsPeJeB.d.ts.map +1 -0
  37. package/dist/ai-pi.browser.d.ts +1 -0
  38. package/dist/ai-pi.browser.js +6 -0
  39. package/dist/ai-pi.browser.js.map +1 -0
  40. package/dist/ai-pi.d.ts +17 -0
  41. package/dist/ai-pi.d.ts.map +1 -0
  42. package/dist/ai-pi.js +904 -0
  43. package/dist/ai-pi.js.map +1 -0
  44. package/dist/ai-react.d.ts +96 -0
  45. package/dist/ai-react.d.ts.map +1 -0
  46. package/dist/ai-react.js +142 -0
  47. package/dist/ai-react.js.map +1 -0
  48. package/dist/ai-server.browser.js +2 -2
  49. package/dist/ai-server.browser.js.map +1 -1
  50. package/dist/ai-server.d.ts +109 -43
  51. package/dist/ai-server.d.ts.map +1 -1
  52. package/dist/ai-server.js +526 -283
  53. package/dist/ai-server.js.map +1 -1
  54. package/dist/ai.d.ts +2 -2
  55. package/dist/ai.js +2 -2
  56. package/dist/bounded-cache-CPHWF-8h.js +41 -0
  57. package/dist/bounded-cache-CPHWF-8h.js.map +1 -0
  58. package/dist/{client-BYzHjkwU.js → client-BReKqwZC.js} +447 -80
  59. package/dist/client-BReKqwZC.js.map +1 -0
  60. package/dist/{client-CzyacQpJ.d.ts → client-h_DKFAjj.d.ts} +14 -13
  61. package/dist/client-h_DKFAjj.d.ts.map +1 -0
  62. package/dist/client.d.ts +4 -2
  63. package/dist/client.js +1 -1
  64. package/dist/{contract-CKRg_E4q.js → contract-BYKASlCV.js} +12 -21
  65. package/dist/contract-BYKASlCV.js.map +1 -0
  66. package/dist/{idempotent-replay-DVOlyYbx.js → idempotent-replay-JdgMQRRm.js} +2 -2
  67. package/dist/{idempotent-replay-DVOlyYbx.js.map → idempotent-replay-JdgMQRRm.js.map} +1 -1
  68. package/dist/index.d.ts +6 -5
  69. package/dist/index.d.ts.map +1 -1
  70. package/dist/index.js +4 -3
  71. package/dist/{errors-DvhSXnxk.d.ts → initial-snapshot-Bx-c0pDP.d.ts} +7 -3
  72. package/dist/initial-snapshot-Bx-c0pDP.d.ts.map +1 -0
  73. package/dist/{internal-Dq2qYxou.js → internal-B2T3U4Rq.js} +29 -2
  74. package/dist/internal-B2T3U4Rq.js.map +1 -0
  75. package/dist/otel.d.ts +1 -1
  76. package/dist/react-BBXgHWFc.d.ts +86 -0
  77. package/dist/react-BBXgHWFc.d.ts.map +1 -0
  78. package/dist/react.d.ts +2 -122
  79. package/dist/react.js +107 -100
  80. package/dist/react.js.map +1 -1
  81. package/dist/reducer-BAXc8JyF.js +87 -0
  82. package/dist/reducer-BAXc8JyF.js.map +1 -0
  83. package/dist/{reducer-otzHjuJj.d.ts → reducer-CqA59Q6U.d.ts} +46 -30
  84. package/dist/reducer-CqA59Q6U.d.ts.map +1 -0
  85. package/dist/reducer-runtime-DQwz_J59.js +28 -0
  86. package/dist/reducer-runtime-DQwz_J59.js.map +1 -0
  87. package/dist/scheduler-qstash.d.ts +3 -3
  88. package/dist/scheduler-qstash.d.ts.map +1 -1
  89. package/dist/scheduler-qstash.js +33 -10
  90. package/dist/scheduler-qstash.js.map +1 -1
  91. package/dist/{scheduler-task-BpzhPnRS.js → scheduler-task-X1SToDjP.js} +18 -3
  92. package/dist/scheduler-task-X1SToDjP.js.map +1 -0
  93. package/dist/scheduler-vercel.d.ts +4 -9
  94. package/dist/scheduler-vercel.d.ts.map +1 -1
  95. package/dist/scheduler-vercel.js +25 -44
  96. package/dist/scheduler-vercel.js.map +1 -1
  97. package/dist/{server-BD5ckxZb.js → server-Dw_k_7kO.js} +904 -219
  98. package/dist/server-Dw_k_7kO.js.map +1 -0
  99. package/dist/{server-DbD7IJVK.d.ts → server-En7cbi3v.d.ts} +116 -26
  100. package/dist/server-En7cbi3v.d.ts.map +1 -0
  101. package/dist/server.d.ts +4 -4
  102. package/dist/server.js +2 -2
  103. package/dist/session-clear-Bo-XTFEy.d.ts +12 -0
  104. package/dist/session-clear-Bo-XTFEy.d.ts.map +1 -0
  105. package/dist/{errors-DCk6ch5n.js → session-clear-DGI4jTQ5.js} +17 -2
  106. package/dist/session-clear-DGI4jTQ5.js.map +1 -0
  107. package/dist/{store-DyZM6fS5.d.ts → store-Djdv0bnZ.d.ts} +73 -3
  108. package/dist/store-Djdv0bnZ.d.ts.map +1 -0
  109. package/dist/store-N8PXxDAS.js.map +1 -1
  110. package/dist/store-memory.d.ts +1 -1
  111. package/dist/store-memory.d.ts.map +1 -1
  112. package/dist/store-memory.js +205 -66
  113. package/dist/store-memory.js.map +1 -1
  114. package/dist/{store-polling-CmxUbV93.js → store-polling-B5FcwJfo.js} +21 -4
  115. package/dist/store-polling-B5FcwJfo.js.map +1 -0
  116. package/dist/store-postgres.d.ts +1 -1
  117. package/dist/store-postgres.d.ts.map +1 -1
  118. package/dist/store-postgres.js +450 -108
  119. package/dist/store-postgres.js.map +1 -1
  120. package/dist/{store-presence-polling-C7-XZyW9.js → store-presence-polling-BAwS8RWn.js} +3 -3
  121. package/dist/{store-presence-polling-C7-XZyW9.js.map → store-presence-polling-BAwS8RWn.js.map} +1 -1
  122. package/dist/store-redis-http.d.ts +1 -1
  123. package/dist/store-redis-http.d.ts.map +1 -1
  124. package/dist/store-redis-http.js +293 -11
  125. package/dist/store-redis-http.js.map +1 -1
  126. package/dist/store-redis-notify-BRITti_o.js +2493 -0
  127. package/dist/store-redis-notify-BRITti_o.js.map +1 -0
  128. package/dist/store-redis.d.ts +1 -1
  129. package/dist/store-redis.d.ts.map +1 -1
  130. package/dist/store-redis.js +11 -11
  131. package/dist/store-redis.js.map +1 -1
  132. package/dist/store-sqlite.d.ts +1 -1
  133. package/dist/store-sqlite.d.ts.map +1 -1
  134. package/dist/store-sqlite.js +197 -33
  135. package/dist/store-sqlite.js.map +1 -1
  136. package/dist/stream-buffer-Cx7AAPGq.js +23 -0
  137. package/dist/stream-buffer-Cx7AAPGq.js.map +1 -0
  138. package/dist/{telemetry-B5jzpy6y.d.ts → telemetry-Cyfqo6Qt.d.ts} +2 -2
  139. package/dist/telemetry-Cyfqo6Qt.d.ts.map +1 -0
  140. package/dist/{wire-BO5wWCb1.js → wire-rSUglYo8.js} +132 -10
  141. package/dist/wire-rSUglYo8.js.map +1 -0
  142. package/docs/01-quickstart.mdx +50 -84
  143. package/docs/{guides/07-examples.mdx → 02-examples.mdx} +10 -20
  144. package/docs/actors/01-introduction.mdx +48 -82
  145. package/docs/actors/02-concurrency.mdx +43 -70
  146. package/docs/actors/03-timers.mdx +28 -42
  147. package/docs/actors/04-routes.mdx +110 -137
  148. package/docs/actors/meta.ts +1 -1
  149. package/docs/agents/01-introduction.mdx +257 -0
  150. package/docs/agents/02-tools.mdx +247 -0
  151. package/docs/agents/03-conversations.mdx +538 -0
  152. package/docs/agents/04-harnesses.mdx +136 -0
  153. package/docs/agents/meta.ts +1 -0
  154. package/docs/client/01-react.mdx +294 -0
  155. package/docs/client/02-transports.mdx +86 -0
  156. package/docs/client/03-presence.mdx +224 -0
  157. package/docs/client/meta.ts +1 -0
  158. package/docs/contract/01-events.mdx +57 -0
  159. package/docs/contract/02-state.mdx +142 -0
  160. package/docs/contract/03-sessions.mdx +175 -0
  161. package/docs/index.mdx +112 -156
  162. package/docs/reference/01-core.mdx +139 -0
  163. package/docs/reference/02-server.mdx +855 -0
  164. package/docs/reference/03-client.mdx +301 -0
  165. package/docs/reference/04-ai.mdx +722 -0
  166. package/docs/reference/05-adapters.mdx +351 -0
  167. package/docs/reference/06-errors.mdx +138 -0
  168. package/docs/reference/meta.ts +1 -1
  169. package/docs/server/01-handlers.mdx +200 -0
  170. package/docs/server/02-timers.mdx +130 -0
  171. package/docs/server/03-cancellation.mdx +141 -0
  172. package/docs/server/04-routes.mdx +243 -0
  173. package/docs/server/05-production.mdx +322 -0
  174. package/docs/server/06-guarantees.mdx +123 -0
  175. package/examples/playground/DEPLOY.md +53 -7
  176. package/examples/playground/app/a0/[appId]/loading.tsx +16 -0
  177. package/examples/playground/app/a0/[appId]/page.tsx +53 -0
  178. package/examples/playground/app/a0/a0.css +818 -0
  179. package/examples/playground/app/a0/app-list.tsx +218 -0
  180. package/examples/playground/app/a0/app-view.tsx +63 -0
  181. package/examples/playground/app/a0/apps/[appId]/preview/route.ts +27 -0
  182. package/examples/playground/app/a0/apps/[appId]/route.ts +28 -0
  183. package/examples/playground/app/a0/apps.test.ts +128 -0
  184. package/examples/playground/app/a0/apps.ts +102 -0
  185. package/examples/playground/app/a0/chat.tsx +410 -0
  186. package/examples/playground/app/a0/columns.tsx +109 -0
  187. package/examples/playground/app/a0/context-menu.tsx +116 -0
  188. package/examples/playground/app/a0/cookies.ts +46 -0
  189. package/examples/playground/app/a0/crash-on-request.ts +72 -0
  190. package/examples/playground/app/a0/crashes/route.ts +3 -0
  191. package/examples/playground/app/a0/crashes.test.ts +33 -0
  192. package/examples/playground/app/a0/crashes.ts +28 -0
  193. package/examples/playground/app/a0/devtools.tsx +164 -0
  194. package/examples/playground/app/a0/events/route.ts +6 -0
  195. package/examples/playground/app/a0/flags.ts +30 -0
  196. package/examples/playground/app/a0/fx/events/route.ts +9 -0
  197. package/examples/playground/app/a0/fx/scheduler/route.ts +7 -0
  198. package/examples/playground/app/a0/fx/short/events/route.ts +11 -0
  199. package/examples/playground/app/a0/layout.tsx +38 -0
  200. package/examples/playground/app/a0/list/route.ts +10 -0
  201. package/examples/playground/app/a0/model.test.ts +73 -0
  202. package/examples/playground/app/a0/model.ts +95 -0
  203. package/examples/playground/app/a0/no-photon.cjs +4 -0
  204. package/examples/playground/app/a0/no-quickjs.cjs +3 -0
  205. package/examples/playground/app/a0/page.tsx +14 -0
  206. package/examples/playground/app/a0/pi/events/route.ts +9 -0
  207. package/examples/playground/app/a0/pi/scheduler/route.ts +7 -0
  208. package/examples/playground/app/a0/pi/short/events/route.ts +11 -0
  209. package/examples/playground/app/a0/preview-pane.tsx +145 -0
  210. package/examples/playground/app/a0/preview.test.ts +53 -0
  211. package/examples/playground/app/a0/preview.ts +26 -0
  212. package/examples/playground/app/a0/sandbox-log.ts +75 -0
  213. package/examples/playground/app/a0/sandbox-session.ts +152 -0
  214. package/examples/playground/app/a0/sandbox.ts +191 -0
  215. package/examples/playground/app/a0/sandboxes/scheduler/route.ts +6 -0
  216. package/examples/playground/app/a0/scheduler/route.ts +7 -0
  217. package/examples/playground/app/a0/server.ts +213 -0
  218. package/examples/playground/app/a0/session.ts +59 -0
  219. package/examples/playground/app/a0/shell.tsx +158 -0
  220. package/examples/playground/app/a0/short/events/route.ts +9 -0
  221. package/examples/playground/app/a0/splitter.tsx +120 -0
  222. package/examples/playground/app/agent/[agentId]/agent-client.tsx +144 -174
  223. package/examples/playground/app/agent/[agentId]/command-receipt.test.tsx +65 -0
  224. package/examples/playground/app/agent/[agentId]/command-receipt.tsx +27 -0
  225. package/examples/playground/app/agent/[agentId]/compaction-event.tsx +25 -24
  226. package/examples/playground/app/agent/[agentId]/compaction-panel.test.tsx +119 -0
  227. package/examples/playground/app/agent/[agentId]/compaction-panel.tsx +208 -165
  228. package/examples/playground/app/agent/[agentId]/page.tsx +2 -16
  229. package/examples/playground/app/agent/events/route.ts +5 -2
  230. package/examples/playground/app/agent/ingress.test.ts +101 -0
  231. package/examples/playground/app/agent/model-input.test.tsx +58 -0
  232. package/examples/playground/app/agent/model-input.tsx +115 -0
  233. package/examples/playground/app/agent/model.test.ts +73 -0
  234. package/examples/playground/app/agent/model.ts +58 -26
  235. package/examples/playground/app/agent/new-agent-session.tsx +37 -19
  236. package/examples/playground/app/agent/page.tsx +4 -4
  237. package/examples/playground/app/agent/server.ts +19 -15
  238. package/examples/playground/app/agent/session.ts +5 -6
  239. package/examples/playground/app/agent/telemetry.test.ts +189 -0
  240. package/examples/playground/app/agent/telemetry.ts +30 -0
  241. package/examples/playground/app/agent/trace.test.ts +23 -0
  242. package/examples/playground/app/agent/trace.ts +18 -0
  243. package/examples/playground/app/canvas/[canvasId]/canvas-client.tsx +12 -12
  244. package/examples/playground/app/canvas/[canvasId]/page.tsx +1 -2
  245. package/examples/playground/app/canvas/[canvasId]/session.ts +2 -2
  246. package/examples/playground/app/canvas/model.ts +53 -53
  247. package/examples/playground/app/chat/[chatId]/agent-state.test.ts +176 -0
  248. package/examples/playground/app/chat/[chatId]/agent-stream-drawer.tsx +16 -1
  249. package/examples/playground/app/chat/[chatId]/chat-client.tsx +55 -77
  250. package/examples/playground/app/chat/[chatId]/chat-view.ts +37 -3
  251. package/examples/playground/app/chat/[chatId]/page.tsx +7 -15
  252. package/examples/playground/app/chat/[chatId]/session.ts +2 -19
  253. package/examples/playground/app/chat/agent/route.ts +9 -0
  254. package/examples/playground/app/chat/model.test.ts +46 -119
  255. package/examples/playground/app/chat/model.ts +82 -128
  256. package/examples/playground/app/chat/scheduler/route.ts +2 -2
  257. package/examples/playground/app/chat/server.test.ts +112 -0
  258. package/examples/playground/app/chat/server.ts +113 -117
  259. package/examples/playground/app/components/activity-feed.tsx +30 -1
  260. package/examples/playground/app/components/activity-history.test.tsx +35 -0
  261. package/examples/playground/app/components/demo-icons.tsx +89 -0
  262. package/examples/playground/app/components/demos.tsx +33 -0
  263. package/examples/playground/app/components/fast-link.test.tsx +58 -0
  264. package/examples/playground/app/components/fast-link.tsx +55 -0
  265. package/examples/playground/app/components/site-header.tsx +96 -0
  266. package/examples/playground/app/counter/counter-client.tsx +3 -3
  267. package/examples/playground/app/counter/model.test.ts +3 -3
  268. package/examples/playground/app/counter/model.ts +11 -21
  269. package/examples/playground/app/counter/page.tsx +2 -15
  270. package/examples/playground/app/counter/session.ts +2 -2
  271. package/examples/playground/app/documents/[documentId]/code-editor.tsx +12 -1
  272. package/examples/playground/app/documents/[documentId]/document-client.tsx +10 -11
  273. package/examples/playground/app/documents/[documentId]/page.tsx +1 -2
  274. package/examples/playground/app/documents/[documentId]/session.ts +2 -2
  275. package/examples/playground/app/documents/model.ts +27 -27
  276. package/examples/playground/app/globals.css +420 -207
  277. package/examples/playground/app/initial-state.test.tsx +54 -0
  278. package/examples/playground/app/layout.tsx +7 -23
  279. package/examples/playground/app/orders/[orderId]/page.tsx +1 -2
  280. package/examples/playground/app/orders/[orderId]/session.ts +2 -2
  281. package/examples/playground/app/orders/model.ts +49 -49
  282. package/examples/playground/app/page.tsx +13 -102
  283. package/examples/playground/app/recovery/[recoveryId]/page.tsx +1 -2
  284. package/examples/playground/app/recovery/[recoveryId]/session.ts +2 -2
  285. package/examples/playground/app/recovery/model.ts +30 -30
  286. package/examples/playground/instrumentation.ts +5 -0
  287. package/examples/playground/next.config.ts +17 -5
  288. package/examples/playground/package.json +13 -2
  289. package/examples/playground/scripts/a0-template.ts +77 -0
  290. package/examples/playground/vercel.json +36 -0
  291. package/package.json +29 -3
  292. package/src/actor-client.ts +16 -4
  293. package/src/actor-react.ts +25 -11
  294. package/src/actor-shared.ts +21 -6
  295. package/src/actor.ts +76 -31
  296. package/src/ai-agent-actions.ts +219 -0
  297. package/src/ai-agent.ts +2517 -0
  298. package/src/ai-app-state.ts +91 -0
  299. package/src/ai-client-state.ts +6 -3
  300. package/src/ai-client.ts +62 -0
  301. package/src/ai-context-schema.ts +25 -5
  302. package/src/ai-context.ts +90 -40
  303. package/src/ai-control-server.ts +92 -72
  304. package/src/ai-coordinator.ts +23 -22
  305. package/src/ai-fx.browser.ts +5 -0
  306. package/src/ai-fx.ts +833 -0
  307. package/src/ai-harness.ts +518 -0
  308. package/src/ai-message-base.ts +209 -0
  309. package/src/ai-message-projection.ts +262 -64
  310. package/src/ai-model-metadata.ts +11 -6
  311. package/src/ai-pi.browser.ts +5 -0
  312. package/src/ai-pi.ts +1263 -0
  313. package/src/ai-progress-batches.ts +26 -0
  314. package/src/ai-projector.ts +95 -14
  315. package/src/ai-react.ts +146 -0
  316. package/src/ai-sdk-step.ts +2 -2
  317. package/src/ai-server.browser.ts +2 -2
  318. package/src/ai-server.ts +23 -1965
  319. package/src/ai-stored-state.ts +48 -163
  320. package/src/ai.ts +339 -155
  321. package/src/bootstrap-stream.ts +72 -0
  322. package/src/bounded-cache.ts +55 -0
  323. package/src/client-render-session.ts +49 -0
  324. package/src/client.ts +688 -151
  325. package/src/contract.ts +92 -42
  326. package/src/deterministic-id.ts +37 -0
  327. package/src/equal-json.ts +32 -0
  328. package/src/errors.ts +13 -1
  329. package/src/index.ts +5 -1
  330. package/src/initial-snapshot.ts +39 -0
  331. package/src/internal.ts +52 -0
  332. package/src/libfx.d.ts +34 -0
  333. package/src/postgres-notification-scope.ts +14 -3
  334. package/src/react.ts +171 -206
  335. package/src/redis-http-reply.ts +256 -0
  336. package/src/redis-http-stream.ts +73 -0
  337. package/src/redis-http-subscriptions.ts +13 -5
  338. package/src/reducer-runtime.ts +52 -0
  339. package/src/reducer.ts +93 -11
  340. package/src/scheduler-qstash.ts +49 -20
  341. package/src/scheduler-task.ts +34 -2
  342. package/src/scheduler-vercel.ts +32 -84
  343. package/src/server-fetch.ts +139 -35
  344. package/src/server.ts +1133 -255
  345. package/src/session-clear.ts +23 -0
  346. package/src/session-socket.ts +154 -49
  347. package/src/sse.ts +71 -4
  348. package/src/store-memory.ts +252 -75
  349. package/src/store-polling.ts +18 -4
  350. package/src/store-postgres.ts +541 -114
  351. package/src/store-redis-core.ts +1450 -493
  352. package/src/store-redis-http.ts +18 -2
  353. package/src/store-redis-notify.ts +262 -85
  354. package/src/store-redis.ts +19 -9
  355. package/src/store-sqlite.ts +319 -45
  356. package/src/store.ts +79 -1
  357. package/src/stream-buffer.ts +43 -0
  358. package/src/telemetry.ts +14 -1
  359. package/src/wire.ts +241 -13
  360. package/dist/actor-ohPC-81x.d.ts.map +0 -1
  361. package/dist/actor-shared-B5tJfzt-.js.map +0 -1
  362. package/dist/ai-CrEf6p_W.d.ts.map +0 -1
  363. package/dist/ai-DgOBltJ_.js.map +0 -1
  364. package/dist/client-BYzHjkwU.js.map +0 -1
  365. package/dist/client-CzyacQpJ.d.ts.map +0 -1
  366. package/dist/contract-CKRg_E4q.js.map +0 -1
  367. package/dist/errors-DCk6ch5n.js.map +0 -1
  368. package/dist/errors-DvhSXnxk.d.ts.map +0 -1
  369. package/dist/internal-Dq2qYxou.js.map +0 -1
  370. package/dist/react.d.ts.map +0 -1
  371. package/dist/reducer-DEMjEY_O.js +0 -29
  372. package/dist/reducer-DEMjEY_O.js.map +0 -1
  373. package/dist/reducer-otzHjuJj.d.ts.map +0 -1
  374. package/dist/scheduler-task-BpzhPnRS.js.map +0 -1
  375. package/dist/server-BD5ckxZb.js.map +0 -1
  376. package/dist/server-DbD7IJVK.d.ts.map +0 -1
  377. package/dist/store-DyZM6fS5.d.ts.map +0 -1
  378. package/dist/store-polling-CmxUbV93.js.map +0 -1
  379. package/dist/store-redis-notify-BVLUfI3j.js +0 -1583
  380. package/dist/store-redis-notify-BVLUfI3j.js.map +0 -1
  381. package/dist/telemetry-B5jzpy6y.d.ts.map +0 -1
  382. package/dist/validate-XKT4FSNn.js +0 -30
  383. package/dist/validate-XKT4FSNn.js.map +0 -1
  384. package/dist/wire-BO5wWCb1.js.map +0 -1
  385. package/docs/concepts/01-contracts.mdx +0 -142
  386. package/docs/concepts/02-handlers.mdx +0 -284
  387. package/docs/concepts/03-durability.mdx +0 -314
  388. package/docs/concepts/04-state.mdx +0 -209
  389. package/docs/guides/01-timers.mdx +0 -185
  390. package/docs/guides/02-cancellation.mdx +0 -161
  391. package/docs/guides/03-react.mdx +0 -384
  392. package/docs/guides/04-local-first.mdx +0 -88
  393. package/docs/guides/05-production.mdx +0 -521
  394. package/docs/guides/06-ai-agents.mdx +0 -1318
  395. package/docs/guides/08-application-data.mdx +0 -113
  396. package/docs/guides/09-presence.mdx +0 -266
  397. package/docs/guides/10-transports.mdx +0 -221
  398. package/docs/reference/01-api.mdx +0 -1896
  399. package/docs/reference/02-errors.mdx +0 -149
  400. package/examples/playground/app/agent/[agentId]/compaction/route.ts +0 -14
  401. package/examples/playground/app/agent/compaction-settings.test.ts +0 -144
  402. package/examples/playground/app/agent/compaction-settings.ts +0 -49
  403. package/examples/playground/app/agent/compaction-timeline.test.ts +0 -377
  404. package/examples/playground/app/agent/compaction-timeline.ts +0 -208
  405. /package/docs/{concepts → contract}/meta.ts +0 -0
  406. /package/docs/{guides → server}/meta.ts +0 -0
package/dist/ai-pi.js ADDED
@@ -0,0 +1,904 @@
1
+ import { u as ambientToolScopeStorage } from "./internal-B2T3U4Rq.js";
2
+ import { t as boundedCache } from "./bounded-cache-CPHWF-8h.js";
3
+ import { c as pending, d as saveHarness, i as gatewayCredential, l as readHarness, n as deferred, r as defineHarness, t as Divergence } from "./ai-harness-BuLh_EYi.js";
4
+ import { createHash } from "node:crypto";
5
+ import { asSchema, jsonSchema } from "ai";
6
+ import { readFile, unlink } from "node:fs/promises";
7
+ import { tmpdir } from "node:os";
8
+ import { basename, dirname, join } from "node:path";
9
+ //#region src/ai-pi.ts
10
+ /**
11
+ * experimental-a2/ai/pi — `pi()`: the Pi harness for `agent({ harness })`.
12
+ * Server-only; Pi comes from the optional `@earendil-works/pi-coding-agent`
13
+ * and `@earendil-works/pi-ai` peer dependencies.
14
+ */
15
+ /**
16
+ * The Pi harness. Every model call Pi makes is one durable step; A2 rebuilds
17
+ * Pi's session for each step from its latest snapshot and the log since.
18
+ */
19
+ function pi(options) {
20
+ if (typeof options?.sandbox !== "function") throw new TypeError("pi() requires sandbox");
21
+ return defineHarness("pi", {
22
+ sandbox: options.sandbox,
23
+ tools: builtinTools,
24
+ step: (step) => runStep(step, async () => options.sandbox({
25
+ session: { id: step.sessionId },
26
+ signal: step.signal
27
+ }))
28
+ });
29
+ }
30
+ const SNAPSHOT_VERSION = 1;
31
+ const GATEWAY = "vercel-ai-gateway";
32
+ const MAX_TRANSFER_BYTES = 4194304;
33
+ const MAX_TRANSFER = "4 MiB";
34
+ const BUILTINS = [
35
+ "read",
36
+ "write",
37
+ "edit",
38
+ "bash"
39
+ ];
40
+ function endStep(state) {
41
+ state.over = true;
42
+ state.stepOver.resolve();
43
+ }
44
+ const diverged = (message) => new Divergence("Pi", message);
45
+ async function runStep(step, sandbox) {
46
+ const modules = await loadPi();
47
+ const credential = gatewayCredential("pi");
48
+ const name = `${step.agentName}.a2.harness.pi`;
49
+ const { replayAll, ...first } = await readHarness({
50
+ step,
51
+ name,
52
+ parse: savedSession
53
+ });
54
+ let read = first;
55
+ let results = read.results;
56
+ const cwd = read.saved?.cwd ?? await sessionCwd({
57
+ key: cwdKey(step.agentName, step.sessionId),
58
+ sandbox
59
+ });
60
+ let completion = {};
61
+ let session;
62
+ let compacting = false;
63
+ let turn;
64
+ const fail = (state, error) => {
65
+ state.failure ??= error;
66
+ endStep(state);
67
+ session?.abort();
68
+ throw state.failure;
69
+ };
70
+ let controller;
71
+ let closed = false;
72
+ const emit = (chunk) => {
73
+ if (!closed) controller.enqueue(chunk);
74
+ };
75
+ const record = (data) => emit({
76
+ type: "data-a2-pi",
77
+ data,
78
+ transient: true
79
+ });
80
+ const answer = async (out, model, context, options) => {
81
+ const state = turn;
82
+ if (state.failure) throw state.failure;
83
+ if (state.over) {
84
+ replay(out, interrupted(model));
85
+ return;
86
+ }
87
+ const kind = compacting ? "compaction" : "step";
88
+ const recorded = state.calls[state.next];
89
+ if (recorded !== void 0) {
90
+ if (recorded.kind !== kind) fail(state, diverged(`call ${state.next} is not a ${kind}`));
91
+ state.next++;
92
+ for (const text of recorded.steers) await session.steer(text);
93
+ replay(out, recorded.response);
94
+ return;
95
+ }
96
+ if (state.plan.end === "stop") fail(state, diverged("Pi continued a turn the log ended"));
97
+ if (state.plan.end === "interrupted") {
98
+ replay(out, interrupted(model));
99
+ return;
100
+ }
101
+ if (kind === "step" && state.liveStep) {
102
+ endStep(state);
103
+ replay(out, interrupted(model));
104
+ return;
105
+ }
106
+ if (kind === "step") state.liveStep = true;
107
+ const upstream = realStream(model, context, {
108
+ ...options,
109
+ headers: {
110
+ ...options?.headers,
111
+ ...gatewayHeaders(credential)
112
+ }
113
+ });
114
+ const live = kind === "step" ? liveStep() : void 0;
115
+ for await (const event of upstream) {
116
+ live?.(event);
117
+ if (event.type === "done" || event.type === "error") {
118
+ const response = event.type === "done" ? event.message : event.error;
119
+ if (kind === "compaction") state.compactions.push(response);
120
+ if (event.type === "error" && event.reason === "error") {
121
+ state.failure ??= new Error(response.errorMessage ?? "the Pi model call failed");
122
+ endStep(state);
123
+ }
124
+ }
125
+ out.push(event);
126
+ }
127
+ };
128
+ /** Streams one live step response as UI chunks and records it. */
129
+ const liveStep = () => {
130
+ const ref = (index) => `pi:${step.requestIndex}:${index}`;
131
+ const started = /* @__PURE__ */ new Set();
132
+ return (event) => {
133
+ switch (event.type) {
134
+ case "start":
135
+ emit({ type: "start-step" });
136
+ break;
137
+ case "text_start":
138
+ emit({
139
+ type: "text-start",
140
+ id: ref(event.contentIndex)
141
+ });
142
+ break;
143
+ case "text_delta":
144
+ emit({
145
+ type: "text-delta",
146
+ id: ref(event.contentIndex),
147
+ delta: event.delta
148
+ });
149
+ break;
150
+ case "text_end":
151
+ emit({
152
+ type: "text-end",
153
+ id: ref(event.contentIndex)
154
+ });
155
+ break;
156
+ case "thinking_start":
157
+ emit({
158
+ type: "reasoning-start",
159
+ id: ref(event.contentIndex)
160
+ });
161
+ break;
162
+ case "thinking_delta":
163
+ emit({
164
+ type: "reasoning-delta",
165
+ id: ref(event.contentIndex),
166
+ delta: event.delta
167
+ });
168
+ break;
169
+ case "thinking_end":
170
+ emit({
171
+ type: "reasoning-end",
172
+ id: ref(event.contentIndex)
173
+ });
174
+ break;
175
+ case "toolcall_start":
176
+ case "toolcall_delta": {
177
+ const call = event.partial.content[event.contentIndex];
178
+ if (!call.id) break;
179
+ if (!started.has(call.id)) {
180
+ started.add(call.id);
181
+ emit({
182
+ type: "tool-input-start",
183
+ toolCallId: call.id,
184
+ toolName: call.name
185
+ });
186
+ }
187
+ if (event.type === "toolcall_delta") emit({
188
+ type: "tool-input-delta",
189
+ toolCallId: call.id,
190
+ inputTextDelta: event.delta
191
+ });
192
+ break;
193
+ }
194
+ case "done":
195
+ case "error": {
196
+ const response = event.type === "done" ? event.message : event.error;
197
+ if (event.type === "done") for (const block of response.content) {
198
+ if (block.type !== "toolCall") continue;
199
+ if (!started.has(block.id)) emit({
200
+ type: "tool-input-start",
201
+ toolCallId: block.id,
202
+ toolName: block.name
203
+ });
204
+ emit(response.stopReason === "length" ? {
205
+ type: "tool-input-error",
206
+ toolCallId: block.id,
207
+ toolName: block.name,
208
+ input: block.arguments,
209
+ errorText: "The response hit the output token limit before this call was complete."
210
+ } : {
211
+ type: "tool-input-available",
212
+ toolCallId: block.id,
213
+ toolName: block.name,
214
+ input: block.arguments
215
+ });
216
+ }
217
+ record({
218
+ call: "step",
219
+ response: storedResponse(response, ref)
220
+ });
221
+ completion = {
222
+ finishReason: finishReason(response.stopReason),
223
+ usage: modelUsage(response.usage)
224
+ };
225
+ break;
226
+ }
227
+ }
228
+ };
229
+ };
230
+ const toolResult = async (toolCallId, signal, shape) => {
231
+ const state = turn;
232
+ if (state.failure) throw state.failure;
233
+ const result = results.get(toolCallId);
234
+ if (result !== void 0) return answeredTool(result, shape);
235
+ if (state.plan.end === "live" && state.liveStep) {
236
+ endStep(state);
237
+ return pending(signal);
238
+ }
239
+ if (state.plan.end === "interrupted") {
240
+ session.abort();
241
+ return pending(signal);
242
+ }
243
+ return fail(state, diverged(`no recorded result for ${toolCallId}`));
244
+ };
245
+ const runtime = await modules.agent.ModelRuntime.create({
246
+ credentials: new modules.ai.InMemoryCredentialStore(),
247
+ modelsPath: null,
248
+ allowModelNetwork: false,
249
+ refreshOnCreate: false
250
+ });
251
+ await runtime.setRuntimeApiKey(GATEWAY, credential.token);
252
+ const model = runtime.getModel(GATEWAY, step.model);
253
+ if (model === void 0) throw new Error(`Pi does not know the Gateway model ${step.model}`);
254
+ const realStream = runtime.streamSimple.bind(runtime);
255
+ runtime.streamSimple = (requested, context, options) => {
256
+ const out = modules.ai.createAssistantMessageEventStream();
257
+ answer(out, requested, context, options).catch((error) => {
258
+ const state = turn;
259
+ if (state) state.failure ??= asError(error);
260
+ replay(out, {
261
+ ...interrupted(requested),
262
+ stopReason: "error"
263
+ });
264
+ });
265
+ return out;
266
+ };
267
+ const tools = await sessionTools(modules, step.tools, cwd, toolResult);
268
+ const createSession = async (from) => {
269
+ const sessionManager = from === void 0 ? modules.agent.SessionManager.inMemory(cwd, { id: sessionUuid(step.agentName, step.sessionId) }) : modules.agent.SessionManager.inMemory(cwd, { id: from.header.id }, [from.header, ...from.entries]);
270
+ const created = await modules.agent.createAgentSession({
271
+ cwd,
272
+ agentDir: join(tmpdir(), "a2-pi"),
273
+ model,
274
+ ...thinkingLevel(step),
275
+ modelRuntime: runtime,
276
+ resourceLoader: resources(modules, step.instructions),
277
+ sessionManager,
278
+ settingsManager: modules.agent.SettingsManager.inMemory({
279
+ retry: {
280
+ enabled: false,
281
+ maxRetries: 0,
282
+ baseDelayMs: 0
283
+ },
284
+ cacheWarming: "off"
285
+ }),
286
+ customTools: tools,
287
+ tools: tools.map((definition) => definition.name)
288
+ });
289
+ created.session.subscribe((event) => {
290
+ if (event.type === "compaction_start") compacting = true;
291
+ if (event.type !== "compaction_end") return;
292
+ compacting = false;
293
+ const state = turn;
294
+ if (state === void 0 || state.over || state.compactions.length === 0) return;
295
+ for (const response of state.compactions.splice(0)) record({
296
+ call: "compaction",
297
+ response
298
+ });
299
+ emit({
300
+ type: "data-a2-compaction",
301
+ id: `pi-compaction:${step.requestIndex}:${compactions++}`,
302
+ data: compactionData(event)
303
+ });
304
+ });
305
+ return created.session;
306
+ };
307
+ let compactions = 0;
308
+ const saveSnapshot = async () => {
309
+ const manager = session.sessionManager;
310
+ const header = manager.getHeader();
311
+ const entries = manager.getEntries();
312
+ const last = entries.findLast((entry) => entry.type === "message" && entry.message.role === "assistant");
313
+ const stop = last?.type === "message" && last.message.role === "assistant" ? last.message.stopReason : void 0;
314
+ if (header === null || step.signal.aborted || stop === "aborted" || stop === "error") return;
315
+ await saveHarness({
316
+ step,
317
+ name,
318
+ state: {
319
+ version: SNAPSHOT_VERSION,
320
+ cwd,
321
+ header,
322
+ entries
323
+ }
324
+ });
325
+ };
326
+ const run = async () => {
327
+ emit({
328
+ type: "start",
329
+ messageId: step.responseMessageId
330
+ });
331
+ try {
332
+ session = await createSession(read.saved);
333
+ } catch (error) {
334
+ if (read.saved === void 0) throw error;
335
+ read = await replayAll();
336
+ results = read.results;
337
+ session = await createSession(void 0);
338
+ }
339
+ for (const plan of read.turns) {
340
+ if (step.signal.aborted) return;
341
+ const state = {
342
+ plan,
343
+ calls: recordedTurn(plan),
344
+ next: 0,
345
+ liveStep: false,
346
+ over: false,
347
+ stepOver: deferred(),
348
+ compactions: []
349
+ };
350
+ turn = state;
351
+ const running = session.prompt(plan.prompt, { expandPromptTemplates: false });
352
+ if (plan.end !== "live") {
353
+ await running.catch((error) => {
354
+ throw state.failure ?? error;
355
+ });
356
+ if (state.failure) throw state.failure;
357
+ continue;
358
+ }
359
+ const ended = await Promise.race([running.then(() => true), state.stepOver.promise.then(() => false)]).catch((error) => {
360
+ throw state.failure ?? error;
361
+ });
362
+ if (!ended) {
363
+ await session.abort();
364
+ await running.catch(() => {});
365
+ }
366
+ if (state.failure) throw state.failure;
367
+ if (ended) await saveSnapshot();
368
+ emit({ type: "finish-step" });
369
+ emit({
370
+ type: "finish",
371
+ ...completion.finishReason === void 0 ? {} : { finishReason: completion.finishReason }
372
+ });
373
+ }
374
+ };
375
+ return {
376
+ stream: new ReadableStream({
377
+ start(streamController) {
378
+ controller = streamController;
379
+ const abort = () => void session?.abort();
380
+ step.signal.addEventListener("abort", abort, { once: true });
381
+ (async () => {
382
+ try {
383
+ await run();
384
+ closed = true;
385
+ streamController.close();
386
+ } catch (error) {
387
+ closed = true;
388
+ streamController.error(step.signal.aborted ? step.signal.reason : error);
389
+ } finally {
390
+ step.signal.removeEventListener("abort", abort);
391
+ session?.dispose();
392
+ }
393
+ })();
394
+ },
395
+ cancel() {
396
+ closed = true;
397
+ session?.abort();
398
+ }
399
+ }),
400
+ completion: () => completion
401
+ };
402
+ }
403
+ /** A turn's recorded model calls, in the order Pi made them. */
404
+ function recordedTurn(turn) {
405
+ const calls = [];
406
+ turn.generations.forEach((generation, index) => {
407
+ calls.push(...recordedCalls(generation));
408
+ const steers = turn.steers.get(index);
409
+ const last = calls.findLast((call) => call.kind === "step");
410
+ if (steers !== void 0 && last !== void 0) last.steers.push(...steers);
411
+ });
412
+ return calls;
413
+ }
414
+ function recordedCalls(generation) {
415
+ const texts = /* @__PURE__ */ new Map();
416
+ const inputs = /* @__PURE__ */ new Map();
417
+ const calls = [];
418
+ for (const chunk of generation.chunks) switch (chunk.type) {
419
+ case "text-delta":
420
+ case "reasoning-delta":
421
+ texts.set(chunk.id, (texts.get(chunk.id) ?? "") + chunk.delta);
422
+ break;
423
+ case "tool-input-available":
424
+ case "tool-input-error":
425
+ inputs.set(chunk.toolCallId, chunk.input);
426
+ break;
427
+ case "data-a2-pi": {
428
+ const record = chunk.data;
429
+ calls.push({
430
+ kind: record.call,
431
+ response: record.call === "step" ? restoredResponse(record.response, texts, inputs) : record.response,
432
+ steers: []
433
+ });
434
+ break;
435
+ }
436
+ }
437
+ if (!calls.some((call) => call.kind === "step")) throw diverged("a completed generation has no recorded response");
438
+ return calls;
439
+ }
440
+ function storedResponse(response, ref) {
441
+ return {
442
+ ...response,
443
+ content: response.content.map((block, index) => {
444
+ switch (block.type) {
445
+ case "text": {
446
+ const { text: _, ...rest } = block;
447
+ return {
448
+ ...rest,
449
+ ref: ref(index)
450
+ };
451
+ }
452
+ case "thinking": {
453
+ const { thinking: _, ...rest } = block;
454
+ return {
455
+ ...rest,
456
+ ref: ref(index)
457
+ };
458
+ }
459
+ case "toolCall": {
460
+ const { arguments: _, ...rest } = block;
461
+ return rest;
462
+ }
463
+ }
464
+ })
465
+ };
466
+ }
467
+ function restoredResponse(stored, texts, inputs) {
468
+ return {
469
+ ...stored,
470
+ content: stored.content.map((block) => {
471
+ if (block.type === "toolCall") return {
472
+ ...block,
473
+ arguments: inputs.get(block.id) ?? {}
474
+ };
475
+ const { ref, ...rest } = block;
476
+ const text = texts.get(ref) ?? "";
477
+ return rest.type === "text" ? {
478
+ ...rest,
479
+ text
480
+ } : {
481
+ ...rest,
482
+ thinking: text
483
+ };
484
+ })
485
+ };
486
+ }
487
+ /** Hands a recorded response to Pi's loop. */
488
+ function replay(out, response) {
489
+ out.push({
490
+ type: "start",
491
+ partial: response
492
+ });
493
+ const reason = response.stopReason;
494
+ if (reason === "error" || reason === "aborted") out.push({
495
+ type: "error",
496
+ reason,
497
+ error: response
498
+ });
499
+ else if (reason === "pending") out.push({
500
+ type: "done",
501
+ reason: "stop",
502
+ message: response
503
+ });
504
+ else out.push({
505
+ type: "done",
506
+ reason,
507
+ message: response
508
+ });
509
+ }
510
+ /** The response of a model call that A2 interrupted. */
511
+ function interrupted(model) {
512
+ return {
513
+ role: "assistant",
514
+ content: [],
515
+ api: model.api,
516
+ provider: model.provider,
517
+ model: model.id,
518
+ usage: {
519
+ input: 0,
520
+ output: 0,
521
+ cacheRead: 0,
522
+ cacheWrite: 0,
523
+ totalTokens: 0,
524
+ cost: {
525
+ input: 0,
526
+ output: 0,
527
+ cacheRead: 0,
528
+ cacheWrite: 0,
529
+ total: 0
530
+ }
531
+ },
532
+ stopReason: "aborted",
533
+ timestamp: Date.now()
534
+ };
535
+ }
536
+ const builtinTools = Object.fromEntries(BUILTINS.map((name) => [name, {
537
+ inputSchema: jsonSchema(async () => builtinDefinition(await loadPi(), name, "/").parameters),
538
+ execute: (input, options) => runBuiltin(name, input, options)
539
+ }]));
540
+ /** Runs one of Pi's tools in the session's sandbox, as Pi's loop would. */
541
+ async function runBuiltin(name, input, options) {
542
+ const sandbox = options.experimental_sandbox;
543
+ if (sandbox === void 0) throw new Error(`pi() runs ${name} in the agent's sandbox`);
544
+ const modules = await loadPi();
545
+ const scope = ambientToolScopeStorage()?.getStore();
546
+ const event = (scope?.context)?.event;
547
+ const definition = builtinDefinition(modules, name, await sessionCwd({
548
+ key: scope?.contract !== void 0 && typeof event?.sessionId === "string" ? cwdKey(scope.contract.name, event.sessionId) : void 0,
549
+ sandbox: async () => sandbox
550
+ }), {
551
+ sandbox,
552
+ signal: options.abortSignal
553
+ });
554
+ const args = modules.ai.validateToolArguments(definition, {
555
+ type: "toolCall",
556
+ id: options.toolCallId,
557
+ name,
558
+ arguments: definition.prepareArguments?.(input) ?? input
559
+ });
560
+ let outputFile;
561
+ try {
562
+ const result = await definition.execute(options.toolCallId, args, options.abortSignal, (update) => {
563
+ outputFile ??= fullOutputPath(update);
564
+ }, void 0);
565
+ outputFile ??= fullOutputPath(result);
566
+ return await recordedResult(result, sandbox);
567
+ } catch (error) {
568
+ outputFile ??= namedOutputFile(error);
569
+ throw error;
570
+ } finally {
571
+ if (outputFile !== void 0) await unlink(outputFile).catch(() => {});
572
+ }
573
+ }
574
+ const fullOutputPath = (result) => {
575
+ const path = result.details?.fullOutputPath;
576
+ return typeof path === "string" ? path : void 0;
577
+ };
578
+ /** The full-output file an aborted or timed-out bash call's error names. */
579
+ function namedOutputFile(error) {
580
+ if (!(error instanceof Error)) return void 0;
581
+ const path = /Full output: ([^\n]+)\]\n\nCommand [^\n]+$/.exec(error.message)?.[1];
582
+ return path !== void 0 && dirname(path) === tmpdir() && /^pi-bash-[0-9a-f]{16}\.log$/.test(basename(path)) ? path : void 0;
583
+ }
584
+ /**
585
+ * What the log keeps of a result: what Pi's tool-result message holds. A
586
+ * long output's full text moves to the path its result names in the sandbox,
587
+ * where the model's `read` finds it.
588
+ */
589
+ async function recordedResult(result, sandbox) {
590
+ const { structuredContent: _, ...kept } = result;
591
+ const details = kept.details;
592
+ const path = fullOutputPath(kept);
593
+ if (path !== void 0) try {
594
+ await sandbox.writeBinaryFile({
595
+ path,
596
+ content: await readFile(path)
597
+ });
598
+ } catch {}
599
+ if (details?.truncation === void 0) return kept;
600
+ const { content: __, ...truncation } = details.truncation;
601
+ return {
602
+ ...kept,
603
+ details: {
604
+ ...details,
605
+ truncation
606
+ }
607
+ };
608
+ }
609
+ const untyped = (definition) => definition;
610
+ function builtinDefinition(modules, name, cwd, call) {
611
+ const sandbox = call?.sandbox;
612
+ const files = call === void 0 ? void 0 : { operations: sandboxFiles(call) };
613
+ switch (name) {
614
+ case "read": return untyped(modules.agent.createReadToolDefinition(cwd, files));
615
+ case "write": return untyped(modules.agent.createWriteToolDefinition(cwd, files));
616
+ case "edit": return untyped(modules.agent.createEditToolDefinition(cwd, files));
617
+ case "bash": return untyped(modules.agent.createBashToolDefinition(cwd, {
618
+ exposeSessionEnvironment: false,
619
+ ...sandbox === void 0 ? {} : { operations: sandboxBash(sandbox) }
620
+ }));
621
+ }
622
+ }
623
+ /**
624
+ * The tools Pi's session declares: Pi's own, and the agent's. Their results
625
+ * come from A2's log; A2's tool handlers ran them.
626
+ */
627
+ async function sessionTools(modules, tools, cwd, result) {
628
+ return Promise.all(Object.entries(tools).filter(([, tool]) => tool.type !== "provider").map(async ([name, tool]) => {
629
+ const builtin = BUILTINS.find((candidate) => candidate === name && builtinTools[name] === tool);
630
+ if (builtin !== void 0) return Object.assign(builtinDefinition(modules, builtin, cwd), { execute: (toolCallId, _params, signal) => result(toolCallId, signal, "pi") });
631
+ return {
632
+ name,
633
+ label: name,
634
+ description: typeof tool.description === "string" ? tool.description : "",
635
+ parameters: await asSchema(tool.inputSchema).jsonSchema,
636
+ execute: (toolCallId, _params, signal) => result(toolCallId, signal, "tool")
637
+ };
638
+ }));
639
+ }
640
+ function answeredTool(result, shape) {
641
+ if (result.error !== void 0) throw new Error(result.error);
642
+ if (result.denied === true) throw new Error("The tool call was denied.");
643
+ if (shape === "pi") return result.output;
644
+ const output = result.output;
645
+ return {
646
+ content: [{
647
+ type: "text",
648
+ text: typeof output === "string" ? output : JSON.stringify(output) ?? ""
649
+ }],
650
+ details: void 0
651
+ };
652
+ }
653
+ /** Pi's file operations, against the sandbox. */
654
+ function sandboxFiles({ sandbox, signal }) {
655
+ const abortSignal = signal === void 0 ? {} : { abortSignal: signal };
656
+ let checked;
657
+ const readFile = async (path) => {
658
+ if (checked?.path === path) {
659
+ const { bytes } = checked;
660
+ checked = void 0;
661
+ return bytes;
662
+ }
663
+ const stream = await sandbox.readFile({
664
+ path,
665
+ ...abortSignal
666
+ });
667
+ if (stream === null) throw Object.assign(/* @__PURE__ */ new Error(`ENOENT: no such file or directory, open '${path}'`), { code: "ENOENT" });
668
+ const chunks = [];
669
+ let size = 0;
670
+ for await (const chunk of stream) {
671
+ size += chunk.byteLength;
672
+ if (size > MAX_TRANSFER_BYTES) throw new Error(`${path} is larger than ${MAX_TRANSFER}. Read or change parts of it with bash, using sed, head, or grep.`);
673
+ chunks.push(chunk);
674
+ }
675
+ return Buffer.concat(chunks);
676
+ };
677
+ return {
678
+ readFile,
679
+ access: async (path) => {
680
+ checked = {
681
+ path,
682
+ bytes: await readFile(path)
683
+ };
684
+ },
685
+ writeFile: async (path, content) => {
686
+ checked = void 0;
687
+ await sandbox.writeTextFile({
688
+ path,
689
+ content,
690
+ ...abortSignal
691
+ });
692
+ },
693
+ mkdir: async () => {}
694
+ };
695
+ }
696
+ /** Pi's shell operations, against the sandbox. */
697
+ const sandboxBash = (sandbox) => ({ exec: (command, cwd, { onData, signal, timeout }) => sandboxExec({
698
+ sandbox,
699
+ command,
700
+ workingDirectory: cwd,
701
+ onData,
702
+ signal,
703
+ timeout
704
+ }) });
705
+ /**
706
+ * Runs a command in the sandbox with Pi's error contract. At most
707
+ * `MAX_TRANSFER_BYTES` of its output reach the server; past that, the
708
+ * command is stopped.
709
+ */
710
+ async function sandboxExec({ sandbox, command, workingDirectory, onData, signal, timeout }) {
711
+ if (signal?.aborted) throw new Error("aborted");
712
+ const stop = new AbortController();
713
+ const abort = () => stop.abort();
714
+ signal?.addEventListener("abort", abort, { once: true });
715
+ let timedOut = false;
716
+ const timer = timeout === void 0 || timeout <= 0 ? void 0 : setTimeout(() => {
717
+ timedOut = true;
718
+ stop.abort();
719
+ }, timeout * 1e3);
720
+ let size = 0;
721
+ let overflowed = false;
722
+ const overflow = (options) => new Error(`The command's output passed ${MAX_TRANSFER}, so it was stopped. Write long output to a file and read parts of it with head, tail, or grep.`, options);
723
+ let exitCode;
724
+ try {
725
+ const process = await sandbox.spawn({
726
+ command,
727
+ ...workingDirectory === void 0 ? {} : { workingDirectory },
728
+ abortSignal: stop.signal
729
+ });
730
+ const pipe = async (stream) => {
731
+ for await (const chunk of process[stream]) {
732
+ size += chunk.byteLength;
733
+ if (size > MAX_TRANSFER_BYTES) {
734
+ overflowed = true;
735
+ stop.abort();
736
+ return;
737
+ }
738
+ onData(Buffer.from(chunk), stream);
739
+ }
740
+ };
741
+ const [exited] = await Promise.all([
742
+ process.wait(),
743
+ pipe("stdout"),
744
+ pipe("stderr")
745
+ ]);
746
+ exitCode = exited.exitCode;
747
+ } catch (error) {
748
+ if (signal?.aborted) throw new Error("aborted", { cause: error });
749
+ if (timedOut) throw new Error(`timeout:${timeout}`, { cause: error });
750
+ if (overflowed) throw overflow({ cause: error });
751
+ throw error;
752
+ } finally {
753
+ clearTimeout(timer);
754
+ signal?.removeEventListener("abort", abort);
755
+ }
756
+ if (signal?.aborted) throw new Error("aborted");
757
+ if (timedOut) throw new Error(`timeout:${timeout}`);
758
+ if (overflowed) throw overflow();
759
+ return { exitCode };
760
+ }
761
+ const cwds = boundedCache({
762
+ maxEntries: 1e3,
763
+ maxBytes: 1e3
764
+ });
765
+ const cwdKey = (agentName, sessionId) => `${agentName}\u001f${sessionId}`;
766
+ /** A session's working directory in its sandbox: Pi's cwd. */
767
+ function sessionCwd({ key, sandbox }) {
768
+ const cached = key === void 0 ? void 0 : cwds.get(key);
769
+ if (cached !== void 0) return cached;
770
+ const cwd = sandbox().then(async (resolved) => {
771
+ const output = {
772
+ stdout: "",
773
+ stderr: ""
774
+ };
775
+ const decoder = {
776
+ stdout: new TextDecoder(),
777
+ stderr: new TextDecoder()
778
+ };
779
+ const { exitCode } = await sandboxExec({
780
+ sandbox: resolved,
781
+ command: "pwd",
782
+ onData: (data, stream) => {
783
+ output[stream] += decoder[stream].decode(data, { stream: true });
784
+ }
785
+ }).catch((error) => {
786
+ throw new Error("pi() could not read the sandbox's working directory", { cause: error });
787
+ });
788
+ const path = output.stdout.trim();
789
+ if (exitCode !== 0 || !path.startsWith("/")) throw new Error(`pi() could not read the sandbox's working directory: ${(output.stderr || output.stdout).slice(0, 1e3)}`);
790
+ return path;
791
+ });
792
+ if (key !== void 0) {
793
+ cwds.set(key, cwd, 1);
794
+ cwd.catch(() => cwds.delete(key));
795
+ }
796
+ return cwd;
797
+ }
798
+ let loading;
799
+ function loadPi() {
800
+ loading ??= Promise.all([import("@earendil-works/pi-coding-agent"), import("@earendil-works/pi-ai")]).then(([agent, ai]) => ({
801
+ agent,
802
+ ai
803
+ }), (error) => {
804
+ loading = void 0;
805
+ throw new Error("pi() needs @earendil-works/pi-coding-agent and @earendil-works/pi-ai: install them", { cause: error });
806
+ });
807
+ return loading;
808
+ }
809
+ /** Pi's resources: nothing discovered from disk, the agent's instructions appended. */
810
+ function resources(modules, instructions) {
811
+ const runtime = modules.agent.createExtensionRuntime();
812
+ return {
813
+ getExtensions: () => ({
814
+ extensions: [],
815
+ errors: [],
816
+ runtime
817
+ }),
818
+ getSkills: () => ({
819
+ skills: [],
820
+ diagnostics: []
821
+ }),
822
+ getPrompts: () => ({
823
+ prompts: [],
824
+ diagnostics: []
825
+ }),
826
+ getThemes: () => ({
827
+ themes: [],
828
+ diagnostics: []
829
+ }),
830
+ getAgentsFiles: () => ({ agentsFiles: [] }),
831
+ getSystemPrompt: () => void 0,
832
+ getSystemPromptSource: () => void 0,
833
+ getAppendSystemPrompt: () => instructions,
834
+ getAppendSystemPromptSources: () => [],
835
+ extendResources: () => {},
836
+ reload: async () => {}
837
+ };
838
+ }
839
+ function thinkingLevel(step) {
840
+ if (step.reasoning === void 0 || step.reasoning === "provider-default") return {};
841
+ return { thinkingLevel: step.reasoning === "none" ? "off" : step.reasoning };
842
+ }
843
+ function gatewayHeaders(credential) {
844
+ return {
845
+ authorization: `Bearer ${credential.token}`,
846
+ "ai-gateway-auth-method": credential.method
847
+ };
848
+ }
849
+ /** A stable Pi session ID for an A2 session, so Pi's cache affinity holds. */
850
+ function sessionUuid(agentName, sessionId) {
851
+ const hex = createHash("sha256").update(`${agentName}\u001f${sessionId}`).digest("hex");
852
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-8${hex.slice(13, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;
853
+ }
854
+ function savedSession(state) {
855
+ if (typeof state !== "object" || state === null) return void 0;
856
+ const { version, cwd, header, entries } = state;
857
+ if (version !== SNAPSHOT_VERSION || typeof cwd !== "string" || typeof header !== "object" || header === null || !Array.isArray(entries)) return void 0;
858
+ return {
859
+ cwd,
860
+ header,
861
+ entries
862
+ };
863
+ }
864
+ function compactionData(event) {
865
+ if (event.result === void 0) return { status: event.aborted ? "interrupted" : "failed" };
866
+ return {
867
+ status: "completed",
868
+ inputTokens: event.result.tokensBefore,
869
+ summary: event.result.summary,
870
+ ...event.result.usage === void 0 ? {} : { usage: modelUsage(event.result.usage) }
871
+ };
872
+ }
873
+ function finishReason(reason) {
874
+ switch (reason) {
875
+ case "stop": return "stop";
876
+ case "length": return "length";
877
+ case "toolUse": return "tool-calls";
878
+ case "error": return "error";
879
+ default: return "other";
880
+ }
881
+ }
882
+ function modelUsage(usage) {
883
+ return {
884
+ inputTokens: usage.input + usage.cacheRead + usage.cacheWrite,
885
+ inputTokenDetails: {
886
+ noCacheTokens: usage.input,
887
+ cacheReadTokens: usage.cacheRead,
888
+ cacheWriteTokens: usage.cacheWrite
889
+ },
890
+ outputTokens: usage.output,
891
+ outputTokenDetails: {
892
+ textTokens: usage.reasoning === void 0 ? void 0 : usage.output - usage.reasoning,
893
+ reasoningTokens: usage.reasoning
894
+ },
895
+ totalTokens: usage.totalTokens
896
+ };
897
+ }
898
+ function asError(error) {
899
+ return error instanceof Error ? error : new Error(String(error));
900
+ }
901
+ //#endregion
902
+ export { pi };
903
+
904
+ //# sourceMappingURL=ai-pi.js.map