macro-agent 0.0.11 → 0.0.12

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 (408) hide show
  1. package/.macro-agent/teams/self-driving/prompts/grinder.md +27 -0
  2. package/.macro-agent/teams/self-driving/prompts/judge.md +27 -0
  3. package/.macro-agent/teams/self-driving/prompts/planner.md +33 -0
  4. package/.macro-agent/teams/self-driving/roles/grinder.yaml +17 -0
  5. package/.macro-agent/teams/self-driving/roles/judge.yaml +24 -0
  6. package/.macro-agent/teams/self-driving/roles/planner.yaml +18 -0
  7. package/.macro-agent/teams/self-driving/team.yaml +103 -0
  8. package/.macro-agent/teams/structured/prompts/developer.md +26 -0
  9. package/.macro-agent/teams/structured/prompts/lead.md +25 -0
  10. package/.macro-agent/teams/structured/prompts/reviewer.md +24 -0
  11. package/.macro-agent/teams/structured/roles/developer.yaml +12 -0
  12. package/.macro-agent/teams/structured/roles/lead.yaml +11 -0
  13. package/.macro-agent/teams/structured/roles/reviewer.yaml +19 -0
  14. package/.macro-agent/teams/structured/team.yaml +89 -0
  15. package/.sudocode/issues.jsonl +6 -0
  16. package/.sudocode/specs.jsonl +7 -0
  17. package/CLAUDE.md +110 -30
  18. package/README.md +60 -3
  19. package/dist/acp/macro-agent.d.ts +4 -0
  20. package/dist/acp/macro-agent.d.ts.map +1 -1
  21. package/dist/acp/macro-agent.js +50 -4
  22. package/dist/acp/macro-agent.js.map +1 -1
  23. package/dist/acp/session-mapper.d.ts +20 -1
  24. package/dist/acp/session-mapper.d.ts.map +1 -1
  25. package/dist/acp/session-mapper.js +90 -1
  26. package/dist/acp/session-mapper.js.map +1 -1
  27. package/dist/acp/types.d.ts +24 -1
  28. package/dist/acp/types.d.ts.map +1 -1
  29. package/dist/acp/types.js.map +1 -1
  30. package/dist/agent/agent-manager.d.ts +25 -1
  31. package/dist/agent/agent-manager.d.ts.map +1 -1
  32. package/dist/agent/agent-manager.js +93 -7
  33. package/dist/agent/agent-manager.js.map +1 -1
  34. package/dist/agent/types.d.ts +22 -0
  35. package/dist/agent/types.d.ts.map +1 -1
  36. package/dist/agent/types.js.map +1 -1
  37. package/dist/agent-detection/command-builder.d.ts +30 -0
  38. package/dist/agent-detection/command-builder.d.ts.map +1 -0
  39. package/dist/agent-detection/command-builder.js +71 -0
  40. package/dist/agent-detection/command-builder.js.map +1 -0
  41. package/dist/agent-detection/detector.d.ts +84 -0
  42. package/dist/agent-detection/detector.d.ts.map +1 -0
  43. package/dist/agent-detection/detector.js +240 -0
  44. package/dist/agent-detection/detector.js.map +1 -0
  45. package/dist/agent-detection/index.d.ts +12 -0
  46. package/dist/agent-detection/index.d.ts.map +1 -0
  47. package/dist/agent-detection/index.js +14 -0
  48. package/dist/agent-detection/index.js.map +1 -0
  49. package/dist/agent-detection/registry.d.ts +53 -0
  50. package/dist/agent-detection/registry.d.ts.map +1 -0
  51. package/dist/agent-detection/registry.js +177 -0
  52. package/dist/agent-detection/registry.js.map +1 -0
  53. package/dist/agent-detection/types.d.ts +121 -0
  54. package/dist/agent-detection/types.d.ts.map +1 -0
  55. package/dist/agent-detection/types.js +20 -0
  56. package/dist/agent-detection/types.js.map +1 -0
  57. package/dist/api/server.d.ts.map +1 -1
  58. package/dist/api/server.js +95 -0
  59. package/dist/api/server.js.map +1 -1
  60. package/dist/cli/index.js +29 -0
  61. package/dist/cli/index.js.map +1 -1
  62. package/dist/cli/mcp.js +38 -0
  63. package/dist/cli/mcp.js.map +1 -1
  64. package/dist/config/index.d.ts +2 -0
  65. package/dist/config/index.d.ts.map +1 -0
  66. package/dist/config/index.js +2 -0
  67. package/dist/config/index.js.map +1 -0
  68. package/dist/config/project-config.d.ts +46 -0
  69. package/dist/config/project-config.d.ts.map +1 -0
  70. package/dist/config/project-config.js +68 -0
  71. package/dist/config/project-config.js.map +1 -0
  72. package/dist/lifecycle/cascade.d.ts +1 -1
  73. package/dist/lifecycle/cascade.d.ts.map +1 -1
  74. package/dist/lifecycle/handlers/index.d.ts +4 -0
  75. package/dist/lifecycle/handlers/index.d.ts.map +1 -1
  76. package/dist/lifecycle/handlers/index.js +2 -0
  77. package/dist/lifecycle/handlers/index.js.map +1 -1
  78. package/dist/lifecycle/handlers/worker.d.ts +4 -0
  79. package/dist/lifecycle/handlers/worker.d.ts.map +1 -1
  80. package/dist/lifecycle/handlers/worker.js +35 -3
  81. package/dist/lifecycle/handlers/worker.js.map +1 -1
  82. package/dist/map/adapter/acp-over-map.d.ts.map +1 -1
  83. package/dist/map/adapter/acp-over-map.js +32 -2
  84. package/dist/map/adapter/acp-over-map.js.map +1 -1
  85. package/dist/map/adapter/event-translator.d.ts.map +1 -1
  86. package/dist/map/adapter/event-translator.js +1 -0
  87. package/dist/map/adapter/event-translator.js.map +1 -1
  88. package/dist/map/adapter/extensions/agent-detection.d.ts +49 -0
  89. package/dist/map/adapter/extensions/agent-detection.d.ts.map +1 -0
  90. package/dist/map/adapter/extensions/agent-detection.js +91 -0
  91. package/dist/map/adapter/extensions/agent-detection.js.map +1 -0
  92. package/dist/map/adapter/extensions/index.d.ts +10 -1
  93. package/dist/map/adapter/extensions/index.d.ts.map +1 -1
  94. package/dist/map/adapter/extensions/index.js +39 -0
  95. package/dist/map/adapter/extensions/index.js.map +1 -1
  96. package/dist/map/adapter/extensions/resume.d.ts +47 -0
  97. package/dist/map/adapter/extensions/resume.d.ts.map +1 -0
  98. package/dist/map/adapter/extensions/resume.js +59 -0
  99. package/dist/map/adapter/extensions/resume.js.map +1 -0
  100. package/dist/map/adapter/extensions/workspace-files.d.ts +42 -0
  101. package/dist/map/adapter/extensions/workspace-files.d.ts.map +1 -0
  102. package/dist/map/adapter/extensions/workspace-files.js +338 -0
  103. package/dist/map/adapter/extensions/workspace-files.js.map +1 -0
  104. package/dist/mcp/mcp-server.d.ts +6 -0
  105. package/dist/mcp/mcp-server.d.ts.map +1 -1
  106. package/dist/mcp/mcp-server.js +45 -0
  107. package/dist/mcp/mcp-server.js.map +1 -1
  108. package/dist/mcp/tools/claim_task.d.ts +35 -0
  109. package/dist/mcp/tools/claim_task.d.ts.map +1 -0
  110. package/dist/mcp/tools/claim_task.js +58 -0
  111. package/dist/mcp/tools/claim_task.js.map +1 -0
  112. package/dist/mcp/tools/done.d.ts +11 -2
  113. package/dist/mcp/tools/done.d.ts.map +1 -1
  114. package/dist/mcp/tools/done.js +15 -10
  115. package/dist/mcp/tools/done.js.map +1 -1
  116. package/dist/mcp/tools/list_claimable_tasks.d.ts +38 -0
  117. package/dist/mcp/tools/list_claimable_tasks.d.ts.map +1 -0
  118. package/dist/mcp/tools/list_claimable_tasks.js +63 -0
  119. package/dist/mcp/tools/list_claimable_tasks.js.map +1 -0
  120. package/dist/mcp/tools/unclaim_task.d.ts +31 -0
  121. package/dist/mcp/tools/unclaim_task.d.ts.map +1 -0
  122. package/dist/mcp/tools/unclaim_task.js +47 -0
  123. package/dist/mcp/tools/unclaim_task.js.map +1 -0
  124. package/dist/metrics/index.d.ts +2 -0
  125. package/dist/metrics/index.d.ts.map +1 -0
  126. package/dist/metrics/index.js +2 -0
  127. package/dist/metrics/index.js.map +1 -0
  128. package/dist/metrics/metrics.d.ts +79 -0
  129. package/dist/metrics/metrics.d.ts.map +1 -0
  130. package/dist/metrics/metrics.js +166 -0
  131. package/dist/metrics/metrics.js.map +1 -0
  132. package/dist/roles/capabilities.d.ts +1 -0
  133. package/dist/roles/capabilities.d.ts.map +1 -1
  134. package/dist/roles/capabilities.js +3 -0
  135. package/dist/roles/capabilities.js.map +1 -1
  136. package/dist/roles/types.d.ts +1 -1
  137. package/dist/roles/types.d.ts.map +1 -1
  138. package/dist/router/message-router.d.ts +41 -0
  139. package/dist/router/message-router.d.ts.map +1 -1
  140. package/dist/router/message-router.js +136 -5
  141. package/dist/router/message-router.js.map +1 -1
  142. package/dist/store/event-store.d.ts +8 -1
  143. package/dist/store/event-store.d.ts.map +1 -1
  144. package/dist/store/event-store.js +120 -4
  145. package/dist/store/event-store.js.map +1 -1
  146. package/dist/store/types/agents.d.ts +1 -1
  147. package/dist/store/types/agents.d.ts.map +1 -1
  148. package/dist/store/types/events.d.ts +1 -1
  149. package/dist/store/types/events.d.ts.map +1 -1
  150. package/dist/store/types/events.js.map +1 -1
  151. package/dist/store/types/index.d.ts +1 -0
  152. package/dist/store/types/index.d.ts.map +1 -1
  153. package/dist/store/types/index.js +1 -0
  154. package/dist/store/types/index.js.map +1 -1
  155. package/dist/store/types/sessions.d.ts +44 -0
  156. package/dist/store/types/sessions.d.ts.map +1 -0
  157. package/dist/store/types/sessions.js +9 -0
  158. package/dist/store/types/sessions.js.map +1 -0
  159. package/dist/store/types/tasks.d.ts +2 -0
  160. package/dist/store/types/tasks.d.ts.map +1 -1
  161. package/dist/task/backend/memory.d.ts +4 -1
  162. package/dist/task/backend/memory.d.ts.map +1 -1
  163. package/dist/task/backend/memory.js +81 -0
  164. package/dist/task/backend/memory.js.map +1 -1
  165. package/dist/task/backend/types.d.ts +30 -0
  166. package/dist/task/backend/types.d.ts.map +1 -1
  167. package/dist/task/backend/types.js.map +1 -1
  168. package/dist/teams/index.d.ts +4 -0
  169. package/dist/teams/index.d.ts.map +1 -0
  170. package/dist/teams/index.js +4 -0
  171. package/dist/teams/index.js.map +1 -0
  172. package/dist/teams/team-loader.d.ts +20 -0
  173. package/dist/teams/team-loader.d.ts.map +1 -0
  174. package/dist/teams/team-loader.js +293 -0
  175. package/dist/teams/team-loader.js.map +1 -0
  176. package/dist/teams/team-runtime.d.ts +139 -0
  177. package/dist/teams/team-runtime.d.ts.map +1 -0
  178. package/dist/teams/team-runtime.js +613 -0
  179. package/dist/teams/team-runtime.js.map +1 -0
  180. package/dist/teams/types.d.ts +266 -0
  181. package/dist/teams/types.d.ts.map +1 -0
  182. package/dist/teams/types.js +20 -0
  183. package/dist/teams/types.js.map +1 -0
  184. package/dist/workspace/dataplane-adapter.d.ts +1 -1
  185. package/dist/workspace/dataplane-adapter.d.ts.map +1 -1
  186. package/dist/workspace/dataplane-adapter.js +1 -1
  187. package/dist/workspace/dataplane-adapter.js.map +1 -1
  188. package/dist/workspace/index.d.ts +1 -1
  189. package/dist/workspace/index.d.ts.map +1 -1
  190. package/dist/workspace/strategies/index.d.ts +6 -0
  191. package/dist/workspace/strategies/index.d.ts.map +1 -0
  192. package/dist/workspace/strategies/index.js +5 -0
  193. package/dist/workspace/strategies/index.js.map +1 -0
  194. package/dist/workspace/strategies/optimistic.d.ts +26 -0
  195. package/dist/workspace/strategies/optimistic.d.ts.map +1 -0
  196. package/dist/workspace/strategies/optimistic.js +121 -0
  197. package/dist/workspace/strategies/optimistic.js.map +1 -0
  198. package/dist/workspace/strategies/queue.d.ts +26 -0
  199. package/dist/workspace/strategies/queue.d.ts.map +1 -0
  200. package/dist/workspace/strategies/queue.js +67 -0
  201. package/dist/workspace/strategies/queue.js.map +1 -0
  202. package/dist/workspace/strategies/registry.d.ts +37 -0
  203. package/dist/workspace/strategies/registry.d.ts.map +1 -0
  204. package/dist/workspace/strategies/registry.js +63 -0
  205. package/dist/workspace/strategies/registry.js.map +1 -0
  206. package/dist/workspace/strategies/trunk.d.ts +20 -0
  207. package/dist/workspace/strategies/trunk.d.ts.map +1 -0
  208. package/dist/workspace/strategies/trunk.js +108 -0
  209. package/dist/workspace/strategies/trunk.js.map +1 -0
  210. package/dist/workspace/strategies/types.d.ts +104 -0
  211. package/dist/workspace/strategies/types.d.ts.map +1 -0
  212. package/dist/workspace/strategies/types.js +11 -0
  213. package/dist/workspace/strategies/types.js.map +1 -0
  214. package/dist/workspace/types.d.ts +1 -1
  215. package/dist/workspace/types.d.ts.map +1 -1
  216. package/dist/workspace/workspace-manager.d.ts +1 -1
  217. package/dist/workspace/workspace-manager.d.ts.map +1 -1
  218. package/docs/implementation-details.md +1127 -0
  219. package/docs/implementation-summary.md +448 -0
  220. package/docs/plan-self-driving-support.md +433 -0
  221. package/docs/spec-self-driving-support.md +462 -0
  222. package/docs/team-templates.md +860 -0
  223. package/docs/teams.md +233 -0
  224. package/package.json +4 -2
  225. package/src/acp/__tests__/integration.test.ts +161 -1
  226. package/src/acp/__tests__/macro-agent.test.ts +95 -0
  227. package/src/acp/__tests__/session-persistence.test.ts +276 -0
  228. package/src/acp/macro-agent.ts +79 -7
  229. package/src/acp/session-mapper.ts +108 -1
  230. package/src/acp/types.ts +33 -1
  231. package/src/agent/agent-manager.ts +158 -6
  232. package/src/agent/types.ts +27 -0
  233. package/src/agent-detection/__tests__/command-builder.test.ts +336 -0
  234. package/src/agent-detection/__tests__/detector.test.ts +768 -0
  235. package/src/agent-detection/__tests__/registry.test.ts +254 -0
  236. package/src/agent-detection/command-builder.ts +90 -0
  237. package/src/agent-detection/detector.ts +307 -0
  238. package/src/agent-detection/index.ts +36 -0
  239. package/src/agent-detection/registry.ts +200 -0
  240. package/src/agent-detection/types.ts +184 -0
  241. package/src/api/server.ts +110 -0
  242. package/src/cli/index.ts +44 -0
  243. package/src/cli/mcp.ts +47 -0
  244. package/src/config/index.ts +9 -0
  245. package/src/config/project-config.ts +107 -0
  246. package/src/lifecycle/cascade.ts +1 -1
  247. package/src/lifecycle/handlers/index.ts +8 -0
  248. package/src/lifecycle/handlers/worker.ts +48 -3
  249. package/src/map/adapter/__tests__/extensions.test.ts +359 -0
  250. package/src/map/adapter/__tests__/workspace-files.test.ts +673 -0
  251. package/src/map/adapter/acp-over-map.ts +45 -2
  252. package/src/map/adapter/event-translator.ts +1 -0
  253. package/src/map/adapter/extensions/agent-detection.ts +201 -0
  254. package/src/map/adapter/extensions/index.ts +63 -0
  255. package/src/map/adapter/extensions/resume.ts +114 -0
  256. package/src/map/adapter/extensions/workspace-files.ts +449 -0
  257. package/src/mcp/mcp-server.ts +67 -0
  258. package/src/mcp/tools/claim_task.ts +86 -0
  259. package/src/mcp/tools/done.ts +24 -10
  260. package/src/mcp/tools/list_claimable_tasks.ts +93 -0
  261. package/src/mcp/tools/unclaim_task.ts +71 -0
  262. package/src/metrics/index.ts +9 -0
  263. package/src/metrics/metrics.ts +280 -0
  264. package/src/roles/capabilities.ts +3 -0
  265. package/src/roles/types.ts +2 -1
  266. package/src/router/__tests__/message-router.test.ts +561 -0
  267. package/src/router/message-router.ts +223 -6
  268. package/src/store/event-store.ts +151 -3
  269. package/src/store/types/agents.ts +1 -1
  270. package/src/store/types/events.ts +2 -1
  271. package/src/store/types/index.ts +1 -0
  272. package/src/store/types/sessions.ts +53 -0
  273. package/src/store/types/tasks.ts +3 -0
  274. package/src/task/backend/memory.ts +116 -0
  275. package/src/task/backend/types.ts +43 -0
  276. package/src/teams/__tests__/cross-subsystem.integration.test.ts +983 -0
  277. package/src/teams/__tests__/e2e/team-runtime.e2e.test.ts +553 -0
  278. package/src/teams/__tests__/team-system.test.ts +1280 -0
  279. package/src/teams/index.ts +13 -0
  280. package/src/teams/team-loader.ts +434 -0
  281. package/src/teams/team-runtime.ts +727 -0
  282. package/src/teams/types.ts +377 -0
  283. package/src/workspace/dataplane-adapter.ts +1 -1
  284. package/src/workspace/index.ts +1 -1
  285. package/src/workspace/strategies/index.ts +18 -0
  286. package/src/workspace/strategies/optimistic.ts +136 -0
  287. package/src/workspace/strategies/queue.ts +81 -0
  288. package/src/workspace/strategies/registry.ts +89 -0
  289. package/src/workspace/strategies/trunk.ts +123 -0
  290. package/src/workspace/strategies/types.ts +145 -0
  291. package/src/workspace/types.ts +1 -1
  292. package/src/workspace/workspace-manager.ts +1 -1
  293. package/.claude/settings.local.json +0 -59
  294. package/dist/map/utils/address-translation.d.ts +0 -99
  295. package/dist/map/utils/address-translation.d.ts.map +0 -1
  296. package/dist/map/utils/address-translation.js +0 -285
  297. package/dist/map/utils/address-translation.js.map +0 -1
  298. package/dist/map/utils/index.d.ts +0 -7
  299. package/dist/map/utils/index.d.ts.map +0 -1
  300. package/dist/map/utils/index.js +0 -7
  301. package/dist/map/utils/index.js.map +0 -1
  302. package/references/acp-factory-ref/CHANGELOG.md +0 -33
  303. package/references/acp-factory-ref/LICENSE +0 -21
  304. package/references/acp-factory-ref/README.md +0 -341
  305. package/references/acp-factory-ref/package-lock.json +0 -3102
  306. package/references/acp-factory-ref/package.json +0 -96
  307. package/references/acp-factory-ref/python/CHANGELOG.md +0 -33
  308. package/references/acp-factory-ref/python/LICENSE +0 -21
  309. package/references/acp-factory-ref/python/Makefile +0 -57
  310. package/references/acp-factory-ref/python/README.md +0 -253
  311. package/references/acp-factory-ref/python/pyproject.toml +0 -73
  312. package/references/acp-factory-ref/python/tests/__init__.py +0 -0
  313. package/references/acp-factory-ref/python/tests/e2e/__init__.py +0 -1
  314. package/references/acp-factory-ref/python/tests/e2e/test_codex_e2e.py +0 -349
  315. package/references/acp-factory-ref/python/tests/e2e/test_gemini_e2e.py +0 -165
  316. package/references/acp-factory-ref/python/tests/e2e/test_opencode_e2e.py +0 -296
  317. package/references/acp-factory-ref/python/tests/test_client_handler.py +0 -543
  318. package/references/acp-factory-ref/python/tests/test_pushable.py +0 -199
  319. package/references/claude-code-acp/.github/workflows/ci.yml +0 -45
  320. package/references/claude-code-acp/.github/workflows/publish.yml +0 -34
  321. package/references/claude-code-acp/.prettierrc.json +0 -4
  322. package/references/claude-code-acp/CHANGELOG.md +0 -249
  323. package/references/claude-code-acp/LICENSE +0 -222
  324. package/references/claude-code-acp/README.md +0 -53
  325. package/references/claude-code-acp/docs/RELEASES.md +0 -24
  326. package/references/claude-code-acp/eslint.config.js +0 -48
  327. package/references/claude-code-acp/package-lock.json +0 -4570
  328. package/references/claude-code-acp/package.json +0 -88
  329. package/references/claude-code-acp/scripts/release.sh +0 -119
  330. package/references/claude-code-acp/src/acp-agent.ts +0 -2065
  331. package/references/claude-code-acp/src/index.ts +0 -26
  332. package/references/claude-code-acp/src/lib.ts +0 -38
  333. package/references/claude-code-acp/src/mcp-server.ts +0 -911
  334. package/references/claude-code-acp/src/settings.ts +0 -522
  335. package/references/claude-code-acp/src/tests/.claude/commands/quick-math.md +0 -5
  336. package/references/claude-code-acp/src/tests/.claude/commands/say-hello.md +0 -6
  337. package/references/claude-code-acp/src/tests/acp-agent-fork.test.ts +0 -479
  338. package/references/claude-code-acp/src/tests/acp-agent.test.ts +0 -1502
  339. package/references/claude-code-acp/src/tests/extract-lines.test.ts +0 -103
  340. package/references/claude-code-acp/src/tests/fork-session.test.ts +0 -335
  341. package/references/claude-code-acp/src/tests/replace-and-calculate-location.test.ts +0 -334
  342. package/references/claude-code-acp/src/tests/settings.test.ts +0 -617
  343. package/references/claude-code-acp/src/tests/skills-options.test.ts +0 -187
  344. package/references/claude-code-acp/src/tests/tools.test.ts +0 -318
  345. package/references/claude-code-acp/src/tests/typescript-declarations.test.ts +0 -558
  346. package/references/claude-code-acp/src/tools.ts +0 -819
  347. package/references/claude-code-acp/src/utils.ts +0 -171
  348. package/references/claude-code-acp/tsconfig.json +0 -18
  349. package/references/claude-code-acp/vitest.config.ts +0 -19
  350. package/references/multi-agent-protocol/.sudocode/issues.jsonl +0 -111
  351. package/references/multi-agent-protocol/.sudocode/specs.jsonl +0 -13
  352. package/references/multi-agent-protocol/LICENSE +0 -21
  353. package/references/multi-agent-protocol/README.md +0 -113
  354. package/references/multi-agent-protocol/docs/00-design-specification.md +0 -496
  355. package/references/multi-agent-protocol/docs/01-open-questions.md +0 -1050
  356. package/references/multi-agent-protocol/docs/02-wire-protocol.md +0 -296
  357. package/references/multi-agent-protocol/docs/03-streaming-semantics.md +0 -252
  358. package/references/multi-agent-protocol/docs/04-error-handling.md +0 -231
  359. package/references/multi-agent-protocol/docs/05-connection-model.md +0 -244
  360. package/references/multi-agent-protocol/docs/06-visibility-permissions.md +0 -243
  361. package/references/multi-agent-protocol/docs/07-federation.md +0 -259
  362. package/references/multi-agent-protocol/docs/08-macro-agent-migration.md +0 -253
  363. package/references/multi-agent-protocol/docs/09-authentication.md +0 -680
  364. package/references/multi-agent-protocol/docs/10-mail-protocol.md +0 -553
  365. package/references/multi-agent-protocol/docs/agent-iam-integration.md +0 -877
  366. package/references/multi-agent-protocol/docs/agentic-mesh-integration-draft.md +0 -459
  367. package/references/multi-agent-protocol/docs/git-transport-draft.md +0 -251
  368. package/references/multi-agent-protocol/docs-site/Gemfile +0 -22
  369. package/references/multi-agent-protocol/docs-site/README.md +0 -82
  370. package/references/multi-agent-protocol/docs-site/_config.yml +0 -91
  371. package/references/multi-agent-protocol/docs-site/_includes/head_custom.html +0 -20
  372. package/references/multi-agent-protocol/docs-site/_sass/color_schemes/map.scss +0 -42
  373. package/references/multi-agent-protocol/docs-site/_sass/custom/custom.scss +0 -34
  374. package/references/multi-agent-protocol/docs-site/examples/full-integration.md +0 -510
  375. package/references/multi-agent-protocol/docs-site/examples/index.md +0 -138
  376. package/references/multi-agent-protocol/docs-site/examples/simple-chat.md +0 -282
  377. package/references/multi-agent-protocol/docs-site/examples/task-queue.md +0 -399
  378. package/references/multi-agent-protocol/docs-site/getting-started/index.md +0 -98
  379. package/references/multi-agent-protocol/docs-site/getting-started/installation.md +0 -219
  380. package/references/multi-agent-protocol/docs-site/getting-started/overview.md +0 -172
  381. package/references/multi-agent-protocol/docs-site/getting-started/quickstart.md +0 -237
  382. package/references/multi-agent-protocol/docs-site/index.md +0 -136
  383. package/references/multi-agent-protocol/docs-site/protocol/authentication.md +0 -391
  384. package/references/multi-agent-protocol/docs-site/protocol/connection-model.md +0 -376
  385. package/references/multi-agent-protocol/docs-site/protocol/design.md +0 -284
  386. package/references/multi-agent-protocol/docs-site/protocol/error-handling.md +0 -312
  387. package/references/multi-agent-protocol/docs-site/protocol/federation.md +0 -449
  388. package/references/multi-agent-protocol/docs-site/protocol/index.md +0 -129
  389. package/references/multi-agent-protocol/docs-site/protocol/permissions.md +0 -398
  390. package/references/multi-agent-protocol/docs-site/protocol/streaming.md +0 -353
  391. package/references/multi-agent-protocol/docs-site/protocol/wire-protocol.md +0 -369
  392. package/references/multi-agent-protocol/docs-site/sdk/api/agent.md +0 -357
  393. package/references/multi-agent-protocol/docs-site/sdk/api/client.md +0 -380
  394. package/references/multi-agent-protocol/docs-site/sdk/api/index.md +0 -62
  395. package/references/multi-agent-protocol/docs-site/sdk/api/server.md +0 -453
  396. package/references/multi-agent-protocol/docs-site/sdk/api/types.md +0 -468
  397. package/references/multi-agent-protocol/docs-site/sdk/guides/agent.md +0 -375
  398. package/references/multi-agent-protocol/docs-site/sdk/guides/authentication.md +0 -405
  399. package/references/multi-agent-protocol/docs-site/sdk/guides/client.md +0 -352
  400. package/references/multi-agent-protocol/docs-site/sdk/guides/index.md +0 -89
  401. package/references/multi-agent-protocol/docs-site/sdk/guides/server.md +0 -360
  402. package/references/multi-agent-protocol/docs-site/sdk/guides/testing.md +0 -446
  403. package/references/multi-agent-protocol/docs-site/sdk/guides/transports.md +0 -363
  404. package/references/multi-agent-protocol/docs-site/sdk/index.md +0 -206
  405. package/references/multi-agent-protocol/package-lock.json +0 -3886
  406. package/references/multi-agent-protocol/package.json +0 -56
  407. package/references/multi-agent-protocol/schema/meta.json +0 -467
  408. package/references/multi-agent-protocol/schema/schema.json +0 -2558
@@ -0,0 +1,673 @@
1
+ /**
2
+ * Tests for Workspace File Search Extension Methods (_macro/workspace/files/*)
3
+ *
4
+ * Tests the search, list, and read handlers using a real temporary filesystem.
5
+ */
6
+
7
+ import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
8
+ import * as fs from "fs";
9
+ import * as path from "path";
10
+ import * as os from "os";
11
+ import {
12
+ registerWorkspaceFileExtensions,
13
+ unregisterWorkspaceFileExtensions,
14
+ type WorkspaceFileServices,
15
+ } from "../extensions/workspace-files.js";
16
+ import type { MAPAdapter, ExtensionHandler, ExtensionContext } from "../interface.js";
17
+ import type { ParticipantCapabilities } from "../types.js";
18
+ import type { AgentId } from "../../../store/types/index.js";
19
+
20
+ // =============================================================================
21
+ // Mock Setup
22
+ // =============================================================================
23
+
24
+ function createMockAdapter(): MAPAdapter & {
25
+ handlers: Map<string, ExtensionHandler>;
26
+ } {
27
+ const handlers = new Map<string, ExtensionHandler>();
28
+
29
+ return {
30
+ handlers,
31
+ registerExtension: vi.fn((method: string, handler: ExtensionHandler) => {
32
+ handlers.set(method, handler);
33
+ }),
34
+ unregisterExtension: vi.fn((method: string) => {
35
+ handlers.delete(method);
36
+ }),
37
+ hasExtension: vi.fn((method: string) => handlers.has(method)),
38
+ getExtensions: vi.fn(() => Array.from(handlers.keys())),
39
+ start: vi.fn(),
40
+ stop: vi.fn(),
41
+ isRunning: vi.fn().mockReturnValue(true),
42
+ acceptConnection: vi.fn(),
43
+ disconnectParticipant: vi.fn(),
44
+ getParticipant: vi.fn(),
45
+ getParticipants: vi.fn().mockReturnValue([]),
46
+ createSubscription: vi.fn(),
47
+ removeSubscription: vi.fn(),
48
+ pauseSubscription: vi.fn(),
49
+ resumeSubscription: vi.fn(),
50
+ getSubscriptions: vi.fn().mockReturnValue([]),
51
+ emitEvent: vi.fn(),
52
+ listAgents: vi.fn().mockReturnValue([]),
53
+ getAgent: vi.fn(),
54
+ listScopes: vi.fn().mockReturnValue([]),
55
+ getScope: vi.fn(),
56
+ sendMessage: vi.fn(),
57
+ onEvent: vi.fn().mockReturnValue(() => {}),
58
+ config: { name: "test", version: "1.0.0" },
59
+ } as unknown as MAPAdapter & { handlers: Map<string, ExtensionHandler> };
60
+ }
61
+
62
+ function createMockContext(): ExtensionContext {
63
+ return {
64
+ participantId: "p-test" as any,
65
+ capabilities: {
66
+ canQuery: true,
67
+ canSubscribe: true,
68
+ canMessage: true,
69
+ canManageTasks: true,
70
+ } as ParticipantCapabilities,
71
+ sessionId: "s-test",
72
+ };
73
+ }
74
+
75
+ // =============================================================================
76
+ // Temporary Workspace Filesystem
77
+ // =============================================================================
78
+
79
+ let tmpDir: string;
80
+
81
+ function createTempWorkspace(): string {
82
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), "workspace-files-test-"));
83
+
84
+ // Create a file structure:
85
+ // src/
86
+ // index.ts
87
+ // utils/
88
+ // helpers.ts
89
+ // README.md
90
+ // package.json
91
+ // .git/ (excluded dir)
92
+ // config
93
+ // node_modules/ (excluded dir)
94
+ // foo.js
95
+ // image.png (binary extension)
96
+
97
+ fs.mkdirSync(path.join(dir, "src", "utils"), { recursive: true });
98
+ fs.writeFileSync(path.join(dir, "src", "index.ts"), 'export const main = "hello";');
99
+ fs.writeFileSync(path.join(dir, "src", "utils", "helpers.ts"), 'export function help() {}');
100
+ fs.writeFileSync(path.join(dir, "README.md"), "# Test Project");
101
+ fs.writeFileSync(path.join(dir, "package.json"), '{"name":"test"}');
102
+
103
+ // Excluded directories
104
+ fs.mkdirSync(path.join(dir, ".git"), { recursive: true });
105
+ fs.writeFileSync(path.join(dir, ".git", "config"), "git config");
106
+ fs.mkdirSync(path.join(dir, "node_modules"), { recursive: true });
107
+ fs.writeFileSync(path.join(dir, "node_modules", "foo.js"), "module");
108
+
109
+ // Binary file
110
+ fs.writeFileSync(path.join(dir, "image.png"), Buffer.from([0x89, 0x50, 0x4e, 0x47]));
111
+
112
+ return dir;
113
+ }
114
+
115
+ function cleanupTempWorkspace(dir: string): void {
116
+ fs.rmSync(dir, { recursive: true, force: true });
117
+ }
118
+
119
+ // =============================================================================
120
+ // Tests
121
+ // =============================================================================
122
+
123
+ describe("Workspace File Extensions", () => {
124
+ let adapter: MAPAdapter & { handlers: Map<string, ExtensionHandler> };
125
+ let services: WorkspaceFileServices;
126
+
127
+ beforeEach(() => {
128
+ tmpDir = createTempWorkspace();
129
+ adapter = createMockAdapter();
130
+
131
+ services = {
132
+ getWorkspace: vi.fn().mockReturnValue({ path: tmpDir }),
133
+ agentExists: vi.fn().mockReturnValue(true),
134
+ };
135
+ });
136
+
137
+ afterEach(() => {
138
+ cleanupTempWorkspace(tmpDir);
139
+ });
140
+
141
+ // ===========================================================================
142
+ // Registration
143
+ // ===========================================================================
144
+
145
+ describe("registration", () => {
146
+ it("registers all three workspace file methods", () => {
147
+ registerWorkspaceFileExtensions(adapter, services);
148
+
149
+ expect(adapter.handlers.has("_macro/workspace/files/search")).toBe(true);
150
+ expect(adapter.handlers.has("_macro/workspace/files/list")).toBe(true);
151
+ expect(adapter.handlers.has("_macro/workspace/files/read")).toBe(true);
152
+ });
153
+
154
+ it("unregisters all three workspace file methods", () => {
155
+ registerWorkspaceFileExtensions(adapter, services);
156
+ unregisterWorkspaceFileExtensions(adapter);
157
+
158
+ expect(adapter.handlers.has("_macro/workspace/files/search")).toBe(false);
159
+ expect(adapter.handlers.has("_macro/workspace/files/list")).toBe(false);
160
+ expect(adapter.handlers.has("_macro/workspace/files/read")).toBe(false);
161
+ });
162
+ });
163
+
164
+ // ===========================================================================
165
+ // _macro/workspace/files/search
166
+ // ===========================================================================
167
+
168
+ describe("_macro/workspace/files/search", () => {
169
+ it("finds files matching a query", async () => {
170
+ registerWorkspaceFileExtensions(adapter, services);
171
+ const handler = adapter.handlers.get("_macro/workspace/files/search")!;
172
+
173
+ const result = (await handler(createMockContext(), {
174
+ agentId: "agent-1",
175
+ query: "index",
176
+ })) as { files: Array<{ path: string; isDirectory: boolean }> };
177
+
178
+ expect(result.files).toHaveLength(1);
179
+ expect(result.files[0].path).toBe("src/index.ts");
180
+ expect(result.files[0].isDirectory).toBe(false);
181
+ });
182
+
183
+ it("finds files matching by extension", async () => {
184
+ registerWorkspaceFileExtensions(adapter, services);
185
+ const handler = adapter.handlers.get("_macro/workspace/files/search")!;
186
+
187
+ const result = (await handler(createMockContext(), {
188
+ agentId: "agent-1",
189
+ query: ".ts",
190
+ })) as { files: Array<{ path: string }> };
191
+
192
+ const paths = result.files.map((f) => f.path);
193
+ expect(paths).toContain("src/index.ts");
194
+ expect(paths).toContain("src/utils/helpers.ts");
195
+ });
196
+
197
+ it("returns MIME types for matched files", async () => {
198
+ registerWorkspaceFileExtensions(adapter, services);
199
+ const handler = adapter.handlers.get("_macro/workspace/files/search")!;
200
+
201
+ const result = (await handler(createMockContext(), {
202
+ agentId: "agent-1",
203
+ query: "index.ts",
204
+ })) as { files: Array<{ mime?: string }> };
205
+
206
+ expect(result.files[0].mime).toBe("text/typescript");
207
+ });
208
+
209
+ it("returns file sizes", async () => {
210
+ registerWorkspaceFileExtensions(adapter, services);
211
+ const handler = adapter.handlers.get("_macro/workspace/files/search")!;
212
+
213
+ const result = (await handler(createMockContext(), {
214
+ agentId: "agent-1",
215
+ query: "README",
216
+ })) as { files: Array<{ size?: number }> };
217
+
218
+ expect(result.files[0].size).toBeGreaterThan(0);
219
+ });
220
+
221
+ it("excludes node_modules and .git directories", async () => {
222
+ registerWorkspaceFileExtensions(adapter, services);
223
+ const handler = adapter.handlers.get("_macro/workspace/files/search")!;
224
+
225
+ // Search for something that exists in node_modules
226
+ const result = (await handler(createMockContext(), {
227
+ agentId: "agent-1",
228
+ query: "foo",
229
+ })) as { files: Array<{ path: string }> };
230
+
231
+ const paths = result.files.map((f) => f.path);
232
+ expect(paths).not.toContain("node_modules/foo.js");
233
+ });
234
+
235
+ it("excludes binary file extensions", async () => {
236
+ registerWorkspaceFileExtensions(adapter, services);
237
+ const handler = adapter.handlers.get("_macro/workspace/files/search")!;
238
+
239
+ const result = (await handler(createMockContext(), {
240
+ agentId: "agent-1",
241
+ query: "image",
242
+ })) as { files: Array<{ path: string }> };
243
+
244
+ const paths = result.files.map((f) => f.path);
245
+ expect(paths).not.toContain("image.png");
246
+ });
247
+
248
+ it("case-insensitive matching", async () => {
249
+ registerWorkspaceFileExtensions(adapter, services);
250
+ const handler = adapter.handlers.get("_macro/workspace/files/search")!;
251
+
252
+ const result = (await handler(createMockContext(), {
253
+ agentId: "agent-1",
254
+ query: "README",
255
+ })) as { files: Array<{ path: string }> };
256
+
257
+ expect(result.files).toHaveLength(1);
258
+ expect(result.files[0].path).toBe("README.md");
259
+ });
260
+
261
+ it("supports path-based queries with /", async () => {
262
+ registerWorkspaceFileExtensions(adapter, services);
263
+ const handler = adapter.handlers.get("_macro/workspace/files/search")!;
264
+
265
+ const result = (await handler(createMockContext(), {
266
+ agentId: "agent-1",
267
+ query: "src/utils",
268
+ })) as { files: Array<{ path: string }> };
269
+
270
+ const paths = result.files.map((f) => f.path);
271
+ // Should find the directory and the file inside
272
+ expect(paths).toContain("src/utils/");
273
+ expect(paths).toContain("src/utils/helpers.ts");
274
+ });
275
+
276
+ it("respects limit parameter", async () => {
277
+ registerWorkspaceFileExtensions(adapter, services);
278
+ const handler = adapter.handlers.get("_macro/workspace/files/search")!;
279
+
280
+ const result = (await handler(createMockContext(), {
281
+ agentId: "agent-1",
282
+ query: ".", // matches everything
283
+ limit: 2,
284
+ })) as { files: Array<{ path: string }> };
285
+
286
+ expect(result.files.length).toBeLessThanOrEqual(2);
287
+ });
288
+
289
+ it("searches within cwd subdirectory", async () => {
290
+ registerWorkspaceFileExtensions(adapter, services);
291
+ const handler = adapter.handlers.get("_macro/workspace/files/search")!;
292
+
293
+ const result = (await handler(createMockContext(), {
294
+ agentId: "agent-1",
295
+ query: "helpers",
296
+ cwd: "src/utils",
297
+ })) as { files: Array<{ path: string }> };
298
+
299
+ expect(result.files).toHaveLength(1);
300
+ expect(result.files[0].path).toBe("src/utils/helpers.ts");
301
+ });
302
+
303
+ it("returns empty array when no matches", async () => {
304
+ registerWorkspaceFileExtensions(adapter, services);
305
+ const handler = adapter.handlers.get("_macro/workspace/files/search")!;
306
+
307
+ const result = (await handler(createMockContext(), {
308
+ agentId: "agent-1",
309
+ query: "nonexistent-file-xyz",
310
+ })) as { files: Array<{ path: string }> };
311
+
312
+ expect(result.files).toEqual([]);
313
+ });
314
+
315
+ it("returns empty files when agent has no workspace", async () => {
316
+ (services.getWorkspace as ReturnType<typeof vi.fn>).mockReturnValue(null);
317
+ registerWorkspaceFileExtensions(adapter, services);
318
+ const handler = adapter.handlers.get("_macro/workspace/files/search")!;
319
+
320
+ const result = (await handler(createMockContext(), {
321
+ agentId: "agent-1",
322
+ query: "test",
323
+ })) as { files: unknown[] };
324
+
325
+ expect(result.files).toEqual([]);
326
+ });
327
+
328
+ it("throws for missing agentId", async () => {
329
+ registerWorkspaceFileExtensions(adapter, services);
330
+ const handler = adapter.handlers.get("_macro/workspace/files/search")!;
331
+
332
+ await expect(
333
+ handler(createMockContext(), { query: "test" })
334
+ ).rejects.toThrow("agentId is required");
335
+ });
336
+
337
+ it("throws for missing query", async () => {
338
+ registerWorkspaceFileExtensions(adapter, services);
339
+ const handler = adapter.handlers.get("_macro/workspace/files/search")!;
340
+
341
+ await expect(
342
+ handler(createMockContext(), { agentId: "agent-1" })
343
+ ).rejects.toThrow("query is required");
344
+ });
345
+
346
+ it("throws for non-existent agent", async () => {
347
+ (services.agentExists as ReturnType<typeof vi.fn>).mockReturnValue(false);
348
+ registerWorkspaceFileExtensions(adapter, services);
349
+ const handler = adapter.handlers.get("_macro/workspace/files/search")!;
350
+
351
+ await expect(
352
+ handler(createMockContext(), { agentId: "missing", query: "test" })
353
+ ).rejects.toThrow("not found");
354
+ });
355
+ });
356
+
357
+ // ===========================================================================
358
+ // _macro/workspace/files/list
359
+ // ===========================================================================
360
+
361
+ describe("_macro/workspace/files/list", () => {
362
+ it("lists files in root directory", async () => {
363
+ registerWorkspaceFileExtensions(adapter, services);
364
+ const handler = adapter.handlers.get("_macro/workspace/files/list")!;
365
+
366
+ const result = (await handler(createMockContext(), {
367
+ agentId: "agent-1",
368
+ })) as { files: Array<{ path: string; isDirectory: boolean }> };
369
+
370
+ const paths = result.files.map((f) => f.path);
371
+ expect(paths).toContain("src/");
372
+ expect(paths).toContain("README.md");
373
+ expect(paths).toContain("package.json");
374
+ });
375
+
376
+ it("lists directories before files (sorted)", async () => {
377
+ registerWorkspaceFileExtensions(adapter, services);
378
+ const handler = adapter.handlers.get("_macro/workspace/files/list")!;
379
+
380
+ const result = (await handler(createMockContext(), {
381
+ agentId: "agent-1",
382
+ })) as { files: Array<{ isDirectory: boolean }> };
383
+
384
+ // All directories should come before files
385
+ const firstFileIndex = result.files.findIndex((f) => !f.isDirectory);
386
+ const lastDirIndex = result.files.findLastIndex((f) => f.isDirectory);
387
+ if (firstFileIndex !== -1 && lastDirIndex !== -1) {
388
+ expect(lastDirIndex).toBeLessThan(firstFileIndex);
389
+ }
390
+ });
391
+
392
+ it("lists files in subdirectory", async () => {
393
+ registerWorkspaceFileExtensions(adapter, services);
394
+ const handler = adapter.handlers.get("_macro/workspace/files/list")!;
395
+
396
+ const result = (await handler(createMockContext(), {
397
+ agentId: "agent-1",
398
+ directory: "src",
399
+ })) as { files: Array<{ path: string }> };
400
+
401
+ const paths = result.files.map((f) => f.path);
402
+ expect(paths).toContain("src/utils/");
403
+ expect(paths).toContain("src/index.ts");
404
+ });
405
+
406
+ it("excludes node_modules and .git from listing", async () => {
407
+ registerWorkspaceFileExtensions(adapter, services);
408
+ const handler = adapter.handlers.get("_macro/workspace/files/list")!;
409
+
410
+ const result = (await handler(createMockContext(), {
411
+ agentId: "agent-1",
412
+ })) as { files: Array<{ path: string }> };
413
+
414
+ const paths = result.files.map((f) => f.path);
415
+ expect(paths).not.toContain("node_modules/");
416
+ expect(paths).not.toContain(".git/");
417
+ });
418
+
419
+ it("excludes binary files from listing", async () => {
420
+ registerWorkspaceFileExtensions(adapter, services);
421
+ const handler = adapter.handlers.get("_macro/workspace/files/list")!;
422
+
423
+ const result = (await handler(createMockContext(), {
424
+ agentId: "agent-1",
425
+ })) as { files: Array<{ path: string }> };
426
+
427
+ const paths = result.files.map((f) => f.path);
428
+ expect(paths).not.toContain("image.png");
429
+ });
430
+
431
+ it("returns MIME and size for files", async () => {
432
+ registerWorkspaceFileExtensions(adapter, services);
433
+ const handler = adapter.handlers.get("_macro/workspace/files/list")!;
434
+
435
+ const result = (await handler(createMockContext(), {
436
+ agentId: "agent-1",
437
+ directory: "src",
438
+ })) as { files: Array<{ path: string; mime?: string; size?: number; isDirectory: boolean }> };
439
+
440
+ const indexFile = result.files.find((f) => f.path === "src/index.ts");
441
+ expect(indexFile).toBeDefined();
442
+ expect(indexFile!.mime).toBe("text/typescript");
443
+ expect(indexFile!.size).toBeGreaterThan(0);
444
+ });
445
+
446
+ it("returns empty files when agent has no workspace", async () => {
447
+ (services.getWorkspace as ReturnType<typeof vi.fn>).mockReturnValue(null);
448
+ registerWorkspaceFileExtensions(adapter, services);
449
+ const handler = adapter.handlers.get("_macro/workspace/files/list")!;
450
+
451
+ const result = (await handler(createMockContext(), {
452
+ agentId: "agent-1",
453
+ })) as { files: unknown[] };
454
+
455
+ expect(result.files).toEqual([]);
456
+ });
457
+
458
+ it("throws for missing agentId", async () => {
459
+ registerWorkspaceFileExtensions(adapter, services);
460
+ const handler = adapter.handlers.get("_macro/workspace/files/list")!;
461
+
462
+ await expect(handler(createMockContext(), {})).rejects.toThrow(
463
+ "agentId is required"
464
+ );
465
+ });
466
+
467
+ it("throws for non-existent agent", async () => {
468
+ (services.agentExists as ReturnType<typeof vi.fn>).mockReturnValue(false);
469
+ registerWorkspaceFileExtensions(adapter, services);
470
+ const handler = adapter.handlers.get("_macro/workspace/files/list")!;
471
+
472
+ await expect(
473
+ handler(createMockContext(), { agentId: "missing" })
474
+ ).rejects.toThrow("not found");
475
+ });
476
+
477
+ it("throws for non-existent directory", async () => {
478
+ registerWorkspaceFileExtensions(adapter, services);
479
+ const handler = adapter.handlers.get("_macro/workspace/files/list")!;
480
+
481
+ await expect(
482
+ handler(createMockContext(), { agentId: "agent-1", directory: "nonexistent" })
483
+ ).rejects.toThrow("Directory not found");
484
+ });
485
+ });
486
+
487
+ // ===========================================================================
488
+ // _macro/workspace/files/read
489
+ // ===========================================================================
490
+
491
+ describe("_macro/workspace/files/read", () => {
492
+ it("reads file contents", async () => {
493
+ registerWorkspaceFileExtensions(adapter, services);
494
+ const handler = adapter.handlers.get("_macro/workspace/files/read")!;
495
+
496
+ const result = (await handler(createMockContext(), {
497
+ agentId: "agent-1",
498
+ path: "src/index.ts",
499
+ })) as { text: string; mime: string; size: number };
500
+
501
+ expect(result.text).toBe('export const main = "hello";');
502
+ expect(result.mime).toBe("text/typescript");
503
+ expect(result.size).toBeGreaterThan(0);
504
+ });
505
+
506
+ it("reads file with correct MIME type", async () => {
507
+ registerWorkspaceFileExtensions(adapter, services);
508
+ const handler = adapter.handlers.get("_macro/workspace/files/read")!;
509
+
510
+ const result = (await handler(createMockContext(), {
511
+ agentId: "agent-1",
512
+ path: "README.md",
513
+ })) as { text: string; mime: string };
514
+
515
+ expect(result.text).toBe("# Test Project");
516
+ expect(result.mime).toBe("text/markdown");
517
+ });
518
+
519
+ it("reads JSON file", async () => {
520
+ registerWorkspaceFileExtensions(adapter, services);
521
+ const handler = adapter.handlers.get("_macro/workspace/files/read")!;
522
+
523
+ const result = (await handler(createMockContext(), {
524
+ agentId: "agent-1",
525
+ path: "package.json",
526
+ })) as { text: string; mime: string };
527
+
528
+ expect(result.text).toBe('{"name":"test"}');
529
+ expect(result.mime).toBe("application/json");
530
+ });
531
+
532
+ it("supports lineRange", async () => {
533
+ // Create a multi-line file
534
+ const multiLineContent = "line 1\nline 2\nline 3\nline 4\nline 5";
535
+ fs.writeFileSync(path.join(tmpDir, "multiline.txt"), multiLineContent);
536
+
537
+ registerWorkspaceFileExtensions(adapter, services);
538
+ const handler = adapter.handlers.get("_macro/workspace/files/read")!;
539
+
540
+ const result = (await handler(createMockContext(), {
541
+ agentId: "agent-1",
542
+ path: "multiline.txt",
543
+ lineRange: { start: 2, end: 4 },
544
+ })) as { text: string };
545
+
546
+ expect(result.text).toBe("line 2\nline 3\nline 4");
547
+ });
548
+
549
+ it("throws for invalid lineRange (start < 1)", async () => {
550
+ fs.writeFileSync(path.join(tmpDir, "lines.txt"), "line 1\nline 2");
551
+ registerWorkspaceFileExtensions(adapter, services);
552
+ const handler = adapter.handlers.get("_macro/workspace/files/read")!;
553
+
554
+ await expect(
555
+ handler(createMockContext(), {
556
+ agentId: "agent-1",
557
+ path: "lines.txt",
558
+ lineRange: { start: 0, end: 2 },
559
+ })
560
+ ).rejects.toThrow("lineRange must have start >= 1");
561
+ });
562
+
563
+ it("throws for invalid lineRange (end < start)", async () => {
564
+ fs.writeFileSync(path.join(tmpDir, "lines.txt"), "line 1\nline 2");
565
+ registerWorkspaceFileExtensions(adapter, services);
566
+ const handler = adapter.handlers.get("_macro/workspace/files/read")!;
567
+
568
+ await expect(
569
+ handler(createMockContext(), {
570
+ agentId: "agent-1",
571
+ path: "lines.txt",
572
+ lineRange: { start: 3, end: 1 },
573
+ })
574
+ ).rejects.toThrow("lineRange must have start >= 1");
575
+ });
576
+
577
+ it("throws for missing agentId", async () => {
578
+ registerWorkspaceFileExtensions(adapter, services);
579
+ const handler = adapter.handlers.get("_macro/workspace/files/read")!;
580
+
581
+ await expect(
582
+ handler(createMockContext(), { path: "src/index.ts" })
583
+ ).rejects.toThrow("agentId is required");
584
+ });
585
+
586
+ it("throws for missing path", async () => {
587
+ registerWorkspaceFileExtensions(adapter, services);
588
+ const handler = adapter.handlers.get("_macro/workspace/files/read")!;
589
+
590
+ await expect(
591
+ handler(createMockContext(), { agentId: "agent-1" })
592
+ ).rejects.toThrow("path is required");
593
+ });
594
+
595
+ it("throws for non-existent agent", async () => {
596
+ (services.agentExists as ReturnType<typeof vi.fn>).mockReturnValue(false);
597
+ registerWorkspaceFileExtensions(adapter, services);
598
+ const handler = adapter.handlers.get("_macro/workspace/files/read")!;
599
+
600
+ await expect(
601
+ handler(createMockContext(), { agentId: "missing", path: "src/index.ts" })
602
+ ).rejects.toThrow("not found");
603
+ });
604
+
605
+ it("throws for agent without workspace", async () => {
606
+ (services.getWorkspace as ReturnType<typeof vi.fn>).mockReturnValue(null);
607
+ registerWorkspaceFileExtensions(adapter, services);
608
+ const handler = adapter.handlers.get("_macro/workspace/files/read")!;
609
+
610
+ await expect(
611
+ handler(createMockContext(), { agentId: "agent-1", path: "src/index.ts" })
612
+ ).rejects.toThrow("has no workspace");
613
+ });
614
+
615
+ it("throws for non-existent file", async () => {
616
+ registerWorkspaceFileExtensions(adapter, services);
617
+ const handler = adapter.handlers.get("_macro/workspace/files/read")!;
618
+
619
+ await expect(
620
+ handler(createMockContext(), { agentId: "agent-1", path: "nonexistent.ts" })
621
+ ).rejects.toThrow("File not found");
622
+ });
623
+
624
+ it("throws for directory path", async () => {
625
+ registerWorkspaceFileExtensions(adapter, services);
626
+ const handler = adapter.handlers.get("_macro/workspace/files/read")!;
627
+
628
+ await expect(
629
+ handler(createMockContext(), { agentId: "agent-1", path: "src" })
630
+ ).rejects.toThrow("Path is a directory");
631
+ });
632
+
633
+ it("rejects path traversal attempts", async () => {
634
+ registerWorkspaceFileExtensions(adapter, services);
635
+ const handler = adapter.handlers.get("_macro/workspace/files/read")!;
636
+
637
+ await expect(
638
+ handler(createMockContext(), { agentId: "agent-1", path: "../../etc/passwd" })
639
+ ).rejects.toThrow("Path traversal not allowed");
640
+ });
641
+ });
642
+
643
+ // ===========================================================================
644
+ // Path Traversal (across all handlers)
645
+ // ===========================================================================
646
+
647
+ describe("path traversal protection", () => {
648
+ it("search rejects cwd with path traversal", async () => {
649
+ registerWorkspaceFileExtensions(adapter, services);
650
+ const handler = adapter.handlers.get("_macro/workspace/files/search")!;
651
+
652
+ await expect(
653
+ handler(createMockContext(), {
654
+ agentId: "agent-1",
655
+ query: "test",
656
+ cwd: "../../etc",
657
+ })
658
+ ).rejects.toThrow("Path traversal not allowed");
659
+ });
660
+
661
+ it("list rejects directory with path traversal", async () => {
662
+ registerWorkspaceFileExtensions(adapter, services);
663
+ const handler = adapter.handlers.get("_macro/workspace/files/list")!;
664
+
665
+ await expect(
666
+ handler(createMockContext(), {
667
+ agentId: "agent-1",
668
+ directory: "../../etc",
669
+ })
670
+ ).rejects.toThrow("Path traversal not allowed");
671
+ });
672
+ });
673
+ });