@animalabs/agent-framework 0.23.1 → 0.24.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 (338) hide show
  1. package/README.md +212 -42
  2. package/dist/src/agent.d.ts +60 -9
  3. package/dist/src/agent.d.ts.map +1 -1
  4. package/dist/src/agent.js +92 -12
  5. package/dist/src/agent.js.map +1 -1
  6. package/dist/src/api/server.d.ts.map +1 -1
  7. package/dist/src/api/server.js +14 -12
  8. package/dist/src/api/server.js.map +1 -1
  9. package/dist/src/code-execution/engine.d.ts +177 -0
  10. package/dist/src/code-execution/engine.d.ts.map +1 -0
  11. package/dist/src/code-execution/engine.js +494 -0
  12. package/dist/src/code-execution/engine.js.map +1 -0
  13. package/dist/src/code-execution/index.d.ts +5 -10
  14. package/dist/src/code-execution/index.d.ts.map +1 -1
  15. package/dist/src/code-execution/index.js +5 -9
  16. package/dist/src/code-execution/index.js.map +1 -1
  17. package/dist/src/code-execution/isolate/calls.d.ts +114 -0
  18. package/dist/src/code-execution/isolate/calls.d.ts.map +1 -0
  19. package/dist/src/code-execution/isolate/calls.js +145 -0
  20. package/dist/src/code-execution/isolate/calls.js.map +1 -0
  21. package/dist/src/code-execution/isolate/child-entry.d.ts +2 -0
  22. package/dist/src/code-execution/isolate/child-entry.d.ts.map +1 -0
  23. package/dist/src/code-execution/isolate/child-entry.js +5 -0
  24. package/dist/src/code-execution/isolate/child-entry.js.map +1 -0
  25. package/dist/src/code-execution/isolate/child-main.d.ts +26 -0
  26. package/dist/src/code-execution/isolate/child-main.d.ts.map +1 -0
  27. package/dist/src/code-execution/isolate/child-main.js +132 -0
  28. package/dist/src/code-execution/isolate/child-main.js.map +1 -0
  29. package/dist/src/code-execution/isolate/child.d.ts +44 -0
  30. package/dist/src/code-execution/isolate/child.d.ts.map +1 -0
  31. package/dist/src/code-execution/isolate/child.js +315 -0
  32. package/dist/src/code-execution/isolate/child.js.map +1 -0
  33. package/dist/src/code-execution/isolate/frames.d.ts +80 -0
  34. package/dist/src/code-execution/isolate/frames.d.ts.map +1 -0
  35. package/dist/src/code-execution/isolate/frames.js +210 -0
  36. package/dist/src/code-execution/isolate/frames.js.map +1 -0
  37. package/dist/src/code-execution/isolate/output.d.ts +68 -0
  38. package/dist/src/code-execution/isolate/output.d.ts.map +1 -0
  39. package/dist/src/code-execution/isolate/output.js +143 -0
  40. package/dist/src/code-execution/isolate/output.js.map +1 -0
  41. package/dist/src/code-execution/isolate/prelude.d.ts +109 -0
  42. package/dist/src/code-execution/isolate/prelude.d.ts.map +1 -0
  43. package/dist/src/code-execution/isolate/prelude.js +401 -0
  44. package/dist/src/code-execution/isolate/prelude.js.map +1 -0
  45. package/dist/src/code-execution/isolate/protocol.d.ts +151 -0
  46. package/dist/src/code-execution/isolate/protocol.d.ts.map +1 -0
  47. package/dist/src/code-execution/isolate/protocol.js +150 -0
  48. package/dist/src/code-execution/isolate/protocol.js.map +1 -0
  49. package/dist/src/code-execution/isolate/render.d.ts +57 -0
  50. package/dist/src/code-execution/isolate/render.d.ts.map +1 -0
  51. package/dist/src/code-execution/isolate/render.js +214 -0
  52. package/dist/src/code-execution/isolate/render.js.map +1 -0
  53. package/dist/src/code-execution/isolate/runner.d.ts +250 -0
  54. package/dist/src/code-execution/isolate/runner.d.ts.map +1 -0
  55. package/dist/src/code-execution/isolate/runner.js +854 -0
  56. package/dist/src/code-execution/isolate/runner.js.map +1 -0
  57. package/dist/src/code-execution/isolate/scripts.d.ts +175 -0
  58. package/dist/src/code-execution/isolate/scripts.d.ts.map +1 -0
  59. package/dist/src/code-execution/isolate/scripts.js +357 -0
  60. package/dist/src/code-execution/isolate/scripts.js.map +1 -0
  61. package/dist/src/code-execution/quickjs.wasm +0 -0
  62. package/dist/src/code-execution/tool-definition.d.ts +93 -43
  63. package/dist/src/code-execution/tool-definition.d.ts.map +1 -1
  64. package/dist/src/code-execution/tool-definition.js +176 -142
  65. package/dist/src/code-execution/tool-definition.js.map +1 -1
  66. package/dist/src/deadline-timer.d.ts +3 -0
  67. package/dist/src/deadline-timer.d.ts.map +1 -1
  68. package/dist/src/deadline-timer.js +1 -1
  69. package/dist/src/deadline-timer.js.map +1 -1
  70. package/dist/src/framework.d.ts +1036 -440
  71. package/dist/src/framework.d.ts.map +1 -1
  72. package/dist/src/framework.js +4131 -2228
  73. package/dist/src/framework.js.map +1 -1
  74. package/dist/src/gate/event-gate.d.ts +28 -1
  75. package/dist/src/gate/event-gate.d.ts.map +1 -1
  76. package/dist/src/gate/event-gate.js +88 -10
  77. package/dist/src/gate/event-gate.js.map +1 -1
  78. package/dist/src/held-writes.d.ts +16 -3
  79. package/dist/src/held-writes.d.ts.map +1 -1
  80. package/dist/src/held-writes.js +16 -3
  81. package/dist/src/held-writes.js.map +1 -1
  82. package/dist/src/index.d.ts +6 -6
  83. package/dist/src/index.d.ts.map +1 -1
  84. package/dist/src/index.js +9 -8
  85. package/dist/src/index.js.map +1 -1
  86. package/dist/src/mcpl/channel-registry.d.ts +471 -75
  87. package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
  88. package/dist/src/mcpl/channel-registry.js +1673 -337
  89. package/dist/src/mcpl/channel-registry.js.map +1 -1
  90. package/dist/src/mcpl/conversation-router.d.ts +12 -7
  91. package/dist/src/mcpl/conversation-router.d.ts.map +1 -1
  92. package/dist/src/mcpl/conversation-router.js +12 -7
  93. package/dist/src/mcpl/conversation-router.js.map +1 -1
  94. package/dist/src/mcpl/convert-block.d.ts.map +1 -1
  95. package/dist/src/mcpl/convert-block.js +9 -5
  96. package/dist/src/mcpl/convert-block.js.map +1 -1
  97. package/dist/src/mcpl/inbound-source.d.ts +50 -0
  98. package/dist/src/mcpl/inbound-source.d.ts.map +1 -1
  99. package/dist/src/mcpl/inbound-source.js +130 -0
  100. package/dist/src/mcpl/inbound-source.js.map +1 -1
  101. package/dist/src/mcpl/index.d.ts +2 -1
  102. package/dist/src/mcpl/index.d.ts.map +1 -1
  103. package/dist/src/mcpl/index.js +3 -2
  104. package/dist/src/mcpl/index.js.map +1 -1
  105. package/dist/src/mcpl/log-value.d.ts +6 -0
  106. package/dist/src/mcpl/log-value.d.ts.map +1 -1
  107. package/dist/src/mcpl/log-value.js +8 -0
  108. package/dist/src/mcpl/log-value.js.map +1 -1
  109. package/dist/src/mcpl/modern-connection.d.ts +15 -6
  110. package/dist/src/mcpl/modern-connection.d.ts.map +1 -1
  111. package/dist/src/mcpl/modern-connection.js +168 -53
  112. package/dist/src/mcpl/modern-connection.js.map +1 -1
  113. package/dist/src/mcpl/prose-grammar.d.ts +4 -5
  114. package/dist/src/mcpl/prose-grammar.d.ts.map +1 -1
  115. package/dist/src/mcpl/prose-grammar.js +4 -5
  116. package/dist/src/mcpl/prose-grammar.js.map +1 -1
  117. package/dist/src/mcpl/protocol-family.d.ts +97 -10
  118. package/dist/src/mcpl/protocol-family.d.ts.map +1 -1
  119. package/dist/src/mcpl/protocol-family.js +173 -16
  120. package/dist/src/mcpl/protocol-family.js.map +1 -1
  121. package/dist/src/mcpl/push-coalescer.d.ts +132 -14
  122. package/dist/src/mcpl/push-coalescer.d.ts.map +1 -1
  123. package/dist/src/mcpl/push-coalescer.js +227 -50
  124. package/dist/src/mcpl/push-coalescer.js.map +1 -1
  125. package/dist/src/mcpl/push-handler.d.ts +6 -1
  126. package/dist/src/mcpl/push-handler.d.ts.map +1 -1
  127. package/dist/src/mcpl/push-handler.js +4 -1
  128. package/dist/src/mcpl/push-handler.js.map +1 -1
  129. package/dist/src/mcpl/reference-fetcher.d.ts +2 -2
  130. package/dist/src/mcpl/reference-fetcher.d.ts.map +1 -1
  131. package/dist/src/mcpl/reference-fetcher.js +4 -4
  132. package/dist/src/mcpl/reference-fetcher.js.map +1 -1
  133. package/dist/src/mcpl/server-connection.d.ts +50 -21
  134. package/dist/src/mcpl/server-connection.d.ts.map +1 -1
  135. package/dist/src/mcpl/server-connection.js +158 -74
  136. package/dist/src/mcpl/server-connection.js.map +1 -1
  137. package/dist/src/mcpl/tags.d.ts +24 -0
  138. package/dist/src/mcpl/tags.d.ts.map +1 -1
  139. package/dist/src/mcpl/tags.js +33 -0
  140. package/dist/src/mcpl/tags.js.map +1 -1
  141. package/dist/src/mcpl/tool-result-normalize.d.ts +2 -1
  142. package/dist/src/mcpl/tool-result-normalize.d.ts.map +1 -1
  143. package/dist/src/mcpl/tool-result-normalize.js.map +1 -1
  144. package/dist/src/mcpl/transport.d.ts +55 -7
  145. package/dist/src/mcpl/transport.d.ts.map +1 -1
  146. package/dist/src/mcpl/transport.js +163 -34
  147. package/dist/src/mcpl/transport.js.map +1 -1
  148. package/dist/src/mcpl/types.d.ts +22 -6
  149. package/dist/src/mcpl/types.d.ts.map +1 -1
  150. package/dist/src/mcpl/types.js.map +1 -1
  151. package/dist/src/module-registry.d.ts +4 -2
  152. package/dist/src/module-registry.d.ts.map +1 -1
  153. package/dist/src/module-registry.js +100 -13
  154. package/dist/src/module-registry.js.map +1 -1
  155. package/dist/src/modules/discord/index.d.ts.map +1 -1
  156. package/dist/src/modules/discord/index.js +8 -13
  157. package/dist/src/modules/discord/index.js.map +1 -1
  158. package/dist/src/modules/history/index.d.ts.map +1 -1
  159. package/dist/src/modules/history/index.js +27 -4
  160. package/dist/src/modules/history/index.js.map +1 -1
  161. package/dist/src/modules/history/semantic.d.ts +15 -3
  162. package/dist/src/modules/history/semantic.d.ts.map +1 -1
  163. package/dist/src/modules/history/semantic.js +27 -5
  164. package/dist/src/modules/history/semantic.js.map +1 -1
  165. package/dist/src/modules/index.d.ts +1 -1
  166. package/dist/src/modules/index.d.ts.map +1 -1
  167. package/dist/src/modules/index.js.map +1 -1
  168. package/dist/src/modules/unknown-tool.d.ts +4 -1
  169. package/dist/src/modules/unknown-tool.d.ts.map +1 -1
  170. package/dist/src/modules/unknown-tool.js +4 -1
  171. package/dist/src/modules/unknown-tool.js.map +1 -1
  172. package/dist/src/modules/workspace/branch-intent.d.ts +3 -1
  173. package/dist/src/modules/workspace/branch-intent.d.ts.map +1 -1
  174. package/dist/src/modules/workspace/branch-intent.js +3 -1
  175. package/dist/src/modules/workspace/branch-intent.js.map +1 -1
  176. package/dist/src/modules/workspace/edit-plan.d.ts +265 -0
  177. package/dist/src/modules/workspace/edit-plan.d.ts.map +1 -0
  178. package/dist/src/modules/workspace/edit-plan.js +794 -0
  179. package/dist/src/modules/workspace/edit-plan.js.map +1 -0
  180. package/dist/src/modules/workspace/edit-text.d.ts +117 -0
  181. package/dist/src/modules/workspace/edit-text.d.ts.map +1 -0
  182. package/dist/src/modules/workspace/edit-text.js +584 -0
  183. package/dist/src/modules/workspace/edit-text.js.map +1 -0
  184. package/dist/src/modules/workspace/effects.d.ts +5 -4
  185. package/dist/src/modules/workspace/effects.d.ts.map +1 -1
  186. package/dist/src/modules/workspace/effects.js +78 -25
  187. package/dist/src/modules/workspace/effects.js.map +1 -1
  188. package/dist/src/modules/workspace/index.d.ts +484 -61
  189. package/dist/src/modules/workspace/index.d.ts.map +1 -1
  190. package/dist/src/modules/workspace/index.js +2173 -645
  191. package/dist/src/modules/workspace/index.js.map +1 -1
  192. package/dist/src/modules/workspace/observe.d.ts +213 -38
  193. package/dist/src/modules/workspace/observe.d.ts.map +1 -1
  194. package/dist/src/modules/workspace/observe.js +416 -36
  195. package/dist/src/modules/workspace/observe.js.map +1 -1
  196. package/dist/src/modules/workspace/reconcile.d.ts.map +1 -1
  197. package/dist/src/modules/workspace/reconcile.js +15 -8
  198. package/dist/src/modules/workspace/reconcile.js.map +1 -1
  199. package/dist/src/modules/workspace/text.d.ts +32 -0
  200. package/dist/src/modules/workspace/text.d.ts.map +1 -0
  201. package/dist/src/modules/workspace/text.js +67 -0
  202. package/dist/src/modules/workspace/text.js.map +1 -0
  203. package/dist/src/modules/workspace/types.d.ts +210 -6
  204. package/dist/src/modules/workspace/types.d.ts.map +1 -1
  205. package/dist/src/modules/workspace/types.js.map +1 -1
  206. package/dist/src/modules/workspace/watcher.d.ts +3 -2
  207. package/dist/src/modules/workspace/watcher.d.ts.map +1 -1
  208. package/dist/src/modules/workspace/watcher.js.map +1 -1
  209. package/dist/src/operator-log.d.ts +52 -24
  210. package/dist/src/operator-log.d.ts.map +1 -1
  211. package/dist/src/operator-log.js.map +1 -1
  212. package/dist/src/recovery/discord-awareness-outbox.d.ts +496 -72
  213. package/dist/src/recovery/discord-awareness-outbox.d.ts.map +1 -1
  214. package/dist/src/recovery/discord-awareness-outbox.js +1196 -289
  215. package/dist/src/recovery/discord-awareness-outbox.js.map +1 -1
  216. package/dist/src/recovery/offline-branch.d.ts +26 -1
  217. package/dist/src/recovery/offline-branch.d.ts.map +1 -1
  218. package/dist/src/recovery/offline-branch.js +164 -39
  219. package/dist/src/recovery/offline-branch.js.map +1 -1
  220. package/dist/src/recovery/recover-cli.js +23 -4
  221. package/dist/src/recovery/recover-cli.js.map +1 -1
  222. package/dist/src/send-tools.d.ts +11 -0
  223. package/dist/src/send-tools.d.ts.map +1 -0
  224. package/dist/src/send-tools.js +11 -0
  225. package/dist/src/send-tools.js.map +1 -0
  226. package/dist/src/tool-result-guard.d.ts +4 -3
  227. package/dist/src/tool-result-guard.d.ts.map +1 -1
  228. package/dist/src/tool-result-guard.js +5 -4
  229. package/dist/src/tool-result-guard.js.map +1 -1
  230. package/dist/src/tool-result-history.d.ts +1 -1
  231. package/dist/src/tool-result-history.js +1 -1
  232. package/dist/src/tune-out/coordinator.d.ts +21 -0
  233. package/dist/src/tune-out/coordinator.d.ts.map +1 -1
  234. package/dist/src/tune-out/coordinator.js +139 -37
  235. package/dist/src/tune-out/coordinator.js.map +1 -1
  236. package/dist/src/types/agent.d.ts +4 -0
  237. package/dist/src/types/agent.d.ts.map +1 -1
  238. package/dist/src/types/events.d.ts +62 -9
  239. package/dist/src/types/events.d.ts.map +1 -1
  240. package/dist/src/types/framework.d.ts +62 -58
  241. package/dist/src/types/framework.d.ts.map +1 -1
  242. package/dist/src/types/module.d.ts +40 -8
  243. package/dist/src/types/module.d.ts.map +1 -1
  244. package/dist/src/types/trace.d.ts +111 -10
  245. package/dist/src/types/trace.d.ts.map +1 -1
  246. package/dist/src/usage/types.d.ts +16 -0
  247. package/dist/src/usage/types.d.ts.map +1 -1
  248. package/dist/src/usage/usage-tracker.d.ts +14 -1
  249. package/dist/src/usage/usage-tracker.d.ts.map +1 -1
  250. package/dist/src/usage/usage-tracker.js +81 -41
  251. package/dist/src/usage/usage-tracker.js.map +1 -1
  252. package/package.json +6 -5
  253. package/src/agent.ts +93 -12
  254. package/src/api/server.ts +14 -12
  255. package/src/code-execution/engine.ts +595 -0
  256. package/src/code-execution/index.ts +5 -17
  257. package/src/code-execution/isolate/calls.ts +199 -0
  258. package/src/code-execution/isolate/child-entry.ts +5 -0
  259. package/src/code-execution/isolate/child-main.ts +132 -0
  260. package/src/code-execution/isolate/child.ts +327 -0
  261. package/src/code-execution/isolate/frames.ts +209 -0
  262. package/src/code-execution/isolate/output.ts +161 -0
  263. package/src/code-execution/isolate/prelude.ts +409 -0
  264. package/src/code-execution/isolate/protocol.ts +240 -0
  265. package/src/code-execution/isolate/render.ts +230 -0
  266. package/src/code-execution/isolate/runner.ts +911 -0
  267. package/src/code-execution/isolate/scripts.ts +479 -0
  268. package/src/code-execution/quickjs.wasm +0 -0
  269. package/src/code-execution/quickjs.wasm.LICENSES +149 -0
  270. package/src/code-execution/tool-definition.ts +236 -167
  271. package/src/deadline-timer.ts +1 -1
  272. package/src/framework.ts +4507 -2406
  273. package/src/gate/event-gate.ts +78 -11
  274. package/src/held-writes.ts +17 -3
  275. package/src/index.ts +30 -22
  276. package/src/mcpl/channel-registry.ts +1825 -368
  277. package/src/mcpl/conversation-router.ts +12 -7
  278. package/src/mcpl/convert-block.ts +9 -5
  279. package/src/mcpl/inbound-source.ts +131 -0
  280. package/src/mcpl/index.ts +4 -2
  281. package/src/mcpl/log-value.ts +9 -0
  282. package/src/mcpl/modern-connection.ts +162 -53
  283. package/src/mcpl/prose-grammar.ts +4 -5
  284. package/src/mcpl/protocol-family.ts +199 -21
  285. package/src/mcpl/push-coalescer.ts +306 -62
  286. package/src/mcpl/push-handler.ts +10 -2
  287. package/src/mcpl/reference-fetcher.ts +4 -4
  288. package/src/mcpl/server-connection.ts +180 -79
  289. package/src/mcpl/tags.ts +36 -0
  290. package/src/mcpl/tool-result-normalize.ts +2 -1
  291. package/src/mcpl/transport.ts +162 -33
  292. package/src/mcpl/types.ts +23 -6
  293. package/src/module-registry.ts +92 -13
  294. package/src/modules/discord/index.ts +8 -13
  295. package/src/modules/history/index.ts +25 -3
  296. package/src/modules/history/semantic.ts +29 -6
  297. package/src/modules/index.ts +1 -0
  298. package/src/modules/unknown-tool.ts +4 -1
  299. package/src/modules/workspace/branch-intent.ts +3 -1
  300. package/src/modules/workspace/edit-plan.ts +954 -0
  301. package/src/modules/workspace/edit-text.ts +618 -0
  302. package/src/modules/workspace/effects.ts +70 -19
  303. package/src/modules/workspace/index.ts +2247 -642
  304. package/src/modules/workspace/observe.ts +465 -56
  305. package/src/modules/workspace/reconcile.ts +14 -7
  306. package/src/modules/workspace/text.ts +68 -0
  307. package/src/modules/workspace/types.ts +211 -6
  308. package/src/modules/workspace/watcher.ts +3 -2
  309. package/src/operator-log.ts +47 -19
  310. package/src/recovery/discord-awareness-outbox.ts +1500 -356
  311. package/src/recovery/offline-branch.ts +189 -55
  312. package/src/recovery/recover-cli.ts +25 -4
  313. package/src/send-tools.ts +11 -0
  314. package/src/tool-result-guard.ts +6 -5
  315. package/src/tool-result-history.ts +1 -1
  316. package/src/tune-out/coordinator.ts +163 -42
  317. package/src/types/agent.ts +4 -0
  318. package/src/types/events.ts +62 -9
  319. package/src/types/framework.ts +62 -58
  320. package/src/types/module.ts +40 -8
  321. package/src/types/trace.ts +121 -15
  322. package/src/usage/types.ts +16 -0
  323. package/src/usage/usage-tracker.ts +86 -43
  324. package/dist/src/code-execution/py-runner.d.ts +0 -191
  325. package/dist/src/code-execution/py-runner.d.ts.map +0 -1
  326. package/dist/src/code-execution/py-runner.js +0 -655
  327. package/dist/src/code-execution/py-runner.js.map +0 -1
  328. package/dist/src/code-execution/runtime-py.d.ts +0 -50
  329. package/dist/src/code-execution/runtime-py.d.ts.map +0 -1
  330. package/dist/src/code-execution/runtime-py.js +0 -677
  331. package/dist/src/code-execution/runtime-py.js.map +0 -1
  332. package/dist/src/mcpl/prose-stream-router.d.ts +0 -88
  333. package/dist/src/mcpl/prose-stream-router.d.ts.map +0 -1
  334. package/dist/src/mcpl/prose-stream-router.js +0 -291
  335. package/dist/src/mcpl/prose-stream-router.js.map +0 -1
  336. package/src/code-execution/py-runner.ts +0 -791
  337. package/src/code-execution/runtime-py.ts +0 -677
  338. package/src/mcpl/prose-stream-router.ts +0 -268
@@ -0,0 +1,230 @@
1
+ /**
2
+ * What the model reads for a return of `code_execution`: how the script ended
3
+ * or that it's still running, first, so no cut can drop it; then what became
4
+ * of its calls, naming each whose effect is uncertain with a count of the
5
+ * rest; then what it returned and what it wrote since the last return.
6
+ */
7
+
8
+ import { fresh, toolRef, type CallSummary, type NamedCall } from './calls.js';
9
+ import type { Ending } from './runner.js';
10
+ import type { ScriptListing, ScriptReturn } from './scripts.js';
11
+ import { renderOutput } from './output.js';
12
+
13
+ /**
14
+ * The most of a script's return value, or of a failure's message or stack,
15
+ * that a return shows, as a head and a tail of half this each. The run keeps
16
+ * them cut to this, so an ended run kept for a later wait holds no more.
17
+ */
18
+ export const VALUE_CHARS = 8_000;
19
+
20
+ /** The most of a failure's name a return shows: a name is a word, so the message and the stack keep the room. */
21
+ export const NAME_CHARS = 200;
22
+
23
+ /**
24
+ * The most a cut's marker adds to its text (bounded's, with a count of up to
25
+ * 16 digits). A text bounded again with this much room past its first bound
26
+ * keeps its first cut, and the count that cut gives, as they are.
27
+ */
28
+ export const CUT_MARK_CHARS = 64;
29
+
30
+ /**
31
+ * `text`, or its head and tail of about `max / 2` each with the count dropped
32
+ * between, as copies of their own. Neither cut parts a surrogate pair.
33
+ */
34
+ export function bounded(text: string, max: number): string {
35
+ if (text.length <= max) return text;
36
+ const half = Math.floor(max / 2);
37
+ return cutOf(text.slice(0, half), text.slice(text.length - half), text.length);
38
+ }
39
+
40
+ /**
41
+ * bounded's cut of a text of `length` characters, past its bound, from its
42
+ * first and its last `max / 2` characters, rounded down: `head` and `tail`,
43
+ * of that one length. So a text that's never held whole, such as a stack's
44
+ * frames as the agent reads them (scriptFrames), is cut as bounded cuts it.
45
+ */
46
+ export function cutOf(head: string, tail: string, length: number): string {
47
+ const half = head.length;
48
+ let kept = half;
49
+ const last = head.charCodeAt(kept - 1);
50
+ if (last >= 0xd800 && last <= 0xdbff) kept -= 1;
51
+ const first = tail.charCodeAt(0);
52
+ const skipped = first >= 0xdc00 && first <= 0xdfff ? 1 : 0;
53
+ return `${fresh(head.slice(0, kept))}\n[… ${length - half + skipped - kept} characters dropped here …]\n${fresh(tail.slice(skipped))}`;
54
+ }
55
+
56
+ /** A duration as the settings give it: exactly, a fraction of a second included. */
57
+ export function formatMs(ms: number): string {
58
+ if (ms < 1000) return `${ms} ms`;
59
+ if (ms % 3_600_000 === 0) return `${ms / 3_600_000} h`;
60
+ if (ms % 60_000 === 0) return `${ms / 60_000} min`;
61
+ return `${ms / 1000} s`;
62
+ }
63
+
64
+ function endingLine(id: string, ending: Ending, lifetimeMs: number): string {
65
+ switch (ending.how) {
66
+ case 'finished':
67
+ return `Script ${id} finished.`;
68
+ case 'failed':
69
+ // The run keeps the message cut to VALUE_CHARS, with room for the cut's marker.
70
+ return `Script ${id} failed: ${ending.error.name ? `${ending.error.name}: ` : ''}${ending.error.message}`;
71
+ case 'stopped': {
72
+ const why = ending.reason === 'agent'
73
+ ? `Script ${id} was stopped, as you asked.`
74
+ : ending.why
75
+ ? `Script ${id} was stopped: ${ending.why}.`
76
+ : `Script ${id} was stopped at its limit of ${formatMs(lifetimeMs)}.`;
77
+ return ending.short ? `${why} Its process didn't stop by itself and was ended, so its output may be short.` : why;
78
+ }
79
+ case 'crashed':
80
+ // The detail is the host's account; what it means for the agent follows.
81
+ return `Script ${id} crashed: ${ending.detail}. A crash is the script's process failing, not an error its code threw: a fault in the host or its runtime, or something the script's own data asked of the runtime that it couldn't do, such as reading values nested thousands deep, or code nested hundreds deep. Running it again may work; if the same script crashes again, change what it does with its data or its code.`;
82
+ }
83
+ }
84
+
85
+ /**
86
+ * The start of `text`, up to `max` characters and "…" when it goes on, never
87
+ * parting a surrogate pair: a glimpse of a text that may already have been cut,
88
+ * whose count a second cut would misstate.
89
+ */
90
+ export function glimpse(text: string, max: number): string {
91
+ if (text.length <= max) return text;
92
+ let cut = max;
93
+ const last = text.charCodeAt(cut - 1);
94
+ if (last >= 0xd800 && last <= 0xdbff) cut -= 1;
95
+ return `${fresh(text.slice(0, cut))}…`;
96
+ }
97
+
98
+ /** A named call as the agent wrote it, with its arguments. */
99
+ function namedRef(call: NamedCall): string {
100
+ return call.tool === 'wake_agent' ? `wake_agent(${call.args})` : `${toolRef(call.tool)}(${call.args})`;
101
+ }
102
+
103
+ function namedLine(call: NamedCall): string {
104
+ switch (call.state) {
105
+ case 'uncertain':
106
+ return `- still running when the script ended, so it may or may not take effect: ${namedRef(call)}`;
107
+ case 'timed-out':
108
+ return `- timed out in the script, and still running when the script ended, so it may still take effect: ${namedRef(call)}`;
109
+ case 'timed-out-answered':
110
+ return `- timed out in the script, and its answer came later: ${namedRef(call)}, answer ${JSON.stringify(call.answer ?? '')}`;
111
+ case 'too-large':
112
+ return `- answered with a result the script couldn't receive, too large for its memory or nested too deep, so it got an error instead: ${namedRef(call)}`;
113
+ case 'unseen':
114
+ return `- answered, but the script ended before it read the answer: ${namedRef(call)}`;
115
+ }
116
+ }
117
+
118
+ /**
119
+ * What became of the calls. At a yield, counts. At the end, counts, and each
120
+ * call whose answer the script didn't see, named with its arguments, past
121
+ * CALLS_NAMED counted by tool.
122
+ */
123
+ function callsLines(calls: CallSummary, running: boolean): string {
124
+ if (calls.made === 0) return running ? 'It has made no tool calls yet.' : 'It made no tool calls.';
125
+ const unseen = calls.named.length + Object.values(calls.more).reduce((sum, n) => sum + n, 0);
126
+ const parts: string[] = [];
127
+ const add = (n: number, words: string) => {
128
+ if (n > 0) parts.push(`${n} ${words}`);
129
+ };
130
+ add(calls.answered, 'answered');
131
+ add(calls.failed, 'answered with an error');
132
+ add(calls.refused, calls.refused === 1 ? 'refused before it ran, so nothing was done' : 'refused before they ran, so nothing was done');
133
+ add(calls.unsent, 'never sent, so nothing was done');
134
+ add(calls.running, 'still running');
135
+ add(calls.waiting, 'waiting their turn in the host');
136
+ // Timed out, answered with a result too large for the script's memory,
137
+ // still running when the script ended (uncertain), or answered after the
138
+ // script stopped reading (unseen): either way the script went on without
139
+ // the answer.
140
+ add(unseen, unseen === 1 ? "whose answer it didn't see" : "whose answers it didn't see");
141
+ const head = `${running ? 'Its calls so far' : 'Its calls'}: ${calls.made}${parts.length ? ` (${parts.join('; ')})` : ''}`;
142
+ if (running || unseen === 0) return `${head}.`;
143
+ const lines = [`${head}:`, ...calls.named.map(namedLine)];
144
+ const more = Object.entries(calls.more);
145
+ if (more.length > 0) {
146
+ lines.push(`- and ${unseen - calls.named.length} more: ${more.map(([tool, n]) => `${toolRef(tool)} ×${n}`).join(', ')}`);
147
+ }
148
+ return lines.join('\n');
149
+ }
150
+
151
+ export interface RenderOptions {
152
+ /** The bound the return was made at, for a yield's line. */
153
+ boundMs: number;
154
+ lifetimeMs: number;
155
+ /**
156
+ * The agent's inline cap for tool results, which the return is stored
157
+ * under: the output is cut to the room the rest of the return leaves in
158
+ * it. None when left out.
159
+ */
160
+ maxChars?: number;
161
+ }
162
+
163
+ /** The text a return gives the model. */
164
+ export function renderReturn(r: ScriptReturn, options: RenderOptions): string {
165
+ const lines: string[] = [];
166
+ if (r.ending === null) {
167
+ lines.push(`Script ${r.scriptId} is still running after ${formatMs(options.boundMs)}.`);
168
+ lines.push(
169
+ r.stopsAtTurnEnd
170
+ ? `It will be stopped when your turn ends if it's still running, since only the primary agent's scripts outlive a turn. ` +
171
+ `Wait for it with {"action": "wait", "script_id": "${r.scriptId}"} to see it finish, or stop it with {"action": "stop", "script_id": "${r.scriptId}"}.`
172
+ : `Wait for it with {"action": "wait", "script_id": "${r.scriptId}"}, stop it with {"action": "stop", "script_id": "${r.scriptId}"}, ` +
173
+ 'or leave it running: it can wake you with wake_agent(), and you are woken if it fails, crashes or reaches its limit.',
174
+ );
175
+ } else {
176
+ lines.push(endingLine(r.scriptId, r.ending, options.lifetimeMs));
177
+ }
178
+ // The ending's line gave the name and message; the script's frames follow (GuestError.stack).
179
+ if (r.ending?.how === 'failed' && r.ending.error.stack) lines.push(r.ending.error.stack);
180
+ lines.push(callsLines(r.calls, r.ending === null));
181
+ // The run keeps the value cut to VALUE_CHARS, with room for the cut's marker.
182
+ if (r.ending?.how === 'finished' && r.ending.value !== undefined) lines.push(`It returned: ${r.ending.value}`);
183
+ const { head, tail, dropped } = r.output;
184
+ if (head.length + tail.length + dropped === 0) {
185
+ lines.push(r.first ? 'No output.' : 'No output since the last return.');
186
+ return lines.join('\n');
187
+ }
188
+ // The output comes last, and past the agent's inline cap the framework's
189
+ // cut would take its tail first: it gets the room the rest leaves, its head
190
+ // and tail cut alike.
191
+ const label = `${r.first ? 'Its output' : 'Its output since the last return'}:\n`;
192
+ const rest = lines.join('\n').length + 1 + label.length;
193
+ lines.push(label + renderOutput(r.output, (options.maxChars ?? Infinity) - rest));
194
+ return lines.join('\n');
195
+ }
196
+
197
+ function minutesAgo(ms: number): string {
198
+ const minutes = Math.round(ms / 60_000);
199
+ return minutes < 1 ? 'under a minute' : `${minutes} min`;
200
+ }
201
+
202
+ /** How a listed script stands, in a few words. */
203
+ function listingState(s: ScriptListing, now: number): string {
204
+ if (s.running) return `running for ${minutesAgo(now - s.startedAt)}`;
205
+ const when = s.endedAt === null ? '' : ` ${minutesAgo(now - s.endedAt)} ago`;
206
+ const e = s.ending;
207
+ switch (e?.how) {
208
+ case 'finished':
209
+ return `finished${when}`;
210
+ case 'failed':
211
+ return `failed${when}: ${e.error.name ? `${e.error.name}: ` : ''}${glimpse(e.error.message, 300)}`;
212
+ case 'crashed':
213
+ return `crashed${when}`;
214
+ case 'stopped':
215
+ return e.reason === 'agent' ? `stopped by you${when}` : e.why ? `stopped${when}: ${e.why}` : `stopped at its limit${when}`;
216
+ default:
217
+ return 'ended';
218
+ }
219
+ }
220
+
221
+ /** A `list` of an agent's scripts: each one's id and how it stands, with how to see more. */
222
+ export function renderList(scripts: ScriptListing[], now: number): string {
223
+ if (scripts.length === 0) return 'You have no scripts.';
224
+ const lines = scripts.map((s) => `- ${s.scriptId}: ${listingState(s, now)}${s.wakes > 0 ? ` (${s.wakes} wake${s.wakes === 1 ? '' : 's'} delivered)` : ''}`);
225
+ return [
226
+ 'Your scripts:',
227
+ ...lines,
228
+ '{"action": "wait", "script_id": ...} gives a script\'s output since its last return, or its result once it has ended.',
229
+ ].join('\n');
230
+ }