@roj-ai/sdk 0.1.36 → 0.2.1

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 (922) hide show
  1. package/dist/bootstrap.d.ts +420 -26
  2. package/dist/bootstrap.d.ts.map +1 -1
  3. package/dist/bootstrap.js +55 -24
  4. package/dist/bootstrap.js.map +1 -1
  5. package/dist/bun-platform/fs.d.ts.map +1 -1
  6. package/dist/bun-platform/fs.js +1 -0
  7. package/dist/bun-platform/fs.js.map +1 -1
  8. package/dist/bun-platform/index.d.ts +4 -1
  9. package/dist/bun-platform/index.d.ts.map +1 -1
  10. package/dist/bun-platform/index.js +7 -1
  11. package/dist/bun-platform/index.js.map +1 -1
  12. package/dist/bun-platform/server-lifecycle.d.ts +30 -0
  13. package/dist/bun-platform/server-lifecycle.d.ts.map +1 -0
  14. package/dist/bun-platform/server-lifecycle.js +182 -0
  15. package/dist/bun-platform/server-lifecycle.js.map +1 -0
  16. package/dist/bun-platform/shell.d.ts +33 -0
  17. package/dist/bun-platform/shell.d.ts.map +1 -0
  18. package/dist/bun-platform/shell.js +322 -0
  19. package/dist/bun-platform/shell.js.map +1 -0
  20. package/dist/config.d.ts +34 -0
  21. package/dist/config.d.ts.map +1 -1
  22. package/dist/config.js +97 -0
  23. package/dist/config.js.map +1 -1
  24. package/dist/core/agents/agent.d.ts +42 -7
  25. package/dist/core/agents/agent.d.ts.map +1 -1
  26. package/dist/core/agents/agent.js +202 -87
  27. package/dist/core/agents/agent.js.map +1 -1
  28. package/dist/core/agents/config.d.ts +8 -1
  29. package/dist/core/agents/config.d.ts.map +1 -1
  30. package/dist/core/agents/config.js +5 -1
  31. package/dist/core/agents/config.js.map +1 -1
  32. package/dist/core/agents/retry.d.ts +1 -1
  33. package/dist/core/agents/retry.d.ts.map +1 -1
  34. package/dist/core/agents/retry.js +14 -16
  35. package/dist/core/agents/retry.js.map +1 -1
  36. package/dist/core/agents/state.d.ts +3 -1
  37. package/dist/core/agents/state.d.ts.map +1 -1
  38. package/dist/core/agents/state.js +1 -1
  39. package/dist/core/agents/state.js.map +1 -1
  40. package/dist/core/context/state.d.ts +3 -3
  41. package/dist/core/context/state.js +2 -2
  42. package/dist/core/events/base-event-store.d.ts.map +1 -1
  43. package/dist/core/events/base-event-store.js +22 -14
  44. package/dist/core/events/base-event-store.js.map +1 -1
  45. package/dist/core/events/file.d.ts +39 -1
  46. package/dist/core/events/file.d.ts.map +1 -1
  47. package/dist/core/events/file.js +159 -20
  48. package/dist/core/events/file.js.map +1 -1
  49. package/dist/core/events/types.d.ts +1 -1
  50. package/dist/core/file-store/containment.d.ts +19 -0
  51. package/dist/core/file-store/containment.d.ts.map +1 -0
  52. package/dist/core/file-store/containment.js +62 -0
  53. package/dist/core/file-store/containment.js.map +1 -0
  54. package/dist/core/file-store/file-store.d.ts +22 -2
  55. package/dist/core/file-store/file-store.d.ts.map +1 -1
  56. package/dist/core/file-store/file-store.js +88 -20
  57. package/dist/core/file-store/file-store.js.map +1 -1
  58. package/dist/core/file-store/types.d.ts +13 -1
  59. package/dist/core/file-store/types.d.ts.map +1 -1
  60. package/dist/core/image/image-processor.d.ts.map +1 -1
  61. package/dist/core/image/image-processor.js +3 -1
  62. package/dist/core/image/image-processor.js.map +1 -1
  63. package/dist/core/image/types.d.ts +2 -0
  64. package/dist/core/image/types.d.ts.map +1 -1
  65. package/dist/core/image/vips-resizer.d.ts.map +1 -1
  66. package/dist/core/image/vips-resizer.js +81 -33
  67. package/dist/core/image/vips-resizer.js.map +1 -1
  68. package/dist/core/llm/anthropic.d.ts +0 -1
  69. package/dist/core/llm/anthropic.d.ts.map +1 -1
  70. package/dist/core/llm/anthropic.js +58 -72
  71. package/dist/core/llm/anthropic.js.map +1 -1
  72. package/dist/core/llm/logger.d.ts +14 -2
  73. package/dist/core/llm/logger.d.ts.map +1 -1
  74. package/dist/core/llm/logger.js +161 -36
  75. package/dist/core/llm/logger.js.map +1 -1
  76. package/dist/core/llm/openrouter.d.ts +0 -1
  77. package/dist/core/llm/openrouter.d.ts.map +1 -1
  78. package/dist/core/llm/openrouter.js +53 -66
  79. package/dist/core/llm/openrouter.js.map +1 -1
  80. package/dist/core/llm/provider-request.d.ts +10 -0
  81. package/dist/core/llm/provider-request.d.ts.map +1 -0
  82. package/dist/core/llm/provider-request.js +41 -0
  83. package/dist/core/llm/provider-request.js.map +1 -0
  84. package/dist/core/llm/provider.d.ts +11 -0
  85. package/dist/core/llm/provider.d.ts.map +1 -1
  86. package/dist/core/llm/provider.js +26 -0
  87. package/dist/core/llm/provider.js.map +1 -1
  88. package/dist/core/llm/state.d.ts +2 -2
  89. package/dist/core/llm/state.js +4 -4
  90. package/dist/core/plugins/plugin-builder.d.ts +57 -3
  91. package/dist/core/plugins/plugin-builder.d.ts.map +1 -1
  92. package/dist/core/plugins/plugin-builder.js +68 -14
  93. package/dist/core/plugins/plugin-builder.js.map +1 -1
  94. package/dist/core/preset/preset-builder.d.ts +3 -2
  95. package/dist/core/preset/preset-builder.d.ts.map +1 -1
  96. package/dist/core/preset/preset-builder.js +7 -16
  97. package/dist/core/preset/preset-builder.js.map +1 -1
  98. package/dist/core/sessions/context.d.ts +23 -5
  99. package/dist/core/sessions/context.d.ts.map +1 -1
  100. package/dist/core/sessions/runtime-activity.d.ts +33 -0
  101. package/dist/core/sessions/runtime-activity.d.ts.map +1 -0
  102. package/dist/core/sessions/runtime-activity.js +55 -0
  103. package/dist/core/sessions/runtime-activity.js.map +1 -0
  104. package/dist/core/sessions/schema.d.ts +23 -2
  105. package/dist/core/sessions/schema.d.ts.map +1 -1
  106. package/dist/core/sessions/schema.js +24 -3
  107. package/dist/core/sessions/schema.js.map +1 -1
  108. package/dist/core/sessions/session-manager.d.ts +83 -6
  109. package/dist/core/sessions/session-manager.d.ts.map +1 -1
  110. package/dist/core/sessions/session-manager.js +517 -118
  111. package/dist/core/sessions/session-manager.js.map +1 -1
  112. package/dist/core/sessions/session-store.d.ts +18 -0
  113. package/dist/core/sessions/session-store.d.ts.map +1 -1
  114. package/dist/core/sessions/session-store.js +33 -0
  115. package/dist/core/sessions/session-store.js.map +1 -1
  116. package/dist/core/sessions/session.d.ts +42 -6
  117. package/dist/core/sessions/session.d.ts.map +1 -1
  118. package/dist/core/sessions/session.js +176 -44
  119. package/dist/core/sessions/session.js.map +1 -1
  120. package/dist/core/sessions/state.d.ts +10 -1
  121. package/dist/core/sessions/state.d.ts.map +1 -1
  122. package/dist/core/sessions/state.js +11 -1
  123. package/dist/core/sessions/state.js.map +1 -1
  124. package/dist/core/system.d.ts +9 -0
  125. package/dist/core/system.d.ts.map +1 -1
  126. package/dist/core/system.js +4 -1
  127. package/dist/core/system.js.map +1 -1
  128. package/dist/core/tools/executor.d.ts +1 -1
  129. package/dist/core/wake-key.d.ts +34 -0
  130. package/dist/core/wake-key.d.ts.map +1 -0
  131. package/dist/core/wake-key.js +51 -0
  132. package/dist/core/wake-key.js.map +1 -0
  133. package/dist/index.d.ts +23 -13
  134. package/dist/index.d.ts.map +1 -1
  135. package/dist/index.js +22 -8
  136. package/dist/index.js.map +1 -1
  137. package/dist/lib/archive/archive-inspection.d.ts +48 -0
  138. package/dist/lib/archive/archive-inspection.d.ts.map +1 -0
  139. package/dist/lib/archive/archive-inspection.fixtures.d.ts +7 -0
  140. package/dist/lib/archive/archive-inspection.fixtures.d.ts.map +1 -0
  141. package/dist/lib/archive/archive-inspection.fixtures.js +134 -0
  142. package/dist/lib/archive/archive-inspection.fixtures.js.map +1 -0
  143. package/dist/lib/archive/archive-inspection.js +253 -0
  144. package/dist/lib/archive/archive-inspection.js.map +1 -0
  145. package/dist/lib/archive/index.d.ts +3 -0
  146. package/dist/lib/archive/index.d.ts.map +1 -0
  147. package/dist/lib/archive/index.js +2 -0
  148. package/dist/lib/archive/index.js.map +1 -0
  149. package/dist/lib/logger/console.d.ts +5 -12
  150. package/dist/lib/logger/console.d.ts.map +1 -1
  151. package/dist/lib/logger/console.js +5 -47
  152. package/dist/lib/logger/console.js.map +1 -1
  153. package/dist/lib/logger/file.d.ts +8 -11
  154. package/dist/lib/logger/file.d.ts.map +1 -1
  155. package/dist/lib/logger/file.js +26 -37
  156. package/dist/lib/logger/file.js.map +1 -1
  157. package/dist/lib/logger/index.d.ts +3 -1
  158. package/dist/lib/logger/index.d.ts.map +1 -1
  159. package/dist/lib/logger/index.js +3 -1
  160. package/dist/lib/logger/index.js.map +1 -1
  161. package/dist/lib/logger/jsonl.d.ts +21 -0
  162. package/dist/lib/logger/jsonl.d.ts.map +1 -0
  163. package/dist/lib/logger/jsonl.js +29 -0
  164. package/dist/lib/logger/jsonl.js.map +1 -0
  165. package/dist/lib/logger/logger.d.ts +22 -0
  166. package/dist/lib/logger/logger.d.ts.map +1 -1
  167. package/dist/lib/logger/logger.js +37 -0
  168. package/dist/lib/logger/logger.js.map +1 -1
  169. package/dist/lib/logger/session-log.d.ts +21 -0
  170. package/dist/lib/logger/session-log.d.ts.map +1 -0
  171. package/dist/lib/logger/session-log.js +37 -0
  172. package/dist/lib/logger/session-log.js.map +1 -0
  173. package/dist/lib/utils/concurrency.d.ts +1 -1
  174. package/dist/lib/utils/concurrency.d.ts.map +1 -1
  175. package/dist/lib/utils/concurrency.js +30 -7
  176. package/dist/lib/utils/concurrency.js.map +1 -1
  177. package/dist/lib/utils/fs-batch.d.ts +17 -0
  178. package/dist/lib/utils/fs-batch.d.ts.map +1 -0
  179. package/dist/lib/utils/fs-batch.js +38 -0
  180. package/dist/lib/utils/fs-batch.js.map +1 -0
  181. package/dist/lib/utils/result.d.ts +7 -22
  182. package/dist/lib/utils/result.d.ts.map +1 -1
  183. package/dist/lib/utils/result.js +6 -17
  184. package/dist/lib/utils/result.js.map +1 -1
  185. package/dist/lib/utils/sleep.d.ts +10 -0
  186. package/dist/lib/utils/sleep.d.ts.map +1 -0
  187. package/dist/lib/utils/sleep.js +26 -0
  188. package/dist/lib/utils/sleep.js.map +1 -0
  189. package/dist/platform/fs-revision.d.ts +21 -0
  190. package/dist/platform/fs-revision.d.ts.map +1 -0
  191. package/dist/platform/fs-revision.js +9 -0
  192. package/dist/platform/fs-revision.js.map +1 -0
  193. package/dist/platform/fs.d.ts +104 -1
  194. package/dist/platform/fs.d.ts.map +1 -1
  195. package/dist/platform/git.d.ts +59 -0
  196. package/dist/platform/git.d.ts.map +1 -0
  197. package/dist/platform/git.js +8 -0
  198. package/dist/platform/git.js.map +1 -0
  199. package/dist/platform/index.d.ts +40 -1
  200. package/dist/platform/index.d.ts.map +1 -1
  201. package/dist/platform/index.js +1 -1
  202. package/dist/platform/index.js.map +1 -1
  203. package/dist/platform/llm-call-log.d.ts +80 -0
  204. package/dist/platform/llm-call-log.d.ts.map +1 -0
  205. package/dist/platform/llm-call-log.js +12 -0
  206. package/dist/platform/llm-call-log.js.map +1 -0
  207. package/dist/platform/scheduler.d.ts +32 -0
  208. package/dist/platform/scheduler.d.ts.map +1 -0
  209. package/dist/platform/scheduler.js +46 -0
  210. package/dist/platform/scheduler.js.map +1 -0
  211. package/dist/platform/session-log.d.ts +36 -0
  212. package/dist/platform/session-log.d.ts.map +1 -0
  213. package/dist/platform/session-log.js +12 -0
  214. package/dist/platform/session-log.js.map +1 -0
  215. package/dist/platform/shell.d.ts +83 -0
  216. package/dist/platform/shell.d.ts.map +1 -0
  217. package/dist/platform/shell.js +13 -0
  218. package/dist/platform/shell.js.map +1 -0
  219. package/dist/plugins/agent-status/plugin.d.ts.map +1 -1
  220. package/dist/plugins/agent-status/plugin.js +1 -0
  221. package/dist/plugins/agent-status/plugin.js.map +1 -1
  222. package/dist/plugins/agents/plugin.d.ts.map +1 -1
  223. package/dist/plugins/agents/plugin.js +129 -62
  224. package/dist/plugins/agents/plugin.js.map +1 -1
  225. package/dist/plugins/filesystem/listing.d.ts +3 -0
  226. package/dist/plugins/filesystem/listing.d.ts.map +1 -1
  227. package/dist/plugins/filesystem/listing.js +66 -10
  228. package/dist/plugins/filesystem/listing.js.map +1 -1
  229. package/dist/plugins/filesystem/plugin.d.ts.map +1 -1
  230. package/dist/plugins/filesystem/plugin.js +8 -6
  231. package/dist/plugins/filesystem/plugin.js.map +1 -1
  232. package/dist/plugins/git-status/plugin.d.ts +34 -7
  233. package/dist/plugins/git-status/plugin.d.ts.map +1 -1
  234. package/dist/plugins/git-status/plugin.js +168 -64
  235. package/dist/plugins/git-status/plugin.js.map +1 -1
  236. package/dist/plugins/llm-debug/plugin.d.ts.map +1 -1
  237. package/dist/plugins/llm-debug/plugin.js +1 -0
  238. package/dist/plugins/llm-debug/plugin.js.map +1 -1
  239. package/dist/plugins/logs/plugin.d.ts +1 -4
  240. package/dist/plugins/logs/plugin.d.ts.map +1 -1
  241. package/dist/plugins/logs/plugin.js +7 -0
  242. package/dist/plugins/logs/plugin.js.map +1 -1
  243. package/dist/plugins/mailbox/helpers.d.ts +2 -2
  244. package/dist/plugins/mailbox/helpers.js +1 -1
  245. package/dist/plugins/mailbox/plugin.d.ts.map +1 -1
  246. package/dist/plugins/mailbox/plugin.js +38 -43
  247. package/dist/plugins/mailbox/plugin.js.map +1 -1
  248. package/dist/plugins/mailbox/query.d.ts +7 -2
  249. package/dist/plugins/mailbox/query.d.ts.map +1 -1
  250. package/dist/plugins/mailbox/query.js +14 -7
  251. package/dist/plugins/mailbox/query.js.map +1 -1
  252. package/dist/plugins/mailbox/state.d.ts +5 -4
  253. package/dist/plugins/mailbox/state.d.ts.map +1 -1
  254. package/dist/plugins/mailbox/state.js +6 -5
  255. package/dist/plugins/mailbox/state.js.map +1 -1
  256. package/dist/plugins/resources/filename.d.ts +4 -0
  257. package/dist/plugins/resources/filename.d.ts.map +1 -0
  258. package/dist/plugins/resources/filename.js +18 -0
  259. package/dist/plugins/resources/filename.js.map +1 -0
  260. package/dist/plugins/resources/plugin.d.ts +3 -0
  261. package/dist/plugins/resources/plugin.d.ts.map +1 -1
  262. package/dist/plugins/resources/plugin.js +97 -60
  263. package/dist/plugins/resources/plugin.js.map +1 -1
  264. package/dist/plugins/resources/state.d.ts +1 -1
  265. package/dist/plugins/resources/state.js +1 -1
  266. package/dist/plugins/result-eviction/plugin.d.ts.map +1 -1
  267. package/dist/plugins/result-eviction/plugin.js +6 -1
  268. package/dist/plugins/result-eviction/plugin.js.map +1 -1
  269. package/dist/plugins/services/plugin.d.ts +4 -1
  270. package/dist/plugins/services/plugin.d.ts.map +1 -1
  271. package/dist/plugins/services/plugin.js +251 -100
  272. package/dist/plugins/services/plugin.js.map +1 -1
  273. package/dist/plugins/services/prompt.d.ts.map +1 -1
  274. package/dist/plugins/services/prompt.js +1 -4
  275. package/dist/plugins/services/prompt.js.map +1 -1
  276. package/dist/plugins/services/schema.d.ts +15 -5
  277. package/dist/plugins/services/schema.d.ts.map +1 -1
  278. package/dist/plugins/services/service.d.ts +100 -18
  279. package/dist/plugins/services/service.d.ts.map +1 -1
  280. package/dist/plugins/services/service.js +680 -230
  281. package/dist/plugins/services/service.js.map +1 -1
  282. package/dist/plugins/session-lifecycle/plugin.d.ts +21 -1
  283. package/dist/plugins/session-lifecycle/plugin.d.ts.map +1 -1
  284. package/dist/plugins/session-lifecycle/plugin.js +53 -40
  285. package/dist/plugins/session-lifecycle/plugin.js.map +1 -1
  286. package/dist/plugins/session-state/plugin.d.ts +21 -13
  287. package/dist/plugins/session-state/plugin.d.ts.map +1 -1
  288. package/dist/plugins/session-state/plugin.js +214 -79
  289. package/dist/plugins/session-state/plugin.js.map +1 -1
  290. package/dist/plugins/session-stats/plugin.d.ts.map +1 -1
  291. package/dist/plugins/session-stats/plugin.js +1 -0
  292. package/dist/plugins/session-stats/plugin.js.map +1 -1
  293. package/dist/plugins/shell/executor.d.ts +17 -15
  294. package/dist/plugins/shell/executor.d.ts.map +1 -1
  295. package/dist/plugins/shell/executor.js +130 -195
  296. package/dist/plugins/shell/executor.js.map +1 -1
  297. package/dist/plugins/shell/index.d.ts +2 -2
  298. package/dist/plugins/shell/index.d.ts.map +1 -1
  299. package/dist/plugins/shell/index.js +2 -2
  300. package/dist/plugins/shell/index.js.map +1 -1
  301. package/dist/plugins/shell/plugin.d.ts +5 -4
  302. package/dist/plugins/shell/plugin.d.ts.map +1 -1
  303. package/dist/plugins/shell/plugin.js +4 -8
  304. package/dist/plugins/shell/plugin.js.map +1 -1
  305. package/dist/plugins/skills/discovery.d.ts.map +1 -1
  306. package/dist/plugins/skills/discovery.js +10 -8
  307. package/dist/plugins/skills/discovery.js.map +1 -1
  308. package/dist/plugins/skills/index.d.ts +1 -1
  309. package/dist/plugins/skills/index.d.ts.map +1 -1
  310. package/dist/plugins/skills/plugin.d.ts +1 -1
  311. package/dist/plugins/skills/plugin.d.ts.map +1 -1
  312. package/dist/plugins/skills/plugin.js +23 -30
  313. package/dist/plugins/skills/plugin.js.map +1 -1
  314. package/dist/plugins/skills/prompts.d.ts +3 -3
  315. package/dist/plugins/skills/prompts.d.ts.map +1 -1
  316. package/dist/plugins/skills/prompts.js.map +1 -1
  317. package/dist/plugins/skills/schema.d.ts +4 -2
  318. package/dist/plugins/skills/schema.d.ts.map +1 -1
  319. package/dist/plugins/todo/schema.d.ts +1 -1
  320. package/dist/plugins/uploads/plugin.d.ts +11 -4
  321. package/dist/plugins/uploads/plugin.d.ts.map +1 -1
  322. package/dist/plugins/uploads/plugin.js +891 -225
  323. package/dist/plugins/uploads/plugin.js.map +1 -1
  324. package/dist/plugins/uploads/preprocessor.d.ts +14 -0
  325. package/dist/plugins/uploads/preprocessor.d.ts.map +1 -1
  326. package/dist/plugins/uploads/preprocessor.js +11 -0
  327. package/dist/plugins/uploads/preprocessor.js.map +1 -1
  328. package/dist/plugins/uploads/preprocessors/image-classifier.d.ts +1 -1
  329. package/dist/plugins/uploads/preprocessors/image-classifier.d.ts.map +1 -1
  330. package/dist/plugins/uploads/preprocessors/image-classifier.js +51 -26
  331. package/dist/plugins/uploads/preprocessors/image-classifier.js.map +1 -1
  332. package/dist/plugins/uploads/preprocessors/markitdown-preprocessor.d.ts +2 -2
  333. package/dist/plugins/uploads/preprocessors/markitdown-preprocessor.d.ts.map +1 -1
  334. package/dist/plugins/uploads/preprocessors/markitdown-preprocessor.js +41 -16
  335. package/dist/plugins/uploads/preprocessors/markitdown-preprocessor.js.map +1 -1
  336. package/dist/plugins/uploads/preprocessors/pdf-preprocessor.d.ts +1 -1
  337. package/dist/plugins/uploads/preprocessors/pdf-preprocessor.d.ts.map +1 -1
  338. package/dist/plugins/uploads/preprocessors/pdf-preprocessor.js +29 -14
  339. package/dist/plugins/uploads/preprocessors/pdf-preprocessor.js.map +1 -1
  340. package/dist/plugins/uploads/preprocessors/zip-preprocessor.d.ts +1 -1
  341. package/dist/plugins/uploads/preprocessors/zip-preprocessor.d.ts.map +1 -1
  342. package/dist/plugins/uploads/preprocessors/zip-preprocessor.js +62 -34
  343. package/dist/plugins/uploads/preprocessors/zip-preprocessor.js.map +1 -1
  344. package/dist/plugins/uploads/schema.d.ts +25 -2
  345. package/dist/plugins/uploads/schema.d.ts.map +1 -1
  346. package/dist/plugins/uploads/schema.js +24 -3
  347. package/dist/plugins/uploads/schema.js.map +1 -1
  348. package/dist/plugins/uploads/state.d.ts +13 -1
  349. package/dist/plugins/uploads/state.d.ts.map +1 -1
  350. package/dist/plugins/uploads/state.js +4 -1
  351. package/dist/plugins/uploads/state.js.map +1 -1
  352. package/dist/plugins/user-chat/plugin.d.ts +12 -5
  353. package/dist/plugins/user-chat/plugin.d.ts.map +1 -1
  354. package/dist/plugins/user-chat/plugin.js +141 -32
  355. package/dist/plugins/user-chat/plugin.js.map +1 -1
  356. package/dist/plugins/workers/context.d.ts +35 -13
  357. package/dist/plugins/workers/context.d.ts.map +1 -1
  358. package/dist/plugins/workers/context.js +82 -32
  359. package/dist/plugins/workers/context.js.map +1 -1
  360. package/dist/plugins/workers/definition.d.ts +7 -0
  361. package/dist/plugins/workers/definition.d.ts.map +1 -1
  362. package/dist/plugins/workers/definition.js.map +1 -1
  363. package/dist/plugins/workers/index.d.ts +4 -4
  364. package/dist/plugins/workers/index.d.ts.map +1 -1
  365. package/dist/plugins/workers/index.js +2 -2
  366. package/dist/plugins/workers/index.js.map +1 -1
  367. package/dist/plugins/workers/plugin.d.ts +10 -57
  368. package/dist/plugins/workers/plugin.d.ts.map +1 -1
  369. package/dist/plugins/workers/plugin.js +385 -123
  370. package/dist/plugins/workers/plugin.js.map +1 -1
  371. package/dist/plugins/workers/state.d.ts +69 -0
  372. package/dist/plugins/workers/state.d.ts.map +1 -0
  373. package/dist/plugins/workers/state.js +52 -0
  374. package/dist/plugins/workers/state.js.map +1 -0
  375. package/dist/plugins/workers/worker.d.ts +15 -4
  376. package/dist/plugins/workers/worker.d.ts.map +1 -1
  377. package/dist/testing/conformance.d.ts +106 -0
  378. package/dist/testing/conformance.d.ts.map +1 -0
  379. package/dist/testing/conformance.js +1463 -0
  380. package/dist/testing/conformance.js.map +1 -0
  381. package/dist/testing/node-platform.d.ts.map +1 -1
  382. package/dist/testing/node-platform.js +5 -0
  383. package/dist/testing/node-platform.js.map +1 -1
  384. package/dist/testing/test-harness.d.ts +11 -1
  385. package/dist/testing/test-harness.d.ts.map +1 -1
  386. package/dist/testing/test-harness.js +17 -37
  387. package/dist/testing/test-harness.js.map +1 -1
  388. package/dist/testing/wait-helpers.d.ts.map +1 -1
  389. package/dist/testing/wait-helpers.js +1 -3
  390. package/dist/testing/wait-helpers.js.map +1 -1
  391. package/dist/transport/adapter/client-adapter.d.ts +6 -0
  392. package/dist/transport/adapter/client-adapter.d.ts.map +1 -1
  393. package/dist/transport/adapter/client-adapter.js +50 -3
  394. package/dist/transport/adapter/client-adapter.js.map +1 -1
  395. package/dist/transport/adapter/heartbeat.d.ts +16 -0
  396. package/dist/transport/adapter/heartbeat.d.ts.map +1 -0
  397. package/dist/transport/adapter/heartbeat.js +41 -0
  398. package/dist/transport/adapter/heartbeat.js.map +1 -0
  399. package/dist/transport/adapter/server-adapter.d.ts.map +1 -1
  400. package/dist/transport/adapter/server-adapter.js +6 -0
  401. package/dist/transport/adapter/server-adapter.js.map +1 -1
  402. package/dist/transport/http/app.d.ts +3 -30
  403. package/dist/transport/http/app.d.ts.map +1 -1
  404. package/dist/transport/http/app.js +3 -7
  405. package/dist/transport/http/app.js.map +1 -1
  406. package/dist/transport/http/context.d.ts +40 -0
  407. package/dist/transport/http/context.d.ts.map +1 -0
  408. package/dist/transport/http/context.js +17 -0
  409. package/dist/transport/http/context.js.map +1 -0
  410. package/dist/transport/http/fetch-guard.d.ts +49 -0
  411. package/dist/transport/http/fetch-guard.d.ts.map +1 -0
  412. package/dist/transport/http/fetch-guard.js +312 -0
  413. package/dist/transport/http/fetch-guard.js.map +1 -0
  414. package/dist/transport/http/index.d.ts +1 -1
  415. package/dist/transport/http/index.d.ts.map +1 -1
  416. package/dist/transport/http/middleware/bearer-auth.d.ts +1 -1
  417. package/dist/transport/http/middleware/bearer-auth.d.ts.map +1 -1
  418. package/dist/transport/http/middleware/error-handler.d.ts +2 -2
  419. package/dist/transport/http/middleware/error-handler.d.ts.map +1 -1
  420. package/dist/transport/http/path-containment.d.ts +20 -0
  421. package/dist/transport/http/path-containment.d.ts.map +1 -0
  422. package/dist/transport/http/path-containment.js +31 -0
  423. package/dist/transport/http/path-containment.js.map +1 -0
  424. package/dist/transport/http/responses.d.ts +30 -0
  425. package/dist/transport/http/responses.d.ts.map +1 -0
  426. package/dist/transport/http/responses.js +5 -0
  427. package/dist/transport/http/responses.js.map +1 -0
  428. package/dist/transport/http/routes/files.d.ts +1 -1
  429. package/dist/transport/http/routes/files.d.ts.map +1 -1
  430. package/dist/transport/http/routes/files.js +54 -155
  431. package/dist/transport/http/routes/files.js.map +1 -1
  432. package/dist/transport/http/routes/resources.d.ts +1 -1
  433. package/dist/transport/http/routes/resources.d.ts.map +1 -1
  434. package/dist/transport/http/routes/resources.js +92 -57
  435. package/dist/transport/http/routes/resources.js.map +1 -1
  436. package/dist/transport/http/routes/rpc.d.ts +6 -1
  437. package/dist/transport/http/routes/rpc.d.ts.map +1 -1
  438. package/dist/transport/http/routes/rpc.js +51 -21
  439. package/dist/transport/http/routes/rpc.js.map +1 -1
  440. package/dist/transport/http/routes/upload.d.ts +1 -1
  441. package/dist/transport/http/routes/upload.d.ts.map +1 -1
  442. package/dist/transport/http/routes/upload.js +256 -169
  443. package/dist/transport/http/routes/upload.js.map +1 -1
  444. package/dist/user-config.d.ts +34 -7
  445. package/dist/user-config.d.ts.map +1 -1
  446. package/dist/user-config.js +71 -0
  447. package/dist/user-config.js.map +1 -1
  448. package/package.json +17 -7
  449. package/src/bootstrap.ts +119 -35
  450. package/src/bun-platform/fs.ts +1 -0
  451. package/src/bun-platform/index.ts +18 -1
  452. package/src/bun-platform/server-lifecycle.ts +218 -0
  453. package/src/bun-platform/shell.ts +362 -0
  454. package/src/config.ts +130 -0
  455. package/src/core/agents/agent.ts +210 -92
  456. package/src/core/agents/config.ts +8 -0
  457. package/src/core/agents/retry.ts +16 -17
  458. package/src/core/agents/state.ts +2 -0
  459. package/src/core/events/base-event-store.ts +24 -16
  460. package/src/core/events/file.ts +198 -22
  461. package/src/core/file-store/containment.ts +75 -0
  462. package/src/core/file-store/file-store.ts +106 -25
  463. package/src/core/file-store/types.ts +14 -1
  464. package/src/core/image/image-processor.ts +3 -1
  465. package/src/core/image/types.ts +2 -0
  466. package/src/core/image/vips-resizer.ts +102 -37
  467. package/src/core/llm/anthropic.ts +63 -79
  468. package/src/core/llm/logger.ts +175 -37
  469. package/src/core/llm/openrouter.ts +57 -72
  470. package/src/core/llm/provider-request.ts +40 -0
  471. package/src/core/llm/provider.ts +28 -0
  472. package/src/core/plugins/plugin-builder.ts +106 -14
  473. package/src/core/preset/preset-builder.ts +12 -22
  474. package/src/core/sessions/context.ts +18 -0
  475. package/src/core/sessions/runtime-activity.ts +78 -0
  476. package/src/core/sessions/schema.ts +29 -3
  477. package/src/core/sessions/session-manager.ts +560 -140
  478. package/src/core/sessions/session-store.ts +38 -0
  479. package/src/core/sessions/session.ts +187 -47
  480. package/src/core/sessions/state.ts +11 -0
  481. package/src/core/system.ts +15 -0
  482. package/src/core/wake-key.ts +65 -0
  483. package/src/index.ts +30 -12
  484. package/src/lib/archive/archive-inspection.fixtures.ts +138 -0
  485. package/src/lib/archive/archive-inspection.ts +359 -0
  486. package/src/lib/archive/index.ts +17 -0
  487. package/src/lib/logger/console.ts +7 -57
  488. package/src/lib/logger/file.ts +28 -50
  489. package/src/lib/logger/index.ts +3 -1
  490. package/src/lib/logger/jsonl.ts +36 -0
  491. package/src/lib/logger/logger.ts +48 -0
  492. package/src/lib/logger/session-log.ts +42 -0
  493. package/src/lib/utils/concurrency.ts +37 -8
  494. package/src/lib/utils/fs-batch.ts +49 -0
  495. package/src/lib/utils/result.ts +7 -31
  496. package/src/lib/utils/sleep.ts +23 -0
  497. package/src/platform/fs-revision.ts +21 -0
  498. package/src/platform/fs.ts +109 -1
  499. package/src/platform/git.ts +67 -0
  500. package/src/platform/index.ts +51 -1
  501. package/src/platform/llm-call-log.ts +86 -0
  502. package/src/platform/scheduler.ts +71 -0
  503. package/src/platform/session-log.ts +39 -0
  504. package/src/platform/shell.ts +89 -0
  505. package/src/plugins/agent-status/plugin.ts +1 -0
  506. package/src/plugins/agents/plugin.ts +134 -81
  507. package/src/plugins/filesystem/listing.ts +70 -12
  508. package/src/plugins/filesystem/plugin.ts +8 -6
  509. package/src/plugins/git-status/plugin.ts +204 -77
  510. package/src/plugins/llm-debug/plugin.ts +1 -0
  511. package/src/plugins/logs/plugin.ts +9 -0
  512. package/src/plugins/mailbox/plugin.ts +46 -64
  513. package/src/plugins/mailbox/query.ts +15 -7
  514. package/src/plugins/mailbox/state.ts +1 -0
  515. package/src/plugins/resources/filename.ts +19 -0
  516. package/src/plugins/resources/plugin.ts +111 -59
  517. package/src/plugins/result-eviction/plugin.ts +6 -1
  518. package/src/plugins/services/plugin.ts +254 -98
  519. package/src/plugins/services/prompt.ts +1 -6
  520. package/src/plugins/services/schema.ts +17 -3
  521. package/src/plugins/services/service.ts +702 -252
  522. package/src/plugins/session-lifecycle/plugin.ts +56 -41
  523. package/src/plugins/session-state/plugin.ts +242 -88
  524. package/src/plugins/session-stats/plugin.ts +1 -0
  525. package/src/plugins/shell/executor.ts +144 -226
  526. package/src/plugins/shell/index.ts +1 -4
  527. package/src/plugins/shell/plugin.ts +7 -9
  528. package/src/plugins/skills/discovery.ts +10 -8
  529. package/src/plugins/skills/index.ts +1 -1
  530. package/src/plugins/skills/plugin.ts +19 -27
  531. package/src/plugins/skills/prompts.ts +3 -3
  532. package/src/plugins/skills/schema.ts +5 -2
  533. package/src/plugins/uploads/plugin.ts +991 -273
  534. package/src/plugins/uploads/preprocessor.ts +25 -0
  535. package/src/plugins/uploads/preprocessors/image-classifier.ts +56 -25
  536. package/src/plugins/uploads/preprocessors/markitdown-preprocessor.ts +41 -15
  537. package/src/plugins/uploads/preprocessors/pdf-preprocessor.ts +32 -16
  538. package/src/plugins/uploads/preprocessors/zip-preprocessor.ts +67 -38
  539. package/src/plugins/uploads/schema.ts +30 -3
  540. package/src/plugins/uploads/state.ts +12 -0
  541. package/src/plugins/user-chat/plugin.ts +196 -40
  542. package/src/plugins/workers/context.ts +102 -39
  543. package/src/plugins/workers/definition.ts +7 -0
  544. package/src/plugins/workers/index.ts +4 -4
  545. package/src/plugins/workers/plugin.ts +461 -151
  546. package/src/plugins/workers/state.ts +64 -0
  547. package/src/plugins/workers/worker.ts +15 -4
  548. package/src/testing/conformance.ts +1751 -0
  549. package/src/testing/node-platform.ts +5 -0
  550. package/src/testing/test-harness.ts +21 -38
  551. package/src/testing/wait-helpers.ts +1 -4
  552. package/src/transport/adapter/client-adapter.ts +60 -3
  553. package/src/transport/adapter/heartbeat.ts +50 -0
  554. package/src/transport/adapter/server-adapter.ts +6 -0
  555. package/src/transport/http/app.ts +7 -35
  556. package/src/transport/http/context.ts +46 -0
  557. package/src/transport/http/fetch-guard.ts +318 -0
  558. package/src/transport/http/index.ts +1 -1
  559. package/src/transport/http/middleware/bearer-auth.ts +1 -1
  560. package/src/transport/http/middleware/error-handler.ts +1 -1
  561. package/src/transport/http/path-containment.ts +44 -0
  562. package/src/transport/http/responses.ts +20 -0
  563. package/src/transport/http/routes/files.ts +69 -159
  564. package/src/transport/http/routes/resources.ts +124 -93
  565. package/src/transport/http/routes/rpc.ts +63 -26
  566. package/src/transport/http/routes/upload.ts +327 -258
  567. package/src/user-config.ts +93 -7
  568. package/dist/config.test.d.ts +0 -2
  569. package/dist/config.test.d.ts.map +0 -1
  570. package/dist/config.test.js +0 -155
  571. package/dist/config.test.js.map +0 -1
  572. package/dist/core/agent-loop.integration.test.d.ts +0 -2
  573. package/dist/core/agent-loop.integration.test.d.ts.map +0 -1
  574. package/dist/core/agent-loop.integration.test.js +0 -414
  575. package/dist/core/agent-loop.integration.test.js.map +0 -1
  576. package/dist/core/agents/agent-config.test.d.ts +0 -2
  577. package/dist/core/agents/agent-config.test.d.ts.map +0 -1
  578. package/dist/core/agents/agent-config.test.js +0 -194
  579. package/dist/core/agents/agent-config.test.js.map +0 -1
  580. package/dist/core/agents/agent-shutdown.test.d.ts +0 -6
  581. package/dist/core/agents/agent-shutdown.test.d.ts.map +0 -1
  582. package/dist/core/agents/agent-shutdown.test.js +0 -180
  583. package/dist/core/agents/agent-shutdown.test.js.map +0 -1
  584. package/dist/core/agents/agent.test.d.ts +0 -2
  585. package/dist/core/agents/agent.test.d.ts.map +0 -1
  586. package/dist/core/agents/agent.test.js +0 -313
  587. package/dist/core/agents/agent.test.js.map +0 -1
  588. package/dist/core/agents/communicator.d.ts +0 -3
  589. package/dist/core/agents/communicator.d.ts.map +0 -1
  590. package/dist/core/agents/communicator.js +0 -13
  591. package/dist/core/agents/communicator.js.map +0 -1
  592. package/dist/core/agents/handler-events.test.d.ts +0 -5
  593. package/dist/core/agents/handler-events.test.d.ts.map +0 -1
  594. package/dist/core/agents/handler-events.test.js +0 -115
  595. package/dist/core/agents/handler-events.test.js.map +0 -1
  596. package/dist/core/agents/response-sanitizer.test.d.ts +0 -2
  597. package/dist/core/agents/response-sanitizer.test.d.ts.map +0 -1
  598. package/dist/core/agents/response-sanitizer.test.js +0 -101
  599. package/dist/core/agents/response-sanitizer.test.js.map +0 -1
  600. package/dist/core/error-recovery.integration.test.d.ts +0 -2
  601. package/dist/core/error-recovery.integration.test.d.ts.map +0 -1
  602. package/dist/core/error-recovery.integration.test.js +0 -288
  603. package/dist/core/error-recovery.integration.test.js.map +0 -1
  604. package/dist/core/event-sourcing.integration.test.d.ts +0 -2
  605. package/dist/core/event-sourcing.integration.test.d.ts.map +0 -1
  606. package/dist/core/event-sourcing.integration.test.js +0 -154
  607. package/dist/core/event-sourcing.integration.test.js.map +0 -1
  608. package/dist/core/events/file.test.d.ts +0 -2
  609. package/dist/core/events/file.test.d.ts.map +0 -1
  610. package/dist/core/events/file.test.js +0 -284
  611. package/dist/core/events/file.test.js.map +0 -1
  612. package/dist/core/events/memory.test.d.ts +0 -2
  613. package/dist/core/events/memory.test.d.ts.map +0 -1
  614. package/dist/core/events/memory.test.js +0 -502
  615. package/dist/core/events/memory.test.js.map +0 -1
  616. package/dist/core/image/image-processor.test.d.ts +0 -2
  617. package/dist/core/image/image-processor.test.d.ts.map +0 -1
  618. package/dist/core/image/image-processor.test.js +0 -171
  619. package/dist/core/image/image-processor.test.js.map +0 -1
  620. package/dist/core/image/vips-resizer.test.d.ts +0 -2
  621. package/dist/core/image/vips-resizer.test.d.ts.map +0 -1
  622. package/dist/core/image/vips-resizer.test.js +0 -336
  623. package/dist/core/image/vips-resizer.test.js.map +0 -1
  624. package/dist/core/llm/anthropic.test.d.ts +0 -2
  625. package/dist/core/llm/anthropic.test.d.ts.map +0 -1
  626. package/dist/core/llm/anthropic.test.js +0 -464
  627. package/dist/core/llm/anthropic.test.js.map +0 -1
  628. package/dist/core/llm/cache-breakpoints.test.d.ts +0 -2
  629. package/dist/core/llm/cache-breakpoints.test.d.ts.map +0 -1
  630. package/dist/core/llm/cache-breakpoints.test.js +0 -69
  631. package/dist/core/llm/cache-breakpoints.test.js.map +0 -1
  632. package/dist/core/llm/cache-live.test.d.ts +0 -16
  633. package/dist/core/llm/cache-live.test.d.ts.map +0 -1
  634. package/dist/core/llm/cache-live.test.js +0 -137
  635. package/dist/core/llm/cache-live.test.js.map +0 -1
  636. package/dist/core/llm/logger.test.d.ts +0 -7
  637. package/dist/core/llm/logger.test.d.ts.map +0 -1
  638. package/dist/core/llm/logger.test.js +0 -228
  639. package/dist/core/llm/logger.test.js.map +0 -1
  640. package/dist/core/llm/message-sanitization.test.d.ts +0 -2
  641. package/dist/core/llm/message-sanitization.test.d.ts.map +0 -1
  642. package/dist/core/llm/message-sanitization.test.js +0 -181
  643. package/dist/core/llm/message-sanitization.test.js.map +0 -1
  644. package/dist/core/llm/mock.test.d.ts +0 -2
  645. package/dist/core/llm/mock.test.d.ts.map +0 -1
  646. package/dist/core/llm/mock.test.js +0 -318
  647. package/dist/core/llm/mock.test.js.map +0 -1
  648. package/dist/core/llm/model-shortlist-live.test.d.ts +0 -35
  649. package/dist/core/llm/model-shortlist-live.test.d.ts.map +0 -1
  650. package/dist/core/llm/model-shortlist-live.test.js +0 -452
  651. package/dist/core/llm/model-shortlist-live.test.js.map +0 -1
  652. package/dist/core/llm/openrouter-mapping.test.d.ts +0 -2
  653. package/dist/core/llm/openrouter-mapping.test.d.ts.map +0 -1
  654. package/dist/core/llm/openrouter-mapping.test.js +0 -190
  655. package/dist/core/llm/openrouter-mapping.test.js.map +0 -1
  656. package/dist/core/llm/openrouter.test.d.ts +0 -2
  657. package/dist/core/llm/openrouter.test.d.ts.map +0 -1
  658. package/dist/core/llm/openrouter.test.js +0 -377
  659. package/dist/core/llm/openrouter.test.js.map +0 -1
  660. package/dist/core/llm/provider-integration.test.d.ts +0 -12
  661. package/dist/core/llm/provider-integration.test.d.ts.map +0 -1
  662. package/dist/core/llm/provider-integration.test.js +0 -350
  663. package/dist/core/llm/provider-integration.test.js.map +0 -1
  664. package/dist/core/llm/reasoning-details.test.d.ts +0 -2
  665. package/dist/core/llm/reasoning-details.test.d.ts.map +0 -1
  666. package/dist/core/llm/reasoning-details.test.js +0 -144
  667. package/dist/core/llm/reasoning-details.test.js.map +0 -1
  668. package/dist/core/llm/routing-provider.test.d.ts +0 -2
  669. package/dist/core/llm/routing-provider.test.d.ts.map +0 -1
  670. package/dist/core/llm/routing-provider.test.js +0 -94
  671. package/dist/core/llm/routing-provider.test.js.map +0 -1
  672. package/dist/core/llm/snapshot-middleware.test.d.ts +0 -2
  673. package/dist/core/llm/snapshot-middleware.test.d.ts.map +0 -1
  674. package/dist/core/llm/snapshot-middleware.test.js +0 -144
  675. package/dist/core/llm/snapshot-middleware.test.js.map +0 -1
  676. package/dist/core/llm/thinking-blocks.test.d.ts +0 -2
  677. package/dist/core/llm/thinking-blocks.test.d.ts.map +0 -1
  678. package/dist/core/llm/thinking-blocks.test.js +0 -291
  679. package/dist/core/llm/thinking-blocks.test.js.map +0 -1
  680. package/dist/core/multi-agent.integration.test.d.ts +0 -2
  681. package/dist/core/multi-agent.integration.test.d.ts.map +0 -1
  682. package/dist/core/multi-agent.integration.test.js +0 -298
  683. package/dist/core/multi-agent.integration.test.js.map +0 -1
  684. package/dist/core/plugin-hooks.integration.test.d.ts +0 -2
  685. package/dist/core/plugin-hooks.integration.test.d.ts.map +0 -1
  686. package/dist/core/plugin-hooks.integration.test.js +0 -458
  687. package/dist/core/plugin-hooks.integration.test.js.map +0 -1
  688. package/dist/core/reasoning-round-trip.integration.test.d.ts +0 -2
  689. package/dist/core/reasoning-round-trip.integration.test.d.ts.map +0 -1
  690. package/dist/core/reasoning-round-trip.integration.test.js +0 -150
  691. package/dist/core/reasoning-round-trip.integration.test.js.map +0 -1
  692. package/dist/core/session-lifecycle.integration.test.d.ts +0 -2
  693. package/dist/core/session-lifecycle.integration.test.d.ts.map +0 -1
  694. package/dist/core/session-lifecycle.integration.test.js +0 -159
  695. package/dist/core/session-lifecycle.integration.test.js.map +0 -1
  696. package/dist/core/sessions/fork-utils.test.d.ts +0 -2
  697. package/dist/core/sessions/fork-utils.test.d.ts.map +0 -1
  698. package/dist/core/sessions/fork-utils.test.js +0 -129
  699. package/dist/core/sessions/fork-utils.test.js.map +0 -1
  700. package/dist/core/sessions/session-overrides.integration.test.d.ts +0 -2
  701. package/dist/core/sessions/session-overrides.integration.test.d.ts.map +0 -1
  702. package/dist/core/sessions/session-overrides.integration.test.js +0 -154
  703. package/dist/core/sessions/session-overrides.integration.test.js.map +0 -1
  704. package/dist/core/sessions/session.test.d.ts +0 -2
  705. package/dist/core/sessions/session.test.d.ts.map +0 -1
  706. package/dist/core/sessions/session.test.js +0 -1100
  707. package/dist/core/sessions/session.test.js.map +0 -1
  708. package/dist/core/tools/executor.test.d.ts +0 -2
  709. package/dist/core/tools/executor.test.d.ts.map +0 -1
  710. package/dist/core/tools/executor.test.js +0 -144
  711. package/dist/core/tools/executor.test.js.map +0 -1
  712. package/dist/lib/logger/console.test.d.ts +0 -2
  713. package/dist/lib/logger/console.test.d.ts.map +0 -1
  714. package/dist/lib/logger/console.test.js +0 -258
  715. package/dist/lib/logger/console.test.js.map +0 -1
  716. package/dist/lib/never.d.ts +0 -2
  717. package/dist/lib/never.d.ts.map +0 -1
  718. package/dist/lib/never.js +0 -4
  719. package/dist/lib/never.js.map +0 -1
  720. package/dist/lib/utils/concurrency.test.d.ts +0 -2
  721. package/dist/lib/utils/concurrency.test.d.ts.map +0 -1
  722. package/dist/lib/utils/concurrency.test.js +0 -135
  723. package/dist/lib/utils/concurrency.test.js.map +0 -1
  724. package/dist/plugins/agent-status/agent-status.test.d.ts +0 -2
  725. package/dist/plugins/agent-status/agent-status.test.d.ts.map +0 -1
  726. package/dist/plugins/agent-status/agent-status.test.js +0 -136
  727. package/dist/plugins/agent-status/agent-status.test.js.map +0 -1
  728. package/dist/plugins/agents/agents.integration.test.d.ts +0 -2
  729. package/dist/plugins/agents/agents.integration.test.d.ts.map +0 -1
  730. package/dist/plugins/agents/agents.integration.test.js +0 -830
  731. package/dist/plugins/agents/agents.integration.test.js.map +0 -1
  732. package/dist/plugins/agents/supervision.integration.test.d.ts +0 -2
  733. package/dist/plugins/agents/supervision.integration.test.d.ts.map +0 -1
  734. package/dist/plugins/agents/supervision.integration.test.js +0 -215
  735. package/dist/plugins/agents/supervision.integration.test.js.map +0 -1
  736. package/dist/plugins/context-compact/compaction-live.test.d.ts +0 -17
  737. package/dist/plugins/context-compact/compaction-live.test.d.ts.map +0 -1
  738. package/dist/plugins/context-compact/compaction-live.test.js +0 -177
  739. package/dist/plugins/context-compact/compaction-live.test.js.map +0 -1
  740. package/dist/plugins/context-compact/context-compact.integration.test.d.ts +0 -2
  741. package/dist/plugins/context-compact/context-compact.integration.test.d.ts.map +0 -1
  742. package/dist/plugins/context-compact/context-compact.integration.test.js +0 -364
  743. package/dist/plugins/context-compact/context-compact.integration.test.js.map +0 -1
  744. package/dist/plugins/context-compact/context-compactor.test.d.ts +0 -2
  745. package/dist/plugins/context-compact/context-compactor.test.d.ts.map +0 -1
  746. package/dist/plugins/context-compact/context-compactor.test.js +0 -858
  747. package/dist/plugins/context-compact/context-compactor.test.js.map +0 -1
  748. package/dist/plugins/context-compact/history-offloader.test.d.ts +0 -2
  749. package/dist/plugins/context-compact/history-offloader.test.d.ts.map +0 -1
  750. package/dist/plugins/context-compact/history-offloader.test.js +0 -77
  751. package/dist/plugins/context-compact/history-offloader.test.js.map +0 -1
  752. package/dist/plugins/filesystem/filesystem.integration.test.d.ts +0 -2
  753. package/dist/plugins/filesystem/filesystem.integration.test.d.ts.map +0 -1
  754. package/dist/plugins/filesystem/filesystem.integration.test.js +0 -447
  755. package/dist/plugins/filesystem/filesystem.integration.test.js.map +0 -1
  756. package/dist/plugins/filesystem/schema.d.ts +0 -7
  757. package/dist/plugins/filesystem/schema.d.ts.map +0 -1
  758. package/dist/plugins/filesystem/schema.js +0 -2
  759. package/dist/plugins/filesystem/schema.js.map +0 -1
  760. package/dist/plugins/limits-guard/limit-guard.test.d.ts +0 -2
  761. package/dist/plugins/limits-guard/limit-guard.test.d.ts.map +0 -1
  762. package/dist/plugins/limits-guard/limit-guard.test.js +0 -194
  763. package/dist/plugins/limits-guard/limit-guard.test.js.map +0 -1
  764. package/dist/plugins/limits-guard/limits-guard.integration.test.d.ts +0 -2
  765. package/dist/plugins/limits-guard/limits-guard.integration.test.d.ts.map +0 -1
  766. package/dist/plugins/limits-guard/limits-guard.integration.test.js +0 -887
  767. package/dist/plugins/limits-guard/limits-guard.integration.test.js.map +0 -1
  768. package/dist/plugins/llm-debug/llm-debug.integration.test.d.ts +0 -2
  769. package/dist/plugins/llm-debug/llm-debug.integration.test.d.ts.map +0 -1
  770. package/dist/plugins/llm-debug/llm-debug.integration.test.js +0 -157
  771. package/dist/plugins/llm-debug/llm-debug.integration.test.js.map +0 -1
  772. package/dist/plugins/mailbox/mailbox.integration.test.d.ts +0 -2
  773. package/dist/plugins/mailbox/mailbox.integration.test.d.ts.map +0 -1
  774. package/dist/plugins/mailbox/mailbox.integration.test.js +0 -678
  775. package/dist/plugins/mailbox/mailbox.integration.test.js.map +0 -1
  776. package/dist/plugins/resources/resources.integration.test.d.ts +0 -2
  777. package/dist/plugins/resources/resources.integration.test.d.ts.map +0 -1
  778. package/dist/plugins/resources/resources.integration.test.js +0 -62
  779. package/dist/plugins/resources/resources.integration.test.js.map +0 -1
  780. package/dist/plugins/result-eviction/result-eviction.integration.test.d.ts +0 -2
  781. package/dist/plugins/result-eviction/result-eviction.integration.test.d.ts.map +0 -1
  782. package/dist/plugins/result-eviction/result-eviction.integration.test.js +0 -294
  783. package/dist/plugins/result-eviction/result-eviction.integration.test.js.map +0 -1
  784. package/dist/plugins/services/pid-registry.test.d.ts +0 -2
  785. package/dist/plugins/services/pid-registry.test.d.ts.map +0 -1
  786. package/dist/plugins/services/pid-registry.test.js +0 -161
  787. package/dist/plugins/services/pid-registry.test.js.map +0 -1
  788. package/dist/plugins/services/services.integration.test.d.ts +0 -2
  789. package/dist/plugins/services/services.integration.test.d.ts.map +0 -1
  790. package/dist/plugins/services/services.integration.test.js +0 -1057
  791. package/dist/plugins/services/services.integration.test.js.map +0 -1
  792. package/dist/plugins/session-lifecycle/session-lifecycle.integration.test.d.ts +0 -2
  793. package/dist/plugins/session-lifecycle/session-lifecycle.integration.test.d.ts.map +0 -1
  794. package/dist/plugins/session-lifecycle/session-lifecycle.integration.test.js +0 -498
  795. package/dist/plugins/session-lifecycle/session-lifecycle.integration.test.js.map +0 -1
  796. package/dist/plugins/session-stats/plugin.test.d.ts +0 -2
  797. package/dist/plugins/session-stats/plugin.test.d.ts.map +0 -1
  798. package/dist/plugins/session-stats/plugin.test.js +0 -145
  799. package/dist/plugins/session-stats/plugin.test.js.map +0 -1
  800. package/dist/plugins/shell/shell.integration.test.d.ts +0 -2
  801. package/dist/plugins/shell/shell.integration.test.d.ts.map +0 -1
  802. package/dist/plugins/shell/shell.integration.test.js +0 -234
  803. package/dist/plugins/shell/shell.integration.test.js.map +0 -1
  804. package/dist/plugins/shell/shell.test.d.ts +0 -2
  805. package/dist/plugins/shell/shell.test.d.ts.map +0 -1
  806. package/dist/plugins/shell/shell.test.js +0 -236
  807. package/dist/plugins/shell/shell.test.js.map +0 -1
  808. package/dist/plugins/skills/discovery.test.d.ts +0 -2
  809. package/dist/plugins/skills/discovery.test.d.ts.map +0 -1
  810. package/dist/plugins/skills/discovery.test.js +0 -312
  811. package/dist/plugins/skills/discovery.test.js.map +0 -1
  812. package/dist/plugins/skills/skills.integration.test.d.ts +0 -2
  813. package/dist/plugins/skills/skills.integration.test.d.ts.map +0 -1
  814. package/dist/plugins/skills/skills.integration.test.js +0 -475
  815. package/dist/plugins/skills/skills.integration.test.js.map +0 -1
  816. package/dist/plugins/todo/todo.integration.test.d.ts +0 -2
  817. package/dist/plugins/todo/todo.integration.test.d.ts.map +0 -1
  818. package/dist/plugins/todo/todo.integration.test.js +0 -605
  819. package/dist/plugins/todo/todo.integration.test.js.map +0 -1
  820. package/dist/plugins/uploads/preprocessors/image-classifier.test.d.ts +0 -2
  821. package/dist/plugins/uploads/preprocessors/image-classifier.test.d.ts.map +0 -1
  822. package/dist/plugins/uploads/preprocessors/image-classifier.test.js +0 -113
  823. package/dist/plugins/uploads/preprocessors/image-classifier.test.js.map +0 -1
  824. package/dist/plugins/uploads/uploads.integration.test.d.ts +0 -2
  825. package/dist/plugins/uploads/uploads.integration.test.d.ts.map +0 -1
  826. package/dist/plugins/uploads/uploads.integration.test.js +0 -639
  827. package/dist/plugins/uploads/uploads.integration.test.js.map +0 -1
  828. package/dist/plugins/user-chat/user-chat.integration.test.d.ts +0 -2
  829. package/dist/plugins/user-chat/user-chat.integration.test.d.ts.map +0 -1
  830. package/dist/plugins/user-chat/user-chat.integration.test.js +0 -754
  831. package/dist/plugins/user-chat/user-chat.integration.test.js.map +0 -1
  832. package/dist/plugins/workers/workers.integration.test.d.ts +0 -2
  833. package/dist/plugins/workers/workers.integration.test.d.ts.map +0 -1
  834. package/dist/plugins/workers/workers.integration.test.js +0 -629
  835. package/dist/plugins/workers/workers.integration.test.js.map +0 -1
  836. package/dist/prompts/macros.test.d.ts +0 -2
  837. package/dist/prompts/macros.test.d.ts.map +0 -1
  838. package/dist/prompts/macros.test.js +0 -80
  839. package/dist/prompts/macros.test.js.map +0 -1
  840. package/dist/testing/test-harness.test.d.ts +0 -2
  841. package/dist/testing/test-harness.test.d.ts.map +0 -1
  842. package/dist/testing/test-harness.test.js +0 -92
  843. package/dist/testing/test-harness.test.js.map +0 -1
  844. package/dist/transport/http/routes/rpc.integration.test.d.ts +0 -2
  845. package/dist/transport/http/routes/rpc.integration.test.d.ts.map +0 -1
  846. package/dist/transport/http/routes/rpc.integration.test.js +0 -189
  847. package/dist/transport/http/routes/rpc.integration.test.js.map +0 -1
  848. package/dist/transport/http/routes/rpc.test.d.ts +0 -2
  849. package/dist/transport/http/routes/rpc.test.d.ts.map +0 -1
  850. package/dist/transport/http/routes/rpc.test.js +0 -316
  851. package/dist/transport/http/routes/rpc.test.js.map +0 -1
  852. package/src/config.test.ts +0 -174
  853. package/src/core/agent-loop.integration.test.ts +0 -503
  854. package/src/core/agents/agent-config.test.ts +0 -240
  855. package/src/core/agents/agent-shutdown.test.ts +0 -236
  856. package/src/core/agents/agent.test.ts +0 -387
  857. package/src/core/agents/communicator.ts +0 -16
  858. package/src/core/agents/handler-events.test.ts +0 -167
  859. package/src/core/agents/response-sanitizer.test.ts +0 -137
  860. package/src/core/error-recovery.integration.test.ts +0 -343
  861. package/src/core/event-sourcing.integration.test.ts +0 -191
  862. package/src/core/events/file.test.ts +0 -436
  863. package/src/core/events/memory.test.ts +0 -741
  864. package/src/core/image/image-processor.test.ts +0 -218
  865. package/src/core/image/vips-resizer.test.ts +0 -388
  866. package/src/core/llm/anthropic.test.ts +0 -546
  867. package/src/core/llm/cache-breakpoints.test.ts +0 -85
  868. package/src/core/llm/cache-live.test.ts +0 -155
  869. package/src/core/llm/logger.test.ts +0 -270
  870. package/src/core/llm/message-sanitization.test.ts +0 -217
  871. package/src/core/llm/mock.test.ts +0 -402
  872. package/src/core/llm/model-shortlist-live.test.ts +0 -577
  873. package/src/core/llm/openrouter-mapping.test.ts +0 -234
  874. package/src/core/llm/openrouter.test.ts +0 -499
  875. package/src/core/llm/provider-integration.test.ts +0 -408
  876. package/src/core/llm/reasoning-details.test.ts +0 -177
  877. package/src/core/llm/routing-provider.test.ts +0 -113
  878. package/src/core/llm/snapshot-middleware.test.ts +0 -168
  879. package/src/core/llm/thinking-blocks.test.ts +0 -345
  880. package/src/core/multi-agent.integration.test.ts +0 -340
  881. package/src/core/plugin-hooks.integration.test.ts +0 -568
  882. package/src/core/reasoning-round-trip.integration.test.ts +0 -188
  883. package/src/core/session-lifecycle.integration.test.ts +0 -202
  884. package/src/core/sessions/fork-utils.test.ts +0 -158
  885. package/src/core/sessions/session-overrides.integration.test.ts +0 -210
  886. package/src/core/sessions/session.test.ts +0 -1736
  887. package/src/core/tools/executor.test.ts +0 -161
  888. package/src/lib/logger/console.test.ts +0 -348
  889. package/src/lib/never.ts +0 -3
  890. package/src/lib/utils/concurrency.test.ts +0 -169
  891. package/src/plugins/agent-status/agent-status.test.ts +0 -164
  892. package/src/plugins/agents/agents.integration.test.ts +0 -976
  893. package/src/plugins/agents/supervision.integration.test.ts +0 -249
  894. package/src/plugins/context-compact/compaction-live.test.ts +0 -221
  895. package/src/plugins/context-compact/context-compact.integration.test.ts +0 -418
  896. package/src/plugins/context-compact/context-compactor.test.ts +0 -1036
  897. package/src/plugins/context-compact/history-offloader.test.ts +0 -100
  898. package/src/plugins/filesystem/filesystem.integration.test.ts +0 -529
  899. package/src/plugins/filesystem/schema.ts +0 -6
  900. package/src/plugins/limits-guard/limit-guard.test.ts +0 -253
  901. package/src/plugins/limits-guard/limits-guard.integration.test.ts +0 -1012
  902. package/src/plugins/llm-debug/llm-debug.integration.test.ts +0 -192
  903. package/src/plugins/mailbox/mailbox.integration.test.ts +0 -794
  904. package/src/plugins/resources/resources.integration.test.ts +0 -68
  905. package/src/plugins/result-eviction/result-eviction.integration.test.ts +0 -332
  906. package/src/plugins/services/pid-registry.test.ts +0 -180
  907. package/src/plugins/services/services.integration.test.ts +0 -1223
  908. package/src/plugins/session-lifecycle/session-lifecycle.integration.test.ts +0 -639
  909. package/src/plugins/session-stats/plugin.test.ts +0 -160
  910. package/src/plugins/shell/shell.integration.test.ts +0 -273
  911. package/src/plugins/shell/shell.test.ts +0 -314
  912. package/src/plugins/skills/discovery.test.ts +0 -395
  913. package/src/plugins/skills/skills.integration.test.ts +0 -580
  914. package/src/plugins/todo/todo.integration.test.ts +0 -687
  915. package/src/plugins/uploads/preprocessors/image-classifier.test.ts +0 -142
  916. package/src/plugins/uploads/uploads.integration.test.ts +0 -831
  917. package/src/plugins/user-chat/user-chat.integration.test.ts +0 -893
  918. package/src/plugins/workers/workers.integration.test.ts +0 -778
  919. package/src/prompts/macros.test.ts +0 -107
  920. package/src/testing/test-harness.test.ts +0 -114
  921. package/src/transport/http/routes/rpc.integration.test.ts +0 -243
  922. package/src/transport/http/routes/rpc.test.ts +0 -372
@@ -1,1012 +0,0 @@
1
- import { describe, expect, it } from 'bun:test'
2
- import z from 'zod/v4'
3
- import { AgentId } from '~/core/agents/schema.js'
4
- import { agentEvents } from '~/core/agents/state.js'
5
- import { MockLLMProvider } from '~/core/llm/mock.js'
6
- import type { InferenceRequest } from '~/core/llm/provider.js'
7
- import { ModelId } from '~/core/llm/schema.js'
8
- import { llmEvents } from '~/core/llm/state.js'
9
- import { selectPluginState } from '~/core/sessions/reducer.js'
10
- import { createTool } from '~/core/tools/definition.js'
11
- import { ToolCallId } from '~/core/tools/schema.js'
12
- import { toolEvents } from '~/core/tools/state.js'
13
- import { Ok } from '~/lib/utils/result.js'
14
- import { contextCompactPlugin } from '~/plugins/context-compact/index.js'
15
- import { getAgentMailbox, selectMailboxState } from '~/plugins/mailbox/query.js'
16
- import { mailboxEvents } from '~/plugins/mailbox/state.js'
17
- import { createMultiAgentPreset, createTestPreset, TestHarness } from '~/testing/index.js'
18
- import type { AgentCounters } from './plugin.js'
19
- import { limitsEvents, limitsGuardPlugin } from './plugin.js'
20
-
21
- function createLimitsHarness(options: Omit<ConstructorParameters<typeof TestHarness>[0], 'systemPlugins'>) {
22
- return new TestHarness({ ...options, systemPlugins: [limitsGuardPlugin] })
23
- }
24
-
25
- import type { TestSession } from '~/testing/index.js'
26
-
27
- /**
28
- * Wait for a specific agent to reach 'paused' status (or timeout).
29
- * Polls the TestSession's state directly (live getter).
30
- */
31
- async function waitForAgentPaused(session: TestSession, agentId: AgentId, timeoutMs = 10000): Promise<void> {
32
- const deadline = Date.now() + timeoutMs
33
- while (Date.now() < deadline) {
34
- const agentState = session.state.agents.get(agentId)
35
- if (agentState?.status === 'paused') return
36
- await new Promise(r => setTimeout(r, 10))
37
- }
38
- throw new Error(`waitForAgentPaused timed out after ${timeoutMs}ms for agent ${agentId}`)
39
- }
40
-
41
- async function waitUntil(predicate: () => boolean, timeoutMs = 10000): Promise<void> {
42
- const deadline = Date.now() + timeoutMs
43
- while (Date.now() < deadline) {
44
- if (predicate()) return
45
- await new Promise((resolve) => setTimeout(resolve, 10))
46
- }
47
- throw new Error(`waitUntil timed out after ${timeoutMs}ms`)
48
- }
49
-
50
- /**
51
- * Wait for all agents to be either idle (pending with no work) or paused.
52
- */
53
- async function waitForAllSettled(session: TestSession, timeoutMs = 10000): Promise<void> {
54
- const deadline = Date.now() + timeoutMs
55
- outer: while (Date.now() < deadline) {
56
- for (const [, agentState] of session.state.agents) {
57
- if (agentState.status === 'paused') continue
58
- if (agentState.status === 'pending' && agentState.pendingToolCalls.length === 0 && agentState.pendingToolResults.length === 0) {
59
- continue
60
- }
61
- await new Promise(r => setTimeout(r, 10))
62
- continue outer
63
- }
64
- // Double-check after a brief delay
65
- await new Promise(r => setTimeout(r, 10))
66
- for (const [, agentState] of session.state.agents) {
67
- if (agentState.status === 'paused') continue
68
- if (agentState.status === 'pending' && agentState.pendingToolCalls.length === 0 && agentState.pendingToolResults.length === 0) {
69
- continue
70
- }
71
- continue outer
72
- }
73
- return
74
- }
75
- throw new Error(`waitForAllSettled timed out after ${timeoutMs}ms`)
76
- }
77
-
78
- describe('limits-guard plugin', () => {
79
- // =========================================================================
80
- // hard limits
81
- // =========================================================================
82
-
83
- describe('hard limits', () => {
84
- it('agent exceeding inference hard limit → agent_paused event → agent stops', async () => {
85
- let inferenceCount = 0
86
-
87
- const harness = createLimitsHarness({
88
- presets: [createTestPreset({
89
- orchestratorSystem: 'Test agent.',
90
- orchestratorPlugins: [limitsGuardPlugin.configureAgent({ limits: { maxTurns: 3 } })],
91
- })],
92
- mockHandler: () => {
93
- inferenceCount++
94
- return {
95
- content: null,
96
- toolCalls: [{ id: ToolCallId(`tc${inferenceCount}`), name: 'tell_user', input: { message: `Turn ${inferenceCount}` } }],
97
- finishReason: 'stop',
98
- metrics: MockLLMProvider.defaultMetrics(),
99
- }
100
- },
101
- })
102
-
103
- const session = await harness.createSession('test')
104
- const entryAgentId = session.getEntryAgentId()!
105
- await session.sendMessage('Start')
106
- await waitForAgentPaused(session, entryAgentId)
107
-
108
- const entryAgent = session.state.agents.get(entryAgentId)!
109
- expect(entryAgent.status).toBe('paused')
110
-
111
- const pausedEvents = await session.getEventsByType(agentEvents, 'agent_paused')
112
- expect(pausedEvents.length).toBeGreaterThanOrEqual(1)
113
- const pauseEvent = pausedEvents.find(e => e.agentId === entryAgentId)
114
- expect(pauseEvent).toBeDefined()
115
- expect(pauseEvent!.reason).toBe('handler')
116
-
117
- await harness.shutdown()
118
- })
119
-
120
- it('agent exceeding tool call hard limit → agent paused', async () => {
121
- let callNum = 0
122
-
123
- const harness = createLimitsHarness({
124
- presets: [createTestPreset({
125
- orchestratorSystem: 'Test agent.',
126
- orchestratorPlugins: [limitsGuardPlugin.configureAgent({ limits: { maxToolCalls: 3, maxTurns: 100 } })],
127
- })],
128
- mockHandler: () => {
129
- callNum++
130
- return {
131
- content: null,
132
- toolCalls: [
133
- { id: ToolCallId(`tc${callNum}a`), name: 'tell_user', input: { message: `A${callNum}` } },
134
- { id: ToolCallId(`tc${callNum}b`), name: 'tell_user', input: { message: `B${callNum}` } },
135
- ],
136
- finishReason: 'stop',
137
- metrics: MockLLMProvider.defaultMetrics(),
138
- }
139
- },
140
- })
141
-
142
- const session = await harness.createSession('test')
143
- const entryAgentId = session.getEntryAgentId()!
144
- await session.sendMessage('Start')
145
- await waitForAgentPaused(session, entryAgentId)
146
-
147
- const entryAgent = session.state.agents.get(entryAgentId)!
148
- expect(entryAgent.status).toBe('paused')
149
-
150
- const counters = selectPluginState<Map<AgentId, AgentCounters>>(session.state, 'agentLimits')?.get(entryAgentId)
151
- expect(counters).toBeDefined()
152
- expect(counters!.toolCallCount).toBeGreaterThanOrEqual(3)
153
-
154
- await harness.shutdown()
155
- })
156
-
157
- it('agent exceeding spawned agent limit → agent paused', async () => {
158
- let orchestratorCalls = 0
159
-
160
- const harness = createLimitsHarness({
161
- presets: [createMultiAgentPreset([
162
- { name: 'worker', system: 'Worker agent.', tools: [], agents: [] },
163
- ], { orchestratorSystem: 'Orchestrator agent.' })],
164
- mockHandler: (request) => {
165
- if (request.systemPrompt.includes('Orchestrator')) {
166
- orchestratorCalls++
167
- return {
168
- content: null,
169
- toolCalls: [
170
- { id: ToolCallId(`tc${orchestratorCalls}a`), name: 'start_worker', input: { message: `Task ${orchestratorCalls}a` } },
171
- { id: ToolCallId(`tc${orchestratorCalls}b`), name: 'start_worker', input: { message: `Task ${orchestratorCalls}b` } },
172
- ],
173
- finishReason: 'stop',
174
- metrics: MockLLMProvider.defaultMetrics(),
175
- }
176
- }
177
- return { content: 'Worker done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() }
178
- },
179
- })
180
-
181
- const session = await harness.createSession('test')
182
- const orchestratorId = session.getEntryAgentId()!
183
- await session.sendMessage('Start')
184
- await waitForAgentPaused(session, orchestratorId, 15000)
185
-
186
- const orch = session.state.agents.get(orchestratorId)!
187
- expect(orch.status).toBe('paused')
188
-
189
- const counters = selectPluginState<Map<AgentId, AgentCounters>>(session.state, 'agentLimits')?.get(orchestratorId)
190
- expect(counters).toBeDefined()
191
- expect(counters!.spawnedAgentCount).toBeGreaterThanOrEqual(10)
192
-
193
- await harness.shutdown()
194
- })
195
-
196
- it('communication-only loop without new inbound work → soft-stops and remains wakeable', async () => {
197
- let inferenceCount = 0
198
-
199
- const harness = createLimitsHarness({
200
- presets: [createTestPreset({
201
- orchestratorSystem: 'Test agent.',
202
- orchestratorPlugins: [limitsGuardPlugin.configureAgent({
203
- limits: { maxConsecutiveNoProgressTurns: 3, maxTurns: 100 },
204
- })],
205
- })],
206
- mockHandler: () => {
207
- inferenceCount++
208
- if (inferenceCount > 4) {
209
- return {
210
- content: 'Recovered for new work',
211
- toolCalls: [],
212
- finishReason: 'stop',
213
- metrics: MockLLMProvider.defaultMetrics(),
214
- }
215
- }
216
- return {
217
- content: null,
218
- toolCalls: [{
219
- id: ToolCallId(`tc${inferenceCount}`),
220
- name: 'tell_user',
221
- input: { message: `Still waiting, update ${inferenceCount}` },
222
- }],
223
- finishReason: 'stop',
224
- metrics: MockLLMProvider.defaultMetrics(),
225
- }
226
- },
227
- })
228
-
229
- const session = await harness.createSession('test')
230
- const entryAgentId = session.getEntryAgentId()!
231
- await session.sendAndWaitForIdle('Start')
232
-
233
- // The response to "Start" had inbound work. The next three turns were
234
- // driven only by the previous tell_user result, so the fourth inference
235
- // reaches the limit and its redundant tool call is suppressed.
236
- expect(inferenceCount).toBe(4)
237
- const toolStarted = await session.getEventsByType(toolEvents, 'tool_started')
238
- expect(toolStarted).toHaveLength(3)
239
-
240
- const pauseEvents = await session.getEventsByType(agentEvents, 'agent_paused')
241
- expect(pauseEvents.some((event) => event.agentId === entryAgentId)).toBe(false)
242
-
243
- const warningEvents = await session.getEventsByType(limitsEvents, 'limit_warning')
244
- const noProgressEvent = warningEvents.find((event) =>
245
- event.agentId === entryAgentId
246
- && event.limitName === 'maxConsecutiveNoProgressTurns'
247
- )
248
- expect(noProgressEvent?.currentValue).toBe(3)
249
- expect(noProgressEvent?.message).toContain('until new input arrives')
250
- expect(session.state.agents.get(entryAgentId)?.status).toBe('pending')
251
-
252
- // The stop is recoverable without agents.resume or human intervention.
253
- await session.sendAndWaitForIdle('Now do real work')
254
- expect(inferenceCount).toBe(5)
255
- expect(session.state.agents.get(entryAgentId)?.status).toBe('pending')
256
-
257
- await harness.shutdown()
258
- })
259
-
260
- it('communication-only replies to distinct user messages do not count as no progress', async () => {
261
- let inferenceCount = 0
262
- let allowProcessing = false
263
- const preset = createTestPreset({
264
- orchestratorSystem: 'Test agent.',
265
- orchestratorPlugins: [limitsGuardPlugin.configureAgent({
266
- limits: { maxConsecutiveNoProgressTurns: 3, maxTurns: 100 },
267
- })],
268
- })
269
- preset.orchestrator.debounceCallback = () => {
270
- if (!allowProcessing) return 'wait'
271
- allowProcessing = false
272
- return 'process_now'
273
- }
274
- preset.orchestrator.checkIntervalMs = 1
275
-
276
- const harness = createLimitsHarness({
277
- presets: [preset],
278
- mockHandler: () => {
279
- inferenceCount++
280
- return {
281
- content: null,
282
- toolCalls: [{
283
- id: ToolCallId(`reply-${inferenceCount}`),
284
- name: 'tell_user',
285
- input: { message: `Reply ${inferenceCount}` },
286
- }],
287
- finishReason: 'stop',
288
- metrics: MockLLMProvider.defaultMetrics(),
289
- }
290
- },
291
- })
292
-
293
- const session = await harness.createSession('test')
294
- const entryAgentId = session.getEntryAgentId()!
295
-
296
- for (let messageNumber = 1; messageNumber <= 3; messageNumber++) {
297
- await session.sendMessage(`User message ${messageNumber}`)
298
- allowProcessing = true
299
- await waitUntil(() => {
300
- const state = session.state.agents.get(entryAgentId)
301
- return inferenceCount === messageNumber && state?.pendingToolResults.length === 1
302
- })
303
-
304
- const counters = selectPluginState<Map<AgentId, AgentCounters>>(
305
- session.state,
306
- 'agentLimits',
307
- )?.get(entryAgentId)
308
- expect(counters?.consecutiveNoProgressTurns).toBe(0)
309
- }
310
-
311
- const consumedEvents = await session.getEventsByType(agentEvents, 'agent_input_consumed')
312
- expect(consumedEvents).toHaveLength(3)
313
- expect(consumedEvents.every((event) => event.sourcePlugins.includes('user-chat'))).toBe(true)
314
-
315
- const pauseEvents = await session.getEventsByType(agentEvents, 'agent_paused')
316
- expect(pauseEvents.some((event) => event.agentId === entryAgentId)).toBe(false)
317
- const warningEvents = await session.getEventsByType(limitsEvents, 'limit_warning')
318
- expect(warningEvents.some((event) => event.limitName === 'maxConsecutiveNoProgressTurns')).toBe(false)
319
-
320
- await harness.shutdown()
321
- })
322
-
323
- it('send_message followed by non-communication work does not trip the no-progress limit', async () => {
324
- let workerInferenceCount = 0
325
- let workCount = 0
326
-
327
- const recordWork = createTool({
328
- name: 'record_work',
329
- description: 'Record one unit of real work.',
330
- input: z.object({}),
331
- execute: async () => {
332
- workCount++
333
- return Ok('work recorded')
334
- },
335
- })
336
-
337
- const harness = createLimitsHarness({
338
- presets: [createMultiAgentPreset([
339
- {
340
- name: 'worker',
341
- system: 'Worker agent.',
342
- tools: [recordWork],
343
- agents: [],
344
- plugins: [limitsGuardPlugin.configureAgent({
345
- limits: { maxConsecutiveNoProgressTurns: 2, maxTurns: 100 },
346
- })],
347
- },
348
- ], { orchestratorSystem: 'Orchestrator agent.' })],
349
- mockHandler: (request) => {
350
- if (request.systemPrompt.endsWith('Orchestrator agent.')) {
351
- const hasStartedWorker = request.messages.some((message) =>
352
- message.role === 'assistant'
353
- && message.toolCalls?.some((toolCall) => toolCall.name === 'start_worker')
354
- )
355
- if (!hasStartedWorker) {
356
- return {
357
- content: null,
358
- toolCalls: [{ id: ToolCallId('start-worker'), name: 'start_worker', input: { message: 'Do the work' } }],
359
- finishReason: 'stop',
360
- metrics: MockLLMProvider.defaultMetrics(),
361
- }
362
- }
363
- return {
364
- content: 'Orchestration complete',
365
- toolCalls: [],
366
- finishReason: 'stop',
367
- metrics: MockLLMProvider.defaultMetrics(),
368
- }
369
- }
370
-
371
- workerInferenceCount++
372
- switch (workerInferenceCount) {
373
- case 1:
374
- return {
375
- content: null,
376
- toolCalls: [{
377
- id: ToolCallId('worker-progress'),
378
- name: 'send_message',
379
- input: { to: 'parent', message: 'Starting real work' },
380
- }],
381
- finishReason: 'stop',
382
- metrics: MockLLMProvider.defaultMetrics(),
383
- }
384
- case 2:
385
- return {
386
- content: null,
387
- toolCalls: [{ id: ToolCallId('worker-work'), name: 'record_work', input: {} }],
388
- finishReason: 'stop',
389
- metrics: MockLLMProvider.defaultMetrics(),
390
- }
391
- case 3:
392
- return {
393
- content: null,
394
- toolCalls: [{
395
- id: ToolCallId('worker-result'),
396
- name: 'send_message',
397
- input: { to: 'parent', message: 'Real work complete' },
398
- }],
399
- finishReason: 'stop',
400
- metrics: MockLLMProvider.defaultMetrics(),
401
- }
402
- default:
403
- return {
404
- content: 'WAITING',
405
- toolCalls: [],
406
- finishReason: 'stop',
407
- metrics: MockLLMProvider.defaultMetrics(),
408
- }
409
- }
410
- },
411
- })
412
-
413
- const session = await harness.createSession('test')
414
- await session.sendAndWaitForIdle('Start', { timeoutMs: 10_000 })
415
-
416
- expect(workCount).toBe(1)
417
- expect(workerInferenceCount).toBe(4)
418
- expect(session.state.agents.get(AgentId('worker_1'))?.status).toBe('pending')
419
-
420
- const pauseEvents = await session.getEventsByType(agentEvents, 'agent_paused')
421
- expect(pauseEvents.some((event) => event.agentId === AgentId('worker_1'))).toBe(false)
422
-
423
- await harness.shutdown()
424
- })
425
- })
426
-
427
- // =========================================================================
428
- // soft limits (status display)
429
- // =========================================================================
430
-
431
- describe('soft limits (status display)', () => {
432
- it('approaching limit (80%) → status contains warning message', async () => {
433
- let inferenceCount = 0
434
- let sawWarning = false
435
-
436
- const harness = createLimitsHarness({
437
- presets: [createTestPreset({
438
- orchestratorSystem: 'Test agent.',
439
- orchestratorPlugins: [limitsGuardPlugin.configureAgent({
440
- limits: { maxTurns: 5, maxConsecutiveNoProgressTurns: 100 },
441
- })],
442
- })],
443
- mockHandler: (request) => {
444
- inferenceCount++
445
- const messagesStr = JSON.stringify(request.messages)
446
- if (messagesStr.includes('Approaching maxTurns limit')) {
447
- sawWarning = true
448
- }
449
- if (inferenceCount < 5) {
450
- return {
451
- content: null,
452
- toolCalls: [{ id: ToolCallId(`tc${inferenceCount}`), name: 'tell_user', input: { message: `Turn ${inferenceCount}` } }],
453
- finishReason: 'stop',
454
- metrics: MockLLMProvider.defaultMetrics(),
455
- }
456
- }
457
- return { content: 'Done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() }
458
- },
459
- })
460
-
461
- const session = await harness.createSession('test')
462
- const entryAgentId = session.getEntryAgentId()!
463
- await session.sendMessage('Start')
464
- // Agent will be paused at turn 5 or finish at turn 5 if last response has no tools
465
- await waitForAllSettled(session)
466
-
467
- expect(sawWarning).toBe(true)
468
-
469
- await harness.shutdown()
470
- })
471
- })
472
-
473
- // =========================================================================
474
- // counter tracking
475
- // =========================================================================
476
-
477
- describe('counter tracking', () => {
478
- it('each inference increments inferenceCount', async () => {
479
- let callCount = 0
480
-
481
- const harness = createLimitsHarness({
482
- presets: [createTestPreset({
483
- orchestratorSystem: 'Test agent.',
484
- orchestratorPlugins: [limitsGuardPlugin.configureAgent({ limits: { maxTurns: 100 } })],
485
- })],
486
- mockHandler: () => {
487
- callCount++
488
- if (callCount <= 2) {
489
- return {
490
- content: null,
491
- toolCalls: [{ id: ToolCallId(`tc${callCount}`), name: 'tell_user', input: { message: `Msg ${callCount}` } }],
492
- finishReason: 'stop',
493
- metrics: MockLLMProvider.defaultMetrics(),
494
- }
495
- }
496
- return { content: 'Done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() }
497
- },
498
- })
499
-
500
- const session = await harness.createSession('test')
501
- await session.sendAndWaitForIdle('Start')
502
-
503
- const counters = selectPluginState<Map<AgentId, AgentCounters>>(session.state, 'agentLimits')?.get(session.getEntryAgentId()!)
504
- expect(counters).toBeDefined()
505
- expect(counters!.inferenceCount).toBe(3) // 2 with tools + 1 final
506
-
507
- await harness.shutdown()
508
- })
509
-
510
- it('each tool call increments toolCallCount', async () => {
511
- let callCount = 0
512
-
513
- const harness = createLimitsHarness({
514
- presets: [createTestPreset({
515
- orchestratorSystem: 'Test agent.',
516
- orchestratorPlugins: [limitsGuardPlugin.configureAgent({ limits: { maxTurns: 100 } })],
517
- })],
518
- mockHandler: () => {
519
- callCount++
520
- if (callCount === 1) {
521
- return {
522
- content: null,
523
- toolCalls: [
524
- { id: ToolCallId('tc1'), name: 'tell_user', input: { message: 'A' } },
525
- { id: ToolCallId('tc2'), name: 'tell_user', input: { message: 'B' } },
526
- ],
527
- finishReason: 'stop',
528
- metrics: MockLLMProvider.defaultMetrics(),
529
- }
530
- }
531
- return { content: 'Done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() }
532
- },
533
- })
534
-
535
- const session = await harness.createSession('test')
536
- await session.sendAndWaitForIdle('Start')
537
-
538
- const counters = selectPluginState<Map<AgentId, AgentCounters>>(session.state, 'agentLimits')?.get(session.getEntryAgentId()!)
539
- expect(counters).toBeDefined()
540
- expect(counters!.toolCallCount).toBe(2)
541
-
542
- await harness.shutdown()
543
- })
544
-
545
- it('each agent spawn increments parent spawnedAgentCount', async () => {
546
- let orchestratorCalls = 0
547
-
548
- const harness = createLimitsHarness({
549
- presets: [createMultiAgentPreset([
550
- { name: 'worker', system: 'Worker agent.', tools: [], agents: [] },
551
- ], { orchestratorSystem: 'Orchestrator agent.' })],
552
- mockHandler: (request) => {
553
- if (request.systemPrompt.includes('Orchestrator')) {
554
- orchestratorCalls++
555
- if (orchestratorCalls === 1) {
556
- return {
557
- content: null,
558
- toolCalls: [
559
- { id: ToolCallId('tc1'), name: 'start_worker', input: { message: 'Task 1' } },
560
- { id: ToolCallId('tc2'), name: 'start_worker', input: { message: 'Task 2' } },
561
- ],
562
- finishReason: 'stop',
563
- metrics: MockLLMProvider.defaultMetrics(),
564
- }
565
- }
566
- return { content: 'Done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() }
567
- }
568
- return { content: 'Worker done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() }
569
- },
570
- })
571
-
572
- const session = await harness.createSession('test')
573
- await session.sendAndWaitForIdle('Start', { timeoutMs: 10000 })
574
-
575
- const orchestratorId = session.getEntryAgentId()!
576
- const counters = selectPluginState<Map<AgentId, AgentCounters>>(session.state, 'agentLimits')?.get(orchestratorId)
577
- expect(counters).toBeDefined()
578
- expect(counters!.spawnedAgentCount).toBe(2)
579
-
580
- await harness.shutdown()
581
- })
582
-
583
- it('each mailbox message increments sender messagesSentCount', async () => {
584
- let orchestratorCalls = 0
585
- let workerCalls = 0
586
-
587
- const harness = createLimitsHarness({
588
- presets: [createMultiAgentPreset([
589
- { name: 'worker', system: 'Worker agent.', tools: [], agents: [] },
590
- ], { orchestratorSystem: 'Orchestrator agent.' })],
591
- mockHandler: (request) => {
592
- if (request.systemPrompt.includes('Orchestrator')) {
593
- orchestratorCalls++
594
- if (orchestratorCalls === 1) {
595
- return {
596
- content: null,
597
- toolCalls: [{ id: ToolCallId('tc1'), name: 'start_worker', input: { message: 'Task' } }],
598
- finishReason: 'stop',
599
- metrics: MockLLMProvider.defaultMetrics(),
600
- }
601
- }
602
- return { content: 'Done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() }
603
- }
604
- workerCalls++
605
- if (workerCalls === 1) {
606
- return {
607
- content: null,
608
- toolCalls: [{ id: ToolCallId('tc2'), name: 'send_message', input: { to: 'parent', message: 'Report' } }],
609
- finishReason: 'stop',
610
- metrics: MockLLMProvider.defaultMetrics(),
611
- }
612
- }
613
- return { content: 'Worker done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() }
614
- },
615
- })
616
-
617
- const session = await harness.createSession('test')
618
- await session.sendAndWaitForIdle('Start', { timeoutMs: 10000 })
619
-
620
- const workerCounters = selectPluginState<Map<AgentId, AgentCounters>>(session.state, 'agentLimits')?.get(AgentId('worker_1'))
621
- expect(workerCounters).toBeDefined()
622
- expect(workerCounters!.messagesSentCount).toBeGreaterThanOrEqual(1)
623
-
624
- await harness.shutdown()
625
- })
626
- })
627
-
628
- // =========================================================================
629
- // resume resets
630
- // =========================================================================
631
-
632
- describe('resume resets', () => {
633
- it('agent_resumed → pattern-based counters reset, cumulative counters preserved', async () => {
634
- const harness = createLimitsHarness({
635
- presets: [createTestPreset({
636
- orchestratorSystem: 'Test agent.',
637
- orchestratorPlugins: [limitsGuardPlugin.configureAgent({
638
- limits: { maxRepeatedResponses: 2, maxTurns: 100 },
639
- })],
640
- })],
641
- // Always return the same text → triggers maxRepeatedResponses
642
- mockHandler: () => ({
643
- content: 'I am stuck',
644
- toolCalls: [],
645
- finishReason: 'stop',
646
- metrics: MockLLMProvider.defaultMetrics(),
647
- }),
648
- })
649
-
650
- const session = await harness.createSession('test')
651
- const entryAgentId = session.getEntryAgentId()!
652
-
653
- // 1st identical response → ok → idle
654
- await session.sendAndWaitForIdle('Message 1')
655
- // 2nd identical response → maxRepeatedResponses = 2 → paused
656
- await session.sendMessage('Message 2')
657
- await waitForAgentPaused(session, entryAgentId)
658
-
659
- expect(session.state.agents.get(entryAgentId)!.status).toBe('paused')
660
-
661
- // Resume the agent
662
- const resumeResult = await session.callPluginMethod('agents.resume', {
663
- agentId: String(entryAgentId),
664
- })
665
- expect(resumeResult.ok).toBe(true)
666
-
667
- // All counters should be reset after resume
668
- const countersAfterResume = selectPluginState<Map<AgentId, AgentCounters>>(session.state, 'agentLimits')?.get(entryAgentId)
669
- expect(countersAfterResume).toBeDefined()
670
- expect(countersAfterResume!.inferenceCount).toBe(0)
671
- expect(countersAfterResume!.toolCallCount).toBe(0)
672
- expect(countersAfterResume!.recentResponseHashes).toEqual([])
673
-
674
- // Agent resumes with reset counters. Wait for it to settle (no work → idle).
675
- await session.waitForIdle()
676
-
677
- // Send 2 more messages to hit the limit again
678
- await session.sendAndWaitForIdle('Message 3')
679
- await session.sendMessage('Message 4')
680
- await waitForAgentPaused(session, entryAgentId)
681
-
682
- const resumedEvents = await session.getEventsByType(agentEvents, 'agent_resumed')
683
- expect(resumedEvents.filter(e => e.agentId === entryAgentId)).toHaveLength(1)
684
-
685
- await harness.shutdown()
686
- })
687
- })
688
-
689
- // =========================================================================
690
- // budgets (cost / tokens)
691
- // =========================================================================
692
-
693
- describe('budgets', () => {
694
- it('agent exceeding cost budget → paused with budget_exceeded event', async () => {
695
- let n = 0
696
- const harness = createLimitsHarness({
697
- presets: [createTestPreset({
698
- orchestratorSystem: 'Test agent.',
699
- // $0.50 per call, $1.00 budget → pauses before the 3rd call.
700
- orchestratorPlugins: [limitsGuardPlugin.configureAgent({ limits: { maxCost: 1.0, maxTurns: 100 } })],
701
- })],
702
- mockHandler: () => {
703
- n++
704
- return {
705
- content: null,
706
- toolCalls: [{ id: ToolCallId(`tc${n}`), name: 'tell_user', input: { message: `Turn ${n}` } }],
707
- finishReason: 'stop',
708
- metrics: MockLLMProvider.defaultMetricsWithCost(0.5),
709
- }
710
- },
711
- })
712
-
713
- const session = await harness.createSession('test')
714
- const entryAgentId = session.getEntryAgentId()!
715
- await session.sendMessage('Start')
716
- await waitForAgentPaused(session, entryAgentId)
717
-
718
- expect(session.state.agents.get(entryAgentId)!.status).toBe('paused')
719
-
720
- const counters = selectPluginState<Map<AgentId, AgentCounters>>(session.state, 'agentLimits')?.get(entryAgentId)
721
- expect(counters!.costSpent).toBeGreaterThanOrEqual(1.0)
722
-
723
- const budgetEvents = await session.getEventsByType(limitsEvents, 'budget_exceeded')
724
- const evt = budgetEvents.find(e => e.agentId === entryAgentId)
725
- expect(evt).toBeDefined()
726
- expect(evt!.scope).toBe('agent')
727
- expect(evt!.limitName).toBe('maxCost')
728
-
729
- await harness.shutdown()
730
- })
731
-
732
- it('costSpent is preserved across resume — budget cannot be bypassed by pausing', async () => {
733
- let n = 0
734
- const harness = createLimitsHarness({
735
- presets: [createTestPreset({
736
- orchestratorSystem: 'Test agent.',
737
- orchestratorPlugins: [limitsGuardPlugin.configureAgent({ limits: { maxCost: 1.0, maxTurns: 100 } })],
738
- })],
739
- mockHandler: () => {
740
- n++
741
- return {
742
- content: null,
743
- toolCalls: [{ id: ToolCallId(`tc${n}`), name: 'tell_user', input: { message: `Turn ${n}` } }],
744
- finishReason: 'stop',
745
- metrics: MockLLMProvider.defaultMetricsWithCost(0.5),
746
- }
747
- },
748
- })
749
-
750
- const session = await harness.createSession('test')
751
- const entryAgentId = session.getEntryAgentId()!
752
- await session.sendMessage('Start')
753
- await waitForAgentPaused(session, entryAgentId)
754
-
755
- const before = selectPluginState<Map<AgentId, AgentCounters>>(session.state, 'agentLimits')?.get(entryAgentId)
756
- expect(before).toBeDefined()
757
- expect(before!.costSpent).toBeGreaterThanOrEqual(1.0)
758
-
759
- await session.callPluginMethod('agents.resume', { agentId: String(entryAgentId) })
760
- // Budget is still exhausted → agent pauses again immediately without inferring.
761
- await waitForAgentPaused(session, entryAgentId)
762
-
763
- const after = selectPluginState<Map<AgentId, AgentCounters>>(session.state, 'agentLimits')?.get(entryAgentId)
764
- expect(after).toBeDefined()
765
- // Anti-looping counter reset…
766
- expect(after!.inferenceCount).toBe(0)
767
- // …but spend preserved, so the cap is not bypassable.
768
- expect(after!.costSpent).toBeGreaterThanOrEqual(before!.costSpent)
769
-
770
- await harness.shutdown()
771
- })
772
-
773
- it('child pausing on budget → parent is notified via a child-paused message', async () => {
774
- let orchestratorCalls = 0
775
- let workerCalls = 0
776
- const harness = createLimitsHarness({
777
- presets: [createTestPreset({
778
- orchestratorSystem: 'Orchestrator agent.',
779
- agents: [{
780
- name: 'worker',
781
- system: 'Worker agent.',
782
- tools: [],
783
- agents: [],
784
- // $0.50 per call, $0.50 budget → pauses at the 2nd inference's
785
- // beforeInference (after one completed call spent the budget).
786
- plugins: [limitsGuardPlugin.configureAgent({ limits: { maxCost: 0.5, maxTurns: 100 } })],
787
- }],
788
- })],
789
- mockHandler: (request) => {
790
- // Worker: keep spending until the budget pauses it.
791
- if (request.systemPrompt.includes('Worker agent.')) {
792
- workerCalls++
793
- return {
794
- content: null,
795
- toolCalls: [{ id: ToolCallId(`w${workerCalls}`), name: 'tell_user', input: { message: `Work ${workerCalls}` } }],
796
- finishReason: 'stop',
797
- metrics: MockLLMProvider.defaultMetricsWithCost(0.5),
798
- }
799
- }
800
- // Orchestrator: spawn the worker exactly once, then idle.
801
- orchestratorCalls++
802
- if (orchestratorCalls === 1) {
803
- return {
804
- content: null,
805
- toolCalls: [{ id: ToolCallId('spawn'), name: 'start_worker', input: { message: 'Do work' } }],
806
- finishReason: 'stop',
807
- metrics: MockLLMProvider.defaultMetrics(),
808
- }
809
- }
810
- return { content: 'Waiting', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() }
811
- },
812
- })
813
-
814
- const session = await harness.createSession('test')
815
- await session.sendMessage('Start')
816
- await waitForAgentPaused(session, AgentId('worker_1'))
817
-
818
- const orchestratorId = session.getEntryAgentId()!
819
- // The mailbox plugin's onPause hook reports the pause to the parent.
820
- // onPause runs *after* the agent_paused event (which flips status to
821
- // 'paused'), so poll for the notification.
822
- const findNotice = async () =>
823
- (await session.getEventsByType(mailboxEvents, 'mailbox_message')).find(m =>
824
- m.toAgentId === orchestratorId
825
- && m.message.from === AgentId('worker_1')
826
- && m.message.content.includes('<child-paused')
827
- && m.message.content.includes('worker_1'),
828
- )
829
- let notice = await findNotice()
830
- const deadline = Date.now() + 5000
831
- while (!notice && Date.now() < deadline) {
832
- await new Promise(r => setTimeout(r, 20))
833
- notice = await findNotice()
834
- }
835
- expect(notice).toBeDefined()
836
-
837
- await harness.shutdown()
838
- })
839
-
840
- it('child-paused notice is actually consumed by a parent that already went idle', async () => {
841
- // Regression guard for the lifecycle: a parent that finished its work is
842
- // NOT in a terminal "complete" state — it's persisted as `pending` with an
843
- // empty mailbox. When the child pauses and delivers <child-paused>, the
844
- // dequeue check flips the parent's decide() from "complete" back to "infer",
845
- // so the parent wakes and reads the message rather than leaving it unconsumed.
846
- let workerCalls = 0
847
- let orchestratorSawChildPaused = false
848
-
849
- const requestHasChildPaused = (request: InferenceRequest): boolean =>
850
- request.messages.some((m) => {
851
- const c = typeof m.content === 'string' ? m.content : JSON.stringify(m.content)
852
- return c.includes('<child-paused')
853
- })
854
-
855
- const harness = createLimitsHarness({
856
- presets: [createTestPreset({
857
- orchestratorSystem: 'Orchestrator agent.',
858
- agents: [{
859
- name: 'worker',
860
- system: 'Worker agent.',
861
- tools: [],
862
- agents: [],
863
- plugins: [limitsGuardPlugin.configureAgent({ limits: { maxCost: 0.5, maxTurns: 100 } })],
864
- }],
865
- })],
866
- mockHandler: (request) => {
867
- if (request.systemPrompt.includes('Worker agent.')) {
868
- workerCalls++
869
- return {
870
- content: null,
871
- toolCalls: [{ id: ToolCallId(`w${workerCalls}`), name: 'tell_user', input: { message: `Work ${workerCalls}` } }],
872
- finishReason: 'stop',
873
- metrics: MockLLMProvider.defaultMetricsWithCost(0.5),
874
- }
875
- }
876
- // Orchestrator: spawn the worker once, then go idle. Any later wake-up
877
- // is driven by an incoming message — record if it carried the notice.
878
- if (requestHasChildPaused(request)) orchestratorSawChildPaused = true
879
- if (workerCalls === 0) {
880
- return {
881
- content: null,
882
- toolCalls: [{ id: ToolCallId('spawn'), name: 'start_worker', input: { message: 'Do work' } }],
883
- finishReason: 'stop',
884
- metrics: MockLLMProvider.defaultMetrics(),
885
- }
886
- }
887
- return { content: 'Acknowledged', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() }
888
- },
889
- })
890
-
891
- const session = await harness.createSession('test')
892
- await session.sendMessage('Start')
893
- await waitForAgentPaused(session, AgentId('worker_1'))
894
-
895
- // The parent should wake from idle and run an inference that includes the
896
- // <child-paused> message — proving the notice is consumed, not orphaned.
897
- const deadline = Date.now() + 5000
898
- while (!orchestratorSawChildPaused && Date.now() < deadline) {
899
- await new Promise(r => setTimeout(r, 20))
900
- }
901
- expect(orchestratorSawChildPaused).toBe(true)
902
-
903
- // And the message is marked consumed in the parent's mailbox.
904
- const orchestratorId = session.getEntryAgentId()!
905
- const mailbox = getAgentMailbox(selectMailboxState(session.state), orchestratorId)
906
- const childPausedMsg = mailbox.find((m) => m.content.includes('<child-paused'))
907
- expect(childPausedMsg).toBeDefined()
908
- expect(childPausedMsg!.consumed).toBe(true)
909
-
910
- await harness.shutdown()
911
- })
912
-
913
- it('compaction (auxiliary inference) cost counts toward the budget', async () => {
914
- // The compaction summarization is a real, billed LLM call routed through
915
- // runAuxiliaryInference → auxiliary_inference_completed. It must be charged
916
- // against the cost budget, otherwise an agent could spend unboundedly on
917
- // compaction without ever tripping its cap.
918
- const REGULAR_COST = 0.1
919
- const SUMMARY_COST = 5.0
920
-
921
- // Compaction request detection: inline compaction appends a trailing user
922
- // message containing the summarization marker.
923
- const isSummarizationRequest = (request: InferenceRequest): boolean => {
924
- const last = request.messages[request.messages.length - 1]
925
- if (!last || last.role !== 'user') return false
926
- const content = typeof last.content === 'string' ? last.content : JSON.stringify(last.content)
927
- return content.includes('[CONTEXT COMPACTION REQUEST]')
928
- }
929
-
930
- const harness = new TestHarness({
931
- systemPlugins: [contextCompactPlugin, limitsGuardPlugin],
932
- presets: [createTestPreset({
933
- orchestratorSystem: 'Test agent.',
934
- plugins: [
935
- contextCompactPlugin.configure({
936
- compaction: { model: ModelId('mock'), maxTokens: 10, keepRecentMessages: 2 },
937
- }),
938
- ],
939
- // Budget large enough to survive the cheap regular turns but small
940
- // enough that one expensive summarization call blows past it.
941
- orchestratorPlugins: [
942
- limitsGuardPlugin.configureAgent({ limits: { maxCost: 2.0, maxTurns: 100 } }),
943
- ],
944
- })],
945
- mockHandler: (request) => {
946
- if (isSummarizationRequest(request)) {
947
- return {
948
- content: 'Summary of conversation so far.',
949
- toolCalls: [],
950
- finishReason: 'stop',
951
- metrics: MockLLMProvider.defaultMetricsWithCost(SUMMARY_COST),
952
- }
953
- }
954
- return {
955
- content: 'Agent response with some content to increase token count.',
956
- toolCalls: [],
957
- finishReason: 'stop',
958
- metrics: MockLLMProvider.defaultMetricsWithCost(REGULAR_COST),
959
- }
960
- },
961
- })
962
-
963
- const session = await harness.createSession('test')
964
- const entryAgentId = session.getEntryAgentId()!
965
-
966
- // Returns once the agent is either idle or paused — used because we don't
967
- // know up front whether the compaction cost trips the budget on the same
968
- // turn (depends on beforeInference hook ordering) or on the next one.
969
- const waitForIdleOrPaused = async (timeoutMs = 10000): Promise<'idle' | 'paused'> => {
970
- const deadline = Date.now() + timeoutMs
971
- while (Date.now() < deadline) {
972
- const st = session.state.agents.get(entryAgentId)
973
- if (st?.status === 'paused') return 'paused'
974
- if (st?.status === 'pending' && st.pendingToolCalls.length === 0 && st.pendingToolResults.length === 0) {
975
- return 'idle'
976
- }
977
- await new Promise(r => setTimeout(r, 10))
978
- }
979
- throw new Error('waitForIdleOrPaused timed out')
980
- }
981
-
982
- await session.sendAndWaitForIdle('First message')
983
- await session.sendAndWaitForIdle('Second message')
984
- // Third message triggers compaction (the expensive summarization call).
985
- // It may pause on this turn or settle idle and pause on the next one.
986
- await session.sendMessage('Third message to trigger compaction')
987
- if (await waitForIdleOrPaused() === 'idle') {
988
- await session.sendMessage('Fourth message')
989
- }
990
- await waitForAgentPaused(session, entryAgentId)
991
-
992
- // Compaction genuinely ran and was billed.
993
- const auxEvents = await session.getEventsByType(llmEvents, 'auxiliary_inference_completed')
994
- expect(auxEvents.some((e) => e.metrics.cost === SUMMARY_COST)).toBe(true)
995
-
996
- // The summarization cost is reflected in the agent's tracked spend…
997
- const counters = selectPluginState<Map<AgentId, AgentCounters>>(session.state, 'agentLimits')?.get(entryAgentId)
998
- expect(counters).toBeDefined()
999
- expect(counters!.costSpent).toBeGreaterThanOrEqual(SUMMARY_COST)
1000
-
1001
- // …and it tripped the cost budget (the regular turns alone, at 0.1 each,
1002
- // could never reach the 2.0 cap on their own here).
1003
- const budgetEvents = await session.getEventsByType(limitsEvents, 'budget_exceeded')
1004
- const evt = budgetEvents.find((e) => e.agentId === entryAgentId)
1005
- expect(evt).toBeDefined()
1006
- expect(evt!.scope).toBe('agent')
1007
- expect(evt!.limitName).toBe('maxCost')
1008
-
1009
- await harness.shutdown()
1010
- })
1011
- })
1012
- })