@diff-review-system/drs 4.0.0-rc.4 → 4.1.0

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 (419) hide show
  1. package/.pi/agents/describe/pr-describer.md +14 -0
  2. package/.pi/agents/review/unified-reviewer.md +33 -7
  3. package/.pi/agents/task/agents-md-updater.md +3 -1
  4. package/.pi/agents/task/review-assistant.md +22 -0
  5. package/.pi/agents/task/review-issue-fixer.md +18 -1
  6. package/.pi/agents/visual/pr-explainer.md +205 -0
  7. package/.pi/workflows/github-pr-describe.yaml +10 -7
  8. package/.pi/workflows/github-pr-fix-review-issues-stacked.yaml +154 -0
  9. package/.pi/workflows/github-pr-post-comment.yaml +10 -10
  10. package/.pi/workflows/github-pr-review-post.yaml +18 -8
  11. package/.pi/workflows/github-pr-review.yaml +354 -7
  12. package/.pi/workflows/github-pr-show-changes.yaml +8 -8
  13. package/.pi/workflows/github-pr-update-agents-md-stacked.yaml +103 -0
  14. package/.pi/workflows/github-pr-visual-explain.yaml +80 -0
  15. package/.pi/workflows/gitlab-mr-describe.yaml +8 -5
  16. package/.pi/workflows/gitlab-mr-fix-review-issues-stacked.yaml +150 -0
  17. package/.pi/workflows/gitlab-mr-post-comment.yaml +8 -8
  18. package/.pi/workflows/gitlab-mr-review.yaml +354 -5
  19. package/.pi/workflows/gitlab-mr-show-changes.yaml +6 -6
  20. package/.pi/workflows/gitlab-mr-update-agents-md-stacked.yaml +100 -0
  21. package/.pi/workflows/gitlab-mr-visual-explain.yaml +78 -0
  22. package/.pi/workflows/local-fix-review-issues.yaml +89 -13
  23. package/.pi/workflows/local-review.yaml +15 -2
  24. package/.pi/workflows/local-update-agents-md.yaml +1 -1
  25. package/.pi/workflows/local-visual-explain.yaml +76 -0
  26. package/.pi/workflows/release-changelog-finalize.yaml +47 -0
  27. package/.pi/workflows/tag-changelog-update.yaml +4 -4
  28. package/.pi/workflows/temporal-control-smoke.yaml +63 -0
  29. package/README.md +130 -27
  30. package/dist/ci/runner.d.ts.map +1 -1
  31. package/dist/ci/runner.js +3 -1
  32. package/dist/ci/runner.js.map +1 -1
  33. package/dist/cli/index.js +258 -9
  34. package/dist/cli/index.js.map +1 -1
  35. package/dist/cli/init.d.ts +6 -1
  36. package/dist/cli/init.d.ts.map +1 -1
  37. package/dist/cli/init.js +29 -10
  38. package/dist/cli/init.js.map +1 -1
  39. package/dist/cli/run-agent.d.ts +4 -7
  40. package/dist/cli/run-agent.d.ts.map +1 -1
  41. package/dist/cli/run-agent.js +4 -0
  42. package/dist/cli/run-agent.js.map +1 -1
  43. package/dist/cli/workflow-executor-selection.d.ts +3 -0
  44. package/dist/cli/workflow-executor-selection.d.ts.map +1 -0
  45. package/dist/cli/workflow-executor-selection.js +15 -0
  46. package/dist/cli/workflow-executor-selection.js.map +1 -0
  47. package/dist/cli/workflow.d.ts +76 -26
  48. package/dist/cli/workflow.d.ts.map +1 -1
  49. package/dist/cli/workflow.js +1624 -192
  50. package/dist/cli/workflow.js.map +1 -1
  51. package/dist/github/client.d.ts +12 -0
  52. package/dist/github/client.d.ts.map +1 -1
  53. package/dist/github/client.js +27 -0
  54. package/dist/github/client.js.map +1 -1
  55. package/dist/github/platform-adapter.d.ts +6 -1
  56. package/dist/github/platform-adapter.d.ts.map +1 -1
  57. package/dist/github/platform-adapter.js +84 -8
  58. package/dist/github/platform-adapter.js.map +1 -1
  59. package/dist/gitlab/client.d.ts +11 -0
  60. package/dist/gitlab/client.d.ts.map +1 -1
  61. package/dist/gitlab/client.js +11 -0
  62. package/dist/gitlab/client.js.map +1 -1
  63. package/dist/gitlab/platform-adapter.d.ts +3 -1
  64. package/dist/gitlab/platform-adapter.d.ts.map +1 -1
  65. package/dist/gitlab/platform-adapter.js +32 -1
  66. package/dist/gitlab/platform-adapter.js.map +1 -1
  67. package/dist/lib/agent-result.d.ts +8 -0
  68. package/dist/lib/agent-result.d.ts.map +1 -0
  69. package/dist/lib/agent-result.js +2 -0
  70. package/dist/lib/agent-result.js.map +1 -0
  71. package/dist/lib/comment-formatter.d.ts +8 -0
  72. package/dist/lib/comment-formatter.d.ts.map +1 -1
  73. package/dist/lib/comment-formatter.js +12 -4
  74. package/dist/lib/comment-formatter.js.map +1 -1
  75. package/dist/lib/comment-poster.d.ts.map +1 -1
  76. package/dist/lib/comment-poster.js +28 -1
  77. package/dist/lib/comment-poster.js.map +1 -1
  78. package/dist/lib/config.d.ts +71 -11
  79. package/dist/lib/config.d.ts.map +1 -1
  80. package/dist/lib/config.js +163 -28
  81. package/dist/lib/config.js.map +1 -1
  82. package/dist/lib/context-compression.d.ts +10 -0
  83. package/dist/lib/context-compression.d.ts.map +1 -1
  84. package/dist/lib/context-compression.js +101 -13
  85. package/dist/lib/context-compression.js.map +1 -1
  86. package/dist/lib/context-loader.d.ts +2 -1
  87. package/dist/lib/context-loader.d.ts.map +1 -1
  88. package/dist/lib/context-loader.js +70 -1
  89. package/dist/lib/context-loader.js.map +1 -1
  90. package/dist/lib/describe-core.d.ts.map +1 -1
  91. package/dist/lib/describe-core.js +3 -2
  92. package/dist/lib/describe-core.js.map +1 -1
  93. package/dist/lib/diff-lines.d.ts +9 -0
  94. package/dist/lib/diff-lines.d.ts.map +1 -1
  95. package/dist/lib/diff-lines.js +17 -9
  96. package/dist/lib/diff-lines.js.map +1 -1
  97. package/dist/lib/exit.js +4 -4
  98. package/dist/lib/exit.js.map +1 -1
  99. package/dist/lib/html-artifact.d.ts +14 -0
  100. package/dist/lib/html-artifact.d.ts.map +1 -0
  101. package/dist/lib/html-artifact.js +59 -0
  102. package/dist/lib/html-artifact.js.map +1 -0
  103. package/dist/lib/issue-parser.js +3 -3
  104. package/dist/lib/issue-parser.js.map +1 -1
  105. package/dist/lib/json-output-schema.d.ts +70 -0
  106. package/dist/lib/json-output-schema.d.ts.map +1 -1
  107. package/dist/lib/json-output-schema.js +40 -0
  108. package/dist/lib/json-output-schema.js.map +1 -1
  109. package/dist/lib/output-paths.d.ts +0 -1
  110. package/dist/lib/output-paths.d.ts.map +1 -1
  111. package/dist/lib/output-paths.js +0 -1
  112. package/dist/lib/output-paths.js.map +1 -1
  113. package/dist/lib/platform-client.d.ts +26 -0
  114. package/dist/lib/platform-client.d.ts.map +1 -1
  115. package/dist/lib/project-setup.d.ts +10 -0
  116. package/dist/lib/project-setup.d.ts.map +1 -0
  117. package/dist/lib/project-setup.js +25 -0
  118. package/dist/lib/project-setup.js.map +1 -0
  119. package/dist/lib/review-artifact-store.d.ts +16 -0
  120. package/dist/lib/review-artifact-store.d.ts.map +1 -0
  121. package/dist/lib/review-artifact-store.js +84 -0
  122. package/dist/lib/review-artifact-store.js.map +1 -0
  123. package/dist/lib/review-artifact.d.ts +69 -0
  124. package/dist/lib/review-artifact.d.ts.map +1 -0
  125. package/dist/lib/review-artifact.js +172 -0
  126. package/dist/lib/review-artifact.js.map +1 -0
  127. package/dist/lib/review-core.d.ts +7 -4
  128. package/dist/lib/review-core.d.ts.map +1 -1
  129. package/dist/lib/review-core.js +82 -165
  130. package/dist/lib/review-core.js.map +1 -1
  131. package/dist/lib/review-orchestrator.d.ts +23 -0
  132. package/dist/lib/review-orchestrator.d.ts.map +1 -1
  133. package/dist/lib/review-orchestrator.js +20 -13
  134. package/dist/lib/review-orchestrator.js.map +1 -1
  135. package/dist/lib/review-parser.d.ts.map +1 -1
  136. package/dist/lib/review-parser.js +15 -12
  137. package/dist/lib/review-parser.js.map +1 -1
  138. package/dist/lib/review-usage.d.ts +4 -0
  139. package/dist/lib/review-usage.d.ts.map +1 -1
  140. package/dist/lib/review-usage.js +25 -0
  141. package/dist/lib/review-usage.js.map +1 -1
  142. package/dist/lib/skills.d.ts +16 -0
  143. package/dist/lib/skills.d.ts.map +1 -0
  144. package/dist/lib/skills.js +140 -0
  145. package/dist/lib/skills.js.map +1 -0
  146. package/dist/lib/trace-collector.d.ts +105 -0
  147. package/dist/lib/trace-collector.d.ts.map +1 -0
  148. package/dist/lib/trace-collector.js +255 -0
  149. package/dist/lib/trace-collector.js.map +1 -0
  150. package/dist/lib/trace-html.d.ts +3 -0
  151. package/dist/lib/trace-html.d.ts.map +1 -0
  152. package/dist/lib/trace-html.js +349 -0
  153. package/dist/lib/trace-html.js.map +1 -0
  154. package/dist/lib/workflow/artifact-store.d.ts +71 -0
  155. package/dist/lib/workflow/artifact-store.d.ts.map +1 -0
  156. package/dist/lib/workflow/artifact-store.js +121 -0
  157. package/dist/lib/workflow/artifact-store.js.map +1 -0
  158. package/dist/lib/workflow/compiled-plan.d.ts +87 -0
  159. package/dist/lib/workflow/compiled-plan.d.ts.map +1 -0
  160. package/dist/lib/workflow/compiled-plan.js +62 -0
  161. package/dist/lib/workflow/compiled-plan.js.map +1 -0
  162. package/dist/lib/workflow/executor.d.ts +18 -0
  163. package/dist/lib/workflow/executor.d.ts.map +1 -0
  164. package/dist/lib/workflow/executor.js +2 -0
  165. package/dist/lib/workflow/executor.js.map +1 -0
  166. package/dist/lib/workflow/graph.d.ts +30 -0
  167. package/dist/lib/workflow/graph.d.ts.map +1 -0
  168. package/dist/lib/workflow/graph.js +139 -0
  169. package/dist/lib/workflow/graph.js.map +1 -0
  170. package/dist/lib/workflow/input.d.ts +4 -0
  171. package/dist/lib/workflow/input.d.ts.map +1 -0
  172. package/dist/lib/workflow/input.js +4 -0
  173. package/dist/lib/workflow/input.js.map +1 -0
  174. package/dist/lib/workflow/node-executor.d.ts +19 -0
  175. package/dist/lib/workflow/node-executor.d.ts.map +1 -0
  176. package/dist/lib/workflow/node-executor.js +2 -0
  177. package/dist/lib/workflow/node-executor.js.map +1 -0
  178. package/dist/lib/workflow/planning.d.ts +51 -0
  179. package/dist/lib/workflow/planning.d.ts.map +1 -0
  180. package/dist/lib/workflow/planning.js +814 -0
  181. package/dist/lib/workflow/planning.js.map +1 -0
  182. package/dist/lib/workflow/types.d.ts +66 -0
  183. package/dist/lib/workflow/types.d.ts.map +1 -0
  184. package/dist/lib/workflow/types.js +2 -0
  185. package/dist/lib/workflow/types.js.map +1 -0
  186. package/dist/lib/workflow-artifacts.d.ts +54 -0
  187. package/dist/lib/workflow-artifacts.d.ts.map +1 -0
  188. package/dist/lib/workflow-artifacts.js +150 -0
  189. package/dist/lib/workflow-artifacts.js.map +1 -0
  190. package/dist/lib/write-json-output.d.ts.map +1 -1
  191. package/dist/lib/write-json-output.js +3 -8
  192. package/dist/lib/write-json-output.js.map +1 -1
  193. package/dist/pi/sdk.d.ts.map +1 -1
  194. package/dist/pi/sdk.js +576 -8
  195. package/dist/pi/sdk.js.map +1 -1
  196. package/dist/runtime/agent-loader.js +2 -2
  197. package/dist/runtime/built-in-paths.d.ts +1 -0
  198. package/dist/runtime/built-in-paths.d.ts.map +1 -1
  199. package/dist/runtime/built-in-paths.js +7 -0
  200. package/dist/runtime/built-in-paths.js.map +1 -1
  201. package/dist/runtime/client.d.ts +2 -0
  202. package/dist/runtime/client.d.ts.map +1 -1
  203. package/dist/runtime/client.js +11 -5
  204. package/dist/runtime/client.js.map +1 -1
  205. package/dist/temporal/activities.d.ts +26 -0
  206. package/dist/temporal/activities.d.ts.map +1 -0
  207. package/dist/temporal/activities.js +219 -0
  208. package/dist/temporal/activities.js.map +1 -0
  209. package/dist/temporal/config.d.ts +4 -0
  210. package/dist/temporal/config.d.ts.map +1 -0
  211. package/dist/temporal/config.js +36 -0
  212. package/dist/temporal/config.js.map +1 -0
  213. package/dist/temporal/executor.d.ts +7 -0
  214. package/dist/temporal/executor.d.ts.map +1 -0
  215. package/dist/temporal/executor.js +233 -0
  216. package/dist/temporal/executor.js.map +1 -0
  217. package/dist/temporal/retry-policy.d.ts +28 -0
  218. package/dist/temporal/retry-policy.d.ts.map +1 -0
  219. package/dist/temporal/retry-policy.js +56 -0
  220. package/dist/temporal/retry-policy.js.map +1 -0
  221. package/dist/temporal/types.d.ts +86 -0
  222. package/dist/temporal/types.d.ts.map +1 -0
  223. package/dist/temporal/types.js +2 -0
  224. package/dist/temporal/types.js.map +1 -0
  225. package/dist/temporal/worker.d.ts +3 -0
  226. package/dist/temporal/worker.d.ts.map +1 -0
  227. package/dist/temporal/worker.js +18 -0
  228. package/dist/temporal/worker.js.map +1 -0
  229. package/dist/temporal/workflow-id.d.ts +27 -0
  230. package/dist/temporal/workflow-id.d.ts.map +1 -0
  231. package/dist/temporal/workflow-id.js +53 -0
  232. package/dist/temporal/workflow-id.js.map +1 -0
  233. package/dist/temporal/workflows.d.ts +6 -0
  234. package/dist/temporal/workflows.d.ts.map +1 -0
  235. package/dist/temporal/workflows.js +342 -0
  236. package/dist/temporal/workflows.js.map +1 -0
  237. package/package.json +26 -15
  238. package/.pi/workflows/github-pr-describe-post.yaml +0 -24
  239. package/.pi/workflows/gitlab-mr-describe-post.yaml +0 -22
  240. package/.pi/workflows/gitlab-mr-review-code-quality.yaml +0 -31
  241. package/.pi/workflows/gitlab-mr-review-post-code-quality.yaml +0 -40
  242. package/.pi/workflows/gitlab-mr-review-post.yaml +0 -30
  243. package/.pi/workflows/local-staged-review.yaml +0 -17
  244. package/dist/cli/run-agent.test.d.ts +0 -2
  245. package/dist/cli/run-agent.test.d.ts.map +0 -1
  246. package/dist/cli/run-agent.test.js +0 -204
  247. package/dist/cli/run-agent.test.js.map +0 -1
  248. package/dist/cli/workflow.test.d.ts +0 -2
  249. package/dist/cli/workflow.test.d.ts.map +0 -1
  250. package/dist/cli/workflow.test.js +0 -1410
  251. package/dist/cli/workflow.test.js.map +0 -1
  252. package/dist/github/client.test.d.ts +0 -2
  253. package/dist/github/client.test.d.ts.map +0 -1
  254. package/dist/github/client.test.js +0 -206
  255. package/dist/github/client.test.js.map +0 -1
  256. package/dist/github/platform-adapter.test.d.ts +0 -2
  257. package/dist/github/platform-adapter.test.d.ts.map +0 -1
  258. package/dist/github/platform-adapter.test.js +0 -40
  259. package/dist/github/platform-adapter.test.js.map +0 -1
  260. package/dist/gitlab/diff-parser.test.d.ts +0 -2
  261. package/dist/gitlab/diff-parser.test.d.ts.map +0 -1
  262. package/dist/gitlab/diff-parser.test.js +0 -315
  263. package/dist/gitlab/diff-parser.test.js.map +0 -1
  264. package/dist/gitlab/platform-adapter.test.d.ts +0 -2
  265. package/dist/gitlab/platform-adapter.test.d.ts.map +0 -1
  266. package/dist/gitlab/platform-adapter.test.js +0 -21
  267. package/dist/gitlab/platform-adapter.test.js.map +0 -1
  268. package/dist/index.test.d.ts +0 -2
  269. package/dist/index.test.d.ts.map +0 -1
  270. package/dist/index.test.js +0 -7
  271. package/dist/index.test.js.map +0 -1
  272. package/dist/lib/code-quality-report.test.d.ts +0 -2
  273. package/dist/lib/code-quality-report.test.d.ts.map +0 -1
  274. package/dist/lib/code-quality-report.test.js +0 -327
  275. package/dist/lib/code-quality-report.test.js.map +0 -1
  276. package/dist/lib/comment-formatter.test.d.ts +0 -2
  277. package/dist/lib/comment-formatter.test.d.ts.map +0 -1
  278. package/dist/lib/comment-formatter.test.js +0 -727
  279. package/dist/lib/comment-formatter.test.js.map +0 -1
  280. package/dist/lib/comment-manager.test.d.ts +0 -2
  281. package/dist/lib/comment-manager.test.d.ts.map +0 -1
  282. package/dist/lib/comment-manager.test.js +0 -680
  283. package/dist/lib/comment-manager.test.js.map +0 -1
  284. package/dist/lib/comment-poster.test.d.ts +0 -5
  285. package/dist/lib/comment-poster.test.d.ts.map +0 -1
  286. package/dist/lib/comment-poster.test.js +0 -255
  287. package/dist/lib/comment-poster.test.js.map +0 -1
  288. package/dist/lib/config-model-overrides.test.d.ts +0 -2
  289. package/dist/lib/config-model-overrides.test.d.ts.map +0 -1
  290. package/dist/lib/config-model-overrides.test.js +0 -218
  291. package/dist/lib/config-model-overrides.test.js.map +0 -1
  292. package/dist/lib/config.test.d.ts +0 -2
  293. package/dist/lib/config.test.d.ts.map +0 -1
  294. package/dist/lib/config.test.js +0 -353
  295. package/dist/lib/config.test.js.map +0 -1
  296. package/dist/lib/context-compression.test.d.ts +0 -2
  297. package/dist/lib/context-compression.test.d.ts.map +0 -1
  298. package/dist/lib/context-compression.test.js +0 -337
  299. package/dist/lib/context-compression.test.js.map +0 -1
  300. package/dist/lib/context-loader.test.d.ts +0 -2
  301. package/dist/lib/context-loader.test.d.ts.map +0 -1
  302. package/dist/lib/context-loader.test.js +0 -212
  303. package/dist/lib/context-loader.test.js.map +0 -1
  304. package/dist/lib/cursor-fix-link.test.d.ts +0 -2
  305. package/dist/lib/cursor-fix-link.test.d.ts.map +0 -1
  306. package/dist/lib/cursor-fix-link.test.js +0 -70
  307. package/dist/lib/cursor-fix-link.test.js.map +0 -1
  308. package/dist/lib/describe-core.test.d.ts +0 -2
  309. package/dist/lib/describe-core.test.d.ts.map +0 -1
  310. package/dist/lib/describe-core.test.js +0 -208
  311. package/dist/lib/describe-core.test.js.map +0 -1
  312. package/dist/lib/describe-output-path.test.d.ts +0 -2
  313. package/dist/lib/describe-output-path.test.d.ts.map +0 -1
  314. package/dist/lib/describe-output-path.test.js +0 -51
  315. package/dist/lib/describe-output-path.test.js.map +0 -1
  316. package/dist/lib/describe-parser.test.d.ts +0 -2
  317. package/dist/lib/describe-parser.test.d.ts.map +0 -1
  318. package/dist/lib/describe-parser.test.js +0 -282
  319. package/dist/lib/describe-parser.test.js.map +0 -1
  320. package/dist/lib/description-executor.test.d.ts +0 -2
  321. package/dist/lib/description-executor.test.d.ts.map +0 -1
  322. package/dist/lib/description-executor.test.js +0 -135
  323. package/dist/lib/description-executor.test.js.map +0 -1
  324. package/dist/lib/description-formatter.test.d.ts +0 -2
  325. package/dist/lib/description-formatter.test.d.ts.map +0 -1
  326. package/dist/lib/description-formatter.test.js +0 -57
  327. package/dist/lib/description-formatter.test.js.map +0 -1
  328. package/dist/lib/diff-lines.test.d.ts +0 -2
  329. package/dist/lib/diff-lines.test.d.ts.map +0 -1
  330. package/dist/lib/diff-lines.test.js +0 -13
  331. package/dist/lib/diff-lines.test.js.map +0 -1
  332. package/dist/lib/diff-parser.test.d.ts +0 -2
  333. package/dist/lib/diff-parser.test.d.ts.map +0 -1
  334. package/dist/lib/diff-parser.test.js +0 -335
  335. package/dist/lib/diff-parser.test.js.map +0 -1
  336. package/dist/lib/error-comment-poster.test.d.ts +0 -2
  337. package/dist/lib/error-comment-poster.test.d.ts.map +0 -1
  338. package/dist/lib/error-comment-poster.test.js +0 -128
  339. package/dist/lib/error-comment-poster.test.js.map +0 -1
  340. package/dist/lib/exit.test.d.ts +0 -2
  341. package/dist/lib/exit.test.d.ts.map +0 -1
  342. package/dist/lib/exit.test.js +0 -120
  343. package/dist/lib/exit.test.js.map +0 -1
  344. package/dist/lib/issue-parser.test.d.ts +0 -2
  345. package/dist/lib/issue-parser.test.d.ts.map +0 -1
  346. package/dist/lib/issue-parser.test.js +0 -281
  347. package/dist/lib/issue-parser.test.js.map +0 -1
  348. package/dist/lib/json-output-schema.test.d.ts +0 -2
  349. package/dist/lib/json-output-schema.test.d.ts.map +0 -1
  350. package/dist/lib/json-output-schema.test.js +0 -92
  351. package/dist/lib/json-output-schema.test.js.map +0 -1
  352. package/dist/lib/json-output.test.d.ts +0 -2
  353. package/dist/lib/json-output.test.d.ts.map +0 -1
  354. package/dist/lib/json-output.test.js +0 -141
  355. package/dist/lib/json-output.test.js.map +0 -1
  356. package/dist/lib/logger.test.d.ts +0 -2
  357. package/dist/lib/logger.test.d.ts.map +0 -1
  358. package/dist/lib/logger.test.js +0 -324
  359. package/dist/lib/logger.test.js.map +0 -1
  360. package/dist/lib/position-validator.test.d.ts +0 -2
  361. package/dist/lib/position-validator.test.d.ts.map +0 -1
  362. package/dist/lib/position-validator.test.js +0 -128
  363. package/dist/lib/position-validator.test.js.map +0 -1
  364. package/dist/lib/prompt-budget.test.d.ts +0 -2
  365. package/dist/lib/prompt-budget.test.d.ts.map +0 -1
  366. package/dist/lib/prompt-budget.test.js +0 -55
  367. package/dist/lib/prompt-budget.test.js.map +0 -1
  368. package/dist/lib/repository-validator.test.d.ts +0 -5
  369. package/dist/lib/repository-validator.test.d.ts.map +0 -1
  370. package/dist/lib/repository-validator.test.js +0 -341
  371. package/dist/lib/repository-validator.test.js.map +0 -1
  372. package/dist/lib/review-core.test.d.ts +0 -2
  373. package/dist/lib/review-core.test.d.ts.map +0 -1
  374. package/dist/lib/review-core.test.js +0 -614
  375. package/dist/lib/review-core.test.js.map +0 -1
  376. package/dist/lib/review-orchestrator.test.d.ts +0 -2
  377. package/dist/lib/review-orchestrator.test.d.ts.map +0 -1
  378. package/dist/lib/review-orchestrator.test.js +0 -552
  379. package/dist/lib/review-orchestrator.test.js.map +0 -1
  380. package/dist/lib/review-output-path.test.d.ts +0 -2
  381. package/dist/lib/review-output-path.test.d.ts.map +0 -1
  382. package/dist/lib/review-output-path.test.js +0 -83
  383. package/dist/lib/review-output-path.test.js.map +0 -1
  384. package/dist/lib/review-parser.test.d.ts +0 -2
  385. package/dist/lib/review-parser.test.d.ts.map +0 -1
  386. package/dist/lib/review-parser.test.js +0 -130
  387. package/dist/lib/review-parser.test.js.map +0 -1
  388. package/dist/lib/review-usage.test.d.ts +0 -2
  389. package/dist/lib/review-usage.test.d.ts.map +0 -1
  390. package/dist/lib/review-usage.test.js +0 -83
  391. package/dist/lib/review-usage.test.js.map +0 -1
  392. package/dist/lib/unified-review-executor.d.ts +0 -58
  393. package/dist/lib/unified-review-executor.d.ts.map +0 -1
  394. package/dist/lib/unified-review-executor.js +0 -201
  395. package/dist/lib/unified-review-executor.js.map +0 -1
  396. package/dist/lib/unified-review-executor.test.d.ts +0 -5
  397. package/dist/lib/unified-review-executor.test.d.ts.map +0 -1
  398. package/dist/lib/unified-review-executor.test.js +0 -472
  399. package/dist/lib/unified-review-executor.test.js.map +0 -1
  400. package/dist/lib/write-json-output.test.d.ts +0 -2
  401. package/dist/lib/write-json-output.test.d.ts.map +0 -1
  402. package/dist/lib/write-json-output.test.js +0 -259
  403. package/dist/lib/write-json-output.test.js.map +0 -1
  404. package/dist/pi/sdk.test.d.ts +0 -2
  405. package/dist/pi/sdk.test.d.ts.map +0 -1
  406. package/dist/pi/sdk.test.js +0 -488
  407. package/dist/pi/sdk.test.js.map +0 -1
  408. package/dist/runtime/agent-loader.test.d.ts +0 -2
  409. package/dist/runtime/agent-loader.test.d.ts.map +0 -1
  410. package/dist/runtime/agent-loader.test.js +0 -277
  411. package/dist/runtime/agent-loader.test.js.map +0 -1
  412. package/dist/runtime/client.test.d.ts +0 -2
  413. package/dist/runtime/client.test.d.ts.map +0 -1
  414. package/dist/runtime/client.test.js +0 -772
  415. package/dist/runtime/client.test.js.map +0 -1
  416. package/dist/runtime/path-config.test.d.ts +0 -2
  417. package/dist/runtime/path-config.test.d.ts.map +0 -1
  418. package/dist/runtime/path-config.test.js +0 -112
  419. package/dist/runtime/path-config.test.js.map +0 -1
package/dist/pi/sdk.js CHANGED
@@ -1,8 +1,15 @@
1
1
  import { randomUUID } from 'crypto';
2
+ import { spawn } from 'child_process';
2
3
  import { isAbsolute, join, resolve } from 'path';
3
4
  import { Type } from '@sinclair/typebox';
4
- import { AuthStorage, createAgentSession, DefaultResourceLoader, getAgentDir, ModelRegistry, SettingsManager, SessionManager, } from '@mariozechner/pi-coding-agent';
5
+ import { AuthStorage, createAgentSession, DefaultResourceLoader, getAgentDir, ModelRegistry, SettingsManager, SessionManager, } from '@earendil-works/pi-coding-agent';
5
6
  import { writeJsonOutput } from '../lib/write-json-output.js';
7
+ import { writeArtifactOutput } from '../lib/html-artifact.js';
8
+ import { isReviewArtifactPayload } from '../lib/review-artifact.js';
9
+ import { resolveWithinWorkingDir } from '../lib/path-utils.js';
10
+ const DEFAULT_GIT_DIFF_MAX_BYTES = 120_000;
11
+ const HARD_GIT_DIFF_MAX_BYTES = 500_000;
12
+ const GIT_DIFF_STDERR_MAX_BYTES = 16_384;
6
13
  function asRecord(value) {
7
14
  return value && typeof value === 'object' && !Array.isArray(value)
8
15
  ? value
@@ -148,6 +155,162 @@ function asPositiveInt(value) {
148
155
  const rounded = Math.round(value);
149
156
  return rounded > 0 ? rounded : undefined;
150
157
  }
158
+ function formatUnknownError(error) {
159
+ if (error instanceof Error) {
160
+ return error.message;
161
+ }
162
+ if (typeof error === 'string') {
163
+ return error;
164
+ }
165
+ try {
166
+ return JSON.stringify(error);
167
+ }
168
+ catch {
169
+ return 'Unknown error';
170
+ }
171
+ }
172
+ function normalizeGitDiffPath(file) {
173
+ const trimmed = file.trim();
174
+ if (!trimmed) {
175
+ throw new Error('git_diff requires a non-empty file path');
176
+ }
177
+ if (trimmed.includes('\0')) {
178
+ throw new Error('git_diff file path must not contain NUL bytes');
179
+ }
180
+ if (isAbsolute(trimmed)) {
181
+ throw new Error('git_diff only accepts repository-relative file paths');
182
+ }
183
+ if (trimmed.split(/[\\/]+/).includes('..')) {
184
+ throw new Error('git_diff file path must stay inside the repository');
185
+ }
186
+ const resolved = resolve('/', trimmed);
187
+ const relativePath = resolved.slice(1);
188
+ if (!relativePath || relativePath === '..' || relativePath.startsWith('../')) {
189
+ throw new Error('git_diff file path must stay inside the repository');
190
+ }
191
+ return relativePath;
192
+ }
193
+ function normalizeGitRev(value, label) {
194
+ const trimmed = value?.trim();
195
+ if (!trimmed) {
196
+ return undefined;
197
+ }
198
+ if (trimmed.startsWith('-') || trimmed.includes('\0') || /\s/.test(trimmed)) {
199
+ throw new Error(`git_diff ${label} revision is not allowed`);
200
+ }
201
+ return trimmed;
202
+ }
203
+ function normalizeGitDiffMaxBytes(maxBytes) {
204
+ if (!maxBytes || !Number.isFinite(maxBytes)) {
205
+ return DEFAULT_GIT_DIFF_MAX_BYTES;
206
+ }
207
+ return Math.max(1, Math.min(Math.floor(maxBytes), HARD_GIT_DIFF_MAX_BYTES));
208
+ }
209
+ function appendCappedChunk(chunks, chunk, maxBytes) {
210
+ const currentBytes = chunks.reduce((sum, existing) => sum + existing.length, 0);
211
+ const remaining = maxBytes - currentBytes;
212
+ if (remaining <= 0) {
213
+ return chunk.length > 0;
214
+ }
215
+ if (chunk.length <= remaining) {
216
+ chunks.push(chunk);
217
+ return false;
218
+ }
219
+ chunks.push(chunk.subarray(0, remaining));
220
+ return true;
221
+ }
222
+ function runGitDiff(workingDir, args, maxBytes) {
223
+ return new Promise((resolvePromise, reject) => {
224
+ const child = spawn('git', ['diff', '--no-ext-diff', '-M', ...args], {
225
+ cwd: workingDir,
226
+ stdio: ['ignore', 'pipe', 'pipe'],
227
+ });
228
+ const stdoutChunks = [];
229
+ const stderrChunks = [];
230
+ let truncated = false;
231
+ child.stdout.on('data', (chunk) => {
232
+ truncated = appendCappedChunk(stdoutChunks, chunk, maxBytes) || truncated;
233
+ });
234
+ child.stderr.on('data', (chunk) => {
235
+ appendCappedChunk(stderrChunks, chunk, GIT_DIFF_STDERR_MAX_BYTES);
236
+ });
237
+ child.on('error', reject);
238
+ child.on('close', (code) => {
239
+ const stderr = Buffer.concat(stderrChunks).toString('utf8').trim();
240
+ if (code !== 0) {
241
+ reject(new Error(stderr || `git diff exited with code ${code ?? 'unknown'}`));
242
+ return;
243
+ }
244
+ resolvePromise({
245
+ stdout: Buffer.concat(stdoutChunks).toString('utf8'),
246
+ truncated,
247
+ });
248
+ });
249
+ });
250
+ }
251
+ function runGitNameStatus(workingDir, args) {
252
+ return new Promise((resolvePromise, reject) => {
253
+ const child = spawn('git', ['diff', '--name-status', '-M', ...args], {
254
+ cwd: workingDir,
255
+ stdio: ['ignore', 'pipe', 'pipe'],
256
+ });
257
+ const stdoutChunks = [];
258
+ const stderrChunks = [];
259
+ child.stdout.on('data', (chunk) => {
260
+ stdoutChunks.push(chunk);
261
+ });
262
+ child.stderr.on('data', (chunk) => {
263
+ appendCappedChunk(stderrChunks, chunk, GIT_DIFF_STDERR_MAX_BYTES);
264
+ });
265
+ child.on('error', reject);
266
+ child.on('close', (code) => {
267
+ const stderr = Buffer.concat(stderrChunks).toString('utf8').trim();
268
+ if (code !== 0) {
269
+ reject(new Error(stderr || `git diff --name-status exited with code ${code ?? 'unknown'}`));
270
+ return;
271
+ }
272
+ resolvePromise(Buffer.concat(stdoutChunks).toString('utf8'));
273
+ });
274
+ });
275
+ }
276
+ function extractGitDiffMetadata(diff) {
277
+ const lines = diff.split('\n');
278
+ const oldPath = lines
279
+ .find((line) => line.startsWith('rename from '))
280
+ ?.slice('rename from '.length);
281
+ const newPath = lines.find((line) => line.startsWith('rename to '))?.slice('rename to '.length);
282
+ return {
283
+ binary: lines.some((line) => line.startsWith('Binary files ') || line.startsWith('GIT binary patch')),
284
+ deleted: lines.some((line) => line.startsWith('deleted file mode')),
285
+ renamed: oldPath !== undefined || newPath !== undefined,
286
+ oldPath,
287
+ newPath,
288
+ empty: diff.trim().length === 0,
289
+ };
290
+ }
291
+ function mergeGitNameStatusMetadata(metadata, nameStatus, file) {
292
+ for (const line of nameStatus.split('\n')) {
293
+ const parts = line.split('\t');
294
+ const status = parts[0];
295
+ if (!status)
296
+ continue;
297
+ if (status.startsWith('R') && parts[2] === file) {
298
+ return {
299
+ ...metadata,
300
+ renamed: true,
301
+ oldPath: parts[1],
302
+ newPath: parts[2],
303
+ };
304
+ }
305
+ if (status === 'D' && parts[1] === file) {
306
+ return {
307
+ ...metadata,
308
+ deleted: true,
309
+ };
310
+ }
311
+ }
312
+ return metadata;
313
+ }
151
314
  function normalizeAgentSkills(value) {
152
315
  const normalized = {};
153
316
  for (const [agentName, skills] of Object.entries(value)) {
@@ -158,6 +321,188 @@ function normalizeAgentSkills(value) {
158
321
  }
159
322
  return normalized;
160
323
  }
324
+ function parseFixChecks(value) {
325
+ if (!Array.isArray(value)) {
326
+ return undefined;
327
+ }
328
+ const checks = [];
329
+ for (const entry of value) {
330
+ const record = asRecord(entry);
331
+ const name = asString(record.name);
332
+ const command = asString(record.command);
333
+ if (!name || !command) {
334
+ continue;
335
+ }
336
+ const check = { name, command };
337
+ const matchPaths = asStringArray(record.matchPaths);
338
+ if (matchPaths && matchPaths.length > 0) {
339
+ check.matchPaths = matchPaths;
340
+ }
341
+ const timeoutMs = asNumber(record.timeoutMs);
342
+ if (timeoutMs !== undefined) {
343
+ check.timeoutMs = timeoutMs;
344
+ }
345
+ checks.push(check);
346
+ }
347
+ return checks.length > 0 ? checks : undefined;
348
+ }
349
+ const DEFAULT_CHECK_TIMEOUT_MS = 120_000;
350
+ const HARD_CHECK_TIMEOUT_MS = 600_000;
351
+ const CHECK_OUTPUT_MAX_BYTES = 64_000;
352
+ function normalizeCheckTimeout(timeoutMs) {
353
+ if (!timeoutMs || !Number.isFinite(timeoutMs)) {
354
+ return DEFAULT_CHECK_TIMEOUT_MS;
355
+ }
356
+ return Math.max(1_000, Math.min(Math.floor(timeoutMs), HARD_CHECK_TIMEOUT_MS));
357
+ }
358
+ function globToRegex(pattern) {
359
+ let regex = '';
360
+ let i = 0;
361
+ while (i < pattern.length) {
362
+ const char = pattern[i];
363
+ if (char === '*' && pattern[i + 1] === '*') {
364
+ regex += '.*';
365
+ i += 2;
366
+ if (pattern[i] === '/') {
367
+ i++;
368
+ }
369
+ }
370
+ else if (char === '*') {
371
+ regex += '[^/]*';
372
+ i++;
373
+ }
374
+ else if (char === '?') {
375
+ regex += '[^/]';
376
+ i++;
377
+ }
378
+ else if ('.+^${}()|[]\\'.includes(char)) {
379
+ regex += '\\' + char;
380
+ i++;
381
+ }
382
+ else {
383
+ regex += char;
384
+ i++;
385
+ }
386
+ }
387
+ return new RegExp('^' + regex + '$');
388
+ }
389
+ function fileMatchesGlobs(filePath, patterns) {
390
+ if (!patterns || patterns.length === 0) {
391
+ return true;
392
+ }
393
+ return patterns.some((pattern) => globToRegex(pattern).test(filePath));
394
+ }
395
+ async function getChangedFiles(workingDir) {
396
+ return new Promise((resolvePromise) => {
397
+ const child = spawn('git', ['status', '--porcelain', '--no-renames'], {
398
+ cwd: workingDir,
399
+ stdio: ['ignore', 'pipe', 'pipe'],
400
+ });
401
+ const stdoutChunks = [];
402
+ child.stdout.on('data', (chunk) => stdoutChunks.push(chunk));
403
+ child.on('error', () => resolvePromise([]));
404
+ child.on('close', () => {
405
+ const output = Buffer.concat(stdoutChunks).toString('utf8').trim();
406
+ resolvePromise(output
407
+ ? output
408
+ .split('\n')
409
+ .map((line) => line.slice(3).trim())
410
+ .filter(Boolean)
411
+ : []);
412
+ });
413
+ });
414
+ }
415
+ function runCheckCommand(workingDir, check) {
416
+ return new Promise((resolvePromise) => {
417
+ const timeoutMs = normalizeCheckTimeout(check.timeoutMs);
418
+ const child = spawn(check.command, {
419
+ cwd: workingDir,
420
+ shell: true,
421
+ stdio: ['ignore', 'pipe', 'pipe'],
422
+ });
423
+ const stdoutChunks = [];
424
+ const stderrChunks = [];
425
+ let truncated = false;
426
+ let timedOut = false;
427
+ const startTime = Date.now();
428
+ const timer = setTimeout(() => {
429
+ timedOut = true;
430
+ child.kill('SIGTERM');
431
+ }, timeoutMs);
432
+ child.stdout.on('data', (chunk) => {
433
+ truncated = appendCappedChunk(stdoutChunks, chunk, CHECK_OUTPUT_MAX_BYTES) || truncated;
434
+ });
435
+ child.stderr.on('data', (chunk) => {
436
+ appendCappedChunk(stderrChunks, chunk, CHECK_OUTPUT_MAX_BYTES);
437
+ });
438
+ child.on('error', () => {
439
+ clearTimeout(timer);
440
+ resolvePromise({
441
+ name: check.name,
442
+ command: check.command,
443
+ exitCode: null,
444
+ stdout: '',
445
+ stderr: `Failed to spawn: ${check.command}`,
446
+ truncated: false,
447
+ skipped: false,
448
+ durationMs: Date.now() - startTime,
449
+ });
450
+ });
451
+ child.on('close', (code) => {
452
+ clearTimeout(timer);
453
+ resolvePromise({
454
+ name: check.name,
455
+ command: check.command,
456
+ exitCode: timedOut ? null : code,
457
+ stdout: Buffer.concat(stdoutChunks).toString('utf8'),
458
+ stderr: (timedOut ? `Timed out after ${timeoutMs}ms\n` : '') +
459
+ Buffer.concat(stderrChunks).toString('utf8'),
460
+ truncated,
461
+ skipped: false,
462
+ durationMs: Date.now() - startTime,
463
+ });
464
+ });
465
+ });
466
+ }
467
+ function findingIdParamProvided(params) {
468
+ return typeof params.findingId === 'string' && params.findingId.trim().length > 0;
469
+ }
470
+ function extractFindingFromArtifact(raw, findingId) {
471
+ const envelope = raw;
472
+ const payload = envelope?.payload ?? raw;
473
+ if (!isReviewArtifactPayload(payload)) {
474
+ return undefined;
475
+ }
476
+ return payload.findings.find((f) => f.id === findingId);
477
+ }
478
+ function buildArtifactManifest(raw, artifactPath) {
479
+ const envelope = raw;
480
+ const payload = envelope?.payload ?? raw;
481
+ if (!isReviewArtifactPayload(payload)) {
482
+ return { artifactPath, ok: false, totalFindings: 0, actionableFindings: 0, findings: [] };
483
+ }
484
+ const findings = payload.findings.map((f) => ({
485
+ id: f.id,
486
+ severity: f.issue.severity,
487
+ state: f.state,
488
+ disposition: f.disposition,
489
+ file: f.issue.file,
490
+ line: f.issue.line,
491
+ title: f.issue.title,
492
+ }));
493
+ const actionableFindings = findings.filter((f) => f.state === 'open' &&
494
+ (f.disposition === 'still_open' ||
495
+ f.disposition === 'partial' ||
496
+ f.disposition === 'regression')).length;
497
+ return {
498
+ artifactPath,
499
+ ok: true,
500
+ reviewId: payload.reviewId,
501
+ totalFindings: findings.length,
502
+ actionableFindings,
503
+ findings,
504
+ };
505
+ }
161
506
  function normalizeSkillPath(cwd, skillPath) {
162
507
  return isAbsolute(skillPath) ? resolve(skillPath) : resolve(cwd, skillPath);
163
508
  }
@@ -255,6 +600,8 @@ class PiSessionRuntime {
255
600
  skillSearchPaths: asStringArray(config.skillSearchPaths),
256
601
  agentSkills: normalizeAgentSkills(asRecord(config.agentSkills)),
257
602
  thinkingLevel: asString(config.thinkingLevel),
603
+ fixChecks: parseFixChecks(config.fixChecks),
604
+ traceCollector: config.traceCollector,
258
605
  retry: asRecord(config.retry),
259
606
  };
260
607
  this.authStorage = AuthStorage.create();
@@ -409,22 +756,26 @@ class PiSessionRuntime {
409
756
  resolveSkillSearchPaths(cwd) {
410
757
  const configuredPaths = this.runtimeConfig.skillSearchPaths ?? [];
411
758
  if (configuredPaths.length === 0) {
412
- return [join(cwd, '.drs', 'skills'), join(cwd, '.pi', 'skills')];
759
+ return [
760
+ join(cwd, '.agents', 'skills'),
761
+ join(cwd, '.drs', 'skills'),
762
+ join(cwd, '.pi', 'skills'),
763
+ ];
413
764
  }
414
765
  return configuredPaths.map((skillPath) => normalizeSkillPath(cwd, skillPath));
415
766
  }
416
767
  resolveAgentSkills(agentName) {
417
768
  return this.runtimeConfig.agentSkills?.[agentName] ?? [];
418
769
  }
419
- resolveCustomTools(workingDir) {
770
+ resolveCustomTools(workingDir, agentTools) {
420
771
  const customTools = [];
421
- if (this.isToolEnabled('write_json_output', true)) {
772
+ if (this.isToolEnabled('write_json_output', true, agentTools)) {
422
773
  customTools.push({
423
774
  name: 'write_json_output',
424
775
  label: 'write_json_output',
425
776
  description: 'Validate and write structured JSON output for DRS agents.',
426
777
  parameters: Type.Object({
427
- outputType: Type.Union([Type.Literal('describe_output'), Type.Literal('review_output')]),
778
+ outputType: Type.Literal('describe_output'),
428
779
  payload: Type.Any(),
429
780
  pretty: Type.Optional(Type.Boolean()),
430
781
  indent: Type.Optional(Type.Number({ minimum: 2, maximum: 8 })),
@@ -444,6 +795,210 @@ class PiSessionRuntime {
444
795
  },
445
796
  });
446
797
  }
798
+ if (this.isToolEnabled('write_artifact_output', false, agentTools)) {
799
+ customTools.push({
800
+ name: 'write_artifact_output',
801
+ label: 'write_artifact_output',
802
+ description: 'Validate and write a self-contained HTML artifact for DRS agents.',
803
+ parameters: Type.Object({
804
+ outputPath: Type.String({ minLength: 1 }),
805
+ content: Type.String({ minLength: 1 }),
806
+ }),
807
+ execute: async (_toolCallId, params) => {
808
+ const pointer = await writeArtifactOutput({
809
+ outputPath: params.outputPath,
810
+ content: params.content,
811
+ workingDir,
812
+ });
813
+ return {
814
+ content: [{ type: 'text', text: JSON.stringify(pointer) }],
815
+ details: pointer,
816
+ };
817
+ },
818
+ });
819
+ }
820
+ if (this.isToolEnabled('git_diff', false, agentTools)) {
821
+ customTools.push({
822
+ name: 'git_diff',
823
+ label: 'git_diff',
824
+ description: 'Read a unified git diff for one repository-relative file path.',
825
+ parameters: Type.Object({
826
+ file: Type.String({ minLength: 1 }),
827
+ base: Type.Optional(Type.String()),
828
+ head: Type.Optional(Type.String()),
829
+ maxBytes: Type.Optional(Type.Number({ minimum: 1, maximum: HARD_GIT_DIFF_MAX_BYTES })),
830
+ }),
831
+ execute: async (_toolCallId, params) => {
832
+ const file = normalizeGitDiffPath(params.file);
833
+ const base = normalizeGitRev(params.base, 'base');
834
+ const head = normalizeGitRev(params.head, 'head');
835
+ const maxBytes = normalizeGitDiffMaxBytes(params.maxBytes);
836
+ const range = base && head ? [`${base}...${head}`] : base ? [base] : [];
837
+ let diff = '';
838
+ let truncated = false;
839
+ let error;
840
+ try {
841
+ const result = await runGitDiff(workingDir, [...range, '--', file], maxBytes);
842
+ diff = result.stdout;
843
+ truncated = result.truncated;
844
+ }
845
+ catch (caught) {
846
+ error = caught instanceof Error ? caught.message : String(caught);
847
+ }
848
+ let metadata = extractGitDiffMetadata(diff);
849
+ if (error === undefined && range.length > 0) {
850
+ try {
851
+ const nameStatus = await runGitNameStatus(workingDir, range);
852
+ metadata = mergeGitNameStatusMetadata(metadata, nameStatus, file);
853
+ }
854
+ catch {
855
+ // Diff text remains authoritative; name-status only enriches metadata.
856
+ }
857
+ }
858
+ const details = {
859
+ file,
860
+ base,
861
+ head,
862
+ ok: error === undefined,
863
+ error,
864
+ truncated,
865
+ bytes: Buffer.byteLength(diff, 'utf8'),
866
+ metadata,
867
+ diff,
868
+ };
869
+ return {
870
+ content: [{ type: 'text', text: JSON.stringify(details) }],
871
+ details,
872
+ };
873
+ },
874
+ });
875
+ }
876
+ if (this.isToolEnabled('read_artifact', false, agentTools)) {
877
+ customTools.push({
878
+ name: 'read_artifact',
879
+ label: 'read_artifact',
880
+ description: 'Read a DRS review artifact from a file path. ' +
881
+ 'Without findingId: returns a compact manifest of all findings (id, severity, state, disposition, file, line, title). ' +
882
+ 'With findingId: returns the full finding detail including issue, verification rationale, and fingerprint.',
883
+ parameters: Type.Object({
884
+ artifactPath: Type.String({ minLength: 1 }),
885
+ findingId: Type.Optional(Type.String({ minLength: 1 })),
886
+ }),
887
+ execute: async (_toolCallId, params) => {
888
+ const { readFile } = await import('fs/promises');
889
+ try {
890
+ const fullPath = resolveWithinWorkingDir(workingDir, params.artifactPath, 'read');
891
+ const raw = JSON.parse(await readFile(fullPath, 'utf-8'));
892
+ if (findingIdParamProvided(params)) {
893
+ const finding = extractFindingFromArtifact(raw, params.findingId);
894
+ if (!finding) {
895
+ const details = {
896
+ artifactPath: params.artifactPath,
897
+ findingId: params.findingId,
898
+ ok: false,
899
+ error: `Finding "${params.findingId}" not found in artifact`,
900
+ };
901
+ return {
902
+ content: [{ type: 'text', text: JSON.stringify(details) }],
903
+ details,
904
+ };
905
+ }
906
+ const details = {
907
+ artifactPath: params.artifactPath,
908
+ findingId: params.findingId,
909
+ ok: true,
910
+ finding,
911
+ };
912
+ return {
913
+ content: [{ type: 'text', text: JSON.stringify(details) }],
914
+ details,
915
+ };
916
+ }
917
+ const manifest = buildArtifactManifest(raw, params.artifactPath);
918
+ return {
919
+ content: [{ type: 'text', text: JSON.stringify(manifest) }],
920
+ details: manifest,
921
+ };
922
+ }
923
+ catch (caught) {
924
+ const error = formatUnknownError(caught);
925
+ const details = {
926
+ artifactPath: params.artifactPath,
927
+ findingId: params.findingId,
928
+ ok: false,
929
+ error,
930
+ };
931
+ return {
932
+ content: [{ type: 'text', text: JSON.stringify(details) }],
933
+ details,
934
+ };
935
+ }
936
+ },
937
+ });
938
+ }
939
+ if (this.isToolEnabled('drs_check', false, agentTools) && this.runtimeConfig.fixChecks) {
940
+ const configuredChecks = this.runtimeConfig.fixChecks;
941
+ customTools.push({
942
+ name: 'drs_check',
943
+ label: 'drs_check',
944
+ description: 'Run configured DRS fix checks (type-check, lint, tests, etc.). ' +
945
+ 'Without name: runs all applicable checks (filtered by matchPaths against changed files). ' +
946
+ 'With name: runs a single named check. ' +
947
+ 'Returns exit code, stdout, and stderr for each check.',
948
+ parameters: Type.Object({
949
+ name: Type.Optional(Type.String({ minLength: 1 })),
950
+ }),
951
+ execute: async (_toolCallId, params) => {
952
+ const changedFiles = await getChangedFiles(workingDir);
953
+ let checksToRun;
954
+ if (params.name) {
955
+ const match = configuredChecks.find((c) => c.name === params.name);
956
+ if (!match) {
957
+ const details = {
958
+ ok: false,
959
+ error: `No check named "${params.name}" is configured`,
960
+ availableChecks: configuredChecks.map((c) => c.name),
961
+ };
962
+ return {
963
+ content: [{ type: 'text', text: JSON.stringify(details) }],
964
+ details,
965
+ };
966
+ }
967
+ checksToRun = [match];
968
+ }
969
+ else {
970
+ checksToRun = configuredChecks.filter((check) => !check.matchPaths ||
971
+ check.matchPaths.length === 0 ||
972
+ changedFiles.some((f) => fileMatchesGlobs(f, check.matchPaths)));
973
+ }
974
+ if (checksToRun.length === 0) {
975
+ const details = {
976
+ ok: true,
977
+ checks: [],
978
+ changedFiles,
979
+ skipped: 'No applicable checks for changed files',
980
+ };
981
+ return {
982
+ content: [{ type: 'text', text: JSON.stringify(details) }],
983
+ details,
984
+ };
985
+ }
986
+ const results = [];
987
+ for (const check of checksToRun) {
988
+ results.push(await runCheckCommand(workingDir, check));
989
+ }
990
+ const details = {
991
+ ok: results.every((r) => r.exitCode === 0),
992
+ checks: results,
993
+ changedFiles,
994
+ };
995
+ return {
996
+ content: [{ type: 'text', text: JSON.stringify(details) }],
997
+ details,
998
+ };
999
+ },
1000
+ });
1001
+ }
447
1002
  return customTools;
448
1003
  }
449
1004
  async createAgentSession(cwd, agentName) {
@@ -487,6 +1042,11 @@ class PiSessionRuntime {
487
1042
  },
488
1043
  })
489
1044
  : undefined;
1045
+ const customTools = this.resolveCustomTools(cwd, settings.tools);
1046
+ const tools = [
1047
+ ...this.resolveTools(cwd, settings.tools),
1048
+ ...customTools.map((tool) => tool.name),
1049
+ ];
490
1050
  const { session } = await createAgentSession({
491
1051
  cwd,
492
1052
  authStorage: this.authStorage,
@@ -495,8 +1055,8 @@ class PiSessionRuntime {
495
1055
  resourceLoader,
496
1056
  sessionManager: SessionManager.inMemory(),
497
1057
  settingsManager,
498
- tools: this.resolveTools(cwd, settings.tools),
499
- customTools: this.resolveCustomTools(cwd),
1058
+ tools,
1059
+ customTools,
500
1060
  thinkingLevel: this.runtimeConfig.thinkingLevel,
501
1061
  });
502
1062
  return session;
@@ -534,6 +1094,9 @@ class PiSessionRuntime {
534
1094
  record.session = await this.createAgentSession(cwd, input.body.agent);
535
1095
  record.agent = input.body.agent;
536
1096
  record.cwd = cwd;
1097
+ if (this.runtimeConfig.traceCollector) {
1098
+ this.runtimeConfig.traceCollector.attachSession(record.session, record.id);
1099
+ }
537
1100
  }
538
1101
  record.error = undefined;
539
1102
  await record.session.prompt(promptText);
@@ -543,6 +1106,11 @@ class PiSessionRuntime {
543
1106
  record.error = error;
544
1107
  return { ok: false };
545
1108
  }
1109
+ finally {
1110
+ if (this.runtimeConfig.traceCollector && record.session) {
1111
+ this.runtimeConfig.traceCollector.finalizeSession(record.id);
1112
+ }
1113
+ }
546
1114
  }
547
1115
  readMessages(input) {
548
1116
  const record = this.getSessionRecord(input.path.id);
@@ -563,7 +1131,7 @@ class PiSessionRuntime {
563
1131
  id: `${record.id}-error`,
564
1132
  role: 'assistant',
565
1133
  time: { completed: Date.now() },
566
- error: record.error instanceof Error ? record.error.message : String(record.error),
1134
+ error: formatUnknownError(record.error),
567
1135
  },
568
1136
  parts: [{ text: '' }],
569
1137
  });