agent-relay 2.0.29 → 2.0.32

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 (894) hide show
  1. package/README.md +19 -0
  2. package/dist/index.cjs +85691 -0
  3. package/dist/src/bridge/index.d.ts.map +1 -0
  4. package/dist/src/bridge/index.js.map +1 -0
  5. package/dist/src/cli/commands/doctor.d.ts +2 -0
  6. package/dist/src/cli/commands/doctor.d.ts.map +1 -0
  7. package/dist/src/cli/commands/doctor.js +451 -0
  8. package/dist/src/cli/commands/doctor.js.map +1 -0
  9. package/dist/src/cli/index.d.ts.map +1 -0
  10. package/dist/src/cli/index.js +29 -1
  11. package/dist/src/cli/index.js.map +1 -0
  12. package/dist/src/config/relay-config.d.ts.map +1 -0
  13. package/dist/src/config/relay-config.js.map +1 -0
  14. package/dist/src/continuity/index.d.ts.map +1 -0
  15. package/dist/src/continuity/index.js.map +1 -0
  16. package/dist/src/daemon/index.d.ts.map +1 -0
  17. package/dist/src/daemon/index.js.map +1 -0
  18. package/dist/src/health-worker-manager.d.ts.map +1 -0
  19. package/dist/src/health-worker-manager.js.map +1 -0
  20. package/dist/src/health-worker.d.ts.map +1 -0
  21. package/dist/src/health-worker.js.map +1 -0
  22. package/dist/src/hooks/index.d.ts.map +1 -0
  23. package/dist/src/hooks/index.js.map +1 -0
  24. package/dist/src/index.d.ts.map +1 -0
  25. package/dist/src/index.js.map +1 -0
  26. package/dist/src/memory/index.d.ts.map +1 -0
  27. package/dist/src/memory/index.js.map +1 -0
  28. package/dist/src/policy/index.d.ts.map +1 -0
  29. package/dist/src/policy/index.js.map +1 -0
  30. package/dist/src/protocol/index.d.ts.map +1 -0
  31. package/dist/src/protocol/index.js.map +1 -0
  32. package/dist/src/resiliency/index.d.ts.map +1 -0
  33. package/dist/src/resiliency/index.js.map +1 -0
  34. package/dist/src/shared/cli-auth-config.d.ts.map +1 -0
  35. package/dist/src/shared/cli-auth-config.js.map +1 -0
  36. package/dist/src/state/index.d.ts.map +1 -0
  37. package/dist/src/state/index.js.map +1 -0
  38. package/dist/src/storage/index.d.ts.map +1 -0
  39. package/dist/src/storage/index.js.map +1 -0
  40. package/dist/src/trajectory/index.d.ts.map +1 -0
  41. package/dist/src/trajectory/index.js.map +1 -0
  42. package/dist/src/utils/index.d.ts.map +1 -0
  43. package/dist/src/utils/index.js.map +1 -0
  44. package/dist/src/wrapper/index.d.ts.map +1 -0
  45. package/dist/src/wrapper/index.js.map +1 -0
  46. package/package.json +83 -20
  47. package/packages/api-types/dist/index.d.ts.map +1 -0
  48. package/packages/api-types/dist/index.js.map +1 -0
  49. package/packages/api-types/dist/schemas/agent.d.ts.map +1 -0
  50. package/packages/api-types/dist/schemas/agent.js.map +1 -0
  51. package/packages/api-types/dist/schemas/api.d.ts.map +1 -0
  52. package/packages/api-types/dist/schemas/api.js.map +1 -0
  53. package/packages/api-types/dist/schemas/decision.d.ts.map +1 -0
  54. package/packages/api-types/dist/schemas/decision.js.map +1 -0
  55. package/packages/api-types/dist/schemas/fleet.d.ts.map +1 -0
  56. package/packages/api-types/dist/schemas/fleet.js.map +1 -0
  57. package/packages/api-types/dist/schemas/history.d.ts.map +1 -0
  58. package/packages/api-types/dist/schemas/history.js.map +1 -0
  59. package/packages/api-types/dist/schemas/index.d.ts.map +1 -0
  60. package/packages/api-types/dist/schemas/index.js.map +1 -0
  61. package/packages/api-types/dist/schemas/message.d.ts.map +1 -0
  62. package/packages/api-types/dist/schemas/message.js.map +1 -0
  63. package/packages/api-types/dist/schemas/session.d.ts.map +1 -0
  64. package/packages/api-types/dist/schemas/session.js.map +1 -0
  65. package/packages/api-types/dist/schemas/task.d.ts.map +1 -0
  66. package/packages/api-types/dist/schemas/task.js.map +1 -0
  67. package/packages/api-types/package.json +1 -1
  68. package/packages/api-types/src/index.ts +22 -0
  69. package/packages/api-types/src/schemas/agent.test.ts +164 -0
  70. package/packages/api-types/src/schemas/agent.ts +110 -0
  71. package/packages/api-types/src/schemas/api.test.ts +372 -0
  72. package/packages/api-types/src/schemas/api.ts +194 -0
  73. package/packages/api-types/src/schemas/decision.test.ts +324 -0
  74. package/packages/api-types/src/schemas/decision.ts +136 -0
  75. package/packages/api-types/src/schemas/fleet.test.ts +212 -0
  76. package/packages/api-types/src/schemas/fleet.ts +83 -0
  77. package/packages/api-types/src/schemas/history.test.ts +242 -0
  78. package/packages/api-types/src/schemas/history.ts +84 -0
  79. package/packages/api-types/src/schemas/index.ts +148 -0
  80. package/packages/api-types/src/schemas/message.test.ts +192 -0
  81. package/packages/api-types/src/schemas/message.ts +98 -0
  82. package/packages/api-types/src/schemas/session.test.ts +104 -0
  83. package/packages/api-types/src/schemas/session.ts +40 -0
  84. package/packages/api-types/src/schemas/task.test.ts +192 -0
  85. package/packages/api-types/src/schemas/task.ts +78 -0
  86. package/packages/api-types/tsconfig.json +19 -0
  87. package/packages/api-types/vitest.config.ts +9 -0
  88. package/packages/benchmark/README.md +200 -0
  89. package/packages/benchmark/datasets/coding-tasks.yaml +127 -0
  90. package/packages/benchmark/datasets/coordination-tasks.yaml +122 -0
  91. package/packages/benchmark/dist/benchmark.d.ts +47 -0
  92. package/packages/benchmark/dist/benchmark.d.ts.map +1 -0
  93. package/packages/benchmark/dist/benchmark.js +224 -0
  94. package/packages/benchmark/dist/benchmark.js.map +1 -0
  95. package/packages/benchmark/dist/cli.d.ts +8 -0
  96. package/packages/benchmark/dist/cli.d.ts.map +1 -0
  97. package/packages/benchmark/dist/cli.js +185 -0
  98. package/packages/benchmark/dist/cli.js.map +1 -0
  99. package/packages/benchmark/dist/harbor.d.ts +53 -0
  100. package/packages/benchmark/dist/harbor.d.ts.map +1 -0
  101. package/packages/benchmark/dist/harbor.js +127 -0
  102. package/packages/benchmark/dist/harbor.js.map +1 -0
  103. package/packages/benchmark/dist/index.d.ts +48 -0
  104. package/packages/benchmark/dist/index.d.ts.map +1 -0
  105. package/packages/benchmark/dist/index.js +50 -0
  106. package/packages/benchmark/dist/index.js.map +1 -0
  107. package/packages/benchmark/dist/runners/base.d.ts +63 -0
  108. package/packages/benchmark/dist/runners/base.d.ts.map +1 -0
  109. package/packages/benchmark/dist/runners/base.js +155 -0
  110. package/packages/benchmark/dist/runners/base.js.map +1 -0
  111. package/packages/benchmark/dist/runners/index.d.ts +10 -0
  112. package/packages/benchmark/dist/runners/index.d.ts.map +1 -0
  113. package/packages/benchmark/dist/runners/index.js +10 -0
  114. package/packages/benchmark/dist/runners/index.js.map +1 -0
  115. package/packages/benchmark/dist/runners/single.d.ts +19 -0
  116. package/packages/benchmark/dist/runners/single.d.ts.map +1 -0
  117. package/packages/benchmark/dist/runners/single.js +111 -0
  118. package/packages/benchmark/dist/runners/single.js.map +1 -0
  119. package/packages/benchmark/dist/runners/subagent.d.ts +32 -0
  120. package/packages/benchmark/dist/runners/subagent.d.ts.map +1 -0
  121. package/packages/benchmark/dist/runners/subagent.js +212 -0
  122. package/packages/benchmark/dist/runners/subagent.js.map +1 -0
  123. package/packages/benchmark/dist/runners/swarm.d.ts +36 -0
  124. package/packages/benchmark/dist/runners/swarm.d.ts.map +1 -0
  125. package/packages/benchmark/dist/runners/swarm.js +273 -0
  126. package/packages/benchmark/dist/runners/swarm.js.map +1 -0
  127. package/packages/benchmark/dist/types.d.ts +178 -0
  128. package/packages/benchmark/dist/types.d.ts.map +1 -0
  129. package/packages/benchmark/dist/types.js +16 -0
  130. package/packages/benchmark/dist/types.js.map +1 -0
  131. package/packages/benchmark/package.json +80 -0
  132. package/packages/benchmark/src/benchmark.ts +298 -0
  133. package/packages/benchmark/src/cli.ts +240 -0
  134. package/packages/benchmark/src/harbor.ts +170 -0
  135. package/packages/benchmark/src/index.ts +73 -0
  136. package/packages/benchmark/src/runners/base.ts +204 -0
  137. package/packages/benchmark/src/runners/index.ts +10 -0
  138. package/packages/benchmark/src/runners/single.ts +121 -0
  139. package/packages/benchmark/src/runners/subagent.ts +240 -0
  140. package/packages/benchmark/src/runners/swarm.ts +326 -0
  141. package/packages/benchmark/src/types.ts +205 -0
  142. package/packages/benchmark/tsconfig.json +20 -0
  143. package/packages/bridge/dist/index.d.ts.map +1 -0
  144. package/packages/bridge/dist/index.js.map +1 -0
  145. package/packages/bridge/dist/multi-project-client.d.ts.map +1 -0
  146. package/packages/bridge/dist/multi-project-client.js.map +1 -0
  147. package/packages/bridge/dist/shadow-cli.d.ts.map +1 -0
  148. package/packages/bridge/dist/shadow-cli.js.map +1 -0
  149. package/packages/bridge/dist/spawner.d.ts.map +1 -0
  150. package/packages/bridge/dist/spawner.js +10 -2
  151. package/packages/bridge/dist/spawner.js.map +1 -0
  152. package/packages/bridge/dist/types.d.ts.map +1 -0
  153. package/packages/bridge/dist/types.js.map +1 -0
  154. package/packages/bridge/dist/utils.d.ts.map +1 -0
  155. package/packages/bridge/dist/utils.js.map +1 -0
  156. package/packages/bridge/package.json +8 -8
  157. package/packages/bridge/src/index.ts +25 -0
  158. package/packages/bridge/src/multi-project-client.test.ts +340 -0
  159. package/packages/bridge/src/multi-project-client.ts +469 -0
  160. package/packages/bridge/src/shadow-cli.ts +95 -0
  161. package/packages/bridge/src/spawner-mcp.test.ts +505 -0
  162. package/packages/bridge/src/spawner.ts +1724 -0
  163. package/packages/bridge/src/types.ts +145 -0
  164. package/packages/bridge/src/utils.test.ts +98 -0
  165. package/packages/bridge/src/utils.ts +67 -0
  166. package/packages/bridge/tsconfig.json +29 -0
  167. package/packages/bridge/vitest.config.ts +9 -0
  168. package/packages/cli-tester/dist/index.d.ts.map +1 -0
  169. package/packages/cli-tester/dist/index.js.map +1 -0
  170. package/packages/cli-tester/dist/utils/credential-check.d.ts.map +1 -0
  171. package/packages/cli-tester/dist/utils/credential-check.js.map +1 -0
  172. package/packages/cli-tester/dist/utils/socket-client.d.ts.map +1 -0
  173. package/packages/cli-tester/dist/utils/socket-client.js.map +1 -0
  174. package/packages/cli-tester/docker/Dockerfile +61 -0
  175. package/packages/cli-tester/docker/docker-compose.yml +71 -0
  176. package/packages/cli-tester/package.json +1 -1
  177. package/packages/cli-tester/src/index.ts +40 -0
  178. package/packages/cli-tester/src/utils/credential-check.ts +284 -0
  179. package/packages/cli-tester/src/utils/socket-client.ts +211 -0
  180. package/packages/cli-tester/tests/credential-check.test.ts +56 -0
  181. package/packages/cli-tester/tsconfig.json +11 -0
  182. package/packages/config/dist/agent-config.d.ts.map +1 -0
  183. package/packages/config/dist/agent-config.js.map +1 -0
  184. package/packages/config/dist/bridge-config.d.ts.map +1 -0
  185. package/packages/config/dist/bridge-config.js.map +1 -0
  186. package/packages/config/dist/bridge-utils.d.ts.map +1 -0
  187. package/packages/config/dist/bridge-utils.js.map +1 -0
  188. package/packages/config/dist/cli-auth-config.d.ts.map +1 -0
  189. package/packages/config/dist/cli-auth-config.js.map +1 -0
  190. package/packages/config/dist/cloud-config.d.ts.map +1 -0
  191. package/packages/config/dist/cloud-config.js.map +1 -0
  192. package/packages/config/dist/index.d.ts.map +1 -0
  193. package/packages/config/dist/index.js.map +1 -0
  194. package/packages/config/dist/project-namespace.d.ts.map +1 -0
  195. package/packages/config/dist/project-namespace.js.map +1 -0
  196. package/packages/config/dist/relay-config.d.ts.map +1 -0
  197. package/packages/config/dist/relay-config.js.map +1 -0
  198. package/packages/config/dist/relay-file-writer.d.ts.map +1 -0
  199. package/packages/config/dist/relay-file-writer.js.map +1 -0
  200. package/packages/config/dist/schemas.d.ts.map +1 -0
  201. package/packages/config/dist/schemas.js.map +1 -0
  202. package/packages/config/dist/shadow-config.d.ts.map +1 -0
  203. package/packages/config/dist/shadow-config.js.map +1 -0
  204. package/packages/config/dist/teams-config.d.ts.map +1 -0
  205. package/packages/config/dist/teams-config.js.map +1 -0
  206. package/packages/config/dist/trajectory-config.d.ts.map +1 -0
  207. package/packages/config/dist/trajectory-config.js.map +1 -0
  208. package/packages/config/package.json +2 -2
  209. package/packages/config/src/agent-config.test.ts +245 -0
  210. package/packages/config/src/agent-config.ts +160 -0
  211. package/packages/config/src/bridge-config.test.ts +132 -0
  212. package/packages/config/src/bridge-config.ts +189 -0
  213. package/packages/config/src/bridge-utils.ts +59 -0
  214. package/packages/config/src/cli-auth-config.ts +548 -0
  215. package/packages/config/src/cloud-config.ts +208 -0
  216. package/packages/config/src/index.ts +12 -0
  217. package/packages/config/src/project-namespace.ts +344 -0
  218. package/packages/config/src/relay-config.test.ts +51 -0
  219. package/packages/config/src/relay-config.ts +36 -0
  220. package/packages/config/src/relay-file-writer.test.ts +351 -0
  221. package/packages/config/src/relay-file-writer.ts +508 -0
  222. package/packages/config/src/schemas.test.ts +59 -0
  223. package/packages/config/src/schemas.ts +201 -0
  224. package/packages/config/src/shadow-config.ts +205 -0
  225. package/packages/config/src/teams-config.ts +135 -0
  226. package/packages/config/src/trajectory-config.ts +222 -0
  227. package/packages/config/tsconfig.json +21 -0
  228. package/packages/config/vitest.config.ts +9 -0
  229. package/packages/continuity/dist/formatter.d.ts.map +1 -0
  230. package/packages/continuity/dist/formatter.js.map +1 -0
  231. package/packages/continuity/dist/handoff-store.d.ts.map +1 -0
  232. package/packages/continuity/dist/handoff-store.js.map +1 -0
  233. package/packages/continuity/dist/index.d.ts.map +1 -0
  234. package/packages/continuity/dist/index.js.map +1 -0
  235. package/packages/continuity/dist/ledger-store.d.ts.map +1 -0
  236. package/packages/continuity/dist/ledger-store.js.map +1 -0
  237. package/packages/continuity/dist/manager.d.ts.map +1 -0
  238. package/packages/continuity/dist/manager.js.map +1 -0
  239. package/packages/continuity/dist/parser.d.ts.map +1 -0
  240. package/packages/continuity/dist/parser.js.map +1 -0
  241. package/packages/continuity/dist/types.d.ts.map +1 -0
  242. package/packages/continuity/dist/types.js.map +1 -0
  243. package/packages/continuity/package.json +1 -1
  244. package/packages/continuity/src/formatter.ts +371 -0
  245. package/packages/continuity/src/handoff-store.ts +523 -0
  246. package/packages/continuity/src/index.ts +9 -0
  247. package/packages/continuity/src/ledger-store.ts +594 -0
  248. package/packages/continuity/src/manager.test.ts +291 -0
  249. package/packages/continuity/src/manager.ts +774 -0
  250. package/packages/continuity/src/parser.test.ts +292 -0
  251. package/packages/continuity/src/parser.ts +680 -0
  252. package/packages/continuity/src/types.ts +211 -0
  253. package/packages/continuity/tsconfig.json +21 -0
  254. package/packages/continuity/vitest.config.ts +9 -0
  255. package/packages/daemon/dist/agent-manager.d.ts.map +1 -0
  256. package/packages/daemon/dist/agent-manager.js.map +1 -0
  257. package/packages/daemon/dist/agent-registry.d.ts.map +1 -0
  258. package/packages/daemon/dist/agent-registry.js.map +1 -0
  259. package/packages/daemon/dist/agent-signing.d.ts.map +1 -0
  260. package/packages/daemon/dist/agent-signing.js.map +1 -0
  261. package/packages/daemon/dist/api.d.ts.map +1 -0
  262. package/packages/daemon/dist/api.js.map +1 -0
  263. package/packages/daemon/dist/auth.d.ts.map +1 -0
  264. package/packages/daemon/dist/auth.js.map +1 -0
  265. package/packages/daemon/dist/channel-membership-store.d.ts.map +1 -0
  266. package/packages/daemon/dist/channel-membership-store.js.map +1 -0
  267. package/packages/daemon/dist/cli-auth.d.ts.map +1 -0
  268. package/packages/daemon/dist/cli-auth.js.map +1 -0
  269. package/packages/daemon/dist/cloud-sync.d.ts.map +1 -0
  270. package/packages/daemon/dist/cloud-sync.js.map +1 -0
  271. package/packages/daemon/dist/connection.d.ts.map +1 -0
  272. package/packages/daemon/dist/connection.js.map +1 -0
  273. package/packages/daemon/dist/consensus-integration.d.ts.map +1 -0
  274. package/packages/daemon/dist/consensus-integration.js.map +1 -0
  275. package/packages/daemon/dist/consensus.d.ts.map +1 -0
  276. package/packages/daemon/dist/consensus.js.map +1 -0
  277. package/packages/daemon/dist/delivery-tracker.d.ts.map +1 -0
  278. package/packages/daemon/dist/delivery-tracker.js.map +1 -0
  279. package/packages/daemon/dist/enhanced-features.d.ts.map +1 -0
  280. package/packages/daemon/dist/enhanced-features.js.map +1 -0
  281. package/packages/daemon/dist/index.d.ts.map +1 -0
  282. package/packages/daemon/dist/index.js.map +1 -0
  283. package/packages/daemon/dist/migrations/index.d.ts.map +1 -0
  284. package/packages/daemon/dist/migrations/index.js.map +1 -0
  285. package/packages/daemon/dist/orchestrator.d.ts.map +1 -0
  286. package/packages/daemon/dist/orchestrator.js.map +1 -0
  287. package/packages/daemon/dist/rate-limiter.d.ts.map +1 -0
  288. package/packages/daemon/dist/rate-limiter.js.map +1 -0
  289. package/packages/daemon/dist/registry.d.ts.map +1 -0
  290. package/packages/daemon/dist/registry.js.map +1 -0
  291. package/packages/daemon/dist/relay-ledger.d.ts.map +1 -0
  292. package/packages/daemon/dist/relay-ledger.js.map +1 -0
  293. package/packages/daemon/dist/relay-watchdog.d.ts.map +1 -0
  294. package/packages/daemon/dist/relay-watchdog.js.map +1 -0
  295. package/packages/daemon/dist/repo-manager.d.ts.map +1 -0
  296. package/packages/daemon/dist/repo-manager.js.map +1 -0
  297. package/packages/daemon/dist/router.d.ts.map +1 -0
  298. package/packages/daemon/dist/router.js.map +1 -0
  299. package/packages/daemon/dist/server.d.ts +1 -0
  300. package/packages/daemon/dist/server.d.ts.map +1 -0
  301. package/packages/daemon/dist/server.js +46 -16
  302. package/packages/daemon/dist/server.js.map +1 -0
  303. package/packages/daemon/dist/spawn-manager.d.ts.map +1 -0
  304. package/packages/daemon/dist/spawn-manager.js.map +1 -0
  305. package/packages/daemon/dist/sync-queue.d.ts.map +1 -0
  306. package/packages/daemon/dist/sync-queue.js.map +1 -0
  307. package/packages/daemon/dist/types.d.ts.map +1 -0
  308. package/packages/daemon/dist/types.js.map +1 -0
  309. package/packages/daemon/dist/workspace-manager.d.ts.map +1 -0
  310. package/packages/daemon/dist/workspace-manager.js.map +1 -0
  311. package/packages/daemon/package.json +12 -12
  312. package/packages/daemon/src/agent-manager.ts +679 -0
  313. package/packages/daemon/src/agent-registry.ts +284 -0
  314. package/packages/daemon/src/agent-signing.ts +707 -0
  315. package/packages/daemon/src/api.ts +1012 -0
  316. package/packages/daemon/src/auth.ts +276 -0
  317. package/packages/daemon/src/channel-membership-store.ts +217 -0
  318. package/packages/daemon/src/cli-auth.ts +906 -0
  319. package/packages/daemon/src/cloud-sync.ts +902 -0
  320. package/packages/daemon/src/connection.ts +534 -0
  321. package/packages/daemon/src/consensus-integration.ts +510 -0
  322. package/packages/daemon/src/consensus.ts +848 -0
  323. package/packages/daemon/src/delivery-tracker.ts +145 -0
  324. package/packages/daemon/src/enhanced-features.ts +390 -0
  325. package/packages/daemon/src/index.ts +52 -0
  326. package/packages/daemon/src/migrations/0001_initial.sql +72 -0
  327. package/packages/daemon/src/migrations/index.test.ts +195 -0
  328. package/packages/daemon/src/migrations/index.ts +286 -0
  329. package/packages/daemon/src/orchestrator.test.ts +231 -0
  330. package/packages/daemon/src/orchestrator.ts +1376 -0
  331. package/packages/daemon/src/rate-limiter.ts +172 -0
  332. package/packages/daemon/src/registry.ts +8 -0
  333. package/packages/daemon/src/relay-ledger.test.ts +358 -0
  334. package/packages/daemon/src/relay-ledger.ts +713 -0
  335. package/packages/daemon/src/relay-watchdog.test.ts +881 -0
  336. package/packages/daemon/src/relay-watchdog.ts +785 -0
  337. package/packages/daemon/src/repo-manager.ts +468 -0
  338. package/packages/daemon/src/router.test.ts +149 -0
  339. package/packages/daemon/src/router.ts +1885 -0
  340. package/packages/daemon/src/server.ts +1871 -0
  341. package/packages/daemon/src/spawn-manager.ts +275 -0
  342. package/packages/daemon/src/sync-queue.ts +477 -0
  343. package/packages/daemon/src/types.ts +158 -0
  344. package/packages/daemon/src/workspace-manager.ts +371 -0
  345. package/packages/daemon/tsconfig.json +21 -0
  346. package/packages/hooks/dist/browser.d.ts.map +1 -0
  347. package/packages/hooks/dist/browser.js.map +1 -0
  348. package/packages/hooks/dist/emitter.d.ts.map +1 -0
  349. package/packages/hooks/dist/emitter.js.map +1 -0
  350. package/packages/hooks/dist/inbox-check/hook.d.ts.map +1 -0
  351. package/packages/hooks/dist/inbox-check/hook.js.map +1 -0
  352. package/packages/hooks/dist/inbox-check/index.d.ts.map +1 -0
  353. package/packages/hooks/dist/inbox-check/index.js.map +1 -0
  354. package/packages/hooks/dist/inbox-check/types.d.ts.map +1 -0
  355. package/packages/hooks/dist/inbox-check/types.js.map +1 -0
  356. package/packages/hooks/dist/inbox-check/utils.d.ts.map +1 -0
  357. package/packages/hooks/dist/inbox-check/utils.js.map +1 -0
  358. package/packages/hooks/dist/index.d.ts.map +1 -0
  359. package/packages/hooks/dist/index.js.map +1 -0
  360. package/packages/hooks/dist/registry.d.ts.map +1 -0
  361. package/packages/hooks/dist/registry.js.map +1 -0
  362. package/packages/hooks/dist/trajectory-hooks.d.ts.map +1 -0
  363. package/packages/hooks/dist/trajectory-hooks.js.map +1 -0
  364. package/packages/hooks/dist/types.d.ts.map +1 -0
  365. package/packages/hooks/dist/types.js.map +1 -0
  366. package/packages/hooks/package.json +4 -4
  367. package/packages/hooks/src/browser.ts +2 -0
  368. package/packages/hooks/src/emitter.ts +84 -0
  369. package/packages/hooks/src/inbox-check/hook.ts +114 -0
  370. package/packages/hooks/src/inbox-check/index.ts +8 -0
  371. package/packages/hooks/src/inbox-check/types.ts +39 -0
  372. package/packages/hooks/src/inbox-check/utils.test.ts +287 -0
  373. package/packages/hooks/src/inbox-check/utils.ts +125 -0
  374. package/packages/hooks/src/index.ts +11 -0
  375. package/packages/hooks/src/registry.ts +614 -0
  376. package/packages/hooks/src/shims.d.ts +3 -0
  377. package/packages/hooks/src/trajectory-hooks.ts +251 -0
  378. package/packages/hooks/src/types.ts +342 -0
  379. package/packages/hooks/tsconfig.json +21 -0
  380. package/packages/hooks/vitest.config.ts +9 -0
  381. package/packages/mcp/dist/bin.d.ts.map +1 -0
  382. package/packages/mcp/dist/bin.js.map +1 -0
  383. package/packages/mcp/dist/client.d.ts +9 -15
  384. package/packages/mcp/dist/client.d.ts.map +1 -0
  385. package/packages/mcp/dist/client.js +42 -74
  386. package/packages/mcp/dist/client.js.map +1 -0
  387. package/packages/mcp/dist/cloud.d.ts.map +1 -0
  388. package/packages/mcp/dist/cloud.js.map +1 -0
  389. package/packages/mcp/dist/errors.d.ts.map +1 -0
  390. package/packages/mcp/dist/errors.js.map +1 -0
  391. package/packages/mcp/dist/file-transport.d.ts.map +1 -0
  392. package/packages/mcp/dist/file-transport.js.map +1 -0
  393. package/packages/mcp/dist/hybrid-client.d.ts.map +1 -0
  394. package/packages/mcp/dist/hybrid-client.js.map +1 -0
  395. package/packages/mcp/dist/index.d.ts.map +1 -0
  396. package/packages/mcp/dist/index.js.map +1 -0
  397. package/packages/mcp/dist/install-cli.d.ts.map +1 -0
  398. package/packages/mcp/dist/install-cli.js.map +1 -0
  399. package/packages/mcp/dist/install.d.ts.map +1 -0
  400. package/packages/mcp/dist/install.js.map +1 -0
  401. package/packages/mcp/dist/prompts/index.d.ts.map +1 -0
  402. package/packages/mcp/dist/prompts/index.js.map +1 -0
  403. package/packages/mcp/dist/prompts/protocol.d.ts.map +1 -0
  404. package/packages/mcp/dist/prompts/protocol.js.map +1 -0
  405. package/packages/mcp/dist/resources/agents.d.ts.map +1 -0
  406. package/packages/mcp/dist/resources/agents.js.map +1 -0
  407. package/packages/mcp/dist/resources/inbox.d.ts.map +1 -0
  408. package/packages/mcp/dist/resources/inbox.js.map +1 -0
  409. package/packages/mcp/dist/resources/index.d.ts.map +1 -0
  410. package/packages/mcp/dist/resources/index.js.map +1 -0
  411. package/packages/mcp/dist/resources/project.d.ts.map +1 -0
  412. package/packages/mcp/dist/resources/project.js.map +1 -0
  413. package/packages/mcp/dist/server.d.ts.map +1 -0
  414. package/packages/mcp/dist/server.js.map +1 -0
  415. package/packages/mcp/dist/simple.d.ts +2 -5
  416. package/packages/mcp/dist/simple.d.ts.map +1 -0
  417. package/packages/mcp/dist/simple.js.map +1 -0
  418. package/packages/mcp/dist/tools/index.d.ts.map +1 -0
  419. package/packages/mcp/dist/tools/index.js.map +1 -0
  420. package/packages/mcp/dist/tools/relay-broadcast.d.ts.map +1 -0
  421. package/packages/mcp/dist/tools/relay-broadcast.js.map +1 -0
  422. package/packages/mcp/dist/tools/relay-channel.d.ts.map +1 -0
  423. package/packages/mcp/dist/tools/relay-channel.js.map +1 -0
  424. package/packages/mcp/dist/tools/relay-connected.d.ts.map +1 -0
  425. package/packages/mcp/dist/tools/relay-connected.js.map +1 -0
  426. package/packages/mcp/dist/tools/relay-consensus.d.ts.map +1 -0
  427. package/packages/mcp/dist/tools/relay-consensus.js.map +1 -0
  428. package/packages/mcp/dist/tools/relay-continuity.d.ts.map +1 -0
  429. package/packages/mcp/dist/tools/relay-continuity.js.map +1 -0
  430. package/packages/mcp/dist/tools/relay-health.d.ts.map +1 -0
  431. package/packages/mcp/dist/tools/relay-health.js.map +1 -0
  432. package/packages/mcp/dist/tools/relay-inbox.d.ts.map +1 -0
  433. package/packages/mcp/dist/tools/relay-inbox.js.map +1 -0
  434. package/packages/mcp/dist/tools/relay-logs.d.ts.map +1 -0
  435. package/packages/mcp/dist/tools/relay-logs.js.map +1 -0
  436. package/packages/mcp/dist/tools/relay-metrics.d.ts.map +1 -0
  437. package/packages/mcp/dist/tools/relay-metrics.js.map +1 -0
  438. package/packages/mcp/dist/tools/relay-release.d.ts.map +1 -0
  439. package/packages/mcp/dist/tools/relay-release.js.map +1 -0
  440. package/packages/mcp/dist/tools/relay-remove-agent.d.ts.map +1 -0
  441. package/packages/mcp/dist/tools/relay-remove-agent.js.map +1 -0
  442. package/packages/mcp/dist/tools/relay-send.d.ts.map +1 -0
  443. package/packages/mcp/dist/tools/relay-send.js +4 -2
  444. package/packages/mcp/dist/tools/relay-send.js.map +1 -0
  445. package/packages/mcp/dist/tools/relay-shadow.d.ts.map +1 -0
  446. package/packages/mcp/dist/tools/relay-shadow.js.map +1 -0
  447. package/packages/mcp/dist/tools/relay-spawn.d.ts.map +1 -0
  448. package/packages/mcp/dist/tools/relay-spawn.js.map +1 -0
  449. package/packages/mcp/dist/tools/relay-status.d.ts.map +1 -0
  450. package/packages/mcp/dist/tools/relay-status.js.map +1 -0
  451. package/packages/mcp/dist/tools/relay-subscribe.d.ts.map +1 -0
  452. package/packages/mcp/dist/tools/relay-subscribe.js.map +1 -0
  453. package/packages/mcp/dist/tools/relay-who.d.ts.map +1 -0
  454. package/packages/mcp/dist/tools/relay-who.js.map +1 -0
  455. package/packages/mcp/package.json +3 -3
  456. package/packages/mcp/src/bin.ts +149 -0
  457. package/packages/mcp/src/client.ts +400 -0
  458. package/packages/mcp/src/cloud.ts +523 -0
  459. package/packages/mcp/src/errors.ts +54 -0
  460. package/packages/mcp/src/file-transport.ts +268 -0
  461. package/packages/mcp/src/hybrid-client.ts +209 -0
  462. package/packages/mcp/src/index.ts +122 -0
  463. package/packages/mcp/src/install-cli.ts +210 -0
  464. package/packages/mcp/src/install.ts +745 -0
  465. package/packages/mcp/src/prompts/index.ts +1 -0
  466. package/packages/mcp/src/prompts/protocol.ts +164 -0
  467. package/packages/mcp/src/resources/agents.ts +21 -0
  468. package/packages/mcp/src/resources/inbox.ts +21 -0
  469. package/packages/mcp/src/resources/index.ts +3 -0
  470. package/packages/mcp/src/resources/project.ts +29 -0
  471. package/packages/mcp/src/server.ts +431 -0
  472. package/packages/mcp/src/simple.ts +214 -0
  473. package/packages/mcp/src/tools/index.ts +133 -0
  474. package/packages/mcp/src/tools/relay-broadcast.ts +32 -0
  475. package/packages/mcp/src/tools/relay-channel.ts +93 -0
  476. package/packages/mcp/src/tools/relay-connected.ts +52 -0
  477. package/packages/mcp/src/tools/relay-consensus.ts +92 -0
  478. package/packages/mcp/src/tools/relay-continuity.ts +127 -0
  479. package/packages/mcp/src/tools/relay-health.ts +148 -0
  480. package/packages/mcp/src/tools/relay-inbox.ts +70 -0
  481. package/packages/mcp/src/tools/relay-logs.ts +106 -0
  482. package/packages/mcp/src/tools/relay-metrics.ts +140 -0
  483. package/packages/mcp/src/tools/relay-release.ts +54 -0
  484. package/packages/mcp/src/tools/relay-remove-agent.ts +58 -0
  485. package/packages/mcp/src/tools/relay-send.ts +84 -0
  486. package/packages/mcp/src/tools/relay-shadow.ts +67 -0
  487. package/packages/mcp/src/tools/relay-spawn.ts +87 -0
  488. package/packages/mcp/src/tools/relay-status.ts +57 -0
  489. package/packages/mcp/src/tools/relay-subscribe.ts +61 -0
  490. package/packages/mcp/src/tools/relay-who.ts +59 -0
  491. package/packages/mcp/tests/client.test.ts +476 -0
  492. package/packages/mcp/tests/discover.test.ts +195 -0
  493. package/packages/mcp/tests/install.test.ts +123 -0
  494. package/packages/mcp/tests/prompts.test.ts +12 -0
  495. package/packages/mcp/tests/resources.test.ts +53 -0
  496. package/packages/mcp/tests/tools.test.ts +1242 -0
  497. package/packages/mcp/tsconfig.json +22 -0
  498. package/packages/mcp/vitest.config.ts +9 -0
  499. package/packages/memory/dist/adapters/index.d.ts.map +1 -0
  500. package/packages/memory/dist/adapters/index.js.map +1 -0
  501. package/packages/memory/dist/adapters/inmemory.d.ts.map +1 -0
  502. package/packages/memory/dist/adapters/inmemory.js.map +1 -0
  503. package/packages/memory/dist/adapters/supermemory.d.ts.map +1 -0
  504. package/packages/memory/dist/adapters/supermemory.js.map +1 -0
  505. package/packages/memory/dist/context-compaction.d.ts.map +1 -0
  506. package/packages/memory/dist/context-compaction.js.map +1 -0
  507. package/packages/memory/dist/factory.d.ts.map +1 -0
  508. package/packages/memory/dist/factory.js.map +1 -0
  509. package/packages/memory/dist/index.d.ts.map +1 -0
  510. package/packages/memory/dist/index.js.map +1 -0
  511. package/packages/memory/dist/memory-hooks.d.ts.map +1 -0
  512. package/packages/memory/dist/memory-hooks.js.map +1 -0
  513. package/packages/memory/dist/service.d.ts.map +1 -0
  514. package/packages/memory/dist/service.js.map +1 -0
  515. package/packages/memory/dist/types.d.ts.map +1 -0
  516. package/packages/memory/dist/types.js.map +1 -0
  517. package/packages/memory/package.json +2 -2
  518. package/packages/memory/src/adapters/index.ts +8 -0
  519. package/packages/memory/src/adapters/inmemory.ts +265 -0
  520. package/packages/memory/src/adapters/supermemory.ts +449 -0
  521. package/packages/memory/src/context-compaction.test.ts +660 -0
  522. package/packages/memory/src/context-compaction.ts +612 -0
  523. package/packages/memory/src/factory.ts +170 -0
  524. package/packages/memory/src/index.ts +33 -0
  525. package/packages/memory/src/memory-hooks.ts +410 -0
  526. package/packages/memory/src/service.ts +194 -0
  527. package/packages/memory/src/types.ts +211 -0
  528. package/packages/memory/tsconfig.json +21 -0
  529. package/packages/memory/vitest.config.ts +9 -0
  530. package/packages/policy/dist/agent-policy.d.ts.map +1 -0
  531. package/packages/policy/dist/agent-policy.js.map +1 -0
  532. package/packages/policy/dist/cloud-policy-fetcher.d.ts.map +1 -0
  533. package/packages/policy/dist/cloud-policy-fetcher.js.map +1 -0
  534. package/packages/policy/dist/index.d.ts.map +1 -0
  535. package/packages/policy/dist/index.js.map +1 -0
  536. package/packages/policy/package.json +2 -2
  537. package/packages/policy/src/agent-policy.ts +866 -0
  538. package/packages/policy/src/cloud-policy-fetcher.ts +78 -0
  539. package/packages/policy/src/index.ts +21 -0
  540. package/packages/policy/tsconfig.json +21 -0
  541. package/packages/policy/vitest.config.ts +9 -0
  542. package/packages/protocol/dist/channels.d.ts.map +1 -0
  543. package/packages/protocol/dist/channels.js.map +1 -0
  544. package/packages/protocol/dist/framing.d.ts.map +1 -0
  545. package/packages/protocol/dist/framing.js.map +1 -0
  546. package/packages/protocol/dist/id-generator.d.ts.map +1 -0
  547. package/packages/protocol/dist/id-generator.js.map +1 -0
  548. package/packages/protocol/dist/index.d.ts.map +1 -0
  549. package/packages/protocol/dist/index.js.map +1 -0
  550. package/packages/protocol/dist/relay-pty-schemas.d.ts +70 -2
  551. package/packages/protocol/dist/relay-pty-schemas.d.ts.map +1 -0
  552. package/packages/protocol/dist/relay-pty-schemas.js.map +1 -0
  553. package/packages/protocol/dist/types.d.ts +8 -0
  554. package/packages/protocol/dist/types.d.ts.map +1 -0
  555. package/packages/protocol/dist/types.js.map +1 -0
  556. package/packages/protocol/package.json +1 -1
  557. package/packages/protocol/src/channels.test.ts +330 -0
  558. package/packages/protocol/src/channels.ts +270 -0
  559. package/packages/protocol/src/framing.test.ts +164 -0
  560. package/packages/protocol/src/framing.ts +242 -0
  561. package/packages/protocol/src/id-generator.ts +69 -0
  562. package/packages/protocol/src/index.ts +4 -0
  563. package/packages/protocol/src/relay-pty-schemas.ts +400 -0
  564. package/packages/protocol/src/types.test.ts +271 -0
  565. package/packages/protocol/src/types.ts +846 -0
  566. package/packages/protocol/tsconfig.json +21 -0
  567. package/packages/protocol/vitest.config.ts +9 -0
  568. package/packages/resiliency/dist/cgroup-manager.d.ts.map +1 -0
  569. package/packages/resiliency/dist/cgroup-manager.js.map +1 -0
  570. package/packages/resiliency/dist/context-persistence.d.ts.map +1 -0
  571. package/packages/resiliency/dist/context-persistence.js.map +1 -0
  572. package/packages/resiliency/dist/crash-insights.d.ts.map +1 -0
  573. package/packages/resiliency/dist/crash-insights.js.map +1 -0
  574. package/packages/resiliency/dist/gossip-health.d.ts.map +1 -0
  575. package/packages/resiliency/dist/gossip-health.js.map +1 -0
  576. package/packages/resiliency/dist/health-monitor.d.ts.map +1 -0
  577. package/packages/resiliency/dist/health-monitor.js.map +1 -0
  578. package/packages/resiliency/dist/index.d.ts.map +1 -0
  579. package/packages/resiliency/dist/index.js.map +1 -0
  580. package/packages/resiliency/dist/leader-watchdog.d.ts.map +1 -0
  581. package/packages/resiliency/dist/leader-watchdog.js.map +1 -0
  582. package/packages/resiliency/dist/logger.d.ts.map +1 -0
  583. package/packages/resiliency/dist/logger.js.map +1 -0
  584. package/packages/resiliency/dist/memory-monitor.d.ts.map +1 -0
  585. package/packages/resiliency/dist/memory-monitor.js.map +1 -0
  586. package/packages/resiliency/dist/metrics.d.ts.map +1 -0
  587. package/packages/resiliency/dist/metrics.js.map +1 -0
  588. package/packages/resiliency/dist/provider-context.d.ts.map +1 -0
  589. package/packages/resiliency/dist/provider-context.js.map +1 -0
  590. package/packages/resiliency/dist/stateless-lead.d.ts.map +1 -0
  591. package/packages/resiliency/dist/stateless-lead.js.map +1 -0
  592. package/packages/resiliency/dist/supervisor.d.ts.map +1 -0
  593. package/packages/resiliency/dist/supervisor.js.map +1 -0
  594. package/packages/resiliency/package.json +1 -1
  595. package/packages/resiliency/src/cgroup-manager.ts +468 -0
  596. package/packages/resiliency/src/context-persistence.ts +538 -0
  597. package/packages/resiliency/src/crash-insights.test.ts +620 -0
  598. package/packages/resiliency/src/crash-insights.ts +660 -0
  599. package/packages/resiliency/src/gossip-health.ts +333 -0
  600. package/packages/resiliency/src/health-monitor.ts +371 -0
  601. package/packages/resiliency/src/index.ts +157 -0
  602. package/packages/resiliency/src/leader-watchdog.ts +260 -0
  603. package/packages/resiliency/src/logger.ts +320 -0
  604. package/packages/resiliency/src/memory-monitor.test.ts +637 -0
  605. package/packages/resiliency/src/memory-monitor.ts +740 -0
  606. package/packages/resiliency/src/metrics.ts +311 -0
  607. package/packages/resiliency/src/provider-context.ts +452 -0
  608. package/packages/resiliency/src/stateless-lead.ts +408 -0
  609. package/packages/resiliency/src/supervisor.ts +578 -0
  610. package/packages/resiliency/tsconfig.json +21 -0
  611. package/packages/resiliency/vitest.config.ts +9 -0
  612. package/packages/sdk/dist/client.d.ts.map +1 -0
  613. package/packages/sdk/dist/client.js.map +1 -0
  614. package/packages/sdk/dist/index.d.ts.map +1 -0
  615. package/packages/sdk/dist/index.js.map +1 -0
  616. package/packages/sdk/dist/logs.d.ts.map +1 -0
  617. package/packages/sdk/dist/logs.js.map +1 -0
  618. package/packages/sdk/dist/protocol/index.d.ts.map +1 -0
  619. package/packages/sdk/dist/protocol/index.js.map +1 -0
  620. package/packages/sdk/dist/standalone.d.ts.map +1 -0
  621. package/packages/sdk/dist/standalone.js.map +1 -0
  622. package/packages/sdk/examples/SWARM_CAPABILITIES.md +498 -0
  623. package/packages/sdk/examples/SWARM_PATTERNS.md +541 -0
  624. package/packages/sdk/package.json +2 -2
  625. package/packages/sdk/src/client.test.ts +568 -0
  626. package/packages/sdk/src/client.ts +1418 -0
  627. package/packages/sdk/src/index.ts +103 -0
  628. package/packages/sdk/src/logs.test.ts +98 -0
  629. package/packages/sdk/src/logs.ts +126 -0
  630. package/packages/sdk/src/protocol/framing.test.ts +164 -0
  631. package/packages/sdk/src/protocol/index.ts +8 -0
  632. package/packages/sdk/src/standalone.ts +176 -0
  633. package/packages/sdk/tsconfig.json +22 -0
  634. package/packages/sdk/vitest.config.ts +9 -0
  635. package/packages/spawner/.trajectories/index.json +5 -0
  636. package/packages/spawner/dist/index.d.ts.map +1 -0
  637. package/packages/spawner/dist/index.js.map +1 -0
  638. package/packages/spawner/dist/types.d.ts.map +1 -0
  639. package/packages/spawner/dist/types.js.map +1 -0
  640. package/packages/spawner/package.json +1 -1
  641. package/packages/spawner/src/index.ts +8 -0
  642. package/packages/spawner/src/types.test.ts +385 -0
  643. package/packages/spawner/src/types.ts +228 -0
  644. package/packages/spawner/tsconfig.json +19 -0
  645. package/packages/spawner/vitest.config.ts +9 -0
  646. package/packages/state/dist/agent-state.d.ts.map +1 -0
  647. package/packages/state/dist/agent-state.js.map +1 -0
  648. package/packages/state/dist/index.d.ts.map +1 -0
  649. package/packages/state/dist/index.js.map +1 -0
  650. package/packages/state/package.json +1 -1
  651. package/packages/state/src/agent-state.test.ts +335 -0
  652. package/packages/state/src/agent-state.ts +153 -0
  653. package/packages/state/src/index.ts +12 -0
  654. package/packages/state/tsconfig.json +21 -0
  655. package/packages/state/vitest.config.ts +9 -0
  656. package/packages/storage/dist/adapter.d.ts +28 -1
  657. package/packages/storage/dist/adapter.d.ts.map +1 -0
  658. package/packages/storage/dist/adapter.js +104 -10
  659. package/packages/storage/dist/adapter.js.map +1 -0
  660. package/packages/storage/dist/batched-sqlite-adapter.d.ts.map +1 -0
  661. package/packages/storage/dist/batched-sqlite-adapter.js.map +1 -0
  662. package/packages/storage/dist/dead-letter-queue.d.ts.map +1 -0
  663. package/packages/storage/dist/dead-letter-queue.js.map +1 -0
  664. package/packages/storage/dist/dlq-adapter.d.ts.map +1 -0
  665. package/packages/storage/dist/dlq-adapter.js.map +1 -0
  666. package/packages/storage/dist/index.d.ts +1 -0
  667. package/packages/storage/dist/index.d.ts.map +1 -0
  668. package/packages/storage/dist/index.js +1 -0
  669. package/packages/storage/dist/index.js.map +1 -0
  670. package/packages/storage/dist/jsonl-adapter.d.ts +77 -0
  671. package/packages/storage/dist/jsonl-adapter.d.ts.map +1 -0
  672. package/packages/storage/dist/jsonl-adapter.js +505 -0
  673. package/packages/storage/dist/jsonl-adapter.js.map +1 -0
  674. package/packages/storage/dist/sqlite-adapter.d.ts +6 -1
  675. package/packages/storage/dist/sqlite-adapter.d.ts.map +1 -0
  676. package/packages/storage/dist/sqlite-adapter.js +47 -0
  677. package/packages/storage/dist/sqlite-adapter.js.map +1 -0
  678. package/packages/storage/package.json +2 -2
  679. package/packages/storage/src/adapter.ts +438 -0
  680. package/packages/storage/src/batched-sqlite-adapter.test.ts +240 -0
  681. package/packages/storage/src/batched-sqlite-adapter.ts +239 -0
  682. package/packages/storage/src/dead-letter-queue.ts +643 -0
  683. package/packages/storage/src/dlq-adapter.test.ts +492 -0
  684. package/packages/storage/src/dlq-adapter.ts +954 -0
  685. package/packages/storage/src/index.ts +6 -0
  686. package/packages/storage/src/jsonl-adapter.test.ts +200 -0
  687. package/packages/storage/src/jsonl-adapter.ts +618 -0
  688. package/packages/storage/src/memory-adapter.test.ts +36 -0
  689. package/packages/storage/src/sqlite-adapter.test.ts +562 -0
  690. package/packages/storage/src/sqlite-adapter.ts +1058 -0
  691. package/packages/storage/tsconfig.json +21 -0
  692. package/packages/storage/vitest.config.ts +9 -0
  693. package/packages/telemetry/dist/client.d.ts.map +1 -0
  694. package/packages/telemetry/dist/client.js.map +1 -0
  695. package/packages/telemetry/dist/config.d.ts.map +1 -0
  696. package/packages/telemetry/dist/config.js.map +1 -0
  697. package/packages/telemetry/dist/events.d.ts.map +1 -0
  698. package/packages/telemetry/dist/events.js.map +1 -0
  699. package/packages/telemetry/dist/index.d.ts.map +1 -0
  700. package/packages/telemetry/dist/index.js.map +1 -0
  701. package/packages/telemetry/dist/machine-id.d.ts.map +1 -0
  702. package/packages/telemetry/dist/machine-id.js.map +1 -0
  703. package/packages/telemetry/dist/posthog-config.d.ts.map +1 -0
  704. package/packages/telemetry/dist/posthog-config.js.map +1 -0
  705. package/packages/telemetry/package.json +1 -1
  706. package/packages/telemetry/src/client.ts +158 -0
  707. package/packages/telemetry/src/config.ts +110 -0
  708. package/packages/telemetry/src/events.ts +137 -0
  709. package/packages/telemetry/src/index.ts +46 -0
  710. package/packages/telemetry/src/machine-id.ts +63 -0
  711. package/packages/telemetry/src/posthog-config.ts +39 -0
  712. package/packages/telemetry/tsconfig.json +21 -0
  713. package/packages/trajectory/dist/index.d.ts.map +1 -0
  714. package/packages/trajectory/dist/index.js.map +1 -0
  715. package/packages/trajectory/dist/integration.d.ts.map +1 -0
  716. package/packages/trajectory/dist/integration.js.map +1 -0
  717. package/packages/trajectory/package.json +2 -2
  718. package/packages/trajectory/src/index.ts +1 -0
  719. package/packages/trajectory/src/integration.ts +1268 -0
  720. package/packages/trajectory/tsconfig.json +21 -0
  721. package/packages/trajectory/vitest.config.ts +9 -0
  722. package/packages/user-directory/dist/index.d.ts.map +1 -0
  723. package/packages/user-directory/dist/index.js.map +1 -0
  724. package/packages/user-directory/dist/user-directory.d.ts.map +1 -0
  725. package/packages/user-directory/dist/user-directory.js.map +1 -0
  726. package/packages/user-directory/package.json +2 -2
  727. package/packages/user-directory/src/index.ts +12 -0
  728. package/packages/user-directory/src/user-directory.ts +393 -0
  729. package/packages/user-directory/tsconfig.json +21 -0
  730. package/packages/user-directory/vitest.config.ts +9 -0
  731. package/packages/utils/dist/cjs/client-helpers.js +127 -0
  732. package/packages/utils/dist/cjs/command-resolver.js +89 -0
  733. package/packages/utils/dist/cjs/error-tracking.js +106 -0
  734. package/packages/utils/dist/cjs/git-remote.js +120 -0
  735. package/packages/utils/dist/cjs/index.js +40 -0
  736. package/packages/utils/dist/cjs/logger.js +105 -0
  737. package/packages/utils/dist/cjs/model-mapping.js +54 -0
  738. package/packages/utils/dist/cjs/name-generator.js +179 -0
  739. package/packages/utils/dist/cjs/package.json +3 -0
  740. package/packages/utils/dist/cjs/precompiled-patterns.js +271 -0
  741. package/packages/utils/dist/cjs/relay-pty-path.js +143 -0
  742. package/packages/utils/dist/cjs/update-checker.js +185 -0
  743. package/packages/utils/dist/client-helpers.d.ts +73 -0
  744. package/packages/utils/dist/client-helpers.d.ts.map +1 -0
  745. package/packages/utils/dist/client-helpers.js +130 -0
  746. package/packages/utils/dist/client-helpers.js.map +1 -0
  747. package/packages/utils/dist/command-resolver.d.ts.map +1 -0
  748. package/packages/utils/dist/command-resolver.js.map +1 -0
  749. package/packages/utils/dist/error-tracking.d.ts.map +1 -0
  750. package/packages/utils/dist/error-tracking.js.map +1 -0
  751. package/packages/utils/dist/git-remote.d.ts.map +1 -0
  752. package/packages/utils/dist/git-remote.js.map +1 -0
  753. package/packages/utils/dist/index.d.ts +1 -0
  754. package/packages/utils/dist/index.d.ts.map +1 -0
  755. package/packages/utils/dist/index.js +1 -0
  756. package/packages/utils/dist/index.js.map +1 -0
  757. package/packages/utils/dist/logger.d.ts.map +1 -0
  758. package/packages/utils/dist/logger.js.map +1 -0
  759. package/packages/utils/dist/model-mapping.d.ts.map +1 -0
  760. package/packages/utils/dist/model-mapping.js.map +1 -0
  761. package/packages/utils/dist/name-generator.d.ts.map +1 -0
  762. package/packages/utils/dist/name-generator.js.map +1 -0
  763. package/packages/utils/dist/precompiled-patterns.d.ts.map +1 -0
  764. package/packages/utils/dist/precompiled-patterns.js.map +1 -0
  765. package/packages/utils/dist/relay-pty-path.d.ts +11 -5
  766. package/packages/utils/dist/relay-pty-path.d.ts.map +1 -0
  767. package/packages/utils/dist/relay-pty-path.js +60 -5
  768. package/packages/utils/dist/relay-pty-path.js.map +1 -0
  769. package/packages/utils/dist/update-checker.d.ts.map +1 -0
  770. package/packages/utils/dist/update-checker.js.map +1 -0
  771. package/packages/utils/package.json +37 -14
  772. package/packages/utils/scripts/build-cjs.mjs +24 -0
  773. package/packages/utils/src/client-helpers.ts +221 -0
  774. package/packages/utils/src/command-resolver.ts +82 -0
  775. package/packages/utils/src/error-tracking.ts +189 -0
  776. package/packages/utils/src/git-remote.ts +143 -0
  777. package/packages/utils/src/index.ts +10 -0
  778. package/packages/utils/src/logger.ts +107 -0
  779. package/packages/utils/src/model-mapping.test.ts +122 -0
  780. package/packages/utils/src/model-mapping.ts +58 -0
  781. package/packages/utils/src/name-generator.test.ts +259 -0
  782. package/packages/utils/src/name-generator.ts +56 -0
  783. package/packages/utils/src/precompiled-patterns.test.ts +452 -0
  784. package/packages/utils/src/precompiled-patterns.ts +395 -0
  785. package/packages/utils/src/relay-pty-path.ts +196 -0
  786. package/packages/utils/src/update-checker.test.ts +260 -0
  787. package/packages/utils/src/update-checker.ts +211 -0
  788. package/packages/utils/tsconfig.json +21 -0
  789. package/packages/utils/vitest.config.ts +9 -0
  790. package/packages/wrapper/dist/__fixtures__/claude-outputs.d.ts.map +1 -0
  791. package/packages/wrapper/dist/__fixtures__/claude-outputs.js.map +1 -0
  792. package/packages/wrapper/dist/__fixtures__/codex-outputs.d.ts.map +1 -0
  793. package/packages/wrapper/dist/__fixtures__/codex-outputs.js.map +1 -0
  794. package/packages/wrapper/dist/__fixtures__/gemini-outputs.d.ts.map +1 -0
  795. package/packages/wrapper/dist/__fixtures__/gemini-outputs.js.map +1 -0
  796. package/packages/wrapper/dist/__fixtures__/index.d.ts.map +1 -0
  797. package/packages/wrapper/dist/__fixtures__/index.js.map +1 -0
  798. package/packages/wrapper/dist/auth-detection.d.ts.map +1 -0
  799. package/packages/wrapper/dist/auth-detection.js.map +1 -0
  800. package/packages/wrapper/dist/base-wrapper.d.ts.map +1 -0
  801. package/packages/wrapper/dist/base-wrapper.js.map +1 -0
  802. package/packages/wrapper/dist/client.d.ts.map +1 -0
  803. package/packages/wrapper/dist/client.js.map +1 -0
  804. package/packages/wrapper/dist/id-generator.d.ts.map +1 -0
  805. package/packages/wrapper/dist/id-generator.js.map +1 -0
  806. package/packages/wrapper/dist/idle-detector.d.ts.map +1 -0
  807. package/packages/wrapper/dist/idle-detector.js.map +1 -0
  808. package/packages/wrapper/dist/inbox.d.ts.map +1 -0
  809. package/packages/wrapper/dist/inbox.js.map +1 -0
  810. package/packages/wrapper/dist/index.d.ts.map +1 -0
  811. package/packages/wrapper/dist/index.js.map +1 -0
  812. package/packages/wrapper/dist/parser.d.ts.map +1 -0
  813. package/packages/wrapper/dist/parser.js.map +1 -0
  814. package/packages/wrapper/dist/prompt-composer.d.ts.map +1 -0
  815. package/packages/wrapper/dist/prompt-composer.js.map +1 -0
  816. package/packages/wrapper/dist/relay-pty-orchestrator.d.ts +10 -0
  817. package/packages/wrapper/dist/relay-pty-orchestrator.d.ts.map +1 -0
  818. package/packages/wrapper/dist/relay-pty-orchestrator.js +69 -0
  819. package/packages/wrapper/dist/relay-pty-orchestrator.js.map +1 -0
  820. package/packages/wrapper/dist/shared.d.ts.map +1 -0
  821. package/packages/wrapper/dist/shared.js.map +1 -0
  822. package/packages/wrapper/dist/stuck-detector.d.ts.map +1 -0
  823. package/packages/wrapper/dist/stuck-detector.js.map +1 -0
  824. package/packages/wrapper/dist/tmux-resolver.d.ts.map +1 -0
  825. package/packages/wrapper/dist/tmux-resolver.js.map +1 -0
  826. package/packages/wrapper/dist/tmux-wrapper.d.ts.map +1 -0
  827. package/packages/wrapper/dist/tmux-wrapper.js.map +1 -0
  828. package/packages/wrapper/dist/trajectory-integration.d.ts.map +1 -0
  829. package/packages/wrapper/dist/trajectory-integration.js.map +1 -0
  830. package/packages/wrapper/dist/wrapper-types.d.ts.map +1 -0
  831. package/packages/wrapper/dist/wrapper-types.js.map +1 -0
  832. package/packages/wrapper/package.json +6 -9
  833. package/packages/wrapper/src/__fixtures__/claude-outputs.ts +471 -0
  834. package/packages/wrapper/src/__fixtures__/codex-outputs.ts +99 -0
  835. package/packages/wrapper/src/__fixtures__/gemini-outputs.ts +151 -0
  836. package/packages/wrapper/src/__fixtures__/index.ts +47 -0
  837. package/packages/wrapper/src/auth-detection.ts +244 -0
  838. package/packages/wrapper/src/base-wrapper.test.ts +589 -0
  839. package/packages/wrapper/src/base-wrapper.ts +810 -0
  840. package/packages/wrapper/src/client.test.ts +262 -0
  841. package/packages/wrapper/src/client.ts +984 -0
  842. package/packages/wrapper/src/id-generator.test.ts +71 -0
  843. package/packages/wrapper/src/id-generator.ts +69 -0
  844. package/packages/wrapper/src/idle-detector.test.ts +418 -0
  845. package/packages/wrapper/src/idle-detector.ts +384 -0
  846. package/packages/wrapper/src/inbox.test.ts +233 -0
  847. package/packages/wrapper/src/inbox.ts +89 -0
  848. package/packages/wrapper/src/index.ts +170 -0
  849. package/packages/wrapper/src/parser.regression.test.ts +251 -0
  850. package/packages/wrapper/src/parser.test.ts +1359 -0
  851. package/packages/wrapper/src/parser.ts +1477 -0
  852. package/packages/wrapper/src/prompt-composer.test.ts +219 -0
  853. package/packages/wrapper/src/prompt-composer.ts +231 -0
  854. package/packages/wrapper/src/relay-pty-orchestrator.test.ts +1204 -0
  855. package/packages/wrapper/src/relay-pty-orchestrator.ts +2626 -0
  856. package/packages/wrapper/src/shared.test.ts +322 -0
  857. package/packages/wrapper/src/shared.ts +495 -0
  858. package/packages/wrapper/src/stuck-detector.test.ts +303 -0
  859. package/packages/wrapper/src/stuck-detector.ts +511 -0
  860. package/packages/wrapper/src/tmux-resolver.test.ts +104 -0
  861. package/packages/wrapper/src/tmux-resolver.ts +207 -0
  862. package/packages/wrapper/src/tmux-wrapper.test.ts +316 -0
  863. package/packages/wrapper/src/tmux-wrapper.ts +2095 -0
  864. package/packages/wrapper/src/trajectory-detection.test.ts +151 -0
  865. package/packages/wrapper/src/trajectory-integration.ts +1261 -0
  866. package/packages/wrapper/src/wrapper-types.ts +45 -0
  867. package/packages/wrapper/tsconfig.json +19 -0
  868. package/packages/wrapper/vitest.config.ts +9 -0
  869. package/scripts/build-cjs.mjs +23 -0
  870. package/scripts/postinstall.js +132 -0
  871. package/.cursor/mcp.json +0 -11
  872. package/.gitattributes +0 -3
  873. package/.gitleaks.toml +0 -26
  874. package/.mcp.json +0 -11
  875. package/.nvmrc +0 -1
  876. package/ARCHITECTURE.md +0 -1245
  877. package/CHANGELOG.md +0 -231
  878. package/TESTING.md +0 -278
  879. package/TRAIL_GIT_AUTH_FIX.md +0 -113
  880. package/scripts/demos/README.md +0 -79
  881. package/scripts/demos/server-capacity.sh +0 -69
  882. package/scripts/demos/sprint-planning.sh +0 -73
  883. package/scripts/hooks/install.sh +0 -16
  884. package/scripts/hooks/pre-commit +0 -60
  885. package/scripts/post-publish-verify/README.md +0 -80
  886. package/scripts/post-publish-verify/run-verify.sh +0 -127
  887. package/scripts/post-publish-verify/verify-install.sh +0 -249
  888. package/scripts/stress-test-orchestrator-integration.mts +0 -1366
  889. package/scripts/stress-test-orchestrator.mjs +0 -584
  890. package/scripts/stress-test-relay-pty.sh +0 -452
  891. package/scripts/test-interactive-terminal.sh +0 -248
  892. package/specs/PRIMITIVES_ROADMAP.md +0 -2154
  893. package/tests/benchmarks/protocol.bench.ts +0 -310
  894. package/turbo.json +0 -37
@@ -0,0 +1,1204 @@
1
+ /**
2
+ * Tests for RelayPtyOrchestrator
3
+ *
4
+ * Tests the TypeScript orchestrator that manages the relay-pty Rust binary.
5
+ * Uses mocks for child process and socket communication.
6
+ */
7
+
8
+ import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
9
+ import { EventEmitter } from 'node:events';
10
+ import type { ChildProcess } from 'node:child_process';
11
+ import type { Socket } from 'node:net';
12
+ import { createHash } from 'node:crypto';
13
+
14
+ // Mock modules before importing the class
15
+ vi.mock('node:child_process', () => ({
16
+ spawn: vi.fn(),
17
+ }));
18
+
19
+ vi.mock('node:net', () => ({
20
+ createConnection: vi.fn(),
21
+ }));
22
+
23
+ const { mockExistsSync } = vi.hoisted(() => ({
24
+ mockExistsSync: vi.fn((path: string) => {
25
+ // Simulate relay-pty binary exists at any relay-pty path
26
+ return typeof path === 'string' && path.includes('relay-pty');
27
+ }),
28
+ }));
29
+
30
+ vi.mock('node:fs', async (importOriginal) => {
31
+ const actual = await importOriginal<typeof import('node:fs')>();
32
+ return {
33
+ ...actual,
34
+ existsSync: mockExistsSync,
35
+ default: {
36
+ ...actual,
37
+ existsSync: mockExistsSync,
38
+ },
39
+ };
40
+ });
41
+
42
+ // Mock the client module
43
+ vi.mock('./client.js', () => ({
44
+ RelayClient: vi.fn().mockImplementation((options: any) => ({
45
+ name: options.agentName,
46
+ state: 'READY' as string,
47
+ connect: vi.fn().mockResolvedValue(undefined),
48
+ sendMessage: vi.fn().mockReturnValue(true),
49
+ sendLog: vi.fn(),
50
+ destroy: vi.fn(),
51
+ onMessage: null,
52
+ onChannelMessage: null,
53
+ })),
54
+ }));
55
+
56
+ // Mock continuity
57
+ vi.mock('@agent-relay/continuity', () => ({
58
+ getContinuityManager: vi.fn(() => null),
59
+ parseContinuityCommand: vi.fn(),
60
+ hasContinuityCommand: vi.fn(() => false),
61
+ }));
62
+
63
+ // Now import after mocks
64
+ import { spawn } from 'node:child_process';
65
+ import { createConnection } from 'node:net';
66
+ import { RelayPtyOrchestrator } from './relay-pty-orchestrator.js';
67
+
68
+ /**
69
+ * Create a mock ChildProcess
70
+ */
71
+ function createMockProcess(): ChildProcess {
72
+ const proc = new EventEmitter() as ChildProcess;
73
+ proc.stdout = new EventEmitter() as any;
74
+ proc.stderr = new EventEmitter() as any;
75
+ proc.stdin = { write: vi.fn() } as any;
76
+ proc.pid = 12345;
77
+ proc.killed = false;
78
+ proc.kill = vi.fn(() => {
79
+ proc.killed = true;
80
+ setTimeout(() => proc.emit('exit', 0, null), 0);
81
+ return true;
82
+ });
83
+ proc.exitCode = null;
84
+ return proc;
85
+ }
86
+
87
+ /**
88
+ * Create a mock Socket
89
+ */
90
+ function createMockSocket(): Socket {
91
+ const socket = new EventEmitter() as Socket;
92
+ socket.write = vi.fn((data: any, cb?: any) => {
93
+ if (typeof cb === 'function') cb();
94
+ return true;
95
+ });
96
+ socket.destroy = vi.fn();
97
+ (socket as any).destroyed = false;
98
+ return socket;
99
+ }
100
+
101
+ describe('RelayPtyOrchestrator', () => {
102
+ let orchestrator: RelayPtyOrchestrator;
103
+ let mockProcess: ChildProcess;
104
+ let mockSocket: Socket;
105
+ const mockSpawn = spawn as unknown as ReturnType<typeof vi.fn>;
106
+ const mockCreateConnection = createConnection as unknown as ReturnType<typeof vi.fn>;
107
+
108
+ // Save original WORKSPACE_ID to restore after each test
109
+ let originalWorkspaceId: string | undefined;
110
+
111
+ beforeEach(() => {
112
+ vi.clearAllMocks();
113
+
114
+ // Save and clear WORKSPACE_ID to test legacy paths by default
115
+ // Tests that need workspace namespacing can set it explicitly
116
+ originalWorkspaceId = process.env.WORKSPACE_ID;
117
+ delete process.env.WORKSPACE_ID;
118
+
119
+ // Reset existsSync mock to default implementation
120
+ mockExistsSync.mockImplementation((path: string) => {
121
+ return typeof path === 'string' && path.includes('relay-pty');
122
+ });
123
+
124
+ // Set up mock process
125
+ mockProcess = createMockProcess();
126
+ mockSpawn.mockReturnValue(mockProcess);
127
+
128
+ // Set up mock socket
129
+ mockSocket = createMockSocket();
130
+ mockCreateConnection.mockImplementation((_path: string, callback: () => void) => {
131
+ setTimeout(() => callback(), 10);
132
+ return mockSocket;
133
+ });
134
+
135
+ // Mock waitUntilCliReady to resolve immediately in tests
136
+ // This avoids waiting for CLI readiness checks which require complex simulation
137
+ vi.spyOn(RelayPtyOrchestrator.prototype, 'waitUntilCliReady').mockResolvedValue(true);
138
+
139
+ // Mock isProcessAlive to return true - the real implementation uses process.kill(pid, 0)
140
+ // which fails for mock PIDs that don't correspond to real processes
141
+ vi.spyOn(RelayPtyOrchestrator.prototype as any, 'isProcessAlive').mockReturnValue(true);
142
+ });
143
+
144
+ afterEach(async () => {
145
+ if (orchestrator?.isRunning) {
146
+ await orchestrator.stop();
147
+ }
148
+
149
+ // Restore original WORKSPACE_ID
150
+ if (originalWorkspaceId !== undefined) {
151
+ process.env.WORKSPACE_ID = originalWorkspaceId;
152
+ } else {
153
+ delete process.env.WORKSPACE_ID;
154
+ }
155
+ });
156
+
157
+ describe('constructor', () => {
158
+ it('sets socket path based on agent name', () => {
159
+ orchestrator = new RelayPtyOrchestrator({
160
+ name: 'TestAgent',
161
+ command: 'claude',
162
+ });
163
+
164
+ // Local mode uses ~/.agent-relay paths
165
+ expect(orchestrator.getSocketPath()).toContain('.agent-relay');
166
+ expect(orchestrator.getSocketPath()).toContain('TestAgent.sock');
167
+ });
168
+
169
+ it('uses workspace-namespaced paths when WORKSPACE_ID is in config.env', () => {
170
+ orchestrator = new RelayPtyOrchestrator({
171
+ name: 'TestAgent',
172
+ command: 'claude',
173
+ env: { WORKSPACE_ID: 'ws-12345' },
174
+ });
175
+
176
+ expect(orchestrator.getSocketPath()).toBe('/tmp/relay/ws-12345/sockets/TestAgent.sock');
177
+ expect(orchestrator.outboxPath).toBe('/tmp/relay/ws-12345/outbox/TestAgent');
178
+ });
179
+
180
+ it('hashes workspace id when socket path is too long', () => {
181
+ const longWorkspaceId = `ws-${'a'.repeat(140)}`;
182
+ const hashedWorkspaceId = createHash('sha256').update(longWorkspaceId).digest('hex').slice(0, 12);
183
+
184
+ orchestrator = new RelayPtyOrchestrator({
185
+ name: 'LongAgent',
186
+ command: 'claude',
187
+ env: { WORKSPACE_ID: longWorkspaceId },
188
+ });
189
+
190
+ expect(orchestrator.getSocketPath()).toBe(`/tmp/relay/${hashedWorkspaceId}/sockets/LongAgent.sock`);
191
+ expect(orchestrator.outboxPath).toBe(`/tmp/relay/${hashedWorkspaceId}/outbox/LongAgent`);
192
+ });
193
+
194
+ it('uses workspace-namespaced paths when WORKSPACE_ID is in process.env', () => {
195
+ const originalEnv = process.env.WORKSPACE_ID;
196
+ process.env.WORKSPACE_ID = 'ws-cloud-99';
197
+
198
+ try {
199
+ orchestrator = new RelayPtyOrchestrator({
200
+ name: 'CloudAgent',
201
+ command: 'claude',
202
+ });
203
+
204
+ expect(orchestrator.getSocketPath()).toBe('/tmp/relay/ws-cloud-99/sockets/CloudAgent.sock');
205
+ expect(orchestrator.outboxPath).toBe('/tmp/relay/ws-cloud-99/outbox/CloudAgent');
206
+ } finally {
207
+ if (originalEnv === undefined) {
208
+ delete process.env.WORKSPACE_ID;
209
+ } else {
210
+ process.env.WORKSPACE_ID = originalEnv;
211
+ }
212
+ }
213
+ });
214
+
215
+ it('uses canonical ~/.agent-relay paths when WORKSPACE_ID is not set', () => {
216
+ // beforeEach already clears WORKSPACE_ID
217
+ orchestrator = new RelayPtyOrchestrator({
218
+ name: 'LocalAgent',
219
+ command: 'claude',
220
+ });
221
+
222
+ // Local mode uses ~/.agent-relay paths, not /tmp
223
+ expect(orchestrator.getSocketPath()).toContain('.agent-relay');
224
+ expect(orchestrator.getSocketPath()).toContain('LocalAgent.sock');
225
+ expect(orchestrator.outboxPath).toContain('.agent-relay');
226
+ expect(orchestrator.outboxPath).toContain('outbox/LocalAgent');
227
+ expect(orchestrator.outboxPath).not.toContain('/tmp/');
228
+ });
229
+ });
230
+
231
+ describe('binary detection', () => {
232
+ it('finds binary at release path', async () => {
233
+ orchestrator = new RelayPtyOrchestrator({
234
+ name: 'TestAgent',
235
+ command: 'claude',
236
+ });
237
+
238
+ await orchestrator.start();
239
+
240
+ expect(mockSpawn).toHaveBeenCalled();
241
+ const spawnCall = mockSpawn.mock.calls[0];
242
+ expect(spawnCall[0]).toContain('relay-pty');
243
+ });
244
+
245
+ it('uses custom binary path if provided', async () => {
246
+ // Update mock to accept custom path
247
+ mockExistsSync.mockImplementation((path: string) => {
248
+ return path === '/custom/path/relay-pty' || (typeof path === 'string' && path.includes('relay-pty'));
249
+ });
250
+
251
+ orchestrator = new RelayPtyOrchestrator({
252
+ name: 'TestAgent',
253
+ command: 'claude',
254
+ relayPtyPath: '/custom/path/relay-pty',
255
+ });
256
+
257
+ await orchestrator.start();
258
+
259
+ const spawnCall = mockSpawn.mock.calls[0];
260
+ expect(spawnCall[0]).toBe('/custom/path/relay-pty');
261
+
262
+ // Reset mock
263
+ mockExistsSync.mockImplementation((path: string) => {
264
+ return typeof path === 'string' && path.includes('relay-pty');
265
+ });
266
+ });
267
+ });
268
+
269
+ describe('process management', () => {
270
+ it('spawns relay-pty with correct arguments', async () => {
271
+ orchestrator = new RelayPtyOrchestrator({
272
+ name: 'TestAgent',
273
+ command: 'claude',
274
+ args: ['--model', 'opus'],
275
+ idleBeforeInjectMs: 1000,
276
+ });
277
+
278
+ await orchestrator.start();
279
+
280
+ const spawnCall = mockSpawn.mock.calls[0];
281
+ const args = spawnCall[1] as string[];
282
+
283
+ expect(args).toContain('--name');
284
+ expect(args).toContain('TestAgent');
285
+ expect(args).toContain('--socket');
286
+ // Socket path should be in ~/.agent-relay for local mode
287
+ const socketArg = args[args.indexOf('--socket') + 1];
288
+ expect(socketArg).toContain('.agent-relay');
289
+ expect(socketArg).toContain('TestAgent.sock');
290
+ expect(args).toContain('--idle-timeout');
291
+ expect(args).toContain('1000');
292
+ expect(args).toContain('--');
293
+ expect(args).toContain('claude');
294
+ expect(args).toContain('--model');
295
+ expect(args).toContain('opus');
296
+ });
297
+
298
+ it('sets environment variables', async () => {
299
+ orchestrator = new RelayPtyOrchestrator({
300
+ name: 'TestAgent',
301
+ command: 'claude',
302
+ env: { CUSTOM_VAR: 'value' },
303
+ });
304
+
305
+ await orchestrator.start();
306
+
307
+ const spawnCall = mockSpawn.mock.calls[0];
308
+ const options = spawnCall[2];
309
+
310
+ expect(options.env.AGENT_RELAY_NAME).toBe('TestAgent');
311
+ expect(options.env.TERM).toBe('xterm-256color');
312
+ expect(options.env.CUSTOM_VAR).toBe('value');
313
+ });
314
+
315
+ it('emits exit event when process exits', async () => {
316
+ orchestrator = new RelayPtyOrchestrator({
317
+ name: 'TestAgent',
318
+ command: 'claude',
319
+ });
320
+
321
+ const exitHandler = vi.fn();
322
+ orchestrator.on('exit', exitHandler);
323
+
324
+ await orchestrator.start();
325
+
326
+ // Simulate process exit
327
+ mockProcess.emit('exit', 0, null);
328
+
329
+ expect(exitHandler).toHaveBeenCalledWith(0);
330
+ });
331
+
332
+ it('calls onExit callback', async () => {
333
+ const onExit = vi.fn();
334
+ orchestrator = new RelayPtyOrchestrator({
335
+ name: 'TestAgent',
336
+ command: 'claude',
337
+ onExit,
338
+ });
339
+
340
+ await orchestrator.start();
341
+ mockProcess.emit('exit', 1, null);
342
+
343
+ expect(onExit).toHaveBeenCalledWith(1);
344
+ });
345
+ });
346
+
347
+ describe('socket communication', () => {
348
+ it('connects to socket after spawn', async () => {
349
+ orchestrator = new RelayPtyOrchestrator({
350
+ name: 'TestAgent',
351
+ command: 'claude',
352
+ });
353
+
354
+ await orchestrator.start();
355
+
356
+ // Should connect to the socket at ~/.agent-relay path for local mode
357
+ expect(mockCreateConnection).toHaveBeenCalled();
358
+ const socketPath = mockCreateConnection.mock.calls[0][0];
359
+ expect(socketPath).toContain('.agent-relay');
360
+ expect(socketPath).toContain('TestAgent.sock');
361
+ });
362
+
363
+ it('retries socket connection on failure', async () => {
364
+ orchestrator = new RelayPtyOrchestrator({
365
+ name: 'TestAgent',
366
+ command: 'claude',
367
+ socketConnectTimeoutMs: 100,
368
+ socketReconnectAttempts: 3,
369
+ });
370
+
371
+ // First two attempts fail, third succeeds
372
+ let attempts = 0;
373
+ mockCreateConnection.mockImplementation((_path: string, callback: () => void) => {
374
+ const sock = createMockSocket();
375
+ attempts++;
376
+ if (attempts < 3) {
377
+ setTimeout(() => sock.emit('error', new Error('Connection refused')), 10);
378
+ } else {
379
+ setTimeout(() => callback(), 10);
380
+ }
381
+ return sock;
382
+ });
383
+
384
+ await orchestrator.start();
385
+
386
+ expect(mockCreateConnection).toHaveBeenCalledTimes(3);
387
+ });
388
+
389
+ it('handles socket close', async () => {
390
+ orchestrator = new RelayPtyOrchestrator({
391
+ name: 'TestAgent',
392
+ command: 'claude',
393
+ });
394
+
395
+ await orchestrator.start();
396
+ mockSocket.emit('close');
397
+
398
+ // Socket should be marked as disconnected
399
+ // (Internal state, verified by inability to inject)
400
+ });
401
+ });
402
+
403
+ describe('output handling', () => {
404
+ it('emits output event for stdout data', async () => {
405
+ orchestrator = new RelayPtyOrchestrator({
406
+ name: 'TestAgent',
407
+ command: 'claude',
408
+ });
409
+
410
+ const outputHandler = vi.fn();
411
+ orchestrator.on('output', outputHandler);
412
+
413
+ await orchestrator.start();
414
+ mockProcess.stdout!.emit('data', Buffer.from('Hello from agent'));
415
+
416
+ expect(outputHandler).toHaveBeenCalledWith('Hello from agent');
417
+ });
418
+
419
+ it('accumulates raw output buffer', async () => {
420
+ orchestrator = new RelayPtyOrchestrator({
421
+ name: 'TestAgent',
422
+ command: 'claude',
423
+ });
424
+
425
+ await orchestrator.start();
426
+ mockProcess.stdout!.emit('data', Buffer.from('Line 1\n'));
427
+ mockProcess.stdout!.emit('data', Buffer.from('Line 2\n'));
428
+
429
+ expect(orchestrator.getRawOutput()).toContain('Line 1');
430
+ expect(orchestrator.getRawOutput()).toContain('Line 2');
431
+ });
432
+
433
+ it('parses relay commands from output', async () => {
434
+ orchestrator = new RelayPtyOrchestrator({
435
+ name: 'TestAgent',
436
+ command: 'claude',
437
+ });
438
+
439
+ await orchestrator.start();
440
+
441
+ // Access the client mock to verify sendMessage calls
442
+ const client = (orchestrator as any).client;
443
+
444
+ // Emit output containing a relay command
445
+ mockProcess.stdout!.emit('data', Buffer.from('->relay:Bob Hello Bob!\n'));
446
+
447
+ // Allow async parsing
448
+ await new Promise(resolve => setTimeout(resolve, 10));
449
+
450
+ expect(client.sendMessage).toHaveBeenCalled();
451
+ });
452
+ });
453
+
454
+ describe('message injection', () => {
455
+ it('processes queued messages when ready', async () => {
456
+ orchestrator = new RelayPtyOrchestrator({
457
+ name: 'TestAgent',
458
+ command: 'claude',
459
+ });
460
+
461
+ await orchestrator.start();
462
+
463
+ // Trigger message handler (normally done by RelayClient)
464
+ const handler = (orchestrator as any).handleIncomingMessage.bind(orchestrator);
465
+ handler('Sender', { body: 'Test message', kind: 'message' }, 'msg-123');
466
+
467
+ // Allow async processing
468
+ await new Promise(resolve => setTimeout(resolve, 100));
469
+
470
+ // Verify socket write was called with inject request
471
+ expect(mockSocket.write).toHaveBeenCalled();
472
+ const writeCall = (mockSocket.write as ReturnType<typeof vi.fn>).mock.calls[0][0];
473
+ expect(writeCall).toContain('"type":"inject"');
474
+ expect(writeCall).toContain('msg-123');
475
+ });
476
+
477
+ it('handles inject_result responses', async () => {
478
+ orchestrator = new RelayPtyOrchestrator({
479
+ name: 'TestAgent',
480
+ command: 'claude',
481
+ });
482
+
483
+ await orchestrator.start();
484
+
485
+ // Trigger a message to inject
486
+ const handler = (orchestrator as any).handleIncomingMessage.bind(orchestrator);
487
+ handler('Sender', { body: 'Test message', kind: 'message' }, 'msg-456');
488
+
489
+ await new Promise(resolve => setTimeout(resolve, 50));
490
+
491
+ // Simulate output containing the injected message pattern
492
+ // This is needed because handleInjectResult now verifies the message appeared in output
493
+ mockProcess.stdout?.emit('data', Buffer.from(
494
+ 'Relay message from Sender [msg-456]: Test message\n'
495
+ ));
496
+
497
+ await new Promise(resolve => setTimeout(resolve, 50));
498
+
499
+ // Simulate successful delivery response
500
+ mockSocket.emit('data', Buffer.from(JSON.stringify({
501
+ type: 'inject_result',
502
+ id: 'msg-456',
503
+ status: 'delivered',
504
+ timestamp: Date.now(),
505
+ }) + '\n'));
506
+
507
+ // Allow time for async verification (verifyInjection polls for up to 2 seconds)
508
+ await new Promise(resolve => setTimeout(resolve, 200));
509
+
510
+ // Check metrics
511
+ const metrics = orchestrator.getInjectionMetrics();
512
+ expect(metrics.total).toBeGreaterThan(0);
513
+ expect(metrics.successFirstTry).toBeGreaterThan(0);
514
+ });
515
+
516
+ it('handles backpressure', async () => {
517
+ orchestrator = new RelayPtyOrchestrator({
518
+ name: 'TestAgent',
519
+ command: 'claude',
520
+ });
521
+
522
+ const backpressureHandler = vi.fn();
523
+ orchestrator.on('backpressure', backpressureHandler);
524
+
525
+ await orchestrator.start();
526
+
527
+ // Simulate backpressure response
528
+ mockSocket.emit('data', Buffer.from(JSON.stringify({
529
+ type: 'backpressure',
530
+ queue_length: 50,
531
+ accept: false,
532
+ }) + '\n'));
533
+
534
+ expect(backpressureHandler).toHaveBeenCalledWith({
535
+ queueLength: 50,
536
+ accept: false,
537
+ });
538
+ expect(orchestrator.isBackpressureActive()).toBe(true);
539
+
540
+ // Clear backpressure
541
+ mockSocket.emit('data', Buffer.from(JSON.stringify({
542
+ type: 'backpressure',
543
+ queue_length: 5,
544
+ accept: true,
545
+ }) + '\n'));
546
+
547
+ expect(orchestrator.isBackpressureActive()).toBe(false);
548
+ });
549
+ });
550
+
551
+ describe('lifecycle', () => {
552
+ it('tracks running state', async () => {
553
+ orchestrator = new RelayPtyOrchestrator({
554
+ name: 'TestAgent',
555
+ command: 'claude',
556
+ });
557
+
558
+ expect(orchestrator.isRunning).toBe(false);
559
+
560
+ await orchestrator.start();
561
+ expect(orchestrator.isRunning).toBe(true);
562
+
563
+ await orchestrator.stop();
564
+ expect(orchestrator.isRunning).toBe(false);
565
+ });
566
+
567
+ it('sends shutdown command on stop', async () => {
568
+ orchestrator = new RelayPtyOrchestrator({
569
+ name: 'TestAgent',
570
+ command: 'claude',
571
+ });
572
+
573
+ await orchestrator.start();
574
+ await orchestrator.stop();
575
+
576
+ // Verify shutdown request was sent
577
+ const writeCalls = (mockSocket.write as ReturnType<typeof vi.fn>).mock.calls;
578
+ const shutdownCall = writeCalls.find((call: any[]) =>
579
+ call[0].includes('"type":"shutdown"')
580
+ );
581
+ expect(shutdownCall).toBeDefined();
582
+ });
583
+
584
+ it('kills process on stop', async () => {
585
+ orchestrator = new RelayPtyOrchestrator({
586
+ name: 'TestAgent',
587
+ command: 'claude',
588
+ });
589
+
590
+ await orchestrator.start();
591
+
592
+ // Simulate process not exiting gracefully
593
+ const stopPromise = orchestrator.stop();
594
+
595
+ // Emit exit after kill
596
+ setTimeout(() => mockProcess.emit('exit', 0, null), 100);
597
+
598
+ await stopPromise;
599
+
600
+ expect(mockProcess.kill).toHaveBeenCalled();
601
+ });
602
+
603
+ it('returns PID', async () => {
604
+ orchestrator = new RelayPtyOrchestrator({
605
+ name: 'TestAgent',
606
+ command: 'claude',
607
+ });
608
+
609
+ await orchestrator.start();
610
+
611
+ expect(orchestrator.pid).toBe(12345);
612
+ });
613
+ });
614
+
615
+ describe('summary and session end detection', () => {
616
+ it('emits summary event', async () => {
617
+ orchestrator = new RelayPtyOrchestrator({
618
+ name: 'TestAgent',
619
+ command: 'claude',
620
+ });
621
+
622
+ const summaryHandler = vi.fn();
623
+ orchestrator.on('summary', summaryHandler);
624
+
625
+ await orchestrator.start();
626
+
627
+ // Emit output with summary block
628
+ mockProcess.stdout!.emit('data', Buffer.from(
629
+ '[[SUMMARY]]{"currentTask": "Test task", "completedTasks": ["Task 1"]}[[/SUMMARY]]'
630
+ ));
631
+
632
+ await new Promise(resolve => setTimeout(resolve, 10));
633
+
634
+ expect(summaryHandler).toHaveBeenCalled();
635
+ expect(summaryHandler.mock.calls[0][0].agentName).toBe('TestAgent');
636
+ });
637
+
638
+ it('emits session-end event', async () => {
639
+ orchestrator = new RelayPtyOrchestrator({
640
+ name: 'TestAgent',
641
+ command: 'claude',
642
+ });
643
+
644
+ const sessionEndHandler = vi.fn();
645
+ orchestrator.on('session-end', sessionEndHandler);
646
+
647
+ await orchestrator.start();
648
+
649
+ // Emit output with session end
650
+ mockProcess.stdout!.emit('data', Buffer.from(
651
+ '[[SESSION_END]]Work complete.[[/SESSION_END]]'
652
+ ));
653
+
654
+ await new Promise(resolve => setTimeout(resolve, 10));
655
+
656
+ expect(sessionEndHandler).toHaveBeenCalled();
657
+ expect(sessionEndHandler.mock.calls[0][0].agentName).toBe('TestAgent');
658
+ });
659
+ });
660
+
661
+ describe('spawn with auto-send task', () => {
662
+ let fetchMock: ReturnType<typeof vi.fn>;
663
+ let originalFetch: typeof globalThis.fetch;
664
+
665
+ beforeEach(() => {
666
+ originalFetch = globalThis.fetch;
667
+ fetchMock = vi.fn();
668
+ globalThis.fetch = fetchMock;
669
+ });
670
+
671
+ afterEach(() => {
672
+ globalThis.fetch = originalFetch;
673
+ });
674
+
675
+ it('calls spawn API when dashboard port is configured', async () => {
676
+ // Mock successful spawn API response
677
+ fetchMock.mockResolvedValueOnce({
678
+ ok: true,
679
+ json: () => Promise.resolve({ success: true }),
680
+ });
681
+
682
+ orchestrator = new RelayPtyOrchestrator({
683
+ name: 'LeadAgent',
684
+ command: 'claude',
685
+ dashboardPort: 3000,
686
+ });
687
+
688
+ await orchestrator.start();
689
+
690
+ // Access the private method via prototype - simulate spawn command detection
691
+ // We'll trigger it by emitting spawn command in output
692
+ // Note: Use "DevWorker" instead of "Worker" since "worker" is a placeholder target
693
+ mockProcess.stdout!.emit('data', Buffer.from(
694
+ '->relay:spawn DevWorker claude "Implement feature X"\n'
695
+ ));
696
+
697
+ // Wait for async spawn processing
698
+ await new Promise(resolve => setTimeout(resolve, 50));
699
+
700
+ // Verify spawn API was called with task included
701
+ // Note: The spawner (not orchestrator) sends the initial task after waitUntilCliReady()
702
+ expect(fetchMock).toHaveBeenCalledWith(
703
+ 'http://localhost:3000/api/spawn',
704
+ expect.objectContaining({
705
+ method: 'POST',
706
+ headers: { 'Content-Type': 'application/json' },
707
+ body: JSON.stringify({ name: 'DevWorker', cli: 'claude', task: 'Implement feature X' }),
708
+ })
709
+ );
710
+ });
711
+
712
+ it('calls onSpawn callback with task when no dashboard port', async () => {
713
+ const onSpawnMock = vi.fn().mockResolvedValue(undefined);
714
+
715
+ orchestrator = new RelayPtyOrchestrator({
716
+ name: 'LeadAgent',
717
+ command: 'claude',
718
+ onSpawn: onSpawnMock,
719
+ });
720
+
721
+ await orchestrator.start();
722
+
723
+ // Trigger spawn command
724
+ // Note: Use "CodeDev" instead of "Developer" to avoid any potential placeholder filtering
725
+ mockProcess.stdout!.emit('data', Buffer.from(
726
+ '->relay:spawn CodeDev claude "Fix the bug"\n'
727
+ ));
728
+
729
+ // Wait for async spawn processing
730
+ await new Promise(resolve => setTimeout(resolve, 50));
731
+
732
+ // Verify onSpawn was called with task included
733
+ // Note: The callback is responsible for sending the initial task
734
+ expect(onSpawnMock).toHaveBeenCalledWith('CodeDev', 'claude', 'Fix the bug');
735
+ });
736
+
737
+ it('does not send task message when task is empty', async () => {
738
+ const onSpawnMock = vi.fn().mockResolvedValue(undefined);
739
+
740
+ orchestrator = new RelayPtyOrchestrator({
741
+ name: 'LeadAgent',
742
+ command: 'claude',
743
+ onSpawn: onSpawnMock,
744
+ });
745
+
746
+ await orchestrator.start();
747
+
748
+ // Clear any previous calls
749
+ const { RelayClient } = await import('./client.js');
750
+ const mockClientInstance = (RelayClient as any).mock.results[0].value;
751
+ mockClientInstance.sendMessage.mockClear();
752
+
753
+ // Trigger spawn command with empty task (using fenced format with whitespace only)
754
+ // Note: Use "DevAgent" instead of "Worker" since "worker" is a placeholder target
755
+ mockProcess.stdout!.emit('data', Buffer.from(
756
+ '->relay:spawn DevAgent claude ""\n'
757
+ ));
758
+
759
+ // Wait for async spawn processing
760
+ await new Promise(resolve => setTimeout(resolve, 50));
761
+
762
+ // Verify no task message was sent (empty task)
763
+ expect(mockClientInstance.sendMessage).not.toHaveBeenCalled();
764
+ });
765
+
766
+ it('deduplicates spawn commands (only spawns once)', async () => {
767
+ const onSpawnMock = vi.fn().mockResolvedValue(undefined);
768
+
769
+ orchestrator = new RelayPtyOrchestrator({
770
+ name: 'LeadAgent',
771
+ command: 'claude',
772
+ onSpawn: onSpawnMock,
773
+ });
774
+
775
+ await orchestrator.start();
776
+
777
+ // Trigger same spawn command twice
778
+ // Note: Use "TaskAgent" instead of "Worker" since "worker" is a placeholder target
779
+ mockProcess.stdout!.emit('data', Buffer.from(
780
+ '->relay:spawn TaskAgent claude "Task A"\n'
781
+ ));
782
+ mockProcess.stdout!.emit('data', Buffer.from(
783
+ '->relay:spawn TaskAgent claude "Task A"\n'
784
+ ));
785
+
786
+ // Wait for async spawn processing
787
+ await new Promise(resolve => setTimeout(resolve, 50));
788
+
789
+ // onSpawn should only be called once (deduplication)
790
+ expect(onSpawnMock).toHaveBeenCalledTimes(1);
791
+ });
792
+ });
793
+
794
+ describe('continuity command handling', () => {
795
+ let mockContinuityManager: {
796
+ handleCommand: ReturnType<typeof vi.fn>;
797
+ getOrCreateLedger: ReturnType<typeof vi.fn>;
798
+ findLedgerByAgentId: ReturnType<typeof vi.fn>;
799
+ };
800
+
801
+ beforeEach(async () => {
802
+ // Create a mock continuity manager
803
+ mockContinuityManager = {
804
+ handleCommand: vi.fn().mockResolvedValue(null),
805
+ getOrCreateLedger: vi.fn().mockResolvedValue({ agentName: 'TestAgent', agentId: 'test-123' }),
806
+ findLedgerByAgentId: vi.fn().mockResolvedValue(null),
807
+ };
808
+
809
+ // Update the mock to return our manager
810
+ const { getContinuityManager } = await import('@agent-relay/continuity');
811
+ (getContinuityManager as any).mockReturnValue(mockContinuityManager);
812
+ });
813
+
814
+ it('handles continuity save command from stderr', async () => {
815
+ orchestrator = new RelayPtyOrchestrator({
816
+ name: 'TestAgent',
817
+ command: 'claude',
818
+ });
819
+
820
+ await orchestrator.start();
821
+
822
+ // Simulate continuity JSON output from relay-pty stderr
823
+ const continuityJson = JSON.stringify({
824
+ type: 'continuity',
825
+ action: 'save',
826
+ content: 'Current task: Testing continuity\nCompleted: Setup'
827
+ });
828
+
829
+ mockProcess.stderr!.emit('data', Buffer.from(continuityJson + '\n'));
830
+
831
+ // Wait for async processing
832
+ await new Promise(resolve => setTimeout(resolve, 50));
833
+
834
+ // Verify handleCommand was called with the mapped command
835
+ expect(mockContinuityManager.handleCommand).toHaveBeenCalledWith(
836
+ 'TestAgent',
837
+ expect.objectContaining({
838
+ type: 'save',
839
+ content: 'Current task: Testing continuity\nCompleted: Setup'
840
+ })
841
+ );
842
+ });
843
+
844
+ it('handles continuity load command from stderr', async () => {
845
+ // Mock handleCommand to return a response for load
846
+ mockContinuityManager.handleCommand.mockResolvedValue('Previous context loaded');
847
+
848
+ orchestrator = new RelayPtyOrchestrator({
849
+ name: 'TestAgent',
850
+ command: 'claude',
851
+ });
852
+
853
+ await orchestrator.start();
854
+
855
+ // Simulate continuity load command
856
+ const continuityJson = JSON.stringify({
857
+ type: 'continuity',
858
+ action: 'load',
859
+ content: ''
860
+ });
861
+
862
+ mockProcess.stderr!.emit('data', Buffer.from(continuityJson + '\n'));
863
+
864
+ // Wait for async processing
865
+ await new Promise(resolve => setTimeout(resolve, 50));
866
+
867
+ // Verify handleCommand was called
868
+ expect(mockContinuityManager.handleCommand).toHaveBeenCalledWith(
869
+ 'TestAgent',
870
+ expect.objectContaining({
871
+ type: 'load'
872
+ })
873
+ );
874
+
875
+ // Verify response was queued for injection
876
+ const queue = (orchestrator as any).messageQueue;
877
+ expect(queue.length).toBeGreaterThan(0);
878
+ expect(queue.some((m: any) => m.body === 'Previous context loaded')).toBe(true);
879
+ });
880
+
881
+ it('handles continuity uncertain command from stderr', async () => {
882
+ orchestrator = new RelayPtyOrchestrator({
883
+ name: 'TestAgent',
884
+ command: 'claude',
885
+ });
886
+
887
+ await orchestrator.start();
888
+
889
+ // Simulate continuity uncertain command
890
+ const continuityJson = JSON.stringify({
891
+ type: 'continuity',
892
+ action: 'uncertain',
893
+ content: 'API rate limit handling unclear'
894
+ });
895
+
896
+ mockProcess.stderr!.emit('data', Buffer.from(continuityJson + '\n'));
897
+
898
+ // Wait for async processing
899
+ await new Promise(resolve => setTimeout(resolve, 50));
900
+
901
+ // Verify handleCommand was called with item field for uncertain
902
+ expect(mockContinuityManager.handleCommand).toHaveBeenCalledWith(
903
+ 'TestAgent',
904
+ expect.objectContaining({
905
+ type: 'uncertain',
906
+ item: 'API rate limit handling unclear'
907
+ })
908
+ );
909
+ });
910
+
911
+ it('deduplicates continuity save commands', async () => {
912
+ orchestrator = new RelayPtyOrchestrator({
913
+ name: 'TestAgent',
914
+ command: 'claude',
915
+ });
916
+
917
+ await orchestrator.start();
918
+
919
+ const continuityJson = JSON.stringify({
920
+ type: 'continuity',
921
+ action: 'save',
922
+ content: 'Same content twice'
923
+ });
924
+
925
+ // Send same command twice
926
+ mockProcess.stderr!.emit('data', Buffer.from(continuityJson + '\n'));
927
+ mockProcess.stderr!.emit('data', Buffer.from(continuityJson + '\n'));
928
+
929
+ // Wait for async processing
930
+ await new Promise(resolve => setTimeout(resolve, 50));
931
+
932
+ // Should only be called once due to deduplication
933
+ expect(mockContinuityManager.handleCommand).toHaveBeenCalledTimes(1);
934
+ });
935
+
936
+ it('ignores unknown continuity actions', async () => {
937
+ orchestrator = new RelayPtyOrchestrator({
938
+ name: 'TestAgent',
939
+ command: 'claude',
940
+ });
941
+
942
+ await orchestrator.start();
943
+
944
+ const continuityJson = JSON.stringify({
945
+ type: 'continuity',
946
+ action: 'unknown_action',
947
+ content: 'Some content'
948
+ });
949
+
950
+ mockProcess.stderr!.emit('data', Buffer.from(continuityJson + '\n'));
951
+
952
+ // Wait for async processing
953
+ await new Promise(resolve => setTimeout(resolve, 50));
954
+
955
+ // Should not call handleCommand for unknown action
956
+ expect(mockContinuityManager.handleCommand).not.toHaveBeenCalled();
957
+ });
958
+ });
959
+
960
+ describe('queue monitor', () => {
961
+ it('starts queue monitor on start()', async () => {
962
+ orchestrator = new RelayPtyOrchestrator({
963
+ name: 'TestAgent',
964
+ command: 'claude',
965
+ });
966
+
967
+ // Spy on setInterval
968
+ const setIntervalSpy = vi.spyOn(global, 'setInterval');
969
+
970
+ await orchestrator.start();
971
+
972
+ // Queue monitor should be started (30 second interval)
973
+ expect(setIntervalSpy).toHaveBeenCalledWith(expect.any(Function), 30000);
974
+
975
+ setIntervalSpy.mockRestore();
976
+ });
977
+
978
+ it('stops queue monitor on stop()', async () => {
979
+ orchestrator = new RelayPtyOrchestrator({
980
+ name: 'TestAgent',
981
+ command: 'claude',
982
+ });
983
+
984
+ const clearIntervalSpy = vi.spyOn(global, 'clearInterval');
985
+
986
+ await orchestrator.start();
987
+ await orchestrator.stop();
988
+
989
+ // Queue monitor should be cleared
990
+ expect(clearIntervalSpy).toHaveBeenCalled();
991
+
992
+ clearIntervalSpy.mockRestore();
993
+ });
994
+
995
+ it('triggers processMessageQueue when queue has stuck messages and agent is idle', async () => {
996
+ orchestrator = new RelayPtyOrchestrator({
997
+ name: 'TestAgent',
998
+ command: 'claude',
999
+ });
1000
+
1001
+ await orchestrator.start();
1002
+
1003
+ // Directly add a message to the queue (simulating a message that got stuck)
1004
+ (orchestrator as any).messageQueue.push({
1005
+ from: 'Alice',
1006
+ body: 'Test message',
1007
+ messageId: 'msg-123',
1008
+ kind: 'message',
1009
+ });
1010
+
1011
+ // Verify message is in queue
1012
+ expect(orchestrator.pendingMessageCount).toBe(1);
1013
+
1014
+ // Spy on processMessageQueue to verify it gets called
1015
+ const processQueueSpy = vi.spyOn(orchestrator as any, 'processMessageQueue');
1016
+
1017
+ // Simulate time passing (agent becomes idle - need 2000ms silence for checkForStuckQueue)
1018
+ // Mock the idle detector to report idle
1019
+ const idleDetector = (orchestrator as any).idleDetector;
1020
+ vi.spyOn(idleDetector, 'checkIdle').mockReturnValue({
1021
+ isIdle: true,
1022
+ confidence: 0.9,
1023
+ signals: [{ source: 'output_silence', confidence: 0.9, timestamp: Date.now() }],
1024
+ });
1025
+
1026
+ // Manually trigger the queue check (simulating timer firing)
1027
+ (orchestrator as any).checkForStuckQueue();
1028
+
1029
+ // processMessageQueue should have been called
1030
+ expect(processQueueSpy).toHaveBeenCalled();
1031
+
1032
+ processQueueSpy.mockRestore();
1033
+ });
1034
+
1035
+ it('does not trigger processing when agent is busy', async () => {
1036
+ orchestrator = new RelayPtyOrchestrator({
1037
+ name: 'TestAgent',
1038
+ command: 'claude',
1039
+ });
1040
+
1041
+ await orchestrator.start();
1042
+
1043
+ // Set isInjecting to true (agent is busy)
1044
+ // Also set injectionStartTime to a recent time to avoid stuck injection recovery
1045
+ (orchestrator as any).isInjecting = true;
1046
+ (orchestrator as any).injectionStartTime = Date.now();
1047
+
1048
+ // Add a message to the queue directly
1049
+ (orchestrator as any).messageQueue.push({
1050
+ from: 'Bob',
1051
+ body: 'Test message 2',
1052
+ messageId: 'msg-456',
1053
+ kind: 'message',
1054
+ });
1055
+
1056
+ // Mock idle detector to report idle (to isolate the isInjecting check)
1057
+ const idleDetector = (orchestrator as any).idleDetector;
1058
+ vi.spyOn(idleDetector, 'checkIdle').mockReturnValue({
1059
+ isIdle: true,
1060
+ confidence: 0.9,
1061
+ signals: [],
1062
+ });
1063
+
1064
+ // Spy on processMessageQueue
1065
+ const processQueueSpy = vi.spyOn(orchestrator as any, 'processMessageQueue');
1066
+
1067
+ // Trigger queue check while busy
1068
+ (orchestrator as any).checkForStuckQueue();
1069
+
1070
+ // processMessageQueue should NOT be called because isInjecting=true
1071
+ expect(processQueueSpy).not.toHaveBeenCalled();
1072
+
1073
+ // Reset
1074
+ (orchestrator as any).isInjecting = false;
1075
+ (orchestrator as any).injectionStartTime = 0;
1076
+ processQueueSpy.mockRestore();
1077
+ });
1078
+
1079
+ it('does not trigger processing when backpressure is active', async () => {
1080
+ orchestrator = new RelayPtyOrchestrator({
1081
+ name: 'TestAgent',
1082
+ command: 'claude',
1083
+ });
1084
+
1085
+ await orchestrator.start();
1086
+
1087
+ // Simulate backpressure
1088
+ mockSocket.emit('data', Buffer.from(JSON.stringify({
1089
+ type: 'backpressure',
1090
+ accept: false,
1091
+ queue_length: 50,
1092
+ }) + '\n'));
1093
+
1094
+ expect(orchestrator.isBackpressureActive()).toBe(true);
1095
+
1096
+ // Add a message to the queue
1097
+ (orchestrator as any).messageQueue.push({
1098
+ from: 'Carol',
1099
+ body: 'Test message 3',
1100
+ messageId: 'msg-789',
1101
+ kind: 'message',
1102
+ });
1103
+
1104
+ // Mock idle detector to report idle (to isolate the backpressure check)
1105
+ const idleDetector = (orchestrator as any).idleDetector;
1106
+ vi.spyOn(idleDetector, 'checkIdle').mockReturnValue({
1107
+ isIdle: true,
1108
+ confidence: 0.9,
1109
+ signals: [],
1110
+ });
1111
+
1112
+ // Spy on processMessageQueue
1113
+ const processQueueSpy = vi.spyOn(orchestrator as any, 'processMessageQueue');
1114
+
1115
+ // Trigger queue check with backpressure active
1116
+ (orchestrator as any).checkForStuckQueue();
1117
+
1118
+ // processMessageQueue should NOT be called because backpressure is active
1119
+ expect(processQueueSpy).not.toHaveBeenCalled();
1120
+
1121
+ processQueueSpy.mockRestore();
1122
+ });
1123
+
1124
+ it('does not trigger processing when queue is empty', async () => {
1125
+ orchestrator = new RelayPtyOrchestrator({
1126
+ name: 'TestAgent',
1127
+ command: 'claude',
1128
+ });
1129
+
1130
+ await orchestrator.start();
1131
+
1132
+ // Queue should be empty
1133
+ expect(orchestrator.pendingMessageCount).toBe(0);
1134
+
1135
+ // Spy on processMessageQueue
1136
+ const processQueueSpy = vi.spyOn(orchestrator as any, 'processMessageQueue');
1137
+
1138
+ // Trigger queue check with empty queue
1139
+ (orchestrator as any).checkForStuckQueue();
1140
+
1141
+ // processMessageQueue should not be called
1142
+ expect(processQueueSpy).not.toHaveBeenCalled();
1143
+
1144
+ processQueueSpy.mockRestore();
1145
+ });
1146
+
1147
+ it('does not trigger processing when agent is not idle', async () => {
1148
+ orchestrator = new RelayPtyOrchestrator({
1149
+ name: 'TestAgent',
1150
+ command: 'claude',
1151
+ });
1152
+
1153
+ await orchestrator.start();
1154
+
1155
+ // Add a message to the queue
1156
+ (orchestrator as any).messageQueue.push({
1157
+ from: 'Dave',
1158
+ body: 'Test message 4',
1159
+ messageId: 'msg-999',
1160
+ kind: 'message',
1161
+ });
1162
+
1163
+ // Mock idle detector to report NOT idle (agent is still working)
1164
+ const idleDetector = (orchestrator as any).idleDetector;
1165
+ vi.spyOn(idleDetector, 'checkIdle').mockReturnValue({
1166
+ isIdle: false,
1167
+ confidence: 0.3,
1168
+ signals: [],
1169
+ });
1170
+
1171
+ // Spy on processMessageQueue
1172
+ const processQueueSpy = vi.spyOn(orchestrator as any, 'processMessageQueue');
1173
+
1174
+ // Trigger queue check while agent is active
1175
+ (orchestrator as any).checkForStuckQueue();
1176
+
1177
+ // processMessageQueue should NOT be called because agent is not idle
1178
+ expect(processQueueSpy).not.toHaveBeenCalled();
1179
+
1180
+ processQueueSpy.mockRestore();
1181
+ });
1182
+ });
1183
+ });
1184
+
1185
+ describe('RelayPtyOrchestrator integration', () => {
1186
+ // Integration tests would require the actual relay-pty binary
1187
+ // These are placeholder tests that would be run with:
1188
+ // npm test -- --testNamePattern="integration" --runInBand
1189
+
1190
+ it.skip('spawns real relay-pty with echo', async () => {
1191
+ // This test requires the relay-pty binary to be built
1192
+ const orchestrator = new RelayPtyOrchestrator({
1193
+ name: 'IntegrationTest',
1194
+ command: 'cat', // Simple command that echoes input
1195
+ });
1196
+
1197
+ await orchestrator.start();
1198
+
1199
+ // Inject a message
1200
+ // ... verify it appears in output
1201
+
1202
+ await orchestrator.stop();
1203
+ });
1204
+ });