@roj-ai/sdk 0.1.3 → 0.1.5

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 (493) hide show
  1. package/dist/bootstrap.js +191 -0
  2. package/dist/bootstrap.js.map +1 -0
  3. package/dist/builtin-events.js +8 -0
  4. package/dist/builtin-events.js.map +1 -0
  5. package/dist/bun-platform/fs.js +39 -0
  6. package/dist/bun-platform/fs.js.map +1 -0
  7. package/dist/bun-platform/index.js +18 -0
  8. package/dist/bun-platform/index.js.map +1 -0
  9. package/dist/bun-platform/process.js +21 -0
  10. package/dist/bun-platform/process.js.map +1 -0
  11. package/dist/config.js +54 -0
  12. package/dist/config.js.map +1 -0
  13. package/dist/config.test.js +155 -0
  14. package/dist/config.test.js.map +1 -0
  15. package/dist/core/agent-loop.integration.test.js +414 -0
  16. package/dist/core/agent-loop.integration.test.js.map +1 -0
  17. package/dist/core/agents/agent-config.test.js +194 -0
  18. package/dist/core/agents/agent-config.test.js.map +1 -0
  19. package/dist/core/agents/agent-roles.js +25 -0
  20. package/dist/core/agents/agent-roles.js.map +1 -0
  21. package/dist/core/agents/agent-shutdown.test.js +180 -0
  22. package/dist/core/agents/agent-shutdown.test.js.map +1 -0
  23. package/dist/core/agents/agent.js +1205 -0
  24. package/dist/core/agents/agent.js.map +1 -0
  25. package/dist/core/agents/agent.test.js +313 -0
  26. package/dist/core/agents/agent.test.js.map +1 -0
  27. package/dist/core/agents/communicator.js +13 -0
  28. package/dist/core/agents/communicator.js.map +1 -0
  29. package/dist/core/agents/config.js +5 -0
  30. package/dist/core/agents/config.js.map +1 -0
  31. package/dist/core/agents/context.js +2 -0
  32. package/dist/core/agents/context.js.map +1 -0
  33. package/dist/core/agents/debounce.js +74 -0
  34. package/dist/core/agents/debounce.js.map +1 -0
  35. package/dist/core/agents/handler-events.test.js +115 -0
  36. package/dist/core/agents/handler-events.test.js.map +1 -0
  37. package/dist/core/agents/index.js +2 -0
  38. package/dist/core/agents/index.js.map +1 -0
  39. package/dist/core/agents/response-sanitizer.js +46 -0
  40. package/dist/core/agents/response-sanitizer.js.map +1 -0
  41. package/dist/core/agents/response-sanitizer.test.js +101 -0
  42. package/dist/core/agents/response-sanitizer.test.js.map +1 -0
  43. package/dist/core/agents/retry.js +105 -0
  44. package/dist/core/agents/retry.js.map +1 -0
  45. package/dist/core/agents/schema.js +39 -0
  46. package/dist/core/agents/schema.js.map +1 -0
  47. package/dist/core/agents/state.js +90 -0
  48. package/dist/core/agents/state.js.map +1 -0
  49. package/dist/core/context/state.js +23 -0
  50. package/dist/core/context/state.js.map +1 -0
  51. package/dist/core/errors.js +38 -0
  52. package/dist/core/errors.js.map +1 -0
  53. package/dist/core/event-sourcing.integration.test.js +154 -0
  54. package/dist/core/event-sourcing.integration.test.js.map +1 -0
  55. package/dist/core/events/base-event-store.js +201 -0
  56. package/dist/core/events/base-event-store.js.map +1 -0
  57. package/dist/core/events/event-store.js +26 -0
  58. package/dist/core/events/event-store.js.map +1 -0
  59. package/dist/core/events/file.js +320 -0
  60. package/dist/core/events/file.js.map +1 -0
  61. package/dist/core/events/file.test.js +284 -0
  62. package/dist/core/events/file.test.js.map +1 -0
  63. package/dist/core/events/index.js +3 -0
  64. package/dist/core/events/index.js.map +1 -0
  65. package/dist/core/events/memory.js +101 -0
  66. package/dist/core/events/memory.js.map +1 -0
  67. package/dist/core/events/memory.test.js +502 -0
  68. package/dist/core/events/memory.test.js.map +1 -0
  69. package/dist/core/events/metadata-utils.js +107 -0
  70. package/dist/core/events/metadata-utils.js.map +1 -0
  71. package/dist/core/events/test-helpers.js +15 -0
  72. package/dist/core/events/test-helpers.js.map +1 -0
  73. package/dist/core/events/types.js +21 -0
  74. package/dist/core/events/types.js.map +1 -0
  75. package/dist/core/file-store/file-store.js +250 -0
  76. package/dist/core/file-store/file-store.js.map +1 -0
  77. package/dist/core/file-store/types.js +7 -0
  78. package/dist/core/file-store/types.js.map +1 -0
  79. package/dist/core/image/image-processor.js +106 -0
  80. package/dist/core/image/image-processor.js.map +1 -0
  81. package/dist/core/image/image-processor.test.js +171 -0
  82. package/dist/core/image/image-processor.test.js.map +1 -0
  83. package/dist/core/image/index.js +4 -0
  84. package/dist/core/image/index.js.map +1 -0
  85. package/dist/core/image/noop-resizer.js +6 -0
  86. package/dist/core/image/noop-resizer.js.map +1 -0
  87. package/dist/core/image/types.js +2 -0
  88. package/dist/core/image/types.js.map +1 -0
  89. package/dist/core/image/vips-resizer.js +100 -0
  90. package/dist/core/image/vips-resizer.js.map +1 -0
  91. package/dist/core/image/vips-resizer.test.js +324 -0
  92. package/dist/core/image/vips-resizer.test.js.map +1 -0
  93. package/dist/core/llm/anthropic.js +396 -0
  94. package/dist/core/llm/anthropic.js.map +1 -0
  95. package/dist/core/llm/anthropic.test.js +434 -0
  96. package/dist/core/llm/anthropic.test.js.map +1 -0
  97. package/dist/core/llm/cache-breakpoints.js +37 -0
  98. package/dist/core/llm/cache-breakpoints.js.map +1 -0
  99. package/dist/core/llm/cache-live.test.js +137 -0
  100. package/dist/core/llm/cache-live.test.js.map +1 -0
  101. package/dist/core/llm/index.js +9 -0
  102. package/dist/core/llm/index.js.map +1 -0
  103. package/dist/core/llm/llm-log-types.js +12 -0
  104. package/dist/core/llm/llm-log-types.js.map +1 -0
  105. package/dist/core/llm/logger.js +241 -0
  106. package/dist/core/llm/logger.js.map +1 -0
  107. package/dist/core/llm/logger.test.js +228 -0
  108. package/dist/core/llm/logger.test.js.map +1 -0
  109. package/dist/core/llm/logging-provider.js +49 -0
  110. package/dist/core/llm/logging-provider.js.map +1 -0
  111. package/dist/core/llm/middleware.js +114 -0
  112. package/dist/core/llm/middleware.js.map +1 -0
  113. package/dist/core/llm/mock.js +186 -0
  114. package/dist/core/llm/mock.js.map +1 -0
  115. package/dist/core/llm/mock.test.js +318 -0
  116. package/dist/core/llm/mock.test.js.map +1 -0
  117. package/dist/core/llm/openrouter-mapping.test.js +125 -0
  118. package/dist/core/llm/openrouter-mapping.test.js.map +1 -0
  119. package/dist/core/llm/openrouter.js +298 -0
  120. package/dist/core/llm/openrouter.js.map +1 -0
  121. package/dist/core/llm/openrouter.test.js +377 -0
  122. package/dist/core/llm/openrouter.test.js.map +1 -0
  123. package/dist/core/llm/provider-integration.test.js +350 -0
  124. package/dist/core/llm/provider-integration.test.js.map +1 -0
  125. package/dist/core/llm/provider.js +18 -0
  126. package/dist/core/llm/provider.js.map +1 -0
  127. package/dist/core/llm/routing-provider.js +52 -0
  128. package/dist/core/llm/routing-provider.js.map +1 -0
  129. package/dist/core/llm/routing-provider.test.js +94 -0
  130. package/dist/core/llm/routing-provider.test.js.map +1 -0
  131. package/dist/core/llm/schema.js +31 -0
  132. package/dist/core/llm/schema.js.map +1 -0
  133. package/dist/core/llm/snapshot-fetch.js +122 -0
  134. package/dist/core/llm/snapshot-fetch.js.map +1 -0
  135. package/dist/core/llm/snapshot-middleware.js +142 -0
  136. package/dist/core/llm/snapshot-middleware.js.map +1 -0
  137. package/dist/core/llm/snapshot-middleware.test.js +144 -0
  138. package/dist/core/llm/snapshot-middleware.test.js.map +1 -0
  139. package/dist/core/llm/state.js +48 -0
  140. package/dist/core/llm/state.js.map +1 -0
  141. package/dist/core/llm/tokens.js +40 -0
  142. package/dist/core/llm/tokens.js.map +1 -0
  143. package/dist/core/multi-agent.integration.test.js +298 -0
  144. package/dist/core/multi-agent.integration.test.js.map +1 -0
  145. package/dist/core/plugin-hooks.integration.test.js +344 -0
  146. package/dist/core/plugin-hooks.integration.test.js.map +1 -0
  147. package/dist/core/plugins/hook-types.js +5 -0
  148. package/dist/core/plugins/hook-types.js.map +1 -0
  149. package/dist/core/plugins/index.js +5 -0
  150. package/dist/core/plugins/index.js.map +1 -0
  151. package/dist/core/plugins/plugin-builder.js +321 -0
  152. package/dist/core/plugins/plugin-builder.js.map +1 -0
  153. package/dist/core/preset/config.js +54 -0
  154. package/dist/core/preset/config.js.map +1 -0
  155. package/dist/core/preset/index.js +6 -0
  156. package/dist/core/preset/index.js.map +1 -0
  157. package/dist/core/preset/preset-builder.js +63 -0
  158. package/dist/core/preset/preset-builder.js.map +1 -0
  159. package/dist/core/session-lifecycle.integration.test.js +159 -0
  160. package/dist/core/session-lifecycle.integration.test.js.map +1 -0
  161. package/dist/core/sessions/apply-event.js +41 -0
  162. package/dist/core/sessions/apply-event.js.map +1 -0
  163. package/dist/core/sessions/context.js +2 -0
  164. package/dist/core/sessions/context.js.map +1 -0
  165. package/dist/core/sessions/fork-utils.js +42 -0
  166. package/dist/core/sessions/fork-utils.js.map +1 -0
  167. package/dist/core/sessions/fork-utils.test.js +129 -0
  168. package/dist/core/sessions/fork-utils.test.js.map +1 -0
  169. package/dist/core/sessions/reducer.js +55 -0
  170. package/dist/core/sessions/reducer.js.map +1 -0
  171. package/dist/core/sessions/schema.js +66 -0
  172. package/dist/core/sessions/schema.js.map +1 -0
  173. package/dist/core/sessions/session-environment.js +2 -0
  174. package/dist/core/sessions/session-environment.js.map +1 -0
  175. package/dist/core/sessions/session-manager.js +650 -0
  176. package/dist/core/sessions/session-manager.js.map +1 -0
  177. package/dist/core/sessions/session-store.js +118 -0
  178. package/dist/core/sessions/session-store.js.map +1 -0
  179. package/dist/core/sessions/session.js +675 -0
  180. package/dist/core/sessions/session.js.map +1 -0
  181. package/dist/core/sessions/session.test.js +1095 -0
  182. package/dist/core/sessions/session.test.js.map +1 -0
  183. package/dist/core/sessions/state.js +377 -0
  184. package/dist/core/sessions/state.js.map +1 -0
  185. package/dist/core/system.js +66 -0
  186. package/dist/core/system.js.map +1 -0
  187. package/dist/core/tools/context.js +2 -0
  188. package/dist/core/tools/context.js.map +1 -0
  189. package/dist/core/tools/definition.js +4 -0
  190. package/dist/core/tools/definition.js.map +1 -0
  191. package/dist/core/tools/executor.js +82 -0
  192. package/dist/core/tools/executor.js.map +1 -0
  193. package/dist/core/tools/executor.test.js +143 -0
  194. package/dist/core/tools/executor.test.js.map +1 -0
  195. package/dist/core/tools/index.js +4 -0
  196. package/dist/core/tools/index.js.map +1 -0
  197. package/dist/core/tools/schema.js +20 -0
  198. package/dist/core/tools/schema.js.map +1 -0
  199. package/dist/core/tools/state.js +29 -0
  200. package/dist/core/tools/state.js.map +1 -0
  201. package/dist/index.js +70 -0
  202. package/dist/index.js.map +1 -0
  203. package/dist/lib/json/index.js +5 -0
  204. package/dist/lib/json/index.js.map +1 -0
  205. package/dist/lib/logger/console.js +147 -0
  206. package/dist/lib/logger/console.js.map +1 -0
  207. package/dist/lib/logger/console.test.js +258 -0
  208. package/dist/lib/logger/console.test.js.map +1 -0
  209. package/dist/lib/logger/file.js +54 -0
  210. package/dist/lib/logger/file.js.map +1 -0
  211. package/dist/lib/logger/index.js +4 -0
  212. package/dist/lib/logger/index.js.map +1 -0
  213. package/dist/lib/logger/logger.js +28 -0
  214. package/dist/lib/logger/logger.js.map +1 -0
  215. package/dist/lib/logger/ring-buffer.js +61 -0
  216. package/dist/lib/logger/ring-buffer.js.map +1 -0
  217. package/dist/lib/logger/tee.js +43 -0
  218. package/dist/lib/logger/tee.js.map +1 -0
  219. package/dist/lib/mime.js +22 -0
  220. package/dist/lib/mime.js.map +1 -0
  221. package/dist/lib/never.js +4 -0
  222. package/dist/lib/never.js.map +1 -0
  223. package/dist/lib/utils/hash.js +35 -0
  224. package/dist/lib/utils/hash.js.map +1 -0
  225. package/dist/lib/utils/result.js +21 -0
  226. package/dist/lib/utils/result.js.map +1 -0
  227. package/dist/platform/fs.js +8 -0
  228. package/dist/platform/fs.js.map +1 -0
  229. package/dist/platform/index.js +9 -0
  230. package/dist/platform/index.js.map +1 -0
  231. package/dist/platform/process.js +8 -0
  232. package/dist/platform/process.js.map +1 -0
  233. package/dist/plugins/agent-status/plugin.js +77 -0
  234. package/dist/plugins/agent-status/plugin.js.map +1 -0
  235. package/dist/plugins/agents/agents.integration.test.js +683 -0
  236. package/dist/plugins/agents/agents.integration.test.js.map +1 -0
  237. package/dist/plugins/agents/index.js +2 -0
  238. package/dist/plugins/agents/index.js.map +1 -0
  239. package/dist/plugins/agents/plugin.js +199 -0
  240. package/dist/plugins/agents/plugin.js.map +1 -0
  241. package/dist/plugins/context-compact/context-compact.integration.test.js +174 -0
  242. package/dist/plugins/context-compact/context-compact.integration.test.js.map +1 -0
  243. package/dist/plugins/context-compact/context-compactor.js +238 -0
  244. package/dist/plugins/context-compact/context-compactor.js.map +1 -0
  245. package/dist/plugins/context-compact/context-compactor.test.js +763 -0
  246. package/dist/plugins/context-compact/context-compactor.test.js.map +1 -0
  247. package/dist/plugins/context-compact/history-offloader.js +42 -0
  248. package/dist/plugins/context-compact/history-offloader.js.map +1 -0
  249. package/dist/plugins/context-compact/history-offloader.test.js +77 -0
  250. package/dist/plugins/context-compact/history-offloader.test.js.map +1 -0
  251. package/dist/plugins/context-compact/index.js +4 -0
  252. package/dist/plugins/context-compact/index.js.map +1 -0
  253. package/dist/plugins/context-compact/plugin.js +37 -0
  254. package/dist/plugins/context-compact/plugin.js.map +1 -0
  255. package/dist/plugins/filesystem/filesystem.integration.test.js +411 -0
  256. package/dist/plugins/filesystem/filesystem.integration.test.js.map +1 -0
  257. package/dist/plugins/filesystem/helpers.js +170 -0
  258. package/dist/plugins/filesystem/helpers.js.map +1 -0
  259. package/dist/plugins/filesystem/index.js +3 -0
  260. package/dist/plugins/filesystem/index.js.map +1 -0
  261. package/dist/plugins/filesystem/listing.js +247 -0
  262. package/dist/plugins/filesystem/listing.js.map +1 -0
  263. package/dist/plugins/filesystem/plugin.js +364 -0
  264. package/dist/plugins/filesystem/plugin.js.map +1 -0
  265. package/dist/plugins/filesystem/schema.js +2 -0
  266. package/dist/plugins/filesystem/schema.js.map +1 -0
  267. package/dist/plugins/git-status/index.js +2 -0
  268. package/dist/plugins/git-status/index.js.map +1 -0
  269. package/dist/plugins/git-status/plugin.js +144 -0
  270. package/dist/plugins/git-status/plugin.js.map +1 -0
  271. package/dist/plugins/limits-guard/config.js +5 -0
  272. package/dist/plugins/limits-guard/config.js.map +1 -0
  273. package/dist/plugins/limits-guard/index.js +3 -0
  274. package/dist/plugins/limits-guard/index.js.map +1 -0
  275. package/dist/plugins/limits-guard/limit-guard.js +125 -0
  276. package/dist/plugins/limits-guard/limit-guard.js.map +1 -0
  277. package/dist/plugins/limits-guard/limit-guard.test.js +121 -0
  278. package/dist/plugins/limits-guard/limit-guard.test.js.map +1 -0
  279. package/dist/plugins/limits-guard/limits-guard.integration.test.js +378 -0
  280. package/dist/plugins/limits-guard/limits-guard.integration.test.js.map +1 -0
  281. package/dist/plugins/limits-guard/plugin.js +240 -0
  282. package/dist/plugins/limits-guard/plugin.js.map +1 -0
  283. package/dist/plugins/llm-debug/index.js +2 -0
  284. package/dist/plugins/llm-debug/index.js.map +1 -0
  285. package/dist/plugins/llm-debug/llm-debug.integration.test.js +157 -0
  286. package/dist/plugins/llm-debug/llm-debug.integration.test.js.map +1 -0
  287. package/dist/plugins/llm-debug/plugin.js +148 -0
  288. package/dist/plugins/llm-debug/plugin.js.map +1 -0
  289. package/dist/plugins/logs/index.js +2 -0
  290. package/dist/plugins/logs/index.js.map +1 -0
  291. package/dist/plugins/logs/plugin.js +38 -0
  292. package/dist/plugins/logs/plugin.js.map +1 -0
  293. package/dist/plugins/mailbox/helpers.js +66 -0
  294. package/dist/plugins/mailbox/helpers.js.map +1 -0
  295. package/dist/plugins/mailbox/index.js +9 -0
  296. package/dist/plugins/mailbox/index.js.map +1 -0
  297. package/dist/plugins/mailbox/mailbox.integration.test.js +605 -0
  298. package/dist/plugins/mailbox/mailbox.integration.test.js.map +1 -0
  299. package/dist/plugins/mailbox/plugin.js +204 -0
  300. package/dist/plugins/mailbox/plugin.js.map +1 -0
  301. package/dist/plugins/mailbox/prompts.js +93 -0
  302. package/dist/plugins/mailbox/prompts.js.map +1 -0
  303. package/dist/plugins/mailbox/query.js +38 -0
  304. package/dist/plugins/mailbox/query.js.map +1 -0
  305. package/dist/plugins/mailbox/schema.js +32 -0
  306. package/dist/plugins/mailbox/schema.js.map +1 -0
  307. package/dist/plugins/mailbox/state.js +41 -0
  308. package/dist/plugins/mailbox/state.js.map +1 -0
  309. package/dist/plugins/resources/index.js +4 -0
  310. package/dist/plugins/resources/index.js.map +1 -0
  311. package/dist/plugins/resources/manifest.js +20 -0
  312. package/dist/plugins/resources/manifest.js.map +1 -0
  313. package/dist/plugins/resources/plugin.js +171 -0
  314. package/dist/plugins/resources/plugin.js.map +1 -0
  315. package/dist/plugins/resources/post-inject.js +32 -0
  316. package/dist/plugins/resources/post-inject.js.map +1 -0
  317. package/dist/plugins/resources/state.js +16 -0
  318. package/dist/plugins/resources/state.js.map +1 -0
  319. package/dist/plugins/result-eviction/index.js +2 -0
  320. package/dist/plugins/result-eviction/index.js.map +1 -0
  321. package/dist/plugins/result-eviction/plugin.js +43 -0
  322. package/dist/plugins/result-eviction/plugin.js.map +1 -0
  323. package/dist/plugins/result-eviction/result-eviction.integration.test.js +217 -0
  324. package/dist/plugins/result-eviction/result-eviction.integration.test.js.map +1 -0
  325. package/dist/plugins/services/plugin.js +453 -0
  326. package/dist/plugins/services/plugin.js.map +1 -0
  327. package/dist/plugins/services/port-pool.js +70 -0
  328. package/dist/plugins/services/port-pool.js.map +1 -0
  329. package/dist/plugins/services/prompt.js +40 -0
  330. package/dist/plugins/services/prompt.js.map +1 -0
  331. package/dist/plugins/services/schema.js +9 -0
  332. package/dist/plugins/services/schema.js.map +1 -0
  333. package/dist/plugins/services/service.js +470 -0
  334. package/dist/plugins/services/service.js.map +1 -0
  335. package/dist/plugins/services/services.integration.test.js +485 -0
  336. package/dist/plugins/services/services.integration.test.js.map +1 -0
  337. package/dist/plugins/session-lifecycle/index.js +2 -0
  338. package/dist/plugins/session-lifecycle/index.js.map +1 -0
  339. package/dist/plugins/session-lifecycle/plugin.js +273 -0
  340. package/dist/plugins/session-lifecycle/plugin.js.map +1 -0
  341. package/dist/plugins/session-lifecycle/session-lifecycle.integration.test.js +498 -0
  342. package/dist/plugins/session-lifecycle/session-lifecycle.integration.test.js.map +1 -0
  343. package/dist/plugins/session-state/plugin.js +159 -0
  344. package/dist/plugins/session-state/plugin.js.map +1 -0
  345. package/dist/plugins/session-stats/index.js +3 -0
  346. package/dist/plugins/session-stats/index.js.map +1 -0
  347. package/dist/plugins/session-stats/plugin.js +81 -0
  348. package/dist/plugins/session-stats/plugin.js.map +1 -0
  349. package/dist/plugins/shell/executor.js +339 -0
  350. package/dist/plugins/shell/executor.js.map +1 -0
  351. package/dist/plugins/shell/index.js +6 -0
  352. package/dist/plugins/shell/index.js.map +1 -0
  353. package/dist/plugins/shell/plugin.js +66 -0
  354. package/dist/plugins/shell/plugin.js.map +1 -0
  355. package/dist/plugins/shell/shell.integration.test.js +234 -0
  356. package/dist/plugins/shell/shell.integration.test.js.map +1 -0
  357. package/dist/plugins/shell/shell.test.js +236 -0
  358. package/dist/plugins/shell/shell.test.js.map +1 -0
  359. package/dist/plugins/skills/discovery.js +205 -0
  360. package/dist/plugins/skills/discovery.js.map +1 -0
  361. package/dist/plugins/skills/discovery.test.js +312 -0
  362. package/dist/plugins/skills/discovery.test.js.map +1 -0
  363. package/dist/plugins/skills/index.js +12 -0
  364. package/dist/plugins/skills/index.js.map +1 -0
  365. package/dist/plugins/skills/plugin.js +293 -0
  366. package/dist/plugins/skills/plugin.js.map +1 -0
  367. package/dist/plugins/skills/prompts.js +70 -0
  368. package/dist/plugins/skills/prompts.js.map +1 -0
  369. package/dist/plugins/skills/schema.js +18 -0
  370. package/dist/plugins/skills/schema.js.map +1 -0
  371. package/dist/plugins/skills/skills.integration.test.js +475 -0
  372. package/dist/plugins/skills/skills.integration.test.js.map +1 -0
  373. package/dist/plugins/snapshotting/index.js +3 -0
  374. package/dist/plugins/snapshotting/index.js.map +1 -0
  375. package/dist/plugins/snapshotting/jj-snapshotter.js +106 -0
  376. package/dist/plugins/snapshotting/jj-snapshotter.js.map +1 -0
  377. package/dist/plugins/snapshotting/plugin.js +28 -0
  378. package/dist/plugins/snapshotting/plugin.js.map +1 -0
  379. package/dist/plugins/snapshotting/snapshotter.js +2 -0
  380. package/dist/plugins/snapshotting/snapshotter.js.map +1 -0
  381. package/dist/plugins/todo/index.js +7 -0
  382. package/dist/plugins/todo/index.js.map +1 -0
  383. package/dist/plugins/todo/plugin.js +319 -0
  384. package/dist/plugins/todo/plugin.js.map +1 -0
  385. package/dist/plugins/todo/prompts.js +54 -0
  386. package/dist/plugins/todo/prompts.js.map +1 -0
  387. package/dist/plugins/todo/schema.js +18 -0
  388. package/dist/plugins/todo/schema.js.map +1 -0
  389. package/dist/plugins/todo/todo.integration.test.js +605 -0
  390. package/dist/plugins/todo/todo.integration.test.js.map +1 -0
  391. package/dist/plugins/uploads/index.js +8 -0
  392. package/dist/plugins/uploads/index.js.map +1 -0
  393. package/dist/plugins/uploads/plugin.js +346 -0
  394. package/dist/plugins/uploads/plugin.js.map +1 -0
  395. package/dist/plugins/uploads/preprocessor.js +44 -0
  396. package/dist/plugins/uploads/preprocessor.js.map +1 -0
  397. package/dist/plugins/uploads/preprocessors/image-classifier.js +127 -0
  398. package/dist/plugins/uploads/preprocessors/image-classifier.js.map +1 -0
  399. package/dist/plugins/uploads/preprocessors/index.js +7 -0
  400. package/dist/plugins/uploads/preprocessors/index.js.map +1 -0
  401. package/dist/plugins/uploads/preprocessors/markitdown-preprocessor.js +204 -0
  402. package/dist/plugins/uploads/preprocessors/markitdown-preprocessor.js.map +1 -0
  403. package/dist/plugins/uploads/preprocessors/zip-preprocessor.js +172 -0
  404. package/dist/plugins/uploads/preprocessors/zip-preprocessor.js.map +1 -0
  405. package/dist/plugins/uploads/schema.js +20 -0
  406. package/dist/plugins/uploads/schema.js.map +1 -0
  407. package/dist/plugins/uploads/state.js +22 -0
  408. package/dist/plugins/uploads/state.js.map +1 -0
  409. package/dist/plugins/uploads/uploads.integration.test.js +496 -0
  410. package/dist/plugins/uploads/uploads.integration.test.js.map +1 -0
  411. package/dist/plugins/user-chat/index.js +5 -0
  412. package/dist/plugins/user-chat/index.js.map +1 -0
  413. package/dist/plugins/user-chat/plugin.js +544 -0
  414. package/dist/plugins/user-chat/plugin.js.map +1 -0
  415. package/dist/plugins/user-chat/prompts.js +29 -0
  416. package/dist/plugins/user-chat/prompts.js.map +1 -0
  417. package/dist/plugins/user-chat/schema.js +46 -0
  418. package/dist/plugins/user-chat/schema.js.map +1 -0
  419. package/dist/plugins/user-chat/user-chat.integration.test.js +668 -0
  420. package/dist/plugins/user-chat/user-chat.integration.test.js.map +1 -0
  421. package/dist/plugins/workers/context.js +143 -0
  422. package/dist/plugins/workers/context.js.map +1 -0
  423. package/dist/plugins/workers/definition.js +30 -0
  424. package/dist/plugins/workers/definition.js.map +1 -0
  425. package/dist/plugins/workers/index.js +7 -0
  426. package/dist/plugins/workers/index.js.map +1 -0
  427. package/dist/plugins/workers/plugin.js +578 -0
  428. package/dist/plugins/workers/plugin.js.map +1 -0
  429. package/dist/plugins/workers/worker.js +18 -0
  430. package/dist/plugins/workers/worker.js.map +1 -0
  431. package/dist/plugins/workers/workers.integration.test.js +629 -0
  432. package/dist/plugins/workers/workers.integration.test.js.map +1 -0
  433. package/dist/prompts/base.js +239 -0
  434. package/dist/prompts/base.js.map +1 -0
  435. package/dist/prompts/builder.js +131 -0
  436. package/dist/prompts/builder.js.map +1 -0
  437. package/dist/prompts/index.js +20 -0
  438. package/dist/prompts/index.js.map +1 -0
  439. package/dist/prompts/macros.js +26 -0
  440. package/dist/prompts/macros.js.map +1 -0
  441. package/dist/prompts/macros.test.js +80 -0
  442. package/dist/prompts/macros.test.js.map +1 -0
  443. package/dist/testing/bootstrap-for-testing.js +28 -0
  444. package/dist/testing/bootstrap-for-testing.js.map +1 -0
  445. package/dist/testing/index.js +7 -0
  446. package/dist/testing/index.js.map +1 -0
  447. package/dist/testing/node-platform.js +65 -0
  448. package/dist/testing/node-platform.js.map +1 -0
  449. package/dist/testing/notification-collector.js +82 -0
  450. package/dist/testing/notification-collector.js.map +1 -0
  451. package/dist/testing/preset-helpers.js +37 -0
  452. package/dist/testing/preset-helpers.js.map +1 -0
  453. package/dist/testing/test-harness.js +226 -0
  454. package/dist/testing/test-harness.js.map +1 -0
  455. package/dist/testing/test-harness.test.js +51 -0
  456. package/dist/testing/test-harness.test.js.map +1 -0
  457. package/dist/testing/wait-helpers.js +64 -0
  458. package/dist/testing/wait-helpers.js.map +1 -0
  459. package/dist/transport/adapter/client-adapter.js +64 -0
  460. package/dist/transport/adapter/client-adapter.js.map +1 -0
  461. package/dist/transport/adapter/index.js +24 -0
  462. package/dist/transport/adapter/index.js.map +1 -0
  463. package/dist/transport/adapter/server-adapter.js +73 -0
  464. package/dist/transport/adapter/server-adapter.js.map +1 -0
  465. package/dist/transport/adapter/types.js +8 -0
  466. package/dist/transport/adapter/types.js.map +1 -0
  467. package/dist/transport/http/app.js +86 -0
  468. package/dist/transport/http/app.js.map +1 -0
  469. package/dist/transport/http/index.js +6 -0
  470. package/dist/transport/http/index.js.map +1 -0
  471. package/dist/transport/http/middleware/bearer-auth.js +33 -0
  472. package/dist/transport/http/middleware/bearer-auth.js.map +1 -0
  473. package/dist/transport/http/middleware/error-handler.js +56 -0
  474. package/dist/transport/http/middleware/error-handler.js.map +1 -0
  475. package/dist/transport/http/routes/files.js +237 -0
  476. package/dist/transport/http/routes/files.js.map +1 -0
  477. package/dist/transport/http/routes/resources.js +77 -0
  478. package/dist/transport/http/routes/resources.js.map +1 -0
  479. package/dist/transport/http/routes/rpc.integration.test.js +189 -0
  480. package/dist/transport/http/routes/rpc.integration.test.js.map +1 -0
  481. package/dist/transport/http/routes/rpc.js +110 -0
  482. package/dist/transport/http/routes/rpc.js.map +1 -0
  483. package/dist/transport/http/routes/rpc.test.js +316 -0
  484. package/dist/transport/http/routes/rpc.test.js.map +1 -0
  485. package/dist/transport/http/routes/upload.js +205 -0
  486. package/dist/transport/http/routes/upload.js.map +1 -0
  487. package/dist/transport/rpc/index.js +7 -0
  488. package/dist/transport/rpc/index.js.map +1 -0
  489. package/dist/transport/rpc/methods.js +8 -0
  490. package/dist/transport/rpc/methods.js.map +1 -0
  491. package/dist/user-config.js +14 -0
  492. package/dist/user-config.js.map +1 -0
  493. package/package.json +47 -57
@@ -0,0 +1,414 @@
1
+ import { describe, expect, it } from 'bun:test';
2
+ import z from 'zod/v4';
3
+ import { agentEvents } from '../core/agents/state.js';
4
+ import { MockLLMProvider } from '../core/llm/mock.js';
5
+ import { ModelId } from '../core/llm/schema.js';
6
+ import { definePlugin } from '../core/plugins/plugin-builder.js';
7
+ import { createTool } from '../core/tools/definition.js';
8
+ import { ToolCallId } from '../core/tools/schema.js';
9
+ import { toolEvents } from '../core/tools/state.js';
10
+ import { createTestPreset, TestHarness } from '../testing/index.js';
11
+ describe('agent processing loop', () => {
12
+ // =========================================================================
13
+ // basic flow
14
+ // =========================================================================
15
+ describe('basic flow', () => {
16
+ it('message → inference → text response (no tools) → agent idle', async () => {
17
+ const harness = new TestHarness({
18
+ presets: [createTestPreset()],
19
+ llmProvider: MockLLMProvider.withFixedResponse({ content: 'Hello back!', toolCalls: [] }),
20
+ });
21
+ const session = await harness.createSession('test');
22
+ await session.sendAndWaitForIdle('Hello');
23
+ // Agent should have processed and gone back to pending
24
+ const entryAgentId = session.getEntryAgentId();
25
+ const agentState = session.state.agents.get(entryAgentId);
26
+ expect(agentState).toBeDefined();
27
+ expect(agentState.status).toBe('pending');
28
+ // Inference events should exist
29
+ const started = await session.getEventsByType('inference_started');
30
+ const completed = await session.getEventsByType('inference_completed');
31
+ expect(started).toHaveLength(1);
32
+ expect(completed).toHaveLength(1);
33
+ await harness.shutdown();
34
+ });
35
+ it('message → inference → 1 tool call → tool result → 2nd inference → idle', async () => {
36
+ const harness = new TestHarness({
37
+ presets: [createTestPreset()],
38
+ llmProvider: MockLLMProvider.withSequence([
39
+ {
40
+ toolCalls: [{ id: ToolCallId('tc1'), name: 'tell_user', input: { message: 'Hi!' } }],
41
+ },
42
+ { content: 'Done', toolCalls: [] },
43
+ ]),
44
+ });
45
+ const session = await harness.createSession('test');
46
+ await session.sendAndWaitForIdle('Do something');
47
+ const inferenceStarted = await session.getEventsByType('inference_started');
48
+ const inferenceCompleted = await session.getEventsByType('inference_completed');
49
+ expect(inferenceStarted).toHaveLength(2);
50
+ expect(inferenceCompleted).toHaveLength(2);
51
+ const toolStarted = await session.getEventsByType('tool_started');
52
+ const toolCompleted = await session.getEventsByType('tool_completed');
53
+ expect(toolStarted).toHaveLength(1);
54
+ expect(toolCompleted).toHaveLength(1);
55
+ await harness.shutdown();
56
+ });
57
+ it('message → inference → multiple tool calls → all executed → 2nd inference → idle', async () => {
58
+ const harness = new TestHarness({
59
+ presets: [createTestPreset()],
60
+ llmProvider: MockLLMProvider.withSequence([
61
+ {
62
+ toolCalls: [
63
+ { id: ToolCallId('tc1'), name: 'tell_user', input: { message: 'First' } },
64
+ { id: ToolCallId('tc2'), name: 'tell_user', input: { message: 'Second' } },
65
+ ],
66
+ },
67
+ { content: 'Done', toolCalls: [] },
68
+ ]),
69
+ });
70
+ const session = await harness.createSession('test');
71
+ await session.sendAndWaitForIdle('Do multiple things');
72
+ const toolStarted = await session.getEventsByType('tool_started');
73
+ const toolCompleted = await session.getEventsByType('tool_completed');
74
+ expect(toolStarted).toHaveLength(2);
75
+ expect(toolCompleted).toHaveLength(2);
76
+ const messages = harness.notifications.getAgentMessages();
77
+ expect(messages).toHaveLength(2);
78
+ expect(messages[0].content).toBe('First');
79
+ expect(messages[1].content).toBe('Second');
80
+ await harness.shutdown();
81
+ });
82
+ it('message → inference → tool call → tool call → tool call → eventually finishes', async () => {
83
+ const harness = new TestHarness({
84
+ presets: [createTestPreset()],
85
+ llmProvider: MockLLMProvider.withSequence([
86
+ {
87
+ toolCalls: [{ id: ToolCallId('tc1'), name: 'tell_user', input: { message: 'Step 1' } }],
88
+ },
89
+ {
90
+ toolCalls: [{ id: ToolCallId('tc2'), name: 'tell_user', input: { message: 'Step 2' } }],
91
+ },
92
+ {
93
+ toolCalls: [{ id: ToolCallId('tc3'), name: 'tell_user', input: { message: 'Step 3' } }],
94
+ },
95
+ { content: 'All done', toolCalls: [] },
96
+ ]),
97
+ });
98
+ const session = await harness.createSession('test');
99
+ await session.sendAndWaitForIdle('Multi step');
100
+ const messages = harness.notifications.getAgentMessages();
101
+ expect(messages).toHaveLength(3);
102
+ const inferenceCompleted = await session.getEventsByType('inference_completed');
103
+ expect(inferenceCompleted).toHaveLength(4);
104
+ await harness.shutdown();
105
+ });
106
+ });
107
+ // =========================================================================
108
+ // tool execution
109
+ // =========================================================================
110
+ describe('tool execution', () => {
111
+ it('tool with valid input → executes successfully → result in history', async () => {
112
+ const harness = new TestHarness({
113
+ presets: [createTestPreset()],
114
+ llmProvider: MockLLMProvider.withSequence([
115
+ {
116
+ toolCalls: [{ id: ToolCallId('tc1'), name: 'tell_user', input: { message: 'Hello!' } }],
117
+ },
118
+ { content: 'Done', toolCalls: [] },
119
+ ]),
120
+ });
121
+ const session = await harness.createSession('test');
122
+ await session.sendAndWaitForIdle('Test');
123
+ const toolCompleted = await session.getEventsByType(toolEvents, 'tool_completed');
124
+ expect(toolCompleted).toHaveLength(1);
125
+ // tool_completed (not tool_failed) means execution succeeded
126
+ const toolFailed = await session.getEventsByType(toolEvents, 'tool_failed');
127
+ expect(toolFailed).toHaveLength(0);
128
+ // The second inference should have the tool result in messages
129
+ const lastRequest = harness.llmProvider.getLastRequest();
130
+ const toolMessages = lastRequest?.messages.filter((m) => m.role === 'tool');
131
+ expect(toolMessages?.length).toBeGreaterThanOrEqual(1);
132
+ await harness.shutdown();
133
+ });
134
+ it('tool returning Err (recoverable) → error tool result, agent continues', async () => {
135
+ const failingTool = createTool({
136
+ name: 'failing_tool',
137
+ description: 'A tool that returns a recoverable error',
138
+ input: z.unknown(),
139
+ execute: async () => ({ ok: false, error: { message: 'Something went wrong', recoverable: true } }),
140
+ });
141
+ const preset = {
142
+ id: 'test',
143
+ name: 'Test Preset',
144
+ orchestrator: {
145
+ system: 'You are a test agent.',
146
+ model: ModelId('mock'),
147
+ tools: [failingTool],
148
+ agents: [],
149
+ debounceMs: 0,
150
+ },
151
+ agents: [],
152
+ };
153
+ const harness = new TestHarness({
154
+ presets: [preset],
155
+ llmProvider: MockLLMProvider.withSequence([
156
+ {
157
+ toolCalls: [{ id: ToolCallId('tc1'), name: 'failing_tool', input: { value: 'test' } }],
158
+ },
159
+ { content: 'Recovered', toolCalls: [] },
160
+ ]),
161
+ });
162
+ const session = await harness.createSession('test');
163
+ await session.sendAndWaitForIdle('Test error');
164
+ // Tool should have failed with the recoverable error
165
+ const toolFailed = await session.getEventsByType(toolEvents, 'tool_failed');
166
+ expect(toolFailed).toHaveLength(1);
167
+ expect(toolFailed[0].error).toContain('Something went wrong');
168
+ // Agent should recover and continue to 2nd inference, ending in pending state
169
+ const inferenceCompleted = await session.getEventsByType('inference_completed');
170
+ expect(inferenceCompleted).toHaveLength(2);
171
+ const entryAgentId = session.getEntryAgentId();
172
+ const agentState = session.state.agents.get(entryAgentId);
173
+ expect(agentState.status).toBe('pending');
174
+ await harness.shutdown();
175
+ });
176
+ });
177
+ // =========================================================================
178
+ // LLM errors
179
+ // =========================================================================
180
+ describe('LLM errors', () => {
181
+ it('non-retryable LLM error → agent enters errored state', async () => {
182
+ const harness = new TestHarness({
183
+ presets: [createTestPreset()],
184
+ // invalid_request is non-retryable (unlike server_error which retries)
185
+ llmProvider: MockLLMProvider.withError({ type: 'invalid_request', message: 'Bad request' }),
186
+ });
187
+ const session = await harness.createSession('test');
188
+ await session.sendMessage('Trigger error');
189
+ // Poll until agent enters errored state or timeout
190
+ const entryAgentId = session.getEntryAgentId();
191
+ const deadline = Date.now() + 5000;
192
+ while (Date.now() < deadline) {
193
+ const agentState = session.state.agents.get(entryAgentId);
194
+ if (agentState?.status === 'errored')
195
+ break;
196
+ await new Promise((r) => setTimeout(r, 50));
197
+ }
198
+ const agentState = session.state.agents.get(entryAgentId);
199
+ expect(agentState.status).toBe('errored');
200
+ const failedEvents = await session.getEventsByType('inference_failed');
201
+ expect(failedEvents).toHaveLength(1);
202
+ await harness.shutdown();
203
+ });
204
+ it('agent with content + toolCalls in same response → both processed', async () => {
205
+ const harness = new TestHarness({
206
+ presets: [createTestPreset()],
207
+ llmProvider: MockLLMProvider.withSequence([
208
+ {
209
+ content: 'Thinking about it...',
210
+ toolCalls: [{ id: ToolCallId('tc1'), name: 'tell_user', input: { message: 'Result' } }],
211
+ },
212
+ { content: 'All done', toolCalls: [] },
213
+ ]),
214
+ });
215
+ const session = await harness.createSession('test');
216
+ await session.sendAndWaitForIdle('Process both');
217
+ // Tool should have been executed
218
+ const toolCompleted = await session.getEventsByType('tool_completed');
219
+ expect(toolCompleted).toHaveLength(1);
220
+ // Content should be in conversation history
221
+ const inferenceCompleted = await session.getEventsByType('inference_completed');
222
+ expect(inferenceCompleted).toHaveLength(2);
223
+ await harness.shutdown();
224
+ });
225
+ });
226
+ // =========================================================================
227
+ // conversation history
228
+ // =========================================================================
229
+ describe('conversation history', () => {
230
+ it('tool results appear in conversation history for next inference', async () => {
231
+ const harness = new TestHarness({
232
+ presets: [createTestPreset()],
233
+ llmProvider: MockLLMProvider.withSequence([
234
+ {
235
+ toolCalls: [{ id: ToolCallId('tc1'), name: 'tell_user', input: { message: 'Hello!' } }],
236
+ },
237
+ { content: 'Done', toolCalls: [] },
238
+ ]),
239
+ });
240
+ const session = await harness.createSession('test');
241
+ await session.sendAndWaitForIdle('Test');
242
+ // The second inference (last request) should have the tool result
243
+ const lastRequest = harness.llmProvider.getLastRequest();
244
+ const toolMessages = lastRequest?.messages.filter((m) => m.role === 'tool') ?? [];
245
+ expect(toolMessages.length).toBeGreaterThanOrEqual(1);
246
+ await harness.shutdown();
247
+ });
248
+ it('system prompt passed to LLM as systemPrompt', async () => {
249
+ const harness = new TestHarness({
250
+ presets: [createTestPreset({ orchestratorSystem: 'You are a helpful test assistant.' })],
251
+ llmProvider: MockLLMProvider.withFixedResponse({ content: 'Ok' }),
252
+ });
253
+ const session = await harness.createSession('test');
254
+ await session.sendAndWaitForIdle('Hello');
255
+ const lastRequest = harness.llmProvider.getLastRequest();
256
+ expect(lastRequest?.systemPrompt).toContain('You are a helpful test assistant.');
257
+ await harness.shutdown();
258
+ });
259
+ });
260
+ // =========================================================================
261
+ // debounce
262
+ // =========================================================================
263
+ describe('debounce', () => {
264
+ it('debounceMs: 0 → instant processing', async () => {
265
+ const harness = new TestHarness({
266
+ presets: [createTestPreset()], // debounceMs: 0 is default in test presets
267
+ llmProvider: MockLLMProvider.withFixedResponse({ content: 'Fast!' }),
268
+ });
269
+ const session = await harness.createSession('test');
270
+ const start = Date.now();
271
+ await session.sendAndWaitForIdle('Quick');
272
+ const elapsed = Date.now() - start;
273
+ // With debounceMs: 0, processing should be nearly instant
274
+ expect(elapsed).toBeLessThan(2000);
275
+ await harness.shutdown();
276
+ });
277
+ it('multiple messages sent rapidly → agent processes after single debounce', async () => {
278
+ const harness = new TestHarness({
279
+ presets: [createTestPreset()],
280
+ llmProvider: MockLLMProvider.withFixedResponse({ content: 'Processed', toolCalls: [] }),
281
+ });
282
+ const session = await harness.createSession('test');
283
+ // Send multiple messages without waiting for idle between them
284
+ await session.sendMessage('First');
285
+ await session.sendMessage('Second');
286
+ await session.sendMessage('Third');
287
+ await session.waitForIdle();
288
+ // With debounceMs: 0, the setTimeout(fn, 0) fires as a macrotask.
289
+ // All sendMessage calls complete in the microtask queue before the macrotask fires,
290
+ // so the agent batches all 3 messages into a single inference cycle.
291
+ const inferenceStarted = await session.getEventsByType('inference_started');
292
+ expect(inferenceStarted).toHaveLength(1);
293
+ // All 3 messages should be visible in the single LLM request (merged into one user message)
294
+ const lastRequest = harness.llmProvider.getLastRequest();
295
+ const userMessage = lastRequest.messages.find((m) => m.role === 'user' && typeof m.content === 'string' && m.content.includes('[User]'));
296
+ expect(userMessage).toBeDefined();
297
+ expect(userMessage.content).toContain('First');
298
+ expect(userMessage.content).toContain('Second');
299
+ expect(userMessage.content).toContain('Third');
300
+ await harness.shutdown();
301
+ });
302
+ });
303
+ // =========================================================================
304
+ // tool execution — error paths
305
+ // =========================================================================
306
+ describe('tool execution — error paths', () => {
307
+ it('tool with invalid input → validation error → returned as tool result', async () => {
308
+ const harness = new TestHarness({
309
+ presets: [createTestPreset()],
310
+ llmProvider: MockLLMProvider.withSequence([
311
+ {
312
+ // tell_user requires { message: string }, pass invalid input
313
+ toolCalls: [{ id: ToolCallId('tc1'), name: 'tell_user', input: { wrong_field: 123 } }],
314
+ },
315
+ { content: 'Recovered from error', toolCalls: [] },
316
+ ]),
317
+ });
318
+ const session = await harness.createSession('test');
319
+ await session.sendAndWaitForIdle('Test invalid input');
320
+ // Tool should have failed due to validation
321
+ const toolFailed = await session.getEventsByType(toolEvents, 'tool_failed');
322
+ expect(toolFailed).toHaveLength(1);
323
+ expect(toolFailed[0].error).toContain('Invalid tool input');
324
+ // Agent should recover and continue to second inference
325
+ const inferenceCompleted = await session.getEventsByType('inference_completed');
326
+ expect(inferenceCompleted).toHaveLength(2);
327
+ // Agent should be in pending (idle) state, not errored
328
+ const entryAgentId = session.getEntryAgentId();
329
+ expect(session.state.agents.get(entryAgentId).status).toBe('pending');
330
+ await harness.shutdown();
331
+ });
332
+ it('tool throwing error → error captured as tool result', async () => {
333
+ const throwingTool = createTool({
334
+ name: 'exploding_tool',
335
+ description: 'A tool that always throws',
336
+ input: z.unknown(),
337
+ execute: async () => {
338
+ throw new Error('Tool exploded!');
339
+ },
340
+ });
341
+ const preset = {
342
+ id: 'test',
343
+ name: 'Test Preset',
344
+ orchestrator: {
345
+ system: 'You are a test agent.',
346
+ model: ModelId('mock'),
347
+ tools: [throwingTool],
348
+ agents: [],
349
+ debounceMs: 0,
350
+ },
351
+ agents: [],
352
+ };
353
+ const harness = new TestHarness({
354
+ presets: [preset],
355
+ llmProvider: MockLLMProvider.withSequence([
356
+ {
357
+ toolCalls: [{ id: ToolCallId('tc1'), name: 'exploding_tool', input: { value: 'boom' } }],
358
+ },
359
+ { content: 'Recovered', toolCalls: [] },
360
+ ]),
361
+ });
362
+ const session = await harness.createSession('test');
363
+ await session.sendAndWaitForIdle('Trigger explosion');
364
+ // Tool should have failed with the thrown error message
365
+ const toolFailed = await session.getEventsByType(toolEvents, 'tool_failed');
366
+ expect(toolFailed).toHaveLength(1);
367
+ expect(toolFailed[0].error).toContain('Tool exploded!');
368
+ // Agent should recover and complete the second inference
369
+ const inferenceCompleted = await session.getEventsByType('inference_completed');
370
+ expect(inferenceCompleted).toHaveLength(2);
371
+ // Agent should be in pending (idle) state
372
+ const entryAgentId = session.getEntryAgentId();
373
+ expect(session.state.agents.get(entryAgentId).status).toBe('pending');
374
+ await harness.shutdown();
375
+ });
376
+ });
377
+ // =========================================================================
378
+ // preamble
379
+ // =========================================================================
380
+ describe('preamble', () => {
381
+ it('preamble messages included before conversation history', async () => {
382
+ // Create a plugin that injects preamble on agent start
383
+ const preamblePlugin = definePlugin('test-preamble')
384
+ .hook('onStart', async (ctx) => {
385
+ await ctx.emitEvent(agentEvents.create('preamble_added', {
386
+ agentId: ctx.agentId,
387
+ messages: [{ role: 'user', content: 'PREAMBLE_MARKER: You must follow these instructions.' }],
388
+ }));
389
+ return null;
390
+ })
391
+ .build();
392
+ const harness = new TestHarness({
393
+ presets: [createTestPreset()],
394
+ llmProvider: MockLLMProvider.withFixedResponse({ content: 'Ok' }),
395
+ systemPlugins: [preamblePlugin],
396
+ });
397
+ const session = await harness.createSession('test');
398
+ await session.sendAndWaitForIdle('Hello after preamble');
399
+ // Verify preamble_added event was emitted
400
+ const preambleEvents = await session.getEventsByType('preamble_added');
401
+ expect(preambleEvents).toHaveLength(1);
402
+ // Verify the LLM request has preamble before the user message
403
+ const lastRequest = harness.llmProvider.getLastRequest();
404
+ const messages = lastRequest.messages;
405
+ const preambleIdx = messages.findIndex((m) => m.role === 'user' && typeof m.content === 'string' && m.content.includes('PREAMBLE_MARKER'));
406
+ const userMsgIdx = messages.findIndex((m) => m.role === 'user' && typeof m.content === 'string' && m.content.includes('Hello after preamble'));
407
+ expect(preambleIdx).toBeGreaterThanOrEqual(0);
408
+ expect(userMsgIdx).toBeGreaterThanOrEqual(0);
409
+ expect(preambleIdx).toBeLessThan(userMsgIdx);
410
+ await harness.shutdown();
411
+ });
412
+ });
413
+ });
414
+ //# sourceMappingURL=agent-loop.integration.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-loop.integration.test.js","sourceRoot":"","sources":["../../src/core/agent-loop.integration.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,194 @@
1
+ import { describe, expect, test } from 'bun:test';
2
+ import { aggressiveDebounceCallback, batchingDebounceCallback, defaultDebounceCallback, waitForResponseDebounceCallback, } from '../../core/agents/debounce.js';
3
+ import { MessageId } from '../../plugins/mailbox/schema';
4
+ import { ToolCallId } from '../tools/schema';
5
+ import { AgentId } from './schema';
6
+ describe('Debounce Callbacks', () => {
7
+ const createMessage = (timestampOffset = 0) => ({
8
+ id: MessageId('msg-1'),
9
+ from: AgentId('agent-1'),
10
+ content: 'Test message',
11
+ timestamp: Date.now() - timestampOffset,
12
+ consumed: false,
13
+ });
14
+ const createToolResult = (toolName, timestampOffset = 0, isError = false) => ({
15
+ toolCallId: ToolCallId('tc-1'),
16
+ toolName,
17
+ timestamp: Date.now() - timestampOffset,
18
+ isError,
19
+ content: '',
20
+ });
21
+ const createContext = (messageCount, oldestWaitingMs, pendingToolResults = []) => ({
22
+ messages: Array.from({ length: messageCount }, () => createMessage()),
23
+ oldestWaitingMs,
24
+ totalPending: messageCount,
25
+ pendingToolResults,
26
+ });
27
+ describe('defaultDebounceCallback', () => {
28
+ test("returns 'wait' when oldest message is less than 500ms old", () => {
29
+ const context = createContext(1, 400);
30
+ expect(defaultDebounceCallback(context)).toBe('wait');
31
+ });
32
+ test("returns 'wait' when oldest message is exactly 500ms old", () => {
33
+ const context = createContext(1, 500);
34
+ expect(defaultDebounceCallback(context)).toBe('wait');
35
+ });
36
+ test("returns 'process_now' when oldest message is more than 500ms old", () => {
37
+ const context = createContext(1, 501);
38
+ expect(defaultDebounceCallback(context)).toBe('process_now');
39
+ });
40
+ test("returns 'process_now' regardless of message count", () => {
41
+ const context = createContext(10, 600);
42
+ expect(defaultDebounceCallback(context)).toBe('process_now');
43
+ });
44
+ });
45
+ describe('aggressiveDebounceCallback', () => {
46
+ test("returns 'wait' when oldest message is less than 100ms old", () => {
47
+ const context = createContext(1, 50);
48
+ expect(aggressiveDebounceCallback(context)).toBe('wait');
49
+ });
50
+ test("returns 'wait' when oldest message is exactly 100ms old", () => {
51
+ const context = createContext(1, 100);
52
+ expect(aggressiveDebounceCallback(context)).toBe('wait');
53
+ });
54
+ test("returns 'process_now' when oldest message is more than 100ms old", () => {
55
+ const context = createContext(1, 101);
56
+ expect(aggressiveDebounceCallback(context)).toBe('process_now');
57
+ });
58
+ test('processes faster than default callback', () => {
59
+ const context = createContext(1, 150);
60
+ // Aggressive should process, default should wait
61
+ expect(aggressiveDebounceCallback(context)).toBe('process_now');
62
+ expect(defaultDebounceCallback(context)).toBe('wait');
63
+ });
64
+ });
65
+ describe('batchingDebounceCallback', () => {
66
+ test("returns 'wait' with few messages and short wait time", () => {
67
+ const context = createContext(2, 500);
68
+ expect(batchingDebounceCallback(context)).toBe('wait');
69
+ });
70
+ test("returns 'process_now' when 5 or more messages", () => {
71
+ const context = createContext(5, 100);
72
+ expect(batchingDebounceCallback(context)).toBe('process_now');
73
+ });
74
+ test("returns 'process_now' when more than 5 messages", () => {
75
+ const context = createContext(10, 50);
76
+ expect(batchingDebounceCallback(context)).toBe('process_now');
77
+ });
78
+ test("returns 'wait' when oldest message is exactly 2000ms old with few messages", () => {
79
+ const context = createContext(2, 2000);
80
+ expect(batchingDebounceCallback(context)).toBe('wait');
81
+ });
82
+ test("returns 'process_now' when oldest message is more than 2000ms old", () => {
83
+ const context = createContext(1, 2001);
84
+ expect(batchingDebounceCallback(context)).toBe('process_now');
85
+ });
86
+ test("returns 'process_now' at threshold of 5 messages", () => {
87
+ const context = createContext(5, 0);
88
+ expect(batchingDebounceCallback(context)).toBe('process_now');
89
+ });
90
+ test("returns 'wait' just below message threshold", () => {
91
+ const context = createContext(4, 1500);
92
+ expect(batchingDebounceCallback(context)).toBe('wait');
93
+ });
94
+ });
95
+ describe('waitForResponseDebounceCallback', () => {
96
+ test("returns 'process_now' when there are new mailbox messages", () => {
97
+ const context = createContext(1, 100, [
98
+ createToolResult('send_message', 1000),
99
+ ]);
100
+ expect(waitForResponseDebounceCallback(context)).toBe('process_now');
101
+ });
102
+ test("returns 'wait' when all pending tool results are communication tools", () => {
103
+ const context = createContext(0, 0, [
104
+ createToolResult('send_message', 1000),
105
+ ]);
106
+ expect(waitForResponseDebounceCallback(context)).toBe('wait');
107
+ });
108
+ test("returns 'wait' for start_* agent tool", () => {
109
+ const context = createContext(0, 0, [
110
+ createToolResult('start_researcher', 1000),
111
+ ]);
112
+ expect(waitForResponseDebounceCallback(context)).toBe('wait');
113
+ });
114
+ test("returns 'wait' for tell_user tool", () => {
115
+ const context = createContext(0, 0, [
116
+ createToolResult('tell_user', 1000),
117
+ ]);
118
+ expect(waitForResponseDebounceCallback(context)).toBe('wait');
119
+ });
120
+ test("returns 'wait' for ask_user tool", () => {
121
+ const context = createContext(0, 0, [
122
+ createToolResult('ask_user', 1000),
123
+ ]);
124
+ expect(waitForResponseDebounceCallback(context)).toBe('wait');
125
+ });
126
+ test("returns 'wait' when multiple communication tools are pending", () => {
127
+ const context = createContext(0, 0, [
128
+ createToolResult('send_message', 1000),
129
+ createToolResult('start_helper', 500),
130
+ ]);
131
+ expect(waitForResponseDebounceCallback(context)).toBe('wait');
132
+ });
133
+ test("returns 'process_now' when ANY tool result is not a communication tool", () => {
134
+ const context = createContext(0, 0, [
135
+ createToolResult('send_message', 1000),
136
+ createToolResult('reveal_secret', 500), // Not a communication tool
137
+ ]);
138
+ expect(waitForResponseDebounceCallback(context)).toBe('process_now');
139
+ });
140
+ test("returns 'process_now' for non-communication tool alone", () => {
141
+ const context = createContext(0, 0, [
142
+ createToolResult('get_my_info', 1000),
143
+ ]);
144
+ expect(waitForResponseDebounceCallback(context)).toBe('process_now');
145
+ });
146
+ test("returns 'process_now' when any tool result has isError=true", () => {
147
+ const context = createContext(0, 0, [
148
+ createToolResult('send_message', 1000, true), // Error!
149
+ ]);
150
+ expect(waitForResponseDebounceCallback(context)).toBe('process_now');
151
+ });
152
+ test("returns 'process_now' when mixed success and error results", () => {
153
+ const context = createContext(0, 0, [
154
+ createToolResult('send_message', 2000, false), // Success
155
+ createToolResult('start_worker', 1000, true), // Error - should trigger immediate processing
156
+ ]);
157
+ expect(waitForResponseDebounceCallback(context)).toBe('process_now');
158
+ });
159
+ test("returns 'process_now' after 60s timeout for communication tools", () => {
160
+ const context = createContext(0, 0, [
161
+ createToolResult('send_message', 61000), // 61 seconds ago
162
+ ]);
163
+ expect(waitForResponseDebounceCallback(context)).toBe('process_now');
164
+ });
165
+ test("returns 'wait' just before 60s timeout", () => {
166
+ const context = createContext(0, 0, [
167
+ createToolResult('send_message', 59000), // 59 seconds ago
168
+ ]);
169
+ expect(waitForResponseDebounceCallback(context)).toBe('wait');
170
+ });
171
+ test("returns 'wait' when no messages and no tool results", () => {
172
+ const context = createContext(0, 0, []);
173
+ expect(waitForResponseDebounceCallback(context)).toBe('wait');
174
+ });
175
+ test('uses oldest tool result timestamp for timeout calculation', () => {
176
+ // One tool result at 59s, one at 30s - should use 59s (oldest)
177
+ const now = Date.now();
178
+ const context = {
179
+ messages: [],
180
+ oldestWaitingMs: 0,
181
+ totalPending: 0,
182
+ pendingToolResults: [
183
+ { toolCallId: ToolCallId('tc-1'), toolName: 'send_message', timestamp: now - 59000, isError: false, content: '' },
184
+ { toolCallId: ToolCallId('tc-2'), toolName: 'send_message', timestamp: now - 30000, isError: false, content: '' },
185
+ ],
186
+ };
187
+ expect(waitForResponseDebounceCallback(context)).toBe('wait');
188
+ // Now make oldest one 61s old
189
+ context.pendingToolResults[0].timestamp = now - 61000;
190
+ expect(waitForResponseDebounceCallback(context)).toBe('process_now');
191
+ });
192
+ });
193
+ });
194
+ //# sourceMappingURL=agent-config.test.js.map