@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,629 @@
1
+ import { describe, expect, it } from 'bun:test';
2
+ import z from 'zod/v4';
3
+ import { MockLLMProvider } from '../../core/llm/mock.js';
4
+ import { selectPluginState } from '../../core/sessions/reducer.js';
5
+ import { ToolCallId } from '../../core/tools/schema.js';
6
+ import { Err, Ok } from '../../lib/utils/result.js';
7
+ import { createTestPreset, TestHarness } from '../../testing/index.js';
8
+ import { createWorkerDefinition, workerEvents, workerPlugin } from './index.js';
9
+ // ============================================================================
10
+ // Test Worker Definitions
11
+ // ============================================================================
12
+ /** A simple worker that completes immediately with a result. */
13
+ const immediateWorker = createWorkerDefinition('immediate', 'Completes immediately', z.object({ value: z.string() }), {
14
+ initialState: () => ({ count: 0 }),
15
+ reduce: (state, event) => {
16
+ if (event.type === 'increment')
17
+ return { count: state.count + 1 };
18
+ return state;
19
+ },
20
+ execute: async (config) => {
21
+ return Ok({
22
+ status: 'done',
23
+ summary: `Processed: ${config.value}`,
24
+ });
25
+ },
26
+ });
27
+ /** A worker that fails with an error. */
28
+ const failingWorker = createWorkerDefinition('failing', 'Always fails', z.object({}), {
29
+ initialState: () => ({}),
30
+ reduce: (state) => state,
31
+ execute: async () => {
32
+ return Err({ message: 'Worker error', resumable: true });
33
+ },
34
+ });
35
+ /** A worker that throws an exception. */
36
+ const throwingWorker = createWorkerDefinition('throwing', 'Throws exception', z.object({}), {
37
+ initialState: () => ({}),
38
+ reduce: (state) => state,
39
+ execute: async () => {
40
+ throw new Error('Unexpected crash');
41
+ },
42
+ });
43
+ /** A worker that emits sub-events before completing. */
44
+ const emittingWorker = createWorkerDefinition('emitting', 'Emits sub-events', z.object({}), {
45
+ initialState: () => ({ items: [] }),
46
+ reduce: (state, event) => {
47
+ if (event.type === 'item_added' && event.item) {
48
+ return { items: [...state.items, event.item] };
49
+ }
50
+ return state;
51
+ },
52
+ execute: async (_config, ctx) => {
53
+ await ctx.emit({ type: 'item_added', item: 'alpha' });
54
+ await ctx.emit({ type: 'item_added', item: 'beta' });
55
+ return Ok({ status: 'done', summary: 'Emitted 2 items' });
56
+ },
57
+ });
58
+ /** A deferred worker that waits for cancellation. */
59
+ function createDeferredWorker() {
60
+ let resolveWorker;
61
+ const started = new Promise((r) => {
62
+ resolveWorker = undefined; // placeholder
63
+ void r; // will be set below
64
+ });
65
+ let startedResolve;
66
+ const startedPromise = new Promise((r) => {
67
+ startedResolve = r;
68
+ });
69
+ const worker = createWorkerDefinition('deferred', 'Waits until cancelled or resolved', z.object({}), {
70
+ initialState: () => ({}),
71
+ reduce: (state) => state,
72
+ execute: async (_config, ctx) => {
73
+ startedResolve();
74
+ // Poll for cancellation
75
+ while (ctx.shouldContinue()) {
76
+ await new Promise((r) => setTimeout(r, 10));
77
+ }
78
+ return Ok({ status: 'cancelled', summary: 'Worker was cancelled' });
79
+ },
80
+ });
81
+ return { worker, started: startedPromise };
82
+ }
83
+ /** A worker that writes a file. */
84
+ const artifactWorker = createWorkerDefinition('artifact', 'Writes files', z.object({}), {
85
+ initialState: () => ({}),
86
+ reduce: (state) => state,
87
+ execute: async (_config, ctx) => {
88
+ await ctx.files.write('output.html', '<h1>Hello</h1>');
89
+ return Ok({ status: 'done', summary: 'Wrote file' });
90
+ },
91
+ });
92
+ /** A worker that notifies the agent. */
93
+ const notifyingWorker = createWorkerDefinition('notifying', 'Notifies agent', z.object({}), {
94
+ initialState: () => ({}),
95
+ reduce: (state) => state,
96
+ execute: async (_config, ctx) => {
97
+ await ctx.notifyAgent('Progress update: 50%');
98
+ return Ok({ status: 'done', summary: 'Notified agent' });
99
+ },
100
+ });
101
+ /** A worker with command support. */
102
+ const commandWorker = createWorkerDefinition('commandable', 'Supports commands', z.object({}), {
103
+ commands: {
104
+ update_config: {
105
+ description: 'Update config',
106
+ schema: z.object({ key: z.string() }),
107
+ },
108
+ },
109
+ initialState: () => ({ commandsReceived: 0 }),
110
+ reduce: (state, event) => {
111
+ if (event.type === 'command_received')
112
+ return { commandsReceived: state.commandsReceived + 1 };
113
+ return state;
114
+ },
115
+ execute: async (_config, ctx) => {
116
+ // Wait a bit for commands to arrive
117
+ while (ctx.shouldContinue()) {
118
+ await new Promise((r) => setTimeout(r, 10));
119
+ }
120
+ return Ok({ status: 'done', summary: 'Done' });
121
+ },
122
+ handleCommand: async (cmd, ctx) => {
123
+ await ctx.emit({ type: 'command_received' });
124
+ return Ok(`Command ${cmd.command} handled`);
125
+ },
126
+ });
127
+ // ============================================================================
128
+ // Helpers
129
+ // ============================================================================
130
+ const allWorkers = [immediateWorker, failingWorker, throwingWorker, emittingWorker, artifactWorker, notifyingWorker, commandWorker];
131
+ function createWorkersPreset(overrides) {
132
+ return createTestPreset({
133
+ ...overrides,
134
+ plugins: [
135
+ workerPlugin.configure({ workers: allWorkers }),
136
+ ...(overrides?.plugins ?? []),
137
+ ],
138
+ });
139
+ }
140
+ function createWorkersHarness(options) {
141
+ return new TestHarness({ ...options, systemPlugins: [workerPlugin] });
142
+ }
143
+ // ============================================================================
144
+ // Tests
145
+ // ============================================================================
146
+ describe('workers plugin', () => {
147
+ // =========================================================================
148
+ // Worker spawning
149
+ // =========================================================================
150
+ describe('worker spawning', () => {
151
+ it('agent calls worker_immediate_start → worker_started event → worker in state', async () => {
152
+ const harness = createWorkersHarness({
153
+ presets: [createWorkersPreset()],
154
+ llmProvider: MockLLMProvider.withSequence([
155
+ {
156
+ toolCalls: [{
157
+ id: ToolCallId('tc1'),
158
+ name: 'worker_immediate_start',
159
+ input: { value: 'test-data' },
160
+ }],
161
+ },
162
+ { content: 'Done', toolCalls: [] },
163
+ ]),
164
+ });
165
+ const session = await harness.createSession('test');
166
+ await session.sendAndWaitForIdle('Start worker');
167
+ const startedEvents = await session.getEventsByType(workerEvents, 'worker_started');
168
+ expect(startedEvents).toHaveLength(1);
169
+ expect(startedEvents[0].workerType).toBe('immediate');
170
+ expect(startedEvents[0].config).toEqual({ value: 'test-data' });
171
+ await harness.shutdown();
172
+ });
173
+ it('spawn non-existent worker type → error returned to LLM', async () => {
174
+ const harness = createWorkersHarness({
175
+ presets: [createWorkersPreset()],
176
+ mockHandler: (request) => {
177
+ const callHistory = harness.llmProvider.getCallHistory();
178
+ if (callHistory.length === 0) {
179
+ return {
180
+ content: null,
181
+ toolCalls: [{
182
+ id: ToolCallId('tc1'),
183
+ name: 'worker_immediate_start',
184
+ input: { value: 'test' },
185
+ }],
186
+ finishReason: 'stop',
187
+ metrics: MockLLMProvider.defaultMetrics(),
188
+ };
189
+ }
190
+ return { content: 'Done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() };
191
+ },
192
+ });
193
+ // Use a preset with no workers configured to test spawn via direct method
194
+ const harnessNoWorkers = createWorkersHarness({
195
+ presets: [createTestPreset({
196
+ plugins: [workerPlugin.configure({ workers: [] })],
197
+ })],
198
+ llmProvider: MockLLMProvider.withFixedResponse({ content: 'Ok', toolCalls: [] }),
199
+ });
200
+ const session = await harnessNoWorkers.createSession('test');
201
+ await session.sendAndWaitForIdle('Hi');
202
+ const entryAgentId = session.getEntryAgentId();
203
+ const result = await session.callPluginMethod('workers.spawn', {
204
+ sessionId: String(session.sessionId),
205
+ agentId: String(entryAgentId),
206
+ workerType: 'nonexistent',
207
+ config: {},
208
+ });
209
+ expect(result.ok).toBe(false);
210
+ await harnessNoWorkers.shutdown();
211
+ });
212
+ it('spawn with invalid config → validation error', async () => {
213
+ const harness = createWorkersHarness({
214
+ presets: [createWorkersPreset()],
215
+ llmProvider: MockLLMProvider.withFixedResponse({ content: 'Ok', toolCalls: [] }),
216
+ });
217
+ const session = await harness.createSession('test');
218
+ await session.sendAndWaitForIdle('Hi');
219
+ const entryAgentId = session.getEntryAgentId();
220
+ const result = await session.callPluginMethod('workers.spawn', {
221
+ sessionId: String(session.sessionId),
222
+ agentId: String(entryAgentId),
223
+ workerType: 'immediate',
224
+ config: { wrong_field: 123 },
225
+ });
226
+ expect(result.ok).toBe(false);
227
+ await harness.shutdown();
228
+ });
229
+ });
230
+ // =========================================================================
231
+ // Worker completion and failure
232
+ // =========================================================================
233
+ describe('worker completion and failure', () => {
234
+ it('worker returns Ok → worker_completed event → status completed', async () => {
235
+ const harness = createWorkersHarness({
236
+ presets: [createWorkersPreset()],
237
+ llmProvider: MockLLMProvider.withSequence([
238
+ {
239
+ toolCalls: [{
240
+ id: ToolCallId('tc1'),
241
+ name: 'worker_immediate_start',
242
+ input: { value: 'hello' },
243
+ }],
244
+ },
245
+ { content: 'Done', toolCalls: [] },
246
+ ]),
247
+ });
248
+ const session = await harness.createSession('test');
249
+ await session.sendAndWaitForIdle('Start worker');
250
+ // Wait briefly for async worker completion
251
+ await new Promise((r) => setTimeout(r, 100));
252
+ const completedEvents = await session.getEventsByType(workerEvents, 'worker_completed');
253
+ expect(completedEvents).toHaveLength(1);
254
+ expect(completedEvents[0].result.summary).toBe('Processed: hello');
255
+ // Verify state
256
+ const workers = selectPluginState(session.state, 'workers');
257
+ expect(workers.size).toBe(1);
258
+ const worker = Array.from(workers.values())[0];
259
+ expect(worker.status).toBe('completed');
260
+ await harness.shutdown();
261
+ });
262
+ it('worker returns Err → worker_failed event → status failed, resumable flag', async () => {
263
+ const harness = createWorkersHarness({
264
+ presets: [createWorkersPreset()],
265
+ llmProvider: MockLLMProvider.withSequence([
266
+ {
267
+ toolCalls: [{
268
+ id: ToolCallId('tc1'),
269
+ name: 'worker_failing_start',
270
+ input: {},
271
+ }],
272
+ },
273
+ { content: 'Done', toolCalls: [] },
274
+ ]),
275
+ });
276
+ const session = await harness.createSession('test');
277
+ await session.sendAndWaitForIdle('Start worker');
278
+ await new Promise((r) => setTimeout(r, 100));
279
+ const failedEvents = await session.getEventsByType(workerEvents, 'worker_failed');
280
+ expect(failedEvents).toHaveLength(1);
281
+ expect(failedEvents[0].error).toBe('Worker error');
282
+ expect(failedEvents[0].resumable).toBe(true);
283
+ const workers = selectPluginState(session.state, 'workers');
284
+ const worker = Array.from(workers.values())[0];
285
+ expect(worker.status).toBe('failed');
286
+ await harness.shutdown();
287
+ });
288
+ it('worker throws exception → worker_failed event, resumable: false', async () => {
289
+ const harness = createWorkersHarness({
290
+ presets: [createWorkersPreset()],
291
+ llmProvider: MockLLMProvider.withSequence([
292
+ {
293
+ toolCalls: [{
294
+ id: ToolCallId('tc1'),
295
+ name: 'worker_throwing_start',
296
+ input: {},
297
+ }],
298
+ },
299
+ { content: 'Done', toolCalls: [] },
300
+ ]),
301
+ });
302
+ const session = await harness.createSession('test');
303
+ await session.sendAndWaitForIdle('Start worker');
304
+ await new Promise((r) => setTimeout(r, 100));
305
+ const failedEvents = await session.getEventsByType(workerEvents, 'worker_failed');
306
+ expect(failedEvents).toHaveLength(1);
307
+ expect(failedEvents[0].error).toBe('Unexpected crash');
308
+ expect(failedEvents[0].resumable).toBe(false);
309
+ await harness.shutdown();
310
+ });
311
+ });
312
+ // =========================================================================
313
+ // Worker sub-events and state reduction
314
+ // =========================================================================
315
+ describe('worker sub-events and state reduction', () => {
316
+ it('worker emits sub-events → worker_sub_event events → state updated via reducer', async () => {
317
+ const harness = createWorkersHarness({
318
+ presets: [createWorkersPreset()],
319
+ llmProvider: MockLLMProvider.withSequence([
320
+ {
321
+ toolCalls: [{
322
+ id: ToolCallId('tc1'),
323
+ name: 'worker_emitting_start',
324
+ input: {},
325
+ }],
326
+ },
327
+ { content: 'Done', toolCalls: [] },
328
+ ]),
329
+ });
330
+ const session = await harness.createSession('test');
331
+ await session.sendAndWaitForIdle('Start worker');
332
+ await new Promise((r) => setTimeout(r, 100));
333
+ const subEvents = await session.getEventsByType(workerEvents, 'worker_sub_event');
334
+ expect(subEvents).toHaveLength(2);
335
+ expect(subEvents[0].subEvent.type).toBe('item_added');
336
+ expect(subEvents[0].subEvent.item).toBe('alpha');
337
+ expect(subEvents[1].subEvent.item).toBe('beta');
338
+ // Verify worker state was updated by reducer
339
+ const workers = selectPluginState(session.state, 'workers');
340
+ const worker = Array.from(workers.values())[0];
341
+ const state = worker.state;
342
+ expect(state.items).toEqual(['alpha', 'beta']);
343
+ await harness.shutdown();
344
+ });
345
+ });
346
+ // =========================================================================
347
+ // Worker control (pause/resume/cancel)
348
+ // =========================================================================
349
+ describe('worker control', () => {
350
+ it('cancel running worker → status cancelled, shouldContinue returns false', async () => {
351
+ const { worker: deferred, started } = createDeferredWorker();
352
+ const harness = createWorkersHarness({
353
+ presets: [createTestPreset({
354
+ plugins: [workerPlugin.configure({ workers: [deferred] })],
355
+ })],
356
+ llmProvider: MockLLMProvider.withSequence([
357
+ {
358
+ toolCalls: [{
359
+ id: ToolCallId('tc1'),
360
+ name: 'worker_deferred_start',
361
+ input: {},
362
+ }],
363
+ },
364
+ { content: 'Done', toolCalls: [] },
365
+ ]),
366
+ });
367
+ const session = await harness.createSession('test');
368
+ await session.sendAndWaitForIdle('Start worker');
369
+ // Wait for worker to start executing
370
+ await started;
371
+ // Get worker ID from state
372
+ const workers = selectPluginState(session.state, 'workers');
373
+ const workerId = Array.from(workers.keys())[0];
374
+ // Cancel the worker
375
+ const entryAgentId = session.getEntryAgentId();
376
+ const result = await session.callPluginMethod('workers.cancel', {
377
+ sessionId: String(session.sessionId),
378
+ agentId: String(entryAgentId),
379
+ workerId: String(workerId),
380
+ });
381
+ expect(result.ok).toBe(true);
382
+ // Wait for worker to finish
383
+ await new Promise((r) => setTimeout(r, 200));
384
+ const statusEvents = await session.getEventsByType(workerEvents, 'worker_status_changed');
385
+ const cancelEvent = statusEvents.find((e) => e.toStatus === 'cancelled');
386
+ expect(cancelEvent).toBeDefined();
387
+ await harness.shutdown();
388
+ });
389
+ it('pause running worker → status paused, resume → status running', async () => {
390
+ const { worker: deferred, started } = createDeferredWorker();
391
+ const harness = createWorkersHarness({
392
+ presets: [createTestPreset({
393
+ plugins: [workerPlugin.configure({ workers: [deferred] })],
394
+ })],
395
+ llmProvider: MockLLMProvider.withSequence([
396
+ {
397
+ toolCalls: [{
398
+ id: ToolCallId('tc1'),
399
+ name: 'worker_deferred_start',
400
+ input: {},
401
+ }],
402
+ },
403
+ { content: 'Done', toolCalls: [] },
404
+ ]),
405
+ });
406
+ const session = await harness.createSession('test');
407
+ await session.sendAndWaitForIdle('Start worker');
408
+ await started;
409
+ const workers = selectPluginState(session.state, 'workers');
410
+ const workerId = Array.from(workers.keys())[0];
411
+ const entryAgentId = session.getEntryAgentId();
412
+ // Pause
413
+ const pauseResult = await session.callPluginMethod('workers.pause', {
414
+ sessionId: String(session.sessionId),
415
+ agentId: String(entryAgentId),
416
+ workerId: String(workerId),
417
+ });
418
+ expect(pauseResult.ok).toBe(true);
419
+ let statusEvents = await session.getEventsByType(workerEvents, 'worker_status_changed');
420
+ expect(statusEvents.some((e) => e.toStatus === 'paused')).toBe(true);
421
+ // Resume
422
+ const resumeResult = await session.callPluginMethod('workers.resume', {
423
+ sessionId: String(session.sessionId),
424
+ agentId: String(entryAgentId),
425
+ workerId: String(workerId),
426
+ });
427
+ expect(resumeResult.ok).toBe(true);
428
+ statusEvents = await session.getEventsByType(workerEvents, 'worker_status_changed');
429
+ const resumed = statusEvents.find((e) => e.fromStatus === 'paused' && e.toStatus === 'running');
430
+ expect(resumed).toBeDefined();
431
+ await harness.shutdown();
432
+ });
433
+ it('pause non-running worker → error', async () => {
434
+ const harness = createWorkersHarness({
435
+ presets: [createWorkersPreset()],
436
+ llmProvider: MockLLMProvider.withSequence([
437
+ {
438
+ toolCalls: [{
439
+ id: ToolCallId('tc1'),
440
+ name: 'worker_immediate_start',
441
+ input: { value: 'x' },
442
+ }],
443
+ },
444
+ { content: 'Done', toolCalls: [] },
445
+ ]),
446
+ });
447
+ const session = await harness.createSession('test');
448
+ await session.sendAndWaitForIdle('Start worker');
449
+ await new Promise((r) => setTimeout(r, 100));
450
+ // Worker already completed - pause should fail
451
+ const workers = selectPluginState(session.state, 'workers');
452
+ const workerId = Array.from(workers.keys())[0];
453
+ const entryAgentId = session.getEntryAgentId();
454
+ const result = await session.callPluginMethod('workers.pause', {
455
+ sessionId: String(session.sessionId),
456
+ agentId: String(entryAgentId),
457
+ workerId: String(workerId),
458
+ });
459
+ expect(result.ok).toBe(false);
460
+ await harness.shutdown();
461
+ });
462
+ });
463
+ // =========================================================================
464
+ // Worker commands
465
+ // =========================================================================
466
+ describe('worker commands', () => {
467
+ it('worker with commands → generates command tool', async () => {
468
+ const harness = createWorkersHarness({
469
+ presets: [createTestPreset({
470
+ plugins: [workerPlugin.configure({ workers: [commandWorker] })],
471
+ })],
472
+ llmProvider: MockLLMProvider.withFixedResponse({ content: 'Ok', toolCalls: [] }),
473
+ });
474
+ const session = await harness.createSession('test');
475
+ await session.sendAndWaitForIdle('Hi');
476
+ const lastRequest = harness.llmProvider.getLastRequest();
477
+ const toolNames = lastRequest?.tools?.map((t) => t.name) ?? [];
478
+ expect(toolNames).toContain('worker_commandable_start');
479
+ expect(toolNames).toContain('worker_commandable_update_config');
480
+ await harness.shutdown();
481
+ });
482
+ });
483
+ // =========================================================================
484
+ // Concurrent worker limit
485
+ // =========================================================================
486
+ describe('concurrent worker limit', () => {
487
+ it('spawning more than 10 workers → 11th fails with max reached', async () => {
488
+ // Create 11 deferred workers with different types
489
+ const deferredWorkers = Array.from({ length: 11 }, (_, i) => {
490
+ const { worker } = createDeferredWorker();
491
+ return createWorkerDefinition(`deferred_${i}`, `Deferred worker ${i}`, z.object({}), {
492
+ initialState: () => ({}),
493
+ reduce: (state) => state,
494
+ execute: async (_config, ctx) => {
495
+ while (ctx.shouldContinue()) {
496
+ await new Promise((r) => setTimeout(r, 10));
497
+ }
498
+ return Ok({ status: 'done', summary: 'Done' });
499
+ },
500
+ });
501
+ });
502
+ const harness = createWorkersHarness({
503
+ presets: [createTestPreset({
504
+ plugins: [workerPlugin.configure({ workers: deferredWorkers })],
505
+ })],
506
+ llmProvider: MockLLMProvider.withFixedResponse({ content: 'Ok', toolCalls: [] }),
507
+ });
508
+ const session = await harness.createSession('test');
509
+ await session.sendAndWaitForIdle('Hi');
510
+ const entryAgentId = session.getEntryAgentId();
511
+ // Spawn 10 workers
512
+ for (let i = 0; i < 10; i++) {
513
+ const result = await session.callPluginMethod('workers.spawn', {
514
+ sessionId: String(session.sessionId),
515
+ agentId: String(entryAgentId),
516
+ workerType: `deferred_${i}`,
517
+ config: {},
518
+ });
519
+ expect(result.ok).toBe(true);
520
+ }
521
+ // 11th should fail
522
+ const result = await session.callPluginMethod('workers.spawn', {
523
+ sessionId: String(session.sessionId),
524
+ agentId: String(entryAgentId),
525
+ workerType: 'deferred_10',
526
+ config: {},
527
+ });
528
+ expect(result.ok).toBe(false);
529
+ await harness.shutdown();
530
+ });
531
+ });
532
+ // =========================================================================
533
+ // Session close cleanup
534
+ // =========================================================================
535
+ describe('session close cleanup', () => {
536
+ it('closing session cancels running workers', async () => {
537
+ const { worker: deferred, started } = createDeferredWorker();
538
+ const harness = createWorkersHarness({
539
+ presets: [createTestPreset({
540
+ plugins: [workerPlugin.configure({ workers: [deferred] })],
541
+ })],
542
+ llmProvider: MockLLMProvider.withSequence([
543
+ {
544
+ toolCalls: [{
545
+ id: ToolCallId('tc1'),
546
+ name: 'worker_deferred_start',
547
+ input: {},
548
+ }],
549
+ },
550
+ { content: 'Done', toolCalls: [] },
551
+ ]),
552
+ });
553
+ const session = await harness.createSession('test');
554
+ await session.sendAndWaitForIdle('Start worker');
555
+ await started;
556
+ // Verify worker is running
557
+ const workers = selectPluginState(session.state, 'workers');
558
+ expect(workers.size).toBe(1);
559
+ const worker = Array.from(workers.values())[0];
560
+ expect(worker.status).toBe('running');
561
+ // Close session → should cancel workers
562
+ await session.close();
563
+ await new Promise((r) => setTimeout(r, 200));
564
+ await harness.shutdown();
565
+ });
566
+ });
567
+ // =========================================================================
568
+ // Worker artifacts
569
+ // =========================================================================
570
+ describe('worker file writing', () => {
571
+ it('worker writes file via files store → worker completes successfully', async () => {
572
+ const harness = createWorkersHarness({
573
+ presets: [createWorkersPreset()],
574
+ llmProvider: MockLLMProvider.withSequence([
575
+ {
576
+ toolCalls: [{
577
+ id: ToolCallId('tc1'),
578
+ name: 'worker_artifact_start',
579
+ input: {},
580
+ }],
581
+ },
582
+ { content: 'Done', toolCalls: [] },
583
+ ]),
584
+ });
585
+ const session = await harness.createSession('test');
586
+ await session.sendAndWaitForIdle('Start worker');
587
+ await new Promise((r) => setTimeout(r, 200));
588
+ const completedEvents = await session.getEventsByType(workerEvents, 'worker_completed');
589
+ expect(completedEvents).toHaveLength(1);
590
+ expect(completedEvents[0].result.summary).toBe('Wrote file');
591
+ const workers = selectPluginState(session.state, 'workers');
592
+ const worker = Array.from(workers.values())[0];
593
+ expect(worker.status).toBe('completed');
594
+ await harness.shutdown();
595
+ });
596
+ });
597
+ // =========================================================================
598
+ // Worker agent notification
599
+ // =========================================================================
600
+ describe('worker agent notification', () => {
601
+ it('worker calls notifyAgent → mailbox message emitted', async () => {
602
+ const harness = createWorkersHarness({
603
+ presets: [createWorkersPreset()],
604
+ llmProvider: MockLLMProvider.withSequence([
605
+ {
606
+ toolCalls: [{
607
+ id: ToolCallId('tc1'),
608
+ name: 'worker_notifying_start',
609
+ input: {},
610
+ }],
611
+ },
612
+ // Agent may be re-scheduled due to mailbox message
613
+ { content: 'Got it', toolCalls: [] },
614
+ { content: 'Done', toolCalls: [] },
615
+ ]),
616
+ });
617
+ const session = await harness.createSession('test');
618
+ await session.sendAndWaitForIdle('Start worker', { timeoutMs: 5000 });
619
+ await new Promise((r) => setTimeout(r, 200));
620
+ // Check for mailbox_message event with worker's notification
621
+ const allEvents = await session.getEvents();
622
+ const mailboxMessages = allEvents.filter((e) => e.type === 'mailbox_message');
623
+ const workerMessage = mailboxMessages.find((e) => e.message?.content === 'Progress update: 50%');
624
+ expect(workerMessage).toBeDefined();
625
+ await harness.shutdown();
626
+ });
627
+ });
628
+ });
629
+ //# sourceMappingURL=workers.integration.test.js.map