@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,605 @@
1
+ import { describe, expect, it } from 'bun:test';
2
+ import { AgentId } from '../../core/agents/schema.js';
3
+ import { MockLLMProvider } from '../../core/llm/mock.js';
4
+ import { ToolCallId } from '../../core/tools/schema.js';
5
+ import { createMultiAgentPreset, createTestPreset, TestHarness } from '../../testing/index.js';
6
+ import { getAgentMailbox, getAgentUnconsumedMailbox, mailboxEvents, selectMailboxState } from './index.js';
7
+ describe('mailbox plugin', () => {
8
+ // =========================================================================
9
+ // send_message tool
10
+ // =========================================================================
11
+ describe('send_message tool', () => {
12
+ it('send_message with to: parent → parent receives message in dequeue', async () => {
13
+ let orchestratorCalls = 0;
14
+ let workerCalls = 0;
15
+ let orchestratorSawWorkerMessage = false;
16
+ const harness = new TestHarness({
17
+ presets: [createMultiAgentPreset([
18
+ { name: 'worker', system: 'Worker agent.', tools: [], agents: [] },
19
+ ], { orchestratorSystem: 'Orchestrator agent.' })],
20
+ mockHandler: (request) => {
21
+ if (request.systemPrompt.includes('Orchestrator')) {
22
+ orchestratorCalls++;
23
+ if (orchestratorCalls === 1) {
24
+ return {
25
+ content: null,
26
+ toolCalls: [{ id: ToolCallId('tc1'), name: 'start_worker', input: { message: 'Do some work' } }],
27
+ finishReason: 'stop',
28
+ metrics: MockLLMProvider.defaultMetrics(),
29
+ };
30
+ }
31
+ const lastMsg = request.messages[request.messages.length - 1];
32
+ if (typeof lastMsg?.content === 'string' && lastMsg.content.includes('Hello from worker')) {
33
+ orchestratorSawWorkerMessage = true;
34
+ }
35
+ return { content: 'Done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() };
36
+ }
37
+ workerCalls++;
38
+ if (workerCalls === 1) {
39
+ return {
40
+ content: null,
41
+ toolCalls: [{ id: ToolCallId('tc2'), name: 'send_message', input: { to: 'parent', message: 'Hello from worker' } }],
42
+ finishReason: 'stop',
43
+ metrics: MockLLMProvider.defaultMetrics(),
44
+ };
45
+ }
46
+ return { content: 'Worker done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() };
47
+ },
48
+ });
49
+ const session = await harness.createSession('test');
50
+ await session.sendAndWaitForIdle('Start');
51
+ expect(orchestratorSawWorkerMessage).toBe(true);
52
+ const events = await session.getEventsByType(mailboxEvents, 'mailbox_message');
53
+ const workerToParent = events.filter(e => e.message.content === 'Hello from worker');
54
+ expect(workerToParent).toHaveLength(1);
55
+ expect(workerToParent[0].toAgentId).toBe(session.getEntryAgentId());
56
+ await harness.shutdown();
57
+ });
58
+ it('send_message with to: childAgentId → child receives message in dequeue', async () => {
59
+ let orchestratorCalls = 0;
60
+ let workerSawExtraMessage = false;
61
+ const harness = new TestHarness({
62
+ presets: [createMultiAgentPreset([
63
+ { name: 'worker', system: 'Worker agent.', tools: [], agents: [] },
64
+ ], { orchestratorSystem: 'Orchestrator agent.' })],
65
+ mockHandler: (request) => {
66
+ if (request.systemPrompt.includes('Orchestrator')) {
67
+ orchestratorCalls++;
68
+ if (orchestratorCalls === 1) {
69
+ return {
70
+ content: null,
71
+ toolCalls: [{ id: ToolCallId('tc1'), name: 'start_worker', input: { message: 'Initial task' } }],
72
+ finishReason: 'stop',
73
+ metrics: MockLLMProvider.defaultMetrics(),
74
+ };
75
+ }
76
+ if (orchestratorCalls === 2) {
77
+ return {
78
+ content: null,
79
+ toolCalls: [{ id: ToolCallId('tc2'), name: 'send_message', input: { to: 'worker_1', message: 'Extra task for you' } }],
80
+ finishReason: 'stop',
81
+ metrics: MockLLMProvider.defaultMetrics(),
82
+ };
83
+ }
84
+ return { content: 'Done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() };
85
+ }
86
+ if (request.messages.some(m => typeof m.content === 'string' && m.content.includes('Extra task for you'))) {
87
+ workerSawExtraMessage = true;
88
+ }
89
+ return { content: 'Worker done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() };
90
+ },
91
+ });
92
+ const session = await harness.createSession('test');
93
+ await session.sendAndWaitForIdle('Start');
94
+ expect(workerSawExtraMessage).toBe(true);
95
+ const events = await session.getEventsByType(mailboxEvents, 'mailbox_message');
96
+ const orchToWorker = events.filter(e => e.message.content === 'Extra task for you');
97
+ expect(orchToWorker).toHaveLength(1);
98
+ expect(orchToWorker[0].toAgentId).toBe(AgentId('worker_1'));
99
+ await harness.shutdown();
100
+ });
101
+ it('send_message to invalid target → tool returns error with allowed agents', async () => {
102
+ let orchestratorCalls = 0;
103
+ let workerCalls = 0;
104
+ let workerReceivedErrorAboutTarget = false;
105
+ const harness = new TestHarness({
106
+ presets: [createMultiAgentPreset([
107
+ { name: 'worker', system: 'Worker agent.', tools: [], agents: [] },
108
+ ], { orchestratorSystem: 'Orchestrator agent.' })],
109
+ mockHandler: (request) => {
110
+ if (request.systemPrompt.includes('Orchestrator')) {
111
+ orchestratorCalls++;
112
+ if (orchestratorCalls === 1) {
113
+ return {
114
+ content: null,
115
+ toolCalls: [{ id: ToolCallId('tc1'), name: 'start_worker', input: { message: 'Do work' } }],
116
+ finishReason: 'stop',
117
+ metrics: MockLLMProvider.defaultMetrics(),
118
+ };
119
+ }
120
+ return { content: 'Done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() };
121
+ }
122
+ workerCalls++;
123
+ if (workerCalls === 1) {
124
+ return {
125
+ content: null,
126
+ toolCalls: [{ id: ToolCallId('tc2'), name: 'send_message', input: { to: 'nonexistent_agent', message: 'Should fail' } }],
127
+ finishReason: 'stop',
128
+ metrics: MockLLMProvider.defaultMetrics(),
129
+ };
130
+ }
131
+ // Second call: verify the tool result contains the error about invalid target
132
+ const toolMessages = request.messages.filter(m => m.role === 'tool');
133
+ if (toolMessages.some(m => typeof m.content === 'string' && m.content.includes('Cannot send message'))) {
134
+ workerReceivedErrorAboutTarget = true;
135
+ }
136
+ return { content: 'Worker done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() };
137
+ },
138
+ });
139
+ const session = await harness.createSession('test');
140
+ await session.sendAndWaitForIdle('Start');
141
+ // No mailbox_message for invalid target
142
+ const events = await session.getEventsByType(mailboxEvents, 'mailbox_message');
143
+ const invalidMessages = events.filter(e => e.message.content === 'Should fail');
144
+ expect(invalidMessages).toHaveLength(0);
145
+ // Worker was called exactly twice (tool call + error result)
146
+ expect(workerCalls).toBe(2);
147
+ // Worker received error message about invalid target with allowed agents
148
+ expect(workerReceivedErrorAboutTarget).toBe(true);
149
+ await harness.shutdown();
150
+ });
151
+ it('mailbox_message event emitted with correct from/to/content', async () => {
152
+ let orchestratorCalls = 0;
153
+ let workerCalls = 0;
154
+ const harness = new TestHarness({
155
+ presets: [createMultiAgentPreset([
156
+ { name: 'worker', system: 'Worker agent.', tools: [], agents: [] },
157
+ ], { orchestratorSystem: 'Orchestrator agent.' })],
158
+ mockHandler: (request) => {
159
+ if (request.systemPrompt.includes('Orchestrator')) {
160
+ orchestratorCalls++;
161
+ if (orchestratorCalls === 1) {
162
+ return {
163
+ content: null,
164
+ toolCalls: [{ id: ToolCallId('tc1'), name: 'start_worker', input: { message: 'Task content' } }],
165
+ finishReason: 'stop',
166
+ metrics: MockLLMProvider.defaultMetrics(),
167
+ };
168
+ }
169
+ return { content: 'Done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() };
170
+ }
171
+ workerCalls++;
172
+ if (workerCalls === 1) {
173
+ return {
174
+ content: null,
175
+ toolCalls: [{ id: ToolCallId('tc2'), name: 'send_message', input: { to: 'parent', message: 'Result payload' } }],
176
+ finishReason: 'stop',
177
+ metrics: MockLLMProvider.defaultMetrics(),
178
+ };
179
+ }
180
+ return { content: 'Worker done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() };
181
+ },
182
+ });
183
+ const session = await harness.createSession('test');
184
+ await session.sendAndWaitForIdle('Start');
185
+ const events = await session.getEventsByType(mailboxEvents, 'mailbox_message');
186
+ const workerMessage = events.find(e => e.message.content === 'Result payload');
187
+ expect(workerMessage).toBeDefined();
188
+ expect(workerMessage.toAgentId).toBe(session.getEntryAgentId());
189
+ expect(workerMessage.message.from).toBe(AgentId('worker_1'));
190
+ expect(workerMessage.message.consumed).toBe(false);
191
+ expect(workerMessage.message.timestamp).toBeGreaterThan(0);
192
+ expect(workerMessage.message.id).toBeDefined();
193
+ await harness.shutdown();
194
+ });
195
+ it('idle agent re-scheduled when message sent via direct mailbox.send', async () => {
196
+ let orchestratorCalls = 0;
197
+ let workerCalls = 0;
198
+ let workerSawFollowUp = false;
199
+ const harness = new TestHarness({
200
+ presets: [createMultiAgentPreset([
201
+ { name: 'worker', system: 'Worker agent.', tools: [], agents: [] },
202
+ ], { orchestratorSystem: 'Orchestrator agent.' })],
203
+ mockHandler: (request) => {
204
+ if (request.systemPrompt.includes('Orchestrator')) {
205
+ orchestratorCalls++;
206
+ if (orchestratorCalls === 1) {
207
+ return {
208
+ content: null,
209
+ toolCalls: [{ id: ToolCallId('tc1'), name: 'start_worker', input: { message: 'Initial work' } }],
210
+ finishReason: 'stop',
211
+ metrics: MockLLMProvider.defaultMetrics(),
212
+ };
213
+ }
214
+ return { content: 'Done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() };
215
+ }
216
+ workerCalls++;
217
+ const lastMsg = request.messages[request.messages.length - 1];
218
+ if (typeof lastMsg?.content === 'string' && lastMsg.content.includes('Follow-up task')) {
219
+ workerSawFollowUp = true;
220
+ }
221
+ return { content: 'Worker done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() };
222
+ },
223
+ });
224
+ const session = await harness.createSession('test');
225
+ await session.sendAndWaitForIdle('Start');
226
+ // Worker processed initial message and became idle
227
+ expect(workerCalls).toBe(1);
228
+ // Send a follow-up message directly — should re-schedule the idle worker
229
+ const result = await session.callPluginMethod('mailbox.send', {
230
+ fromAgentId: String(session.getEntryAgentId()),
231
+ toAgentId: 'worker_1',
232
+ content: 'Follow-up task',
233
+ });
234
+ expect(result.ok).toBe(true);
235
+ await session.waitForIdle();
236
+ // Worker was re-scheduled and processed the new message
237
+ expect(workerCalls).toBe(2);
238
+ expect(workerSawFollowUp).toBe(true);
239
+ await harness.shutdown();
240
+ });
241
+ });
242
+ // =========================================================================
243
+ // dequeue
244
+ // =========================================================================
245
+ describe('dequeue', () => {
246
+ it('unconsumed messages delivered to agent as LLM user message before inference', async () => {
247
+ let orchestratorCalls = 0;
248
+ const harness = new TestHarness({
249
+ presets: [createMultiAgentPreset([
250
+ { name: 'worker', system: 'Worker agent.', tools: [], agents: [] },
251
+ ], { orchestratorSystem: 'Orchestrator agent.' })],
252
+ mockHandler: (request) => {
253
+ if (request.systemPrompt.includes('Orchestrator')) {
254
+ orchestratorCalls++;
255
+ if (orchestratorCalls === 1) {
256
+ return {
257
+ content: null,
258
+ toolCalls: [{ id: ToolCallId('tc1'), name: 'start_worker', input: { message: 'Process this data' } }],
259
+ finishReason: 'stop',
260
+ metrics: MockLLMProvider.defaultMetrics(),
261
+ };
262
+ }
263
+ return { content: 'Done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() };
264
+ }
265
+ return { content: 'Worker done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() };
266
+ },
267
+ });
268
+ const session = await harness.createSession('test');
269
+ await session.sendAndWaitForIdle('Start');
270
+ // Find the worker's LLM request
271
+ const calls = harness.llmProvider.getCallHistory();
272
+ const workerCall = calls.find(c => c.systemPrompt.includes('Worker'));
273
+ expect(workerCall).toBeDefined();
274
+ // The mailbox message should be in the request as a user message
275
+ const userMessages = workerCall.messages.filter(m => m.role === 'user');
276
+ expect(userMessages.length).toBeGreaterThanOrEqual(1);
277
+ // The message content should contain the task (formatted as XML by formatMailboxForLLM)
278
+ const lastUserMsg = userMessages[userMessages.length - 1];
279
+ const content = typeof lastUserMsg.content === 'string' ? lastUserMsg.content : '';
280
+ expect(content).toContain('Process this data');
281
+ expect(content).toContain('<message');
282
+ await harness.shutdown();
283
+ });
284
+ it('messages marked as consumed after delivery (mailbox_consumed event)', async () => {
285
+ let orchestratorCalls = 0;
286
+ const harness = new TestHarness({
287
+ presets: [createMultiAgentPreset([
288
+ { name: 'worker', system: 'Worker agent.', tools: [], agents: [] },
289
+ ], { orchestratorSystem: 'Orchestrator agent.' })],
290
+ mockHandler: (request) => {
291
+ if (request.systemPrompt.includes('Orchestrator')) {
292
+ orchestratorCalls++;
293
+ if (orchestratorCalls === 1) {
294
+ return {
295
+ content: null,
296
+ toolCalls: [{ id: ToolCallId('tc1'), name: 'start_worker', input: { message: 'Task for worker' } }],
297
+ finishReason: 'stop',
298
+ metrics: MockLLMProvider.defaultMetrics(),
299
+ };
300
+ }
301
+ return { content: 'Done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() };
302
+ }
303
+ return { content: 'Worker done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() };
304
+ },
305
+ });
306
+ const session = await harness.createSession('test');
307
+ await session.sendAndWaitForIdle('Start');
308
+ // mailbox_consumed event emitted
309
+ const consumedEvents = await session.getEventsByType(mailboxEvents, 'mailbox_consumed');
310
+ const workerConsumed = consumedEvents.filter(e => e.agentId === AgentId('worker_1'));
311
+ expect(workerConsumed).toHaveLength(1);
312
+ // All worker messages should be consumed in state
313
+ const mailboxState = selectMailboxState(session.state);
314
+ const unconsumed = getAgentUnconsumedMailbox(mailboxState, AgentId('worker_1'));
315
+ expect(unconsumed).toHaveLength(0);
316
+ await harness.shutdown();
317
+ });
318
+ it('message ordering preserved — multiple messages delivered in sequence', async () => {
319
+ let orchestratorCalls = 0;
320
+ const harness = new TestHarness({
321
+ presets: [createMultiAgentPreset([
322
+ { name: 'worker', system: 'Worker agent.', tools: [], agents: [] },
323
+ ], { orchestratorSystem: 'Orchestrator agent.' })],
324
+ mockHandler: (request) => {
325
+ if (request.systemPrompt.includes('Orchestrator')) {
326
+ orchestratorCalls++;
327
+ if (orchestratorCalls === 1) {
328
+ return {
329
+ content: null,
330
+ toolCalls: [{ id: ToolCallId('tc1'), name: 'start_worker', input: { message: 'First message' } }],
331
+ finishReason: 'stop',
332
+ metrics: MockLLMProvider.defaultMetrics(),
333
+ };
334
+ }
335
+ if (orchestratorCalls === 2) {
336
+ return {
337
+ content: null,
338
+ toolCalls: [
339
+ { id: ToolCallId('tc2'), name: 'send_message', input: { to: 'worker_1', message: 'Second message' } },
340
+ { id: ToolCallId('tc3'), name: 'send_message', input: { to: 'worker_1', message: 'Third message' } },
341
+ ],
342
+ finishReason: 'stop',
343
+ metrics: MockLLMProvider.defaultMetrics(),
344
+ };
345
+ }
346
+ return { content: 'Done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() };
347
+ }
348
+ return { content: 'Worker done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() };
349
+ },
350
+ });
351
+ const session = await harness.createSession('test');
352
+ await session.sendAndWaitForIdle('Start');
353
+ // Check message order in state
354
+ const mailboxState = selectMailboxState(session.state);
355
+ const allMessages = getAgentMailbox(mailboxState, AgentId('worker_1'));
356
+ expect(allMessages).toHaveLength(3);
357
+ const contents = allMessages.map(m => m.content);
358
+ expect(contents[0]).toBe('First message');
359
+ expect(contents[1]).toBe('Second message');
360
+ expect(contents[2]).toBe('Third message');
361
+ await harness.shutdown();
362
+ });
363
+ it('messages from different senders all delivered', async () => {
364
+ let orchestratorCalls = 0;
365
+ let worker1Calls = 0;
366
+ let subworkerCalls = 0;
367
+ const harness = new TestHarness({
368
+ presets: [createMultiAgentPreset([
369
+ { name: 'worker', system: 'Worker agent.', tools: [], agents: ['subworker'] },
370
+ { name: 'subworker', system: 'Subworker agent.', tools: [], agents: [] },
371
+ ], { orchestratorSystem: 'Orchestrator agent.' })],
372
+ mockHandler: (request) => {
373
+ if (request.systemPrompt.includes('Orchestrator')) {
374
+ orchestratorCalls++;
375
+ if (orchestratorCalls === 1) {
376
+ return {
377
+ content: null,
378
+ toolCalls: [{ id: ToolCallId('tc1'), name: 'start_worker', input: { message: 'Go' } }],
379
+ finishReason: 'stop',
380
+ metrics: MockLLMProvider.defaultMetrics(),
381
+ };
382
+ }
383
+ return { content: 'Done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() };
384
+ }
385
+ if (request.systemPrompt.includes('Worker agent')) {
386
+ worker1Calls++;
387
+ if (worker1Calls === 1) {
388
+ // Worker spawns subworker
389
+ return {
390
+ content: null,
391
+ toolCalls: [{ id: ToolCallId('tc2'), name: 'start_subworker', input: { message: 'Subtask' } }],
392
+ finishReason: 'stop',
393
+ metrics: MockLLMProvider.defaultMetrics(),
394
+ };
395
+ }
396
+ return { content: 'Worker done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() };
397
+ }
398
+ // Subworker
399
+ subworkerCalls++;
400
+ if (subworkerCalls === 1) {
401
+ return {
402
+ content: null,
403
+ toolCalls: [{ id: ToolCallId('tc3'), name: 'send_message', input: { to: 'parent', message: 'From subworker' } }],
404
+ finishReason: 'stop',
405
+ metrics: MockLLMProvider.defaultMetrics(),
406
+ };
407
+ }
408
+ return { content: 'Subworker done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() };
409
+ },
410
+ });
411
+ const session = await harness.createSession('test');
412
+ await session.sendAndWaitForIdle('Start', { timeoutMs: 10000 });
413
+ // Worker should have messages from both orchestrator (initial) and subworker
414
+ const mailboxState = selectMailboxState(session.state);
415
+ const workerMailbox = getAgentMailbox(mailboxState, AgentId('worker_1'));
416
+ const fromOrchestrator = workerMailbox.filter(m => m.from === session.getEntryAgentId());
417
+ const fromSubworker = workerMailbox.filter(m => m.from === AgentId('subworker_1'));
418
+ expect(fromOrchestrator).toHaveLength(1);
419
+ expect(fromSubworker).toHaveLength(1);
420
+ await harness.shutdown();
421
+ });
422
+ });
423
+ // =========================================================================
424
+ // onComplete hook
425
+ // =========================================================================
426
+ describe('onComplete hook', () => {
427
+ it('agent with sendCompletionMessage: true → parent receives "Task completed." on agent completion', async () => {
428
+ let orchestratorCalls = 0;
429
+ const harness = new TestHarness({
430
+ presets: [createMultiAgentPreset([
431
+ {
432
+ name: 'worker',
433
+ system: 'Worker agent.',
434
+ tools: [],
435
+ agents: [],
436
+ plugins: [{ pluginName: 'mailbox', config: { sendCompletionMessage: true } }],
437
+ },
438
+ ], { orchestratorSystem: 'Orchestrator agent.' })],
439
+ mockHandler: (request) => {
440
+ if (request.systemPrompt.includes('Orchestrator')) {
441
+ orchestratorCalls++;
442
+ if (orchestratorCalls === 1) {
443
+ return {
444
+ content: null,
445
+ toolCalls: [{ id: ToolCallId('tc1'), name: 'start_worker', input: { message: 'Do work' } }],
446
+ finishReason: 'stop',
447
+ metrics: MockLLMProvider.defaultMetrics(),
448
+ };
449
+ }
450
+ return { content: 'Done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() };
451
+ }
452
+ // Worker responds with content only → completes → onComplete fires
453
+ return { content: 'Work finished', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() };
454
+ },
455
+ });
456
+ const session = await harness.createSession('test');
457
+ await session.sendAndWaitForIdle('Start');
458
+ // Check that "Task completed." was sent to parent
459
+ const events = await session.getEventsByType(mailboxEvents, 'mailbox_message');
460
+ const completionMessages = events.filter(e => e.message.content === 'Task completed.');
461
+ expect(completionMessages).toHaveLength(1);
462
+ expect(completionMessages[0].toAgentId).toBe(session.getEntryAgentId());
463
+ expect(completionMessages[0].message.from).toBe(AgentId('worker_1'));
464
+ await harness.shutdown();
465
+ });
466
+ it('agent with sendCompletionMessage: false → no completion message', async () => {
467
+ let orchestratorCalls = 0;
468
+ const harness = new TestHarness({
469
+ presets: [createMultiAgentPreset([
470
+ {
471
+ name: 'worker',
472
+ system: 'Worker agent.',
473
+ tools: [],
474
+ agents: [],
475
+ // No sendCompletionMessage config
476
+ },
477
+ ], { orchestratorSystem: 'Orchestrator agent.' })],
478
+ mockHandler: (request) => {
479
+ if (request.systemPrompt.includes('Orchestrator')) {
480
+ orchestratorCalls++;
481
+ if (orchestratorCalls === 1) {
482
+ return {
483
+ content: null,
484
+ toolCalls: [{ id: ToolCallId('tc1'), name: 'start_worker', input: { message: 'Do work' } }],
485
+ finishReason: 'stop',
486
+ metrics: MockLLMProvider.defaultMetrics(),
487
+ };
488
+ }
489
+ return { content: 'Done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() };
490
+ }
491
+ return { content: 'Work finished', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() };
492
+ },
493
+ });
494
+ const session = await harness.createSession('test');
495
+ await session.sendAndWaitForIdle('Start');
496
+ const events = await session.getEventsByType(mailboxEvents, 'mailbox_message');
497
+ const completionMessages = events.filter(e => e.message.content === 'Task completed.');
498
+ expect(completionMessages).toHaveLength(0);
499
+ await harness.shutdown();
500
+ });
501
+ it('agent without parent → no completion message even with flag true', async () => {
502
+ const harness = new TestHarness({
503
+ presets: [createTestPreset({
504
+ orchestratorPlugins: [
505
+ { pluginName: 'mailbox', config: { sendCompletionMessage: true } },
506
+ ],
507
+ })],
508
+ llmProvider: MockLLMProvider.withFixedResponse({ content: 'Done', toolCalls: [] }),
509
+ });
510
+ const session = await harness.createSession('test');
511
+ await session.sendAndWaitForIdle('Test');
512
+ // Orchestrator has no parent → no completion message
513
+ const events = await session.getEventsByType(mailboxEvents, 'mailbox_message');
514
+ const completionMessages = events.filter(e => e.message.content === 'Task completed.');
515
+ expect(completionMessages).toHaveLength(0);
516
+ await harness.shutdown();
517
+ });
518
+ });
519
+ // =========================================================================
520
+ // send method (direct)
521
+ // =========================================================================
522
+ describe('send method (direct)', () => {
523
+ it('mailbox.send between valid agents → message delivered', async () => {
524
+ let orchestratorCalls = 0;
525
+ const harness = new TestHarness({
526
+ presets: [createMultiAgentPreset([
527
+ { name: 'worker', system: 'Worker agent.', tools: [], agents: [] },
528
+ ], { orchestratorSystem: 'Orchestrator agent.' })],
529
+ mockHandler: (request) => {
530
+ if (request.systemPrompt.includes('Orchestrator')) {
531
+ orchestratorCalls++;
532
+ if (orchestratorCalls === 1) {
533
+ return {
534
+ content: null,
535
+ toolCalls: [{ id: ToolCallId('tc1'), name: 'start_worker', input: { message: 'Init' } }],
536
+ finishReason: 'stop',
537
+ metrics: MockLLMProvider.defaultMetrics(),
538
+ };
539
+ }
540
+ return { content: 'Done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() };
541
+ }
542
+ return { content: 'Worker done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() };
543
+ },
544
+ });
545
+ const session = await harness.createSession('test');
546
+ await session.sendAndWaitForIdle('Start');
547
+ const orchestratorId = session.getEntryAgentId();
548
+ // Send via direct method
549
+ const result = await session.callPluginMethod('mailbox.send', {
550
+ fromAgentId: String(orchestratorId),
551
+ toAgentId: 'worker_1',
552
+ content: 'Direct hello',
553
+ });
554
+ expect(result.ok).toBe(true);
555
+ // Event emitted
556
+ const events = await session.getEventsByType(mailboxEvents, 'mailbox_message');
557
+ const directMsg = events.find(e => e.message.content === 'Direct hello');
558
+ expect(directMsg).toBeDefined();
559
+ expect(directMsg.toAgentId).toBe(AgentId('worker_1'));
560
+ expect(directMsg.message.from).toBe(orchestratorId);
561
+ await harness.shutdown();
562
+ });
563
+ it('mailbox.send between non-related agents → error', async () => {
564
+ let orchestratorCalls = 0;
565
+ const harness = new TestHarness({
566
+ presets: [createMultiAgentPreset([
567
+ { name: 'worker', system: 'Worker agent.', tools: [], agents: [] },
568
+ ], { orchestratorSystem: 'Orchestrator agent.' })],
569
+ mockHandler: (request) => {
570
+ if (request.systemPrompt.includes('Orchestrator')) {
571
+ orchestratorCalls++;
572
+ if (orchestratorCalls === 1) {
573
+ // Spawn two workers
574
+ return {
575
+ content: null,
576
+ toolCalls: [
577
+ { id: ToolCallId('tc1'), name: 'start_worker', input: { message: 'Task 1' } },
578
+ { id: ToolCallId('tc2'), name: 'start_worker', input: { message: 'Task 2' } },
579
+ ],
580
+ finishReason: 'stop',
581
+ metrics: MockLLMProvider.defaultMetrics(),
582
+ };
583
+ }
584
+ return { content: 'Done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() };
585
+ }
586
+ return { content: 'Worker done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() };
587
+ },
588
+ });
589
+ const session = await harness.createSession('test');
590
+ await session.sendAndWaitForIdle('Start');
591
+ // Try to send between siblings (worker_1 → worker_2)
592
+ const result = await session.callPluginMethod('mailbox.send', {
593
+ fromAgentId: 'worker_1',
594
+ toAgentId: 'worker_2',
595
+ content: 'Should fail',
596
+ });
597
+ expect(result.ok).toBe(false);
598
+ if (!result.ok) {
599
+ expect(result.error.message).toContain('Cannot send message');
600
+ }
601
+ await harness.shutdown();
602
+ });
603
+ });
604
+ });
605
+ //# sourceMappingURL=mailbox.integration.test.js.map