@clinebot/core 0.0.33 → 0.0.35

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 (412) hide show
  1. package/README.md +12 -8
  2. package/dist/ClineCore.d.ts +48 -29
  3. package/dist/ClineCore.d.ts.map +1 -1
  4. package/dist/auth/client.d.ts +19 -0
  5. package/dist/auth/client.d.ts.map +1 -1
  6. package/dist/auth/cline.d.ts.map +1 -1
  7. package/dist/auth/oca.d.ts.map +1 -1
  8. package/dist/auth/server.d.ts +32 -0
  9. package/dist/auth/server.d.ts.map +1 -1
  10. package/dist/auth/types.d.ts +29 -0
  11. package/dist/auth/types.d.ts.map +1 -1
  12. package/dist/extensions/config/agent-config-loader.d.ts +2 -2
  13. package/dist/extensions/config/agent-config-loader.d.ts.map +1 -1
  14. package/dist/extensions/config/agent-config-parser.d.ts +1 -1
  15. package/dist/extensions/config/agent-config-parser.d.ts.map +1 -1
  16. package/dist/extensions/config/hooks-config-loader.d.ts +2 -2
  17. package/dist/extensions/config/hooks-config-loader.d.ts.map +1 -1
  18. package/dist/extensions/config/index.d.ts +3 -3
  19. package/dist/extensions/config/index.d.ts.map +1 -1
  20. package/dist/extensions/config/user-instruction-config-loader.d.ts +2 -2
  21. package/dist/extensions/config/user-instruction-config-loader.d.ts.map +1 -1
  22. package/dist/extensions/index.d.ts +2 -1
  23. package/dist/extensions/index.d.ts.map +1 -1
  24. package/dist/extensions/plugin/plugin-config-loader.d.ts +2 -1
  25. package/dist/extensions/plugin/plugin-config-loader.d.ts.map +1 -1
  26. package/dist/extensions/plugin/plugin-load-report.d.ts +19 -0
  27. package/dist/extensions/plugin/plugin-load-report.d.ts.map +1 -0
  28. package/dist/extensions/plugin/plugin-loader.d.ts +6 -0
  29. package/dist/extensions/plugin/plugin-loader.d.ts.map +1 -1
  30. package/dist/extensions/plugin/plugin-sandbox.d.ts +2 -1
  31. package/dist/extensions/plugin/plugin-sandbox.d.ts.map +1 -1
  32. package/dist/extensions/plugin-sandbox-bootstrap.js +242 -242
  33. package/dist/extensions/tools/constants.d.ts.map +1 -0
  34. package/dist/extensions/tools/definitions.d.ts.map +1 -0
  35. package/dist/extensions/tools/executors/apply-patch-parser.d.ts.map +1 -0
  36. package/dist/extensions/tools/executors/apply-patch.d.ts.map +1 -0
  37. package/dist/extensions/tools/executors/bash.d.ts.map +1 -0
  38. package/dist/extensions/tools/executors/editor.d.ts.map +1 -0
  39. package/dist/extensions/tools/executors/file-read.d.ts.map +1 -0
  40. package/dist/extensions/tools/executors/index.d.ts.map +1 -0
  41. package/dist/extensions/tools/executors/search.d.ts.map +1 -0
  42. package/dist/extensions/tools/executors/web-fetch.d.ts.map +1 -0
  43. package/dist/extensions/tools/helpers.d.ts.map +1 -0
  44. package/dist/extensions/tools/index.d.ts.map +1 -0
  45. package/dist/{tools → extensions/tools}/model-tool-routing.d.ts +1 -1
  46. package/dist/extensions/tools/model-tool-routing.d.ts.map +1 -0
  47. package/dist/{tools → extensions/tools}/presets.d.ts +1 -2
  48. package/dist/extensions/tools/presets.d.ts.map +1 -0
  49. package/dist/extensions/tools/schemas.d.ts.map +1 -0
  50. package/dist/extensions/tools/team/delegated-agent.d.ts.map +1 -0
  51. package/dist/extensions/tools/team/index.d.ts.map +1 -0
  52. package/dist/{team → extensions/tools/team}/multi-agent.d.ts +1 -3
  53. package/dist/extensions/tools/team/multi-agent.d.ts.map +1 -0
  54. package/dist/extensions/tools/team/projections.d.ts.map +1 -0
  55. package/dist/extensions/tools/team/runtime.d.ts.map +1 -0
  56. package/dist/{team → extensions/tools/team}/spawn-agent-tool.d.ts +0 -1
  57. package/dist/extensions/tools/team/spawn-agent-tool.d.ts.map +1 -0
  58. package/dist/extensions/tools/team/subagent-prompts.d.ts.map +1 -0
  59. package/dist/extensions/tools/team/team-tools.d.ts.map +1 -0
  60. package/dist/{tools → extensions/tools}/types.d.ts +4 -3
  61. package/dist/extensions/tools/types.d.ts.map +1 -0
  62. package/dist/{runtime → hooks}/checkpoint-hooks.d.ts +7 -0
  63. package/dist/hooks/checkpoint-hooks.d.ts.map +1 -0
  64. package/dist/{runtime → hooks}/hook-file-hooks.d.ts +0 -2
  65. package/dist/hooks/hook-file-hooks.d.ts.map +1 -0
  66. package/dist/hooks/subprocess.d.ts +3 -130
  67. package/dist/hooks/subprocess.d.ts.map +1 -1
  68. package/dist/index.d.ts +38 -35
  69. package/dist/index.d.ts.map +1 -1
  70. package/dist/index.js +386 -384
  71. package/dist/runtime/history.d.ts +4 -0
  72. package/dist/runtime/history.d.ts.map +1 -0
  73. package/dist/runtime/host.d.ts +9 -0
  74. package/dist/runtime/host.d.ts.map +1 -0
  75. package/dist/{session → runtime}/rpc-runtime-ensure.d.ts +13 -1
  76. package/dist/{session → runtime}/rpc-runtime-ensure.d.ts.map +1 -1
  77. package/dist/{session → runtime}/rpc-spawn-lease.d.ts.map +1 -1
  78. package/dist/runtime/runtime-builder.d.ts +1 -1
  79. package/dist/runtime/runtime-builder.d.ts.map +1 -1
  80. package/dist/{session/session-manager.d.ts → runtime/runtime-host.d.ts} +55 -12
  81. package/dist/runtime/runtime-host.d.ts.map +1 -0
  82. package/dist/{session → runtime}/runtime-oauth-token-manager.d.ts +1 -1
  83. package/dist/{session → runtime}/runtime-oauth-token-manager.d.ts.map +1 -1
  84. package/dist/runtime/session-runtime.d.ts +2 -2
  85. package/dist/runtime/session-runtime.d.ts.map +1 -1
  86. package/dist/runtime/subprocess-sandbox.d.ts +2 -0
  87. package/dist/runtime/subprocess-sandbox.d.ts.map +1 -1
  88. package/dist/runtime/tool-approval.d.ts.map +1 -1
  89. package/dist/{session/session-agent-events.d.ts → services/agent-events.d.ts} +4 -4
  90. package/dist/services/agent-events.d.ts.map +1 -0
  91. package/dist/services/config.d.ts +3 -0
  92. package/dist/services/config.d.ts.map +1 -0
  93. package/dist/services/local-runtime-bootstrap.d.ts +41 -0
  94. package/dist/services/local-runtime-bootstrap.d.ts.map +1 -0
  95. package/dist/services/providers/local-provider-registry.d.ts.map +1 -0
  96. package/dist/services/providers/local-provider-service.d.ts.map +1 -0
  97. package/dist/{session → services}/session-artifacts.d.ts +2 -4
  98. package/dist/services/session-artifacts.d.ts.map +1 -0
  99. package/dist/{session/utils/helpers.d.ts → services/session-data.d.ts} +19 -27
  100. package/dist/services/session-data.d.ts.map +1 -0
  101. package/dist/{session → services}/session-telemetry.d.ts +2 -2
  102. package/dist/services/session-telemetry.d.ts.map +1 -0
  103. package/dist/{storage → services/storage}/file-team-store.d.ts +2 -2
  104. package/dist/services/storage/file-team-store.d.ts.map +1 -0
  105. package/dist/{storage → services/storage}/provider-settings-legacy-migration.d.ts +1 -1
  106. package/dist/services/storage/provider-settings-legacy-migration.d.ts.map +1 -0
  107. package/dist/{storage → services/storage}/provider-settings-manager.d.ts +1 -1
  108. package/dist/services/storage/provider-settings-manager.d.ts.map +1 -0
  109. package/dist/{storage → services/storage}/sqlite-session-store.d.ts +3 -3
  110. package/dist/services/storage/sqlite-session-store.d.ts.map +1 -0
  111. package/dist/{storage → services/storage}/sqlite-team-store.d.ts +2 -2
  112. package/dist/services/storage/sqlite-team-store.d.ts.map +1 -0
  113. package/dist/{storage → services/storage}/team-store.d.ts +1 -1
  114. package/dist/services/storage/team-store.d.ts.map +1 -0
  115. package/dist/services/telemetry/ITelemetryAdapter.d.ts.map +1 -0
  116. package/dist/services/telemetry/OpenTelemetryAdapter.d.ts.map +1 -0
  117. package/dist/services/telemetry/OpenTelemetryProvider.d.ts.map +1 -0
  118. package/dist/services/telemetry/TelemetryLoggerSink.d.ts.map +1 -0
  119. package/dist/services/telemetry/TelemetryService.d.ts.map +1 -0
  120. package/dist/services/telemetry/core-events.d.ts.map +1 -0
  121. package/dist/services/telemetry/distinct-id.d.ts.map +1 -0
  122. package/dist/services/telemetry/index.d.ts.map +1 -0
  123. package/dist/{telemetry → services/telemetry}/index.js +6 -6
  124. package/dist/{session/utils → services}/usage.d.ts +1 -1
  125. package/dist/services/usage.d.ts.map +1 -0
  126. package/dist/services/workspace/file-indexer.d.ts.map +1 -0
  127. package/dist/services/workspace/index.d.ts.map +1 -0
  128. package/dist/services/workspace/mention-enricher.d.ts.map +1 -0
  129. package/dist/services/workspace-manifest.d.ts.map +1 -0
  130. package/dist/session/file-session-service.d.ts +4 -1
  131. package/dist/session/file-session-service.d.ts.map +1 -1
  132. package/dist/session/persistence-service.d.ts +8 -6
  133. package/dist/session/persistence-service.d.ts.map +1 -1
  134. package/dist/session/rpc-session-service.d.ts +3 -0
  135. package/dist/session/rpc-session-service.d.ts.map +1 -1
  136. package/dist/session/session-service.d.ts +8 -9
  137. package/dist/session/session-service.d.ts.map +1 -1
  138. package/dist/session/session-team-coordination.d.ts +4 -4
  139. package/dist/session/session-team-coordination.d.ts.map +1 -1
  140. package/dist/session/sqlite-rpc-session-backend.d.ts.map +1 -1
  141. package/dist/{session/default-session-manager.d.ts → transports/local.d.ts} +24 -14
  142. package/dist/transports/local.d.ts.map +1 -0
  143. package/dist/transports/rpc.d.ts +51 -0
  144. package/dist/transports/rpc.d.ts.map +1 -0
  145. package/dist/transports/runtime-host-support.d.ts +21 -0
  146. package/dist/transports/runtime-host-support.d.ts.map +1 -0
  147. package/dist/types/chat-schema.d.ts.map +1 -0
  148. package/dist/types/config.d.ts +3 -2
  149. package/dist/types/config.d.ts.map +1 -1
  150. package/dist/{session/utils/types.d.ts → types/session.d.ts} +15 -6
  151. package/dist/types/session.d.ts.map +1 -0
  152. package/dist/types/sessions.d.ts +19 -0
  153. package/dist/types/sessions.d.ts.map +1 -1
  154. package/dist/types/storage.d.ts +1 -3
  155. package/dist/types/storage.d.ts.map +1 -1
  156. package/dist/types.d.ts +7 -6
  157. package/dist/types.d.ts.map +1 -1
  158. package/package.json +7 -12
  159. package/src/ClineCore.test.ts +95 -19
  160. package/src/ClineCore.ts +120 -50
  161. package/src/auth/client.test.ts +29 -0
  162. package/src/auth/client.ts +21 -0
  163. package/src/auth/cline.ts +3 -1
  164. package/src/auth/codex.ts +1 -1
  165. package/src/auth/oca.ts +3 -1
  166. package/src/auth/server.test.ts +287 -0
  167. package/src/auth/server.ts +50 -1
  168. package/src/auth/types.ts +29 -0
  169. package/src/extensions/config/agent-config-loader.test.ts +3 -3
  170. package/src/extensions/config/agent-config-loader.ts +1 -5
  171. package/src/extensions/config/agent-config-parser.ts +1 -1
  172. package/src/extensions/config/hooks-config-loader.ts +1 -2
  173. package/src/extensions/config/index.ts +0 -4
  174. package/src/extensions/config/user-instruction-config-loader.ts +0 -4
  175. package/src/extensions/index.ts +6 -0
  176. package/src/extensions/plugin/plugin-config-loader.test.ts +39 -0
  177. package/src/extensions/plugin/plugin-config-loader.ts +18 -10
  178. package/src/extensions/plugin/plugin-load-report.ts +20 -0
  179. package/src/extensions/plugin/plugin-loader.test.ts +45 -0
  180. package/src/extensions/plugin/plugin-loader.ts +57 -3
  181. package/src/extensions/plugin/plugin-sandbox-bootstrap.ts +158 -86
  182. package/src/extensions/plugin/plugin-sandbox.test.ts +70 -0
  183. package/src/extensions/plugin/plugin-sandbox.ts +17 -6
  184. package/src/{tools → extensions/tools}/definitions.ts +1 -1
  185. package/src/extensions/tools/executors/file-read.test.ts +125 -0
  186. package/src/{tools → extensions/tools}/executors/file-read.ts +29 -4
  187. package/src/{tools → extensions/tools}/executors/search.ts +1 -1
  188. package/src/{tools → extensions/tools}/model-tool-routing.ts +1 -1
  189. package/src/{tools → extensions/tools}/presets.ts +2 -3
  190. package/src/extensions/tools/team/multi-agent.lifecycle.test.ts +455 -0
  191. package/src/{team → extensions/tools/team}/multi-agent.ts +80 -17
  192. package/src/{team → extensions/tools/team}/spawn-agent-tool.test.ts +0 -6
  193. package/src/{team → extensions/tools/team}/spawn-agent-tool.ts +1 -7
  194. package/src/{team → extensions/tools/team}/subagent-prompts.ts +2 -2
  195. package/src/{team → extensions/tools/team}/team-tools.test.ts +146 -30
  196. package/src/{team → extensions/tools/team}/team-tools.ts +98 -69
  197. package/src/{tools → extensions/tools}/types.ts +5 -3
  198. package/src/{runtime → hooks}/checkpoint-hooks.ts +27 -0
  199. package/src/{runtime → hooks}/hook-file-hooks.test.ts +42 -7
  200. package/src/{runtime → hooks}/hook-file-hooks.ts +6 -11
  201. package/src/hooks/subprocess.ts +48 -257
  202. package/src/index.ts +178 -158
  203. package/src/runtime/history.test.ts +114 -0
  204. package/src/runtime/history.ts +237 -0
  205. package/src/runtime/host.test.ts +230 -0
  206. package/src/runtime/host.ts +362 -0
  207. package/src/runtime/rpc-runtime-ensure.test.ts +123 -0
  208. package/src/{session → runtime}/rpc-runtime-ensure.ts +165 -27
  209. package/src/{session → runtime}/rpc-spawn-lease.test.ts +33 -1
  210. package/src/{session → runtime}/rpc-spawn-lease.ts +54 -20
  211. package/src/runtime/runtime-builder.team-persistence.test.ts +6 -3
  212. package/src/runtime/runtime-builder.test.ts +101 -4
  213. package/src/runtime/runtime-builder.ts +125 -86
  214. package/src/runtime/runtime-host.ts +178 -0
  215. package/src/{session → runtime}/runtime-oauth-token-manager.ts +1 -1
  216. package/src/runtime/runtime-parity.test.ts +1 -1
  217. package/src/runtime/session-runtime.ts +2 -2
  218. package/src/runtime/subprocess-sandbox.ts +26 -23
  219. package/src/runtime/tool-approval.ts +13 -15
  220. package/src/{session/session-agent-events.ts → services/agent-events.ts} +7 -7
  221. package/src/services/config.ts +5 -0
  222. package/src/services/local-runtime-bootstrap.ts +280 -0
  223. package/src/{providers → services/providers}/local-provider-service.ts +4 -4
  224. package/src/{session → services}/session-artifacts.ts +23 -19
  225. package/src/{session/utils/helpers.test.ts → services/session-data.test.ts} +1 -1
  226. package/src/{session/utils/helpers.ts → services/session-data.ts} +76 -72
  227. package/src/{session → services}/session-telemetry.ts +7 -9
  228. package/src/services/storage/artifact-store.ts +1 -0
  229. package/src/{storage → services/storage}/file-team-store.ts +2 -2
  230. package/src/{storage → services/storage}/provider-settings-legacy-migration.test.ts +1 -1
  231. package/src/{storage → services/storage}/provider-settings-legacy-migration.ts +2 -2
  232. package/src/{storage → services/storage}/provider-settings-manager.ts +2 -2
  233. package/src/services/storage/session-store.ts +1 -0
  234. package/src/{storage → services/storage}/sqlite-session-store.ts +7 -12
  235. package/src/{storage → services/storage}/sqlite-team-store.ts +4 -4
  236. package/src/{storage → services/storage}/team-store.ts +1 -1
  237. package/src/{session/utils → services}/usage.ts +1 -1
  238. package/src/{input → services/workspace}/file-indexer.test.ts +30 -1
  239. package/src/{input → services/workspace}/file-indexer.ts +26 -2
  240. package/src/{input → services/workspace}/mention-enricher.test.ts +21 -0
  241. package/src/{input → services/workspace}/mention-enricher.ts +1 -1
  242. package/src/session/file-session-service.ts +9 -7
  243. package/src/session/index.ts +25 -17
  244. package/src/session/persistence-service.test.ts +121 -24
  245. package/src/session/persistence-service.ts +118 -102
  246. package/src/session/rpc-session-service.ts +9 -2
  247. package/src/session/session-service.team-persistence.test.ts +1 -1
  248. package/src/session/session-service.ts +32 -19
  249. package/src/session/session-team-coordination.ts +13 -6
  250. package/src/session/sqlite-rpc-session-backend.ts +4 -6
  251. package/src/session/workspace-manager.ts +1 -1
  252. package/src/{session/default-session-manager.e2e.test.ts → transports/local.e2e.test.ts} +13 -17
  253. package/src/{session/default-session-manager.test.ts → transports/local.test.ts} +316 -230
  254. package/src/{session/default-session-manager.ts → transports/local.ts} +138 -172
  255. package/src/transports/rpc.test.ts +82 -0
  256. package/src/transports/rpc.ts +665 -0
  257. package/src/transports/runtime-host-support.ts +86 -0
  258. package/src/types/config.ts +3 -2
  259. package/src/{session/utils/types.ts → types/session.ts} +18 -5
  260. package/src/types/sessions.ts +21 -0
  261. package/src/types/storage.ts +1 -6
  262. package/src/types.ts +25 -18
  263. package/dist/chat/chat-schema.d.ts.map +0 -1
  264. package/dist/input/file-indexer.d.ts.map +0 -1
  265. package/dist/input/index.d.ts.map +0 -1
  266. package/dist/input/mention-enricher.d.ts.map +0 -1
  267. package/dist/prompt/default-system.d.ts +0 -2
  268. package/dist/prompt/default-system.d.ts.map +0 -1
  269. package/dist/providers/local-provider-registry.d.ts.map +0 -1
  270. package/dist/providers/local-provider-service.d.ts.map +0 -1
  271. package/dist/runtime/checkpoint-hooks.d.ts.map +0 -1
  272. package/dist/runtime/hook-file-hooks.d.ts.map +0 -1
  273. package/dist/runtime/team-runtime-registry.d.ts +0 -13
  274. package/dist/runtime/team-runtime-registry.d.ts.map +0 -1
  275. package/dist/session/default-session-manager.d.ts.map +0 -1
  276. package/dist/session/session-agent-events.d.ts.map +0 -1
  277. package/dist/session/session-artifacts.d.ts.map +0 -1
  278. package/dist/session/session-config-builder.d.ts +0 -16
  279. package/dist/session/session-config-builder.d.ts.map +0 -1
  280. package/dist/session/session-host.d.ts +0 -15
  281. package/dist/session/session-host.d.ts.map +0 -1
  282. package/dist/session/session-manager.d.ts.map +0 -1
  283. package/dist/session/session-telemetry.d.ts.map +0 -1
  284. package/dist/session/utils/helpers.d.ts.map +0 -1
  285. package/dist/session/utils/types.d.ts.map +0 -1
  286. package/dist/session/utils/usage.d.ts.map +0 -1
  287. package/dist/session/workspace-manifest.d.ts.map +0 -1
  288. package/dist/storage/file-team-store.d.ts.map +0 -1
  289. package/dist/storage/provider-settings-legacy-migration.d.ts.map +0 -1
  290. package/dist/storage/provider-settings-manager.d.ts.map +0 -1
  291. package/dist/storage/sqlite-session-store.d.ts.map +0 -1
  292. package/dist/storage/sqlite-team-store.d.ts.map +0 -1
  293. package/dist/storage/team-store.d.ts.map +0 -1
  294. package/dist/team/delegated-agent.d.ts.map +0 -1
  295. package/dist/team/index.d.ts.map +0 -1
  296. package/dist/team/multi-agent.d.ts.map +0 -1
  297. package/dist/team/projections.d.ts.map +0 -1
  298. package/dist/team/runtime.d.ts.map +0 -1
  299. package/dist/team/spawn-agent-tool.d.ts.map +0 -1
  300. package/dist/team/subagent-prompts.d.ts.map +0 -1
  301. package/dist/team/team-tools.d.ts.map +0 -1
  302. package/dist/telemetry/ITelemetryAdapter.d.ts.map +0 -1
  303. package/dist/telemetry/OpenTelemetryAdapter.d.ts.map +0 -1
  304. package/dist/telemetry/OpenTelemetryProvider.d.ts.map +0 -1
  305. package/dist/telemetry/TelemetryLoggerSink.d.ts.map +0 -1
  306. package/dist/telemetry/TelemetryService.d.ts.map +0 -1
  307. package/dist/telemetry/core-events.d.ts.map +0 -1
  308. package/dist/telemetry/distinct-id.d.ts.map +0 -1
  309. package/dist/telemetry/index.d.ts.map +0 -1
  310. package/dist/tools/constants.d.ts.map +0 -1
  311. package/dist/tools/definitions.d.ts.map +0 -1
  312. package/dist/tools/executors/apply-patch-parser.d.ts.map +0 -1
  313. package/dist/tools/executors/apply-patch.d.ts.map +0 -1
  314. package/dist/tools/executors/bash.d.ts.map +0 -1
  315. package/dist/tools/executors/editor.d.ts.map +0 -1
  316. package/dist/tools/executors/file-read.d.ts.map +0 -1
  317. package/dist/tools/executors/index.d.ts.map +0 -1
  318. package/dist/tools/executors/search.d.ts.map +0 -1
  319. package/dist/tools/executors/web-fetch.d.ts.map +0 -1
  320. package/dist/tools/helpers.d.ts.map +0 -1
  321. package/dist/tools/index.d.ts.map +0 -1
  322. package/dist/tools/model-tool-routing.d.ts.map +0 -1
  323. package/dist/tools/presets.d.ts.map +0 -1
  324. package/dist/tools/schemas.d.ts.map +0 -1
  325. package/dist/tools/types.d.ts.map +0 -1
  326. package/src/prompt/default-system.ts +0 -21
  327. package/src/runtime/team-runtime-registry.ts +0 -43
  328. package/src/session/session-config-builder.ts +0 -126
  329. package/src/session/session-host.test.ts +0 -89
  330. package/src/session/session-host.ts +0 -213
  331. package/src/session/session-manager.ts +0 -74
  332. package/src/storage/artifact-store.ts +0 -1
  333. package/src/storage/session-store.ts +0 -1
  334. package/src/team/multi-agent.lifecycle.test.ts +0 -201
  335. package/src/tools/executors/file-read.test.ts +0 -49
  336. /package/dist/{tools → extensions/tools}/constants.d.ts +0 -0
  337. /package/dist/{tools → extensions/tools}/definitions.d.ts +0 -0
  338. /package/dist/{tools → extensions/tools}/executors/apply-patch-parser.d.ts +0 -0
  339. /package/dist/{tools → extensions/tools}/executors/apply-patch.d.ts +0 -0
  340. /package/dist/{tools → extensions/tools}/executors/bash.d.ts +0 -0
  341. /package/dist/{tools → extensions/tools}/executors/editor.d.ts +0 -0
  342. /package/dist/{tools → extensions/tools}/executors/file-read.d.ts +0 -0
  343. /package/dist/{tools → extensions/tools}/executors/index.d.ts +0 -0
  344. /package/dist/{tools → extensions/tools}/executors/search.d.ts +0 -0
  345. /package/dist/{tools → extensions/tools}/executors/web-fetch.d.ts +0 -0
  346. /package/dist/{tools → extensions/tools}/helpers.d.ts +0 -0
  347. /package/dist/{tools → extensions/tools}/index.d.ts +0 -0
  348. /package/dist/{tools → extensions/tools}/schemas.d.ts +0 -0
  349. /package/dist/{team → extensions/tools/team}/delegated-agent.d.ts +0 -0
  350. /package/dist/{team → extensions/tools/team}/index.d.ts +0 -0
  351. /package/dist/{team → extensions/tools/team}/projections.d.ts +0 -0
  352. /package/dist/{team → extensions/tools/team}/runtime.d.ts +0 -0
  353. /package/dist/{team → extensions/tools/team}/subagent-prompts.d.ts +0 -0
  354. /package/dist/{team → extensions/tools/team}/team-tools.d.ts +0 -0
  355. /package/dist/{session → runtime}/rpc-spawn-lease.d.ts +0 -0
  356. /package/dist/{providers → services/providers}/local-provider-registry.d.ts +0 -0
  357. /package/dist/{providers → services/providers}/local-provider-service.d.ts +0 -0
  358. /package/dist/{telemetry → services/telemetry}/ITelemetryAdapter.d.ts +0 -0
  359. /package/dist/{telemetry → services/telemetry}/OpenTelemetryAdapter.d.ts +0 -0
  360. /package/dist/{telemetry → services/telemetry}/OpenTelemetryProvider.d.ts +0 -0
  361. /package/dist/{telemetry → services/telemetry}/TelemetryLoggerSink.d.ts +0 -0
  362. /package/dist/{telemetry → services/telemetry}/TelemetryService.d.ts +0 -0
  363. /package/dist/{telemetry → services/telemetry}/core-events.d.ts +0 -0
  364. /package/dist/{telemetry → services/telemetry}/distinct-id.d.ts +0 -0
  365. /package/dist/{telemetry → services/telemetry}/index.d.ts +0 -0
  366. /package/dist/{input → services/workspace}/file-indexer.d.ts +0 -0
  367. /package/dist/{input → services/workspace}/index.d.ts +0 -0
  368. /package/dist/{input → services/workspace}/mention-enricher.d.ts +0 -0
  369. /package/dist/{session → services}/workspace-manifest.d.ts +0 -0
  370. /package/dist/{chat → types}/chat-schema.d.ts +0 -0
  371. /package/src/{tools → extensions/tools}/constants.ts +0 -0
  372. /package/src/{tools → extensions/tools}/definitions.test.ts +0 -0
  373. /package/src/{tools → extensions/tools}/executors/apply-patch-parser.ts +0 -0
  374. /package/src/{tools → extensions/tools}/executors/apply-patch.ts +0 -0
  375. /package/src/{tools → extensions/tools}/executors/bash.test.ts +0 -0
  376. /package/src/{tools → extensions/tools}/executors/bash.ts +0 -0
  377. /package/src/{tools → extensions/tools}/executors/editor.test.ts +0 -0
  378. /package/src/{tools → extensions/tools}/executors/editor.ts +0 -0
  379. /package/src/{tools → extensions/tools}/executors/index.ts +0 -0
  380. /package/src/{tools → extensions/tools}/executors/web-fetch.ts +0 -0
  381. /package/src/{tools → extensions/tools}/helpers.ts +0 -0
  382. /package/src/{tools → extensions/tools}/index.ts +0 -0
  383. /package/src/{tools → extensions/tools}/model-tool-routing.test.ts +0 -0
  384. /package/src/{tools → extensions/tools}/presets.test.ts +0 -0
  385. /package/src/{tools → extensions/tools}/schemas.ts +0 -0
  386. /package/src/{team → extensions/tools/team}/delegated-agent.ts +0 -0
  387. /package/src/{team → extensions/tools/team}/index.ts +0 -0
  388. /package/src/{team → extensions/tools/team}/projections.ts +0 -0
  389. /package/src/{team → extensions/tools/team}/runtime.ts +0 -0
  390. /package/src/{runtime → hooks}/checkpoint-hooks.test.ts +0 -0
  391. /package/src/{session → runtime}/runtime-oauth-token-manager.test.ts +0 -0
  392. /package/src/{providers → services/providers}/local-provider-registry.ts +0 -0
  393. /package/src/{providers → services/providers}/local-provider-service.test.ts +0 -0
  394. /package/src/{storage → services/storage}/index.ts +0 -0
  395. /package/src/{storage → services/storage}/provider-settings-manager.test.ts +0 -0
  396. /package/src/{telemetry → services/telemetry}/ITelemetryAdapter.ts +0 -0
  397. /package/src/{telemetry → services/telemetry}/OpenTelemetryAdapter.test.ts +0 -0
  398. /package/src/{telemetry → services/telemetry}/OpenTelemetryAdapter.ts +0 -0
  399. /package/src/{telemetry → services/telemetry}/OpenTelemetryProvider.test.ts +0 -0
  400. /package/src/{telemetry → services/telemetry}/OpenTelemetryProvider.ts +0 -0
  401. /package/src/{telemetry → services/telemetry}/TelemetryLoggerSink.test.ts +0 -0
  402. /package/src/{telemetry → services/telemetry}/TelemetryLoggerSink.ts +0 -0
  403. /package/src/{telemetry → services/telemetry}/TelemetryService.test.ts +0 -0
  404. /package/src/{telemetry → services/telemetry}/TelemetryService.ts +0 -0
  405. /package/src/{telemetry → services/telemetry}/core-events.ts +0 -0
  406. /package/src/{telemetry → services/telemetry}/distinct-id.test.ts +0 -0
  407. /package/src/{telemetry → services/telemetry}/distinct-id.ts +0 -0
  408. /package/src/{telemetry → services/telemetry}/index.ts +0 -0
  409. /package/src/{input → services/workspace}/file-indexer.d.ts +0 -0
  410. /package/src/{input → services/workspace}/index.ts +0 -0
  411. /package/src/{session → services}/workspace-manifest.ts +0 -0
  412. /package/src/{chat → types}/chat-schema.ts +0 -0
@@ -0,0 +1,125 @@
1
+ import * as fs from "node:fs/promises";
2
+ import * as os from "node:os";
3
+ import * as path from "node:path";
4
+ import { describe, expect, it } from "vitest";
5
+ import { createFileReadExecutor } from "./file-read";
6
+
7
+ describe("createFileReadExecutor", () => {
8
+ it("reads a file from an absolute path", async () => {
9
+ const dir = await fs.mkdtemp(path.join(os.tmpdir(), "agents-file-read-"));
10
+ const filePath = path.join(dir, "example.txt");
11
+ await fs.writeFile(filePath, "hello absolute path", "utf-8");
12
+
13
+ try {
14
+ const readFile = createFileReadExecutor();
15
+ const result = await readFile(
16
+ { path: filePath },
17
+ {
18
+ agentId: "agent-1",
19
+ conversationId: "conv-1",
20
+ iteration: 1,
21
+ },
22
+ );
23
+ expect(result).toBe("1 | hello absolute path");
24
+ } finally {
25
+ await fs.rm(dir, { recursive: true, force: true });
26
+ }
27
+ });
28
+
29
+ it("returns only the requested inclusive line range", async () => {
30
+ const dir = await fs.mkdtemp(path.join(os.tmpdir(), "agents-file-read-"));
31
+ const filePath = path.join(dir, "example.txt");
32
+ await fs.writeFile(filePath, "alpha\nbeta\ngamma\ndelta", "utf-8");
33
+
34
+ try {
35
+ const readFile = createFileReadExecutor();
36
+ const result = await readFile(
37
+ { path: filePath, start_line: 2, end_line: 3 },
38
+ {
39
+ agentId: "agent-1",
40
+ conversationId: "conv-1",
41
+ iteration: 1,
42
+ },
43
+ );
44
+ expect(result).toBe("2 | beta\n3 | gamma");
45
+ } finally {
46
+ await fs.rm(dir, { recursive: true, force: true });
47
+ }
48
+ });
49
+
50
+ it("returns image blocks for image files when the model supports images", async () => {
51
+ const dir = await fs.mkdtemp(path.join(os.tmpdir(), "agents-file-read-"));
52
+ const filePath = path.join(dir, "example.png");
53
+ const pngBytes = Buffer.from(
54
+ "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==",
55
+ "base64",
56
+ );
57
+ await fs.writeFile(filePath, pngBytes);
58
+
59
+ try {
60
+ const readFile = createFileReadExecutor();
61
+ const result = await readFile(
62
+ { path: filePath },
63
+ {
64
+ agentId: "agent-1",
65
+ conversationId: "conv-1",
66
+ iteration: 1,
67
+ metadata: {
68
+ modelSupportsImages: true,
69
+ },
70
+ },
71
+ );
72
+ expect(result).toEqual([
73
+ {
74
+ type: "text",
75
+ text: "Successfully read image",
76
+ },
77
+ {
78
+ type: "image",
79
+ data: pngBytes.toString("base64"),
80
+ mediaType: "image/png",
81
+ },
82
+ ]);
83
+ } finally {
84
+ await fs.rm(dir, { recursive: true, force: true });
85
+ }
86
+ });
87
+
88
+ it("returns image blocks for gif files when the model supports images", async () => {
89
+ const dir = await fs.mkdtemp(path.join(os.tmpdir(), "agents-file-read-"));
90
+ const filePath = path.join(dir, "example.gif");
91
+ const gifBytes = Buffer.from(
92
+ "R0lGODdhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=",
93
+ "base64",
94
+ );
95
+ await fs.writeFile(filePath, gifBytes);
96
+
97
+ try {
98
+ const readFile = createFileReadExecutor();
99
+ const result = await readFile(
100
+ { path: filePath },
101
+ {
102
+ agentId: "agent-1",
103
+ conversationId: "conv-1",
104
+ iteration: 1,
105
+ metadata: {
106
+ modelSupportsImages: true,
107
+ },
108
+ },
109
+ );
110
+ expect(result).toEqual([
111
+ {
112
+ type: "text",
113
+ text: "Successfully read image",
114
+ },
115
+ {
116
+ type: "image",
117
+ data: gifBytes.toString("base64"),
118
+ mediaType: "image/gif",
119
+ },
120
+ ]);
121
+ } finally {
122
+ await fs.rm(dir, { recursive: true, force: true });
123
+ }
124
+ });
125
+ });
@@ -10,6 +10,14 @@ import type { ToolContext } from "@clinebot/shared";
10
10
  import type { ReadFileRequest } from "../schemas";
11
11
  import type { FileReadExecutor } from "../types";
12
12
 
13
+ const IMAGE_MEDIA_TYPES = new Map<string, string>([
14
+ [".gif", "image/gif"],
15
+ [".png", "image/png"],
16
+ [".jpg", "image/jpeg"],
17
+ [".jpeg", "image/jpeg"],
18
+ [".webp", "image/webp"],
19
+ ]);
20
+
13
21
  /**
14
22
  * Options for the file read executor
15
23
  */
@@ -60,14 +68,13 @@ export function createFileReadExecutor(
60
68
  ...options,
61
69
  };
62
70
 
63
- return async (
64
- request: ReadFileRequest,
65
- _context: ToolContext,
66
- ): Promise<string> => {
71
+ return async (request: ReadFileRequest, context: ToolContext) => {
67
72
  const { path: filePath, start_line, end_line } = request;
68
73
  const resolvedPath = path.isAbsolute(filePath)
69
74
  ? path.normalize(filePath)
70
75
  : path.resolve(process.cwd(), filePath);
76
+ const extension = path.extname(resolvedPath).toLowerCase();
77
+ const imageMediaType = IMAGE_MEDIA_TYPES.get(extension);
71
78
 
72
79
  // Check if file exists
73
80
  const stat = await fs.stat(resolvedPath);
@@ -84,6 +91,24 @@ export function createFileReadExecutor(
84
91
  );
85
92
  }
86
93
 
94
+ if (imageMediaType) {
95
+ if (context.metadata?.modelSupportsImages !== true) {
96
+ throw new Error("Current model does not support image input");
97
+ }
98
+ const data = await fs.readFile(resolvedPath);
99
+ return [
100
+ {
101
+ type: "text",
102
+ text: "Successfully read image",
103
+ },
104
+ {
105
+ type: "image",
106
+ data: data.toString("base64"),
107
+ mediaType: imageMediaType,
108
+ },
109
+ ];
110
+ }
111
+
87
112
  // Read file content
88
113
  const content = await fs.readFile(resolvedPath, encoding);
89
114
  const allLines = content.split("\n");
@@ -7,7 +7,7 @@
7
7
  import * as fs from "node:fs/promises";
8
8
  import * as path from "node:path";
9
9
  import type { ToolContext } from "@clinebot/shared";
10
- import { getFileIndex } from "../../input";
10
+ import { getFileIndex } from "../../../services/workspace";
11
11
  import type { SearchExecutor } from "../types";
12
12
 
13
13
  /**
@@ -1,4 +1,4 @@
1
- import type { CoreAgentMode } from "../types/config";
1
+ import type { CoreAgentMode } from "../../types/config";
2
2
  import type { DefaultToolName, DefaultToolsConfig } from "./types";
3
3
 
4
4
  export interface ToolRoutingRule {
@@ -132,13 +132,12 @@ export const ToolPresets = {
132
132
  export type ToolPresetName = keyof typeof ToolPresets;
133
133
 
134
134
  export function resolveToolPresetName(options: {
135
- mode?: "act" | "plan";
136
- yolo?: boolean;
135
+ mode?: "act" | "plan" | "yolo";
137
136
  }): ToolPresetName {
138
137
  if (options.mode === "plan") {
139
138
  return "readonly";
140
139
  }
141
- return options.yolo === true ? "yolo" : "development";
140
+ return options.mode === "yolo" ? "yolo" : "development";
142
141
  }
143
142
 
144
143
  /**
@@ -0,0 +1,455 @@
1
+ import type { AgentEvent } from "@clinebot/shared";
2
+ import { describe, expect, it, vi } from "vitest";
3
+ import {
4
+ AgentTeamsRuntime,
5
+ type TeamEvent,
6
+ TeamMessageType,
7
+ } from "./multi-agent";
8
+
9
+ const { createAgentMock } = vi.hoisted(() => ({
10
+ createAgentMock: vi.fn(),
11
+ }));
12
+
13
+ vi.mock("@clinebot/agents", async () => {
14
+ const actual =
15
+ await vi.importActual<typeof import("@clinebot/agents")>(
16
+ "@clinebot/agents",
17
+ );
18
+
19
+ return {
20
+ ...actual,
21
+ createAgent: createAgentMock,
22
+ };
23
+ });
24
+
25
+ describe("AgentTeamsRuntime teammate lifecycle events", () => {
26
+ it("spawns teammates with a 10 minute API timeout", () => {
27
+ createAgentMock.mockReturnValueOnce({
28
+ abort: vi.fn(),
29
+ run: vi.fn(),
30
+ continue: vi.fn(),
31
+ canStartRun: vi.fn(() => true),
32
+ getAgentId: vi.fn(() => "teammate-1"),
33
+ getConversationId: vi.fn(() => "conv-1"),
34
+ getMessages: vi.fn(() => []),
35
+ });
36
+ const runtime = new AgentTeamsRuntime({
37
+ teamName: "test-team",
38
+ });
39
+
40
+ runtime.spawnTeammate({
41
+ agentId: "python-poet",
42
+ config: {
43
+ providerId: "anthropic",
44
+ modelId: "claude-sonnet-4-5-20250929",
45
+ systemPrompt: "Write concise Python-focused haiku",
46
+ tools: [],
47
+ },
48
+ });
49
+
50
+ expect(createAgentMock).toHaveBeenCalledWith(
51
+ expect.objectContaining({
52
+ apiTimeoutMs: 10 * 60 * 1000,
53
+ }),
54
+ );
55
+ });
56
+
57
+ it("does not emit task_start when teammate is already busy", async () => {
58
+ const events: TeamEvent[] = [];
59
+ createAgentMock.mockReturnValueOnce({
60
+ abort: vi.fn(),
61
+ run: vi.fn(),
62
+ continue: vi.fn(),
63
+ canStartRun: vi.fn(() => false),
64
+ getAgentId: vi.fn(() => "teammate-1"),
65
+ getConversationId: vi.fn(() => "conv-1"),
66
+ getMessages: vi.fn(() => []),
67
+ });
68
+ const runtime = new AgentTeamsRuntime({
69
+ teamName: "test-team",
70
+ onTeamEvent: (event) => events.push(event),
71
+ });
72
+
73
+ runtime.spawnTeammate({
74
+ agentId: "python-poet",
75
+ config: {
76
+ providerId: "anthropic",
77
+ modelId: "claude-sonnet-4-5-20250929",
78
+ systemPrompt: "Write concise Python-focused haiku",
79
+ maxIterations: 7,
80
+ tools: [],
81
+ },
82
+ });
83
+
84
+ await expect(
85
+ runtime.routeToTeammate("python-poet", "write something"),
86
+ ).rejects.toThrow(
87
+ "Cannot start a new run while another run is already in progress",
88
+ );
89
+ expect(
90
+ events.some((event) => event.type === TeamMessageType.TaskStart),
91
+ ).toBe(false);
92
+ });
93
+
94
+ it("emits teammate_spawned with lifecycle payload", () => {
95
+ const events: TeamEvent[] = [];
96
+ createAgentMock.mockReturnValueOnce({
97
+ abort: vi.fn(),
98
+ run: vi.fn(),
99
+ continue: vi.fn(),
100
+ canStartRun: vi.fn(() => true),
101
+ getAgentId: vi.fn(() => "teammate-1"),
102
+ getConversationId: vi.fn(() => "conv-1"),
103
+ getMessages: vi.fn(() => []),
104
+ });
105
+ const runtime = new AgentTeamsRuntime({
106
+ teamName: "test-team",
107
+ onTeamEvent: (event) => events.push(event),
108
+ });
109
+
110
+ runtime.spawnTeammate({
111
+ agentId: "python-poet",
112
+ config: {
113
+ providerId: "anthropic",
114
+ modelId: "claude-sonnet-4-5-20250929",
115
+ systemPrompt: "Write concise Python-focused haiku",
116
+ maxIterations: 7,
117
+ tools: [],
118
+ },
119
+ });
120
+
121
+ expect(events).toContainEqual({
122
+ type: TeamMessageType.TeammateSpawned,
123
+ agentId: "python-poet",
124
+ role: undefined,
125
+ teammate: {
126
+ rolePrompt: "Write concise Python-focused haiku",
127
+ modelId: "claude-sonnet-4-5-20250929",
128
+ maxIterations: 7,
129
+ runtimeAgentId: "teammate-1",
130
+ conversationId: "conv-1",
131
+ parentAgentId: null,
132
+ },
133
+ });
134
+ });
135
+
136
+ it("swallows abort-like shutdown errors from teammates", () => {
137
+ const events: TeamEvent[] = [];
138
+ createAgentMock.mockReturnValueOnce({
139
+ abort: vi.fn(() => {
140
+ throw new DOMException("This operation was aborted", "AbortError");
141
+ }),
142
+ run: vi.fn(),
143
+ continue: vi.fn(),
144
+ canStartRun: vi.fn(() => true),
145
+ getAgentId: vi.fn(() => "teammate-1"),
146
+ getConversationId: vi.fn(() => "conv-1"),
147
+ getMessages: vi.fn(() => []),
148
+ });
149
+ const runtime = new AgentTeamsRuntime({
150
+ teamName: "test-team",
151
+ onTeamEvent: (event) => events.push(event),
152
+ });
153
+
154
+ runtime.spawnTeammate({
155
+ agentId: "python-poet",
156
+ config: {
157
+ providerId: "anthropic",
158
+ modelId: "claude-sonnet-4-5-20250929",
159
+ systemPrompt: "Write concise Python-focused haiku",
160
+ tools: [],
161
+ },
162
+ });
163
+
164
+ expect(() =>
165
+ runtime.shutdownTeammate("python-poet", "manual_restart"),
166
+ ).not.toThrow();
167
+ expect(runtime.getSnapshot().members).toContainEqual(
168
+ expect.objectContaining({
169
+ agentId: "python-poet",
170
+ status: "stopped",
171
+ }),
172
+ );
173
+ expect(events).toContainEqual({
174
+ type: TeamMessageType.TeammateShutdown,
175
+ agentId: "python-poet",
176
+ reason: "manual_restart",
177
+ });
178
+ });
179
+
180
+ it("prepends unread mailbox notification to teammate message", async () => {
181
+ let routedMessage: string | undefined;
182
+ createAgentMock.mockReturnValueOnce({
183
+ abort: vi.fn(),
184
+ run: vi.fn(async (message) => {
185
+ routedMessage = message;
186
+ return {
187
+ text: "Task completed",
188
+ iterations: 1,
189
+ finishReason: "end_turn",
190
+ durationMs: 100,
191
+ usage: {
192
+ inputTokens: 10,
193
+ outputTokens: 20,
194
+ cacheReadTokens: 0,
195
+ cacheWriteTokens: 0,
196
+ totalCost: 0,
197
+ },
198
+ messages: [],
199
+ };
200
+ }),
201
+ continue: vi.fn(),
202
+ canStartRun: vi.fn(() => true),
203
+ getAgentId: vi.fn(() => "teammate-1"),
204
+ getConversationId: vi.fn(() => "conv-1"),
205
+ getMessages: vi.fn(() => []),
206
+ });
207
+ const runtime = new AgentTeamsRuntime({
208
+ teamName: "test-team",
209
+ });
210
+
211
+ runtime.spawnTeammate({
212
+ agentId: "alice",
213
+ config: {
214
+ providerId: "anthropic",
215
+ modelId: "claude-sonnet-4-5-20250929",
216
+ systemPrompt: "Helper teammate",
217
+ tools: [],
218
+ },
219
+ });
220
+
221
+ // Send message from lead to alice
222
+ runtime.sendMessage(
223
+ "lead",
224
+ "alice",
225
+ "Status check",
226
+ "How is your work going?",
227
+ );
228
+
229
+ // Route task to alice
230
+ await runtime.routeToTeammate("alice", "Complete your task");
231
+
232
+ // Verify the routed message includes mailbox notification
233
+ expect(routedMessage).toBeDefined();
234
+ expect(routedMessage).toContain("[MAILBOX]");
235
+ expect(routedMessage).toContain("You have 1 unread message(s)");
236
+ expect(routedMessage).toContain(
237
+ "Message from lead | subject: Status check",
238
+ );
239
+ expect(routedMessage).toContain("How is your work going?");
240
+ expect(routedMessage).toContain("Complete your task");
241
+
242
+ // Verify message is marked as read
243
+ const unreadAfter = runtime.listMailbox("alice", { unreadOnly: true });
244
+ expect(unreadAfter).toHaveLength(0);
245
+ });
246
+
247
+ it("does not prepend notification when no unread mail", async () => {
248
+ let routedMessage: string | undefined;
249
+ createAgentMock.mockReturnValueOnce({
250
+ abort: vi.fn(),
251
+ run: vi.fn(async (message) => {
252
+ routedMessage = message;
253
+ return {
254
+ text: "Task completed",
255
+ iterations: 1,
256
+ finishReason: "end_turn",
257
+ durationMs: 100,
258
+ usage: {
259
+ inputTokens: 10,
260
+ outputTokens: 20,
261
+ cacheReadTokens: 0,
262
+ cacheWriteTokens: 0,
263
+ totalCost: 0,
264
+ },
265
+ messages: [],
266
+ };
267
+ }),
268
+ continue: vi.fn(),
269
+ canStartRun: vi.fn(() => true),
270
+ getAgentId: vi.fn(() => "teammate-1"),
271
+ getConversationId: vi.fn(() => "conv-1"),
272
+ getMessages: vi.fn(() => []),
273
+ });
274
+ const runtime = new AgentTeamsRuntime({
275
+ teamName: "test-team",
276
+ });
277
+
278
+ runtime.spawnTeammate({
279
+ agentId: "bob",
280
+ config: {
281
+ providerId: "anthropic",
282
+ modelId: "claude-sonnet-4-5-20250929",
283
+ systemPrompt: "Helper teammate",
284
+ tools: [],
285
+ },
286
+ });
287
+
288
+ // Route task to bob with no prior messages
289
+ await runtime.routeToTeammate("bob", "Complete your task");
290
+
291
+ // Verify the routed message does not contain mailbox notification
292
+ expect(routedMessage).toBeDefined();
293
+ expect(routedMessage).toBe("Complete your task");
294
+ expect(routedMessage).not.toContain("[MAILBOX]");
295
+ });
296
+
297
+ it("queues steer message notification when recipient is running", () => {
298
+ let consumePendingMessage: (() => string | undefined) | undefined;
299
+ createAgentMock.mockImplementationOnce((config) => {
300
+ consumePendingMessage = config.consumePendingUserMessage;
301
+ return {
302
+ abort: vi.fn(),
303
+ run: vi.fn(),
304
+ continue: vi.fn(),
305
+ canStartRun: vi.fn(() => true),
306
+ getAgentId: vi.fn(() => "teammate-1"),
307
+ getConversationId: vi.fn(() => "conv-1"),
308
+ getMessages: vi.fn(() => []),
309
+ };
310
+ });
311
+ const runtime = new AgentTeamsRuntime({
312
+ teamName: "test-team",
313
+ });
314
+
315
+ runtime.spawnTeammate({
316
+ agentId: "charlie",
317
+ config: {
318
+ providerId: "anthropic",
319
+ modelId: "claude-sonnet-4-5-20250929",
320
+ systemPrompt: "Helper teammate",
321
+ tools: [],
322
+ },
323
+ });
324
+
325
+ // Simulate teammate is running by incrementing runningCount
326
+ const runtimeMembers = (
327
+ runtime as unknown as { members: Map<string, { runningCount: number }> }
328
+ ).members;
329
+ const member = runtimeMembers.get("charlie");
330
+ if (member) {
331
+ member.runningCount = 1;
332
+ }
333
+
334
+ // Send message from lead while charlie is running
335
+ runtime.sendMessage("lead", "charlie", "urgent update", "Fix the bug now!");
336
+
337
+ // Verify steer message is queued
338
+ expect(consumePendingMessage).toBeDefined();
339
+ const steerMsg = consumePendingMessage?.();
340
+ expect(steerMsg).toBeDefined();
341
+ expect(steerMsg).toContain("[MAILBOX]");
342
+ expect(steerMsg).toContain("lead");
343
+ expect(steerMsg).toContain("urgent update");
344
+ expect(steerMsg).toContain("team_read_mailbox");
345
+
346
+ // Verify consuming again returns undefined
347
+ expect(consumePendingMessage?.()).toBeUndefined();
348
+ });
349
+
350
+ it("does not queue steer message when recipient is idle", () => {
351
+ let consumePendingMessage: (() => string | undefined) | undefined;
352
+ createAgentMock.mockImplementationOnce((config) => {
353
+ consumePendingMessage = config.consumePendingUserMessage;
354
+ return {
355
+ abort: vi.fn(),
356
+ run: vi.fn(),
357
+ continue: vi.fn(),
358
+ canStartRun: vi.fn(() => true),
359
+ getAgentId: vi.fn(() => "teammate-1"),
360
+ getConversationId: vi.fn(() => "conv-1"),
361
+ getMessages: vi.fn(() => []),
362
+ };
363
+ });
364
+ const runtime = new AgentTeamsRuntime({
365
+ teamName: "test-team",
366
+ });
367
+
368
+ runtime.spawnTeammate({
369
+ agentId: "diana",
370
+ config: {
371
+ providerId: "anthropic",
372
+ modelId: "claude-sonnet-4-5-20250929",
373
+ systemPrompt: "Helper teammate",
374
+ tools: [],
375
+ },
376
+ });
377
+
378
+ // Send message from lead while diana is idle (runningCount = 0)
379
+ runtime.sendMessage("lead", "diana", "hello", "Hi there");
380
+
381
+ // Verify no steer message is queued
382
+ expect(consumePendingMessage?.()).toBeUndefined();
383
+
384
+ // Message should still be in mailbox for next route
385
+ const mailbox = runtime.listMailbox("diana", { unreadOnly: true });
386
+ expect(mailbox).toHaveLength(1);
387
+ expect(mailbox[0].subject).toBe("hello");
388
+ });
389
+
390
+ it("includes tool and run error details in run_progress activity", async () => {
391
+ const events: TeamEvent[] = [];
392
+ let wrappedOnEvent: ((event: AgentEvent) => void) | undefined;
393
+ createAgentMock.mockImplementationOnce((config) => {
394
+ wrappedOnEvent = config.onEvent;
395
+ return {
396
+ abort: vi.fn(),
397
+ run: vi.fn(async () => {
398
+ wrappedOnEvent?.({
399
+ type: "content_end",
400
+ contentType: "tool",
401
+ toolName: "team_mission_log",
402
+ error: "RPC backend returned 500 while appending mission log",
403
+ });
404
+ wrappedOnEvent?.({
405
+ type: "error",
406
+ error: new Error("API request timed out after 120000ms"),
407
+ recoverable: false,
408
+ iteration: 11,
409
+ });
410
+ throw new Error("API request timed out after 120000ms");
411
+ }),
412
+ continue: vi.fn(),
413
+ canStartRun: vi.fn(() => true),
414
+ getAgentId: vi.fn(() => "teammate-1"),
415
+ getConversationId: vi.fn(() => "conv-1"),
416
+ getMessages: vi.fn(() => []),
417
+ };
418
+ });
419
+ const runtime = new AgentTeamsRuntime({
420
+ teamName: "test-team",
421
+ onTeamEvent: (event) => events.push(event),
422
+ });
423
+
424
+ runtime.spawnTeammate({
425
+ agentId: "providers-investigator",
426
+ config: {
427
+ providerId: "anthropic",
428
+ modelId: "claude-sonnet-4-5-20250929",
429
+ systemPrompt: "Investigate providers thoroughly",
430
+ tools: [],
431
+ },
432
+ });
433
+
434
+ const run = runtime.startTeammateRun(
435
+ "providers-investigator",
436
+ "Investigate providers",
437
+ );
438
+ const settled = await runtime.awaitRun(run.id);
439
+
440
+ expect(settled.status).toBe("failed");
441
+ expect(events).toContainEqual(
442
+ expect.objectContaining({
443
+ type: TeamMessageType.RunProgress,
444
+ message:
445
+ "tool_team_mission_log_error: RPC backend returned 500 while appending mission log",
446
+ }),
447
+ );
448
+ expect(events).toContainEqual(
449
+ expect.objectContaining({
450
+ type: TeamMessageType.RunProgress,
451
+ message: "run_error: API request timed out after 120000ms",
452
+ }),
453
+ );
454
+ });
455
+ });