@diff-review-system/drs 3.3.1 → 4.0.1

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 (387) hide show
  1. package/.pi/agents/describe/pr-describer.md +14 -0
  2. package/.pi/agents/review/unified-reviewer.md +31 -1
  3. package/.pi/agents/task/agents-md-updater.md +26 -0
  4. package/.pi/agents/task/changelog-updater.md +29 -0
  5. package/.pi/agents/task/review-issue-fixer.md +42 -0
  6. package/.pi/agents/visual/pr-explainer.md +205 -0
  7. package/.pi/workflows/github-pr-describe.yaml +26 -0
  8. package/.pi/workflows/github-pr-fix-review-issues-stacked.yaml +148 -0
  9. package/.pi/workflows/github-pr-post-comment.yaml +19 -0
  10. package/.pi/workflows/github-pr-review-post.yaml +43 -0
  11. package/.pi/workflows/github-pr-review.yaml +364 -0
  12. package/.pi/workflows/github-pr-show-changes.yaml +25 -0
  13. package/.pi/workflows/github-pr-update-agents-md-stacked.yaml +103 -0
  14. package/.pi/workflows/github-pr-visual-explain.yaml +35 -0
  15. package/.pi/workflows/gitlab-mr-describe.yaml +24 -0
  16. package/.pi/workflows/gitlab-mr-fix-review-issues-stacked.yaml +144 -0
  17. package/.pi/workflows/gitlab-mr-post-comment.yaml +17 -0
  18. package/.pi/workflows/gitlab-mr-review.yaml +364 -0
  19. package/.pi/workflows/gitlab-mr-show-changes.yaml +23 -0
  20. package/.pi/workflows/gitlab-mr-update-agents-md-stacked.yaml +100 -0
  21. package/.pi/workflows/gitlab-mr-visual-explain.yaml +33 -0
  22. package/.pi/workflows/local-changelog-update.yaml +23 -0
  23. package/.pi/workflows/local-fix-review-issues.yaml +111 -0
  24. package/.pi/workflows/local-review.yaml +24 -0
  25. package/.pi/workflows/local-update-agents-md.yaml +24 -0
  26. package/.pi/workflows/local-visual-explain.yaml +31 -0
  27. package/.pi/workflows/release-changelog-finalize.yaml +47 -0
  28. package/.pi/workflows/tag-changelog-update.yaml +26 -0
  29. package/README.md +281 -104
  30. package/dist/ci/runner.d.ts.map +1 -1
  31. package/dist/ci/runner.js +9 -8
  32. package/dist/ci/runner.js.map +1 -1
  33. package/dist/cli/index.js +95 -325
  34. package/dist/cli/index.js.map +1 -1
  35. package/dist/cli/init.d.ts.map +1 -1
  36. package/dist/cli/init.js +25 -23
  37. package/dist/cli/init.js.map +1 -1
  38. package/dist/cli/run-agent.d.ts +26 -0
  39. package/dist/cli/run-agent.d.ts.map +1 -0
  40. package/dist/cli/run-agent.js +143 -0
  41. package/dist/cli/run-agent.js.map +1 -0
  42. package/dist/cli/workflow.d.ts +105 -0
  43. package/dist/cli/workflow.d.ts.map +1 -0
  44. package/dist/cli/workflow.js +3309 -0
  45. package/dist/cli/workflow.js.map +1 -0
  46. package/dist/github/client.d.ts +12 -0
  47. package/dist/github/client.d.ts.map +1 -1
  48. package/dist/github/client.js +27 -0
  49. package/dist/github/client.js.map +1 -1
  50. package/dist/github/platform-adapter.d.ts +6 -1
  51. package/dist/github/platform-adapter.d.ts.map +1 -1
  52. package/dist/github/platform-adapter.js +84 -8
  53. package/dist/github/platform-adapter.js.map +1 -1
  54. package/dist/gitlab/client.d.ts +11 -0
  55. package/dist/gitlab/client.d.ts.map +1 -1
  56. package/dist/gitlab/client.js +11 -0
  57. package/dist/gitlab/client.js.map +1 -1
  58. package/dist/gitlab/platform-adapter.d.ts +3 -1
  59. package/dist/gitlab/platform-adapter.d.ts.map +1 -1
  60. package/dist/gitlab/platform-adapter.js +32 -1
  61. package/dist/gitlab/platform-adapter.js.map +1 -1
  62. package/dist/lib/agent-id.d.ts +9 -0
  63. package/dist/lib/agent-id.d.ts.map +1 -0
  64. package/dist/lib/agent-id.js +32 -0
  65. package/dist/lib/agent-id.js.map +1 -0
  66. package/dist/lib/comment-formatter.d.ts +15 -1
  67. package/dist/lib/comment-formatter.d.ts.map +1 -1
  68. package/dist/lib/comment-formatter.js +53 -4
  69. package/dist/lib/comment-formatter.js.map +1 -1
  70. package/dist/lib/comment-manager.d.ts +4 -0
  71. package/dist/lib/comment-manager.d.ts.map +1 -1
  72. package/dist/lib/comment-manager.js +7 -1
  73. package/dist/lib/comment-manager.js.map +1 -1
  74. package/dist/lib/comment-poster.d.ts +2 -2
  75. package/dist/lib/comment-poster.d.ts.map +1 -1
  76. package/dist/lib/comment-poster.js +31 -4
  77. package/dist/lib/comment-poster.js.map +1 -1
  78. package/dist/lib/config.d.ts +160 -44
  79. package/dist/lib/config.d.ts.map +1 -1
  80. package/dist/lib/config.js +475 -101
  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 +5 -4
  87. package/dist/lib/context-loader.d.ts.map +1 -1
  88. package/dist/lib/context-loader.js +79 -7
  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/description-executor.js +1 -1
  94. package/dist/lib/description-executor.js.map +1 -1
  95. package/dist/lib/diff-lines.d.ts +18 -0
  96. package/dist/lib/diff-lines.d.ts.map +1 -0
  97. package/dist/lib/diff-lines.js +40 -0
  98. package/dist/lib/diff-lines.js.map +1 -0
  99. package/dist/lib/exit.js +4 -4
  100. package/dist/lib/exit.js.map +1 -1
  101. package/dist/lib/html-artifact.d.ts +14 -0
  102. package/dist/lib/html-artifact.d.ts.map +1 -0
  103. package/dist/lib/html-artifact.js +59 -0
  104. package/dist/lib/html-artifact.js.map +1 -0
  105. package/dist/lib/issue-parser.js +3 -3
  106. package/dist/lib/issue-parser.js.map +1 -1
  107. package/dist/lib/json-output-schema.d.ts +70 -0
  108. package/dist/lib/json-output-schema.d.ts.map +1 -1
  109. package/dist/lib/json-output-schema.js +40 -0
  110. package/dist/lib/json-output-schema.js.map +1 -1
  111. package/dist/lib/logger.d.ts +1 -1
  112. package/dist/lib/logger.d.ts.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/review-artifact.d.ts +69 -0
  116. package/dist/lib/review-artifact.d.ts.map +1 -0
  117. package/dist/lib/review-artifact.js +171 -0
  118. package/dist/lib/review-artifact.js.map +1 -0
  119. package/dist/lib/review-core.d.ts +6 -4
  120. package/dist/lib/review-core.d.ts.map +1 -1
  121. package/dist/lib/review-core.js +88 -173
  122. package/dist/lib/review-core.js.map +1 -1
  123. package/dist/lib/review-orchestrator.d.ts +23 -0
  124. package/dist/lib/review-orchestrator.d.ts.map +1 -1
  125. package/dist/lib/review-orchestrator.js +31 -21
  126. package/dist/lib/review-orchestrator.js.map +1 -1
  127. package/dist/lib/review-usage.d.ts +4 -0
  128. package/dist/lib/review-usage.d.ts.map +1 -1
  129. package/dist/lib/review-usage.js +25 -0
  130. package/dist/lib/review-usage.js.map +1 -1
  131. package/dist/lib/trace-collector.d.ts +105 -0
  132. package/dist/lib/trace-collector.d.ts.map +1 -0
  133. package/dist/lib/trace-collector.js +255 -0
  134. package/dist/lib/trace-collector.js.map +1 -0
  135. package/dist/lib/trace-html.d.ts +3 -0
  136. package/dist/lib/trace-html.d.ts.map +1 -0
  137. package/dist/lib/trace-html.js +349 -0
  138. package/dist/lib/trace-html.js.map +1 -0
  139. package/dist/lib/workflow-artifacts.d.ts +54 -0
  140. package/dist/lib/workflow-artifacts.d.ts.map +1 -0
  141. package/dist/lib/workflow-artifacts.js +150 -0
  142. package/dist/lib/workflow-artifacts.js.map +1 -0
  143. package/dist/pi/sdk.d.ts.map +1 -1
  144. package/dist/pi/sdk.js +605 -16
  145. package/dist/pi/sdk.js.map +1 -1
  146. package/dist/runtime/agent-loader.d.ts +10 -6
  147. package/dist/runtime/agent-loader.d.ts.map +1 -1
  148. package/dist/runtime/agent-loader.js +55 -29
  149. package/dist/runtime/agent-loader.js.map +1 -1
  150. package/dist/runtime/built-in-paths.d.ts +1 -0
  151. package/dist/runtime/built-in-paths.d.ts.map +1 -1
  152. package/dist/runtime/built-in-paths.js +7 -0
  153. package/dist/runtime/built-in-paths.js.map +1 -1
  154. package/dist/runtime/client.d.ts +14 -0
  155. package/dist/runtime/client.d.ts.map +1 -1
  156. package/dist/runtime/client.js +87 -56
  157. package/dist/runtime/client.js.map +1 -1
  158. package/dist/runtime/path-config.d.ts +2 -2
  159. package/dist/runtime/path-config.d.ts.map +1 -1
  160. package/dist/runtime/path-config.js +8 -8
  161. package/dist/runtime/path-config.js.map +1 -1
  162. package/package.json +22 -16
  163. package/.pi/agents/review/documentation.md +0 -56
  164. package/.pi/agents/review/performance.md +0 -53
  165. package/.pi/agents/review/quality.md +0 -59
  166. package/.pi/agents/review/security.md +0 -53
  167. package/.pi/agents/review/style.md +0 -132
  168. package/dist/cli/describe-mr.d.ts +0 -11
  169. package/dist/cli/describe-mr.d.ts.map +0 -1
  170. package/dist/cli/describe-mr.js +0 -134
  171. package/dist/cli/describe-mr.js.map +0 -1
  172. package/dist/cli/describe-pr.d.ts +0 -12
  173. package/dist/cli/describe-pr.d.ts.map +0 -1
  174. package/dist/cli/describe-pr.js +0 -135
  175. package/dist/cli/describe-pr.js.map +0 -1
  176. package/dist/cli/post-comments.d.ts +0 -20
  177. package/dist/cli/post-comments.d.ts.map +0 -1
  178. package/dist/cli/post-comments.js +0 -225
  179. package/dist/cli/post-comments.js.map +0 -1
  180. package/dist/cli/review-local.d.ts +0 -13
  181. package/dist/cli/review-local.d.ts.map +0 -1
  182. package/dist/cli/review-local.integration.test.d.ts +0 -2
  183. package/dist/cli/review-local.integration.test.d.ts.map +0 -1
  184. package/dist/cli/review-local.integration.test.js +0 -343
  185. package/dist/cli/review-local.integration.test.js.map +0 -1
  186. package/dist/cli/review-local.js +0 -90
  187. package/dist/cli/review-local.js.map +0 -1
  188. package/dist/cli/review-local.live.e2e.test.d.ts +0 -2
  189. package/dist/cli/review-local.live.e2e.test.d.ts.map +0 -1
  190. package/dist/cli/review-local.live.e2e.test.js +0 -153
  191. package/dist/cli/review-local.live.e2e.test.js.map +0 -1
  192. package/dist/cli/review-local.test.d.ts +0 -2
  193. package/dist/cli/review-local.test.d.ts.map +0 -1
  194. package/dist/cli/review-local.test.js +0 -164
  195. package/dist/cli/review-local.test.js.map +0 -1
  196. package/dist/cli/review-mr.d.ts +0 -22
  197. package/dist/cli/review-mr.d.ts.map +0 -1
  198. package/dist/cli/review-mr.js +0 -181
  199. package/dist/cli/review-mr.js.map +0 -1
  200. package/dist/cli/review-mr.test.d.ts +0 -2
  201. package/dist/cli/review-mr.test.d.ts.map +0 -1
  202. package/dist/cli/review-mr.test.js +0 -142
  203. package/dist/cli/review-mr.test.js.map +0 -1
  204. package/dist/cli/review-pr.d.ts +0 -22
  205. package/dist/cli/review-pr.d.ts.map +0 -1
  206. package/dist/cli/review-pr.js +0 -181
  207. package/dist/cli/review-pr.js.map +0 -1
  208. package/dist/cli/review-pr.test.d.ts +0 -2
  209. package/dist/cli/review-pr.test.d.ts.map +0 -1
  210. package/dist/cli/review-pr.test.js +0 -137
  211. package/dist/cli/review-pr.test.js.map +0 -1
  212. package/dist/cli/review-url.d.ts +0 -35
  213. package/dist/cli/review-url.d.ts.map +0 -1
  214. package/dist/cli/review-url.js +0 -110
  215. package/dist/cli/review-url.js.map +0 -1
  216. package/dist/cli/review-url.test.d.ts +0 -2
  217. package/dist/cli/review-url.test.d.ts.map +0 -1
  218. package/dist/cli/review-url.test.js +0 -132
  219. package/dist/cli/review-url.test.js.map +0 -1
  220. package/dist/cli/show-changes.d.ts +0 -15
  221. package/dist/cli/show-changes.d.ts.map +0 -1
  222. package/dist/cli/show-changes.js +0 -184
  223. package/dist/cli/show-changes.js.map +0 -1
  224. package/dist/github/client.test.d.ts +0 -2
  225. package/dist/github/client.test.d.ts.map +0 -1
  226. package/dist/github/client.test.js +0 -206
  227. package/dist/github/client.test.js.map +0 -1
  228. package/dist/github/platform-adapter.test.d.ts +0 -2
  229. package/dist/github/platform-adapter.test.d.ts.map +0 -1
  230. package/dist/github/platform-adapter.test.js +0 -40
  231. package/dist/github/platform-adapter.test.js.map +0 -1
  232. package/dist/gitlab/diff-parser.test.d.ts +0 -2
  233. package/dist/gitlab/diff-parser.test.d.ts.map +0 -1
  234. package/dist/gitlab/diff-parser.test.js +0 -315
  235. package/dist/gitlab/diff-parser.test.js.map +0 -1
  236. package/dist/gitlab/platform-adapter.test.d.ts +0 -2
  237. package/dist/gitlab/platform-adapter.test.d.ts.map +0 -1
  238. package/dist/gitlab/platform-adapter.test.js +0 -21
  239. package/dist/gitlab/platform-adapter.test.js.map +0 -1
  240. package/dist/index.test.d.ts +0 -2
  241. package/dist/index.test.d.ts.map +0 -1
  242. package/dist/index.test.js +0 -7
  243. package/dist/index.test.js.map +0 -1
  244. package/dist/lib/code-quality-report.test.d.ts +0 -2
  245. package/dist/lib/code-quality-report.test.d.ts.map +0 -1
  246. package/dist/lib/code-quality-report.test.js +0 -327
  247. package/dist/lib/code-quality-report.test.js.map +0 -1
  248. package/dist/lib/comment-formatter.test.d.ts +0 -2
  249. package/dist/lib/comment-formatter.test.d.ts.map +0 -1
  250. package/dist/lib/comment-formatter.test.js +0 -694
  251. package/dist/lib/comment-formatter.test.js.map +0 -1
  252. package/dist/lib/comment-manager.test.d.ts +0 -2
  253. package/dist/lib/comment-manager.test.d.ts.map +0 -1
  254. package/dist/lib/comment-manager.test.js +0 -680
  255. package/dist/lib/comment-manager.test.js.map +0 -1
  256. package/dist/lib/comment-poster.test.d.ts +0 -5
  257. package/dist/lib/comment-poster.test.d.ts.map +0 -1
  258. package/dist/lib/comment-poster.test.js +0 -245
  259. package/dist/lib/comment-poster.test.js.map +0 -1
  260. package/dist/lib/config-model-overrides.test.d.ts +0 -12
  261. package/dist/lib/config-model-overrides.test.d.ts.map +0 -1
  262. package/dist/lib/config-model-overrides.test.js +0 -254
  263. package/dist/lib/config-model-overrides.test.js.map +0 -1
  264. package/dist/lib/config.test.d.ts +0 -2
  265. package/dist/lib/config.test.d.ts.map +0 -1
  266. package/dist/lib/config.test.js +0 -73
  267. package/dist/lib/config.test.js.map +0 -1
  268. package/dist/lib/context-compression.test.d.ts +0 -2
  269. package/dist/lib/context-compression.test.d.ts.map +0 -1
  270. package/dist/lib/context-compression.test.js +0 -337
  271. package/dist/lib/context-compression.test.js.map +0 -1
  272. package/dist/lib/context-loader.test.d.ts +0 -2
  273. package/dist/lib/context-loader.test.d.ts.map +0 -1
  274. package/dist/lib/context-loader.test.js +0 -207
  275. package/dist/lib/context-loader.test.js.map +0 -1
  276. package/dist/lib/cursor-fix-link.test.d.ts +0 -2
  277. package/dist/lib/cursor-fix-link.test.d.ts.map +0 -1
  278. package/dist/lib/cursor-fix-link.test.js +0 -70
  279. package/dist/lib/cursor-fix-link.test.js.map +0 -1
  280. package/dist/lib/describe-core.test.d.ts +0 -2
  281. package/dist/lib/describe-core.test.d.ts.map +0 -1
  282. package/dist/lib/describe-core.test.js +0 -208
  283. package/dist/lib/describe-core.test.js.map +0 -1
  284. package/dist/lib/describe-output-path.test.d.ts +0 -2
  285. package/dist/lib/describe-output-path.test.d.ts.map +0 -1
  286. package/dist/lib/describe-output-path.test.js +0 -51
  287. package/dist/lib/describe-output-path.test.js.map +0 -1
  288. package/dist/lib/describe-parser.test.d.ts +0 -2
  289. package/dist/lib/describe-parser.test.d.ts.map +0 -1
  290. package/dist/lib/describe-parser.test.js +0 -282
  291. package/dist/lib/describe-parser.test.js.map +0 -1
  292. package/dist/lib/description-executor.test.d.ts +0 -2
  293. package/dist/lib/description-executor.test.d.ts.map +0 -1
  294. package/dist/lib/description-executor.test.js +0 -128
  295. package/dist/lib/description-executor.test.js.map +0 -1
  296. package/dist/lib/description-formatter.test.d.ts +0 -2
  297. package/dist/lib/description-formatter.test.d.ts.map +0 -1
  298. package/dist/lib/description-formatter.test.js +0 -57
  299. package/dist/lib/description-formatter.test.js.map +0 -1
  300. package/dist/lib/diff-parser.test.d.ts +0 -2
  301. package/dist/lib/diff-parser.test.d.ts.map +0 -1
  302. package/dist/lib/diff-parser.test.js +0 -335
  303. package/dist/lib/diff-parser.test.js.map +0 -1
  304. package/dist/lib/error-comment-poster.test.d.ts +0 -2
  305. package/dist/lib/error-comment-poster.test.d.ts.map +0 -1
  306. package/dist/lib/error-comment-poster.test.js +0 -128
  307. package/dist/lib/error-comment-poster.test.js.map +0 -1
  308. package/dist/lib/exit.test.d.ts +0 -2
  309. package/dist/lib/exit.test.d.ts.map +0 -1
  310. package/dist/lib/exit.test.js +0 -120
  311. package/dist/lib/exit.test.js.map +0 -1
  312. package/dist/lib/issue-parser.test.d.ts +0 -2
  313. package/dist/lib/issue-parser.test.d.ts.map +0 -1
  314. package/dist/lib/issue-parser.test.js +0 -281
  315. package/dist/lib/issue-parser.test.js.map +0 -1
  316. package/dist/lib/json-output-schema.test.d.ts +0 -2
  317. package/dist/lib/json-output-schema.test.d.ts.map +0 -1
  318. package/dist/lib/json-output-schema.test.js +0 -92
  319. package/dist/lib/json-output-schema.test.js.map +0 -1
  320. package/dist/lib/json-output.test.d.ts +0 -2
  321. package/dist/lib/json-output.test.d.ts.map +0 -1
  322. package/dist/lib/json-output.test.js +0 -141
  323. package/dist/lib/json-output.test.js.map +0 -1
  324. package/dist/lib/logger.test.d.ts +0 -2
  325. package/dist/lib/logger.test.d.ts.map +0 -1
  326. package/dist/lib/logger.test.js +0 -324
  327. package/dist/lib/logger.test.js.map +0 -1
  328. package/dist/lib/position-validator.test.d.ts +0 -2
  329. package/dist/lib/position-validator.test.d.ts.map +0 -1
  330. package/dist/lib/position-validator.test.js +0 -128
  331. package/dist/lib/position-validator.test.js.map +0 -1
  332. package/dist/lib/prompt-budget.test.d.ts +0 -2
  333. package/dist/lib/prompt-budget.test.d.ts.map +0 -1
  334. package/dist/lib/prompt-budget.test.js +0 -55
  335. package/dist/lib/prompt-budget.test.js.map +0 -1
  336. package/dist/lib/repository-validator.test.d.ts +0 -5
  337. package/dist/lib/repository-validator.test.d.ts.map +0 -1
  338. package/dist/lib/repository-validator.test.js +0 -341
  339. package/dist/lib/repository-validator.test.js.map +0 -1
  340. package/dist/lib/review-core.test.d.ts +0 -2
  341. package/dist/lib/review-core.test.d.ts.map +0 -1
  342. package/dist/lib/review-core.test.js +0 -600
  343. package/dist/lib/review-core.test.js.map +0 -1
  344. package/dist/lib/review-orchestrator.test.d.ts +0 -2
  345. package/dist/lib/review-orchestrator.test.d.ts.map +0 -1
  346. package/dist/lib/review-orchestrator.test.js +0 -531
  347. package/dist/lib/review-orchestrator.test.js.map +0 -1
  348. package/dist/lib/review-output-path.test.d.ts +0 -2
  349. package/dist/lib/review-output-path.test.d.ts.map +0 -1
  350. package/dist/lib/review-output-path.test.js +0 -83
  351. package/dist/lib/review-output-path.test.js.map +0 -1
  352. package/dist/lib/review-parser.test.d.ts +0 -2
  353. package/dist/lib/review-parser.test.d.ts.map +0 -1
  354. package/dist/lib/review-parser.test.js +0 -130
  355. package/dist/lib/review-parser.test.js.map +0 -1
  356. package/dist/lib/review-usage.test.d.ts +0 -2
  357. package/dist/lib/review-usage.test.d.ts.map +0 -1
  358. package/dist/lib/review-usage.test.js +0 -83
  359. package/dist/lib/review-usage.test.js.map +0 -1
  360. package/dist/lib/unified-review-executor.d.ts +0 -60
  361. package/dist/lib/unified-review-executor.d.ts.map +0 -1
  362. package/dist/lib/unified-review-executor.js +0 -207
  363. package/dist/lib/unified-review-executor.js.map +0 -1
  364. package/dist/lib/unified-review-executor.test.d.ts +0 -5
  365. package/dist/lib/unified-review-executor.test.d.ts.map +0 -1
  366. package/dist/lib/unified-review-executor.test.js +0 -472
  367. package/dist/lib/unified-review-executor.test.js.map +0 -1
  368. package/dist/lib/write-json-output.test.d.ts +0 -2
  369. package/dist/lib/write-json-output.test.d.ts.map +0 -1
  370. package/dist/lib/write-json-output.test.js +0 -259
  371. package/dist/lib/write-json-output.test.js.map +0 -1
  372. package/dist/pi/sdk.test.d.ts +0 -2
  373. package/dist/pi/sdk.test.d.ts.map +0 -1
  374. package/dist/pi/sdk.test.js +0 -449
  375. package/dist/pi/sdk.test.js.map +0 -1
  376. package/dist/runtime/agent-loader.test.d.ts +0 -2
  377. package/dist/runtime/agent-loader.test.d.ts.map +0 -1
  378. package/dist/runtime/agent-loader.test.js +0 -280
  379. package/dist/runtime/agent-loader.test.js.map +0 -1
  380. package/dist/runtime/client.test.d.ts +0 -2
  381. package/dist/runtime/client.test.d.ts.map +0 -1
  382. package/dist/runtime/client.test.js +0 -523
  383. package/dist/runtime/client.test.js.map +0 -1
  384. package/dist/runtime/path-config.test.d.ts +0 -2
  385. package/dist/runtime/path-config.test.d.ts.map +0 -1
  386. package/dist/runtime/path-config.test.js +0 -112
  387. 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, createBashTool, createEditTool, createFindTool, createGrepTool, createLsTool, createReadTool, createWriteTool, DefaultResourceLoader, ModelRegistry, 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
@@ -141,6 +148,169 @@ function asStringArray(value) {
141
148
  .map((entry) => (typeof entry === 'string' ? entry.trim() : ''))
142
149
  .filter((entry) => entry.length > 0);
143
150
  }
151
+ function asPositiveInt(value) {
152
+ if (typeof value !== 'number' || !Number.isFinite(value)) {
153
+ return undefined;
154
+ }
155
+ const rounded = Math.round(value);
156
+ return rounded > 0 ? rounded : undefined;
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
+ }
144
314
  function normalizeAgentSkills(value) {
145
315
  const normalized = {};
146
316
  for (const [agentName, skills] of Object.entries(value)) {
@@ -151,6 +321,188 @@ function normalizeAgentSkills(value) {
151
321
  }
152
322
  return normalized;
153
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
+ }
154
506
  function normalizeSkillPath(cwd, skillPath) {
155
507
  return isAbsolute(skillPath) ? resolve(skillPath) : resolve(cwd, skillPath);
156
508
  }
@@ -248,9 +600,12 @@ class PiSessionRuntime {
248
600
  skillSearchPaths: asStringArray(config.skillSearchPaths),
249
601
  agentSkills: normalizeAgentSkills(asRecord(config.agentSkills)),
250
602
  thinkingLevel: asString(config.thinkingLevel),
603
+ fixChecks: parseFixChecks(config.fixChecks),
604
+ traceCollector: config.traceCollector,
605
+ retry: asRecord(config.retry),
251
606
  };
252
607
  this.authStorage = AuthStorage.create();
253
- this.modelRegistry = new ModelRegistry(this.authStorage);
608
+ this.modelRegistry = ModelRegistry.create(this.authStorage);
254
609
  this.registerCustomProviders();
255
610
  this.sessionApi = {
256
611
  create: (input) => this.createSession(input),
@@ -372,29 +727,29 @@ class PiSessionRuntime {
372
727
  const value = this.runtimeConfig.tools?.[toolName];
373
728
  return typeof value === 'boolean' ? value : defaultValue;
374
729
  }
375
- resolveTools(cwd, agentTools) {
730
+ resolveTools(_cwd, agentTools) {
376
731
  const tools = [];
377
732
  if (this.isToolEnabled('Read', true, agentTools)) {
378
- tools.push(createReadTool(cwd));
733
+ tools.push('read');
379
734
  }
380
735
  if (this.isToolEnabled('Bash', true, agentTools)) {
381
- tools.push(createBashTool(cwd));
736
+ tools.push('bash');
382
737
  }
383
738
  if (this.isToolEnabled('Edit', false, agentTools)) {
384
- tools.push(createEditTool(cwd));
739
+ tools.push('edit');
385
740
  }
386
741
  if (this.isToolEnabled('Write', false, agentTools)) {
387
- tools.push(createWriteTool(cwd));
742
+ tools.push('write');
388
743
  }
389
744
  if (this.isToolEnabled('Grep', true, agentTools)) {
390
- tools.push(createGrepTool(cwd));
745
+ tools.push('grep');
391
746
  }
392
747
  if (this.isToolEnabled('Glob', true, agentTools)) {
393
- tools.push(createFindTool(cwd));
394
- tools.push(createLsTool(cwd));
748
+ tools.push('find');
749
+ tools.push('ls');
395
750
  }
396
751
  if (tools.length === 0) {
397
- tools.push(createReadTool(cwd), createBashTool(cwd));
752
+ tools.push('read', 'bash');
398
753
  }
399
754
  return tools;
400
755
  }
@@ -408,9 +763,9 @@ class PiSessionRuntime {
408
763
  resolveAgentSkills(agentName) {
409
764
  return this.runtimeConfig.agentSkills?.[agentName] ?? [];
410
765
  }
411
- resolveCustomTools(workingDir) {
766
+ resolveCustomTools(workingDir, agentTools) {
412
767
  const customTools = [];
413
- if (this.isToolEnabled('write_json_output', true)) {
768
+ if (this.isToolEnabled('write_json_output', true, agentTools)) {
414
769
  customTools.push({
415
770
  name: 'write_json_output',
416
771
  label: 'write_json_output',
@@ -436,6 +791,210 @@ class PiSessionRuntime {
436
791
  },
437
792
  });
438
793
  }
794
+ if (this.isToolEnabled('write_artifact_output', false, agentTools)) {
795
+ customTools.push({
796
+ name: 'write_artifact_output',
797
+ label: 'write_artifact_output',
798
+ description: 'Validate and write a self-contained HTML artifact for DRS agents.',
799
+ parameters: Type.Object({
800
+ outputPath: Type.String({ minLength: 1 }),
801
+ content: Type.String({ minLength: 1 }),
802
+ }),
803
+ execute: async (_toolCallId, params) => {
804
+ const pointer = await writeArtifactOutput({
805
+ outputPath: params.outputPath,
806
+ content: params.content,
807
+ workingDir,
808
+ });
809
+ return {
810
+ content: [{ type: 'text', text: JSON.stringify(pointer) }],
811
+ details: pointer,
812
+ };
813
+ },
814
+ });
815
+ }
816
+ if (this.isToolEnabled('git_diff', false, agentTools)) {
817
+ customTools.push({
818
+ name: 'git_diff',
819
+ label: 'git_diff',
820
+ description: 'Read a unified git diff for one repository-relative file path.',
821
+ parameters: Type.Object({
822
+ file: Type.String({ minLength: 1 }),
823
+ base: Type.Optional(Type.String()),
824
+ head: Type.Optional(Type.String()),
825
+ maxBytes: Type.Optional(Type.Number({ minimum: 1, maximum: HARD_GIT_DIFF_MAX_BYTES })),
826
+ }),
827
+ execute: async (_toolCallId, params) => {
828
+ const file = normalizeGitDiffPath(params.file);
829
+ const base = normalizeGitRev(params.base, 'base');
830
+ const head = normalizeGitRev(params.head, 'head');
831
+ const maxBytes = normalizeGitDiffMaxBytes(params.maxBytes);
832
+ const range = base && head ? [`${base}...${head}`] : base ? [base] : [];
833
+ let diff = '';
834
+ let truncated = false;
835
+ let error;
836
+ try {
837
+ const result = await runGitDiff(workingDir, [...range, '--', file], maxBytes);
838
+ diff = result.stdout;
839
+ truncated = result.truncated;
840
+ }
841
+ catch (caught) {
842
+ error = caught instanceof Error ? caught.message : String(caught);
843
+ }
844
+ let metadata = extractGitDiffMetadata(diff);
845
+ if (error === undefined && range.length > 0) {
846
+ try {
847
+ const nameStatus = await runGitNameStatus(workingDir, range);
848
+ metadata = mergeGitNameStatusMetadata(metadata, nameStatus, file);
849
+ }
850
+ catch {
851
+ // Diff text remains authoritative; name-status only enriches metadata.
852
+ }
853
+ }
854
+ const details = {
855
+ file,
856
+ base,
857
+ head,
858
+ ok: error === undefined,
859
+ error,
860
+ truncated,
861
+ bytes: Buffer.byteLength(diff, 'utf8'),
862
+ metadata,
863
+ diff,
864
+ };
865
+ return {
866
+ content: [{ type: 'text', text: JSON.stringify(details) }],
867
+ details,
868
+ };
869
+ },
870
+ });
871
+ }
872
+ if (this.isToolEnabled('read_artifact', false, agentTools)) {
873
+ customTools.push({
874
+ name: 'read_artifact',
875
+ label: 'read_artifact',
876
+ description: 'Read a DRS review artifact from a file path. ' +
877
+ 'Without findingId: returns a compact manifest of all findings (id, severity, state, disposition, file, line, title). ' +
878
+ 'With findingId: returns the full finding detail including issue, verification rationale, and fingerprint.',
879
+ parameters: Type.Object({
880
+ artifactPath: Type.String({ minLength: 1 }),
881
+ findingId: Type.Optional(Type.String({ minLength: 1 })),
882
+ }),
883
+ execute: async (_toolCallId, params) => {
884
+ const { readFile } = await import('fs/promises');
885
+ try {
886
+ const fullPath = resolveWithinWorkingDir(workingDir, params.artifactPath, 'read');
887
+ const raw = JSON.parse(await readFile(fullPath, 'utf-8'));
888
+ if (findingIdParamProvided(params)) {
889
+ const finding = extractFindingFromArtifact(raw, params.findingId);
890
+ if (!finding) {
891
+ const details = {
892
+ artifactPath: params.artifactPath,
893
+ findingId: params.findingId,
894
+ ok: false,
895
+ error: `Finding "${params.findingId}" not found in artifact`,
896
+ };
897
+ return {
898
+ content: [{ type: 'text', text: JSON.stringify(details) }],
899
+ details,
900
+ };
901
+ }
902
+ const details = {
903
+ artifactPath: params.artifactPath,
904
+ findingId: params.findingId,
905
+ ok: true,
906
+ finding,
907
+ };
908
+ return {
909
+ content: [{ type: 'text', text: JSON.stringify(details) }],
910
+ details,
911
+ };
912
+ }
913
+ const manifest = buildArtifactManifest(raw, params.artifactPath);
914
+ return {
915
+ content: [{ type: 'text', text: JSON.stringify(manifest) }],
916
+ details: manifest,
917
+ };
918
+ }
919
+ catch (caught) {
920
+ const error = formatUnknownError(caught);
921
+ const details = {
922
+ artifactPath: params.artifactPath,
923
+ findingId: params.findingId,
924
+ ok: false,
925
+ error,
926
+ };
927
+ return {
928
+ content: [{ type: 'text', text: JSON.stringify(details) }],
929
+ details,
930
+ };
931
+ }
932
+ },
933
+ });
934
+ }
935
+ if (this.isToolEnabled('drs_check', false, agentTools) && this.runtimeConfig.fixChecks) {
936
+ const configuredChecks = this.runtimeConfig.fixChecks;
937
+ customTools.push({
938
+ name: 'drs_check',
939
+ label: 'drs_check',
940
+ description: 'Run configured DRS fix checks (type-check, lint, tests, etc.). ' +
941
+ 'Without name: runs all applicable checks (filtered by matchPaths against changed files). ' +
942
+ 'With name: runs a single named check. ' +
943
+ 'Returns exit code, stdout, and stderr for each check.',
944
+ parameters: Type.Object({
945
+ name: Type.Optional(Type.String({ minLength: 1 })),
946
+ }),
947
+ execute: async (_toolCallId, params) => {
948
+ const changedFiles = await getChangedFiles(workingDir);
949
+ let checksToRun;
950
+ if (params.name) {
951
+ const match = configuredChecks.find((c) => c.name === params.name);
952
+ if (!match) {
953
+ const details = {
954
+ ok: false,
955
+ error: `No check named "${params.name}" is configured`,
956
+ availableChecks: configuredChecks.map((c) => c.name),
957
+ };
958
+ return {
959
+ content: [{ type: 'text', text: JSON.stringify(details) }],
960
+ details,
961
+ };
962
+ }
963
+ checksToRun = [match];
964
+ }
965
+ else {
966
+ checksToRun = configuredChecks.filter((check) => !check.matchPaths ||
967
+ check.matchPaths.length === 0 ||
968
+ changedFiles.some((f) => fileMatchesGlobs(f, check.matchPaths)));
969
+ }
970
+ if (checksToRun.length === 0) {
971
+ const details = {
972
+ ok: true,
973
+ checks: [],
974
+ changedFiles,
975
+ skipped: 'No applicable checks for changed files',
976
+ };
977
+ return {
978
+ content: [{ type: 'text', text: JSON.stringify(details) }],
979
+ details,
980
+ };
981
+ }
982
+ const results = [];
983
+ for (const check of checksToRun) {
984
+ results.push(await runCheckCommand(workingDir, check));
985
+ }
986
+ const details = {
987
+ ok: results.every((r) => r.exitCode === 0),
988
+ checks: results,
989
+ changedFiles,
990
+ };
991
+ return {
992
+ content: [{ type: 'text', text: JSON.stringify(details) }],
993
+ details,
994
+ };
995
+ },
996
+ });
997
+ }
439
998
  return customTools;
440
999
  }
441
1000
  async createAgentSession(cwd, agentName) {
@@ -444,6 +1003,7 @@ class PiSessionRuntime {
444
1003
  const skillSearchPaths = this.resolveSkillSearchPaths(cwd);
445
1004
  const resourceLoader = new DefaultResourceLoader({
446
1005
  cwd,
1006
+ agentDir: getAgentDir(),
447
1007
  noSkills: true,
448
1008
  additionalSkillPaths: skillSearchPaths,
449
1009
  skillsOverride: configuredSkillNames.size > 0
@@ -463,6 +1023,26 @@ class PiSessionRuntime {
463
1023
  throw new Error(`Missing skill definitions for ${agentName}: ${missingSkills.join(', ')}. Checked skill search paths: ${skillSearchPaths.join(', ')}`);
464
1024
  }
465
1025
  }
1026
+ const providerRetry = this.runtimeConfig.retry?.provider;
1027
+ const providerTimeoutMs = asPositiveInt(providerRetry?.timeoutMs);
1028
+ const providerMaxRetries = asPositiveInt(providerRetry?.maxRetries);
1029
+ const providerMaxRetryDelayMs = asPositiveInt(providerRetry?.maxRetryDelayMs);
1030
+ const settingsManager = (providerTimeoutMs ?? providerMaxRetries ?? providerMaxRetryDelayMs)
1031
+ ? SettingsManager.inMemory({
1032
+ retry: {
1033
+ provider: {
1034
+ ...(providerTimeoutMs ? { timeoutMs: providerTimeoutMs } : {}),
1035
+ ...(providerMaxRetries ? { maxRetries: providerMaxRetries } : {}),
1036
+ ...(providerMaxRetryDelayMs ? { maxRetryDelayMs: providerMaxRetryDelayMs } : {}),
1037
+ },
1038
+ },
1039
+ })
1040
+ : undefined;
1041
+ const customTools = this.resolveCustomTools(cwd, settings.tools);
1042
+ const tools = [
1043
+ ...this.resolveTools(cwd, settings.tools),
1044
+ ...customTools.map((tool) => tool.name),
1045
+ ];
466
1046
  const { session } = await createAgentSession({
467
1047
  cwd,
468
1048
  authStorage: this.authStorage,
@@ -470,8 +1050,9 @@ class PiSessionRuntime {
470
1050
  model: this.resolveModel(settings.model),
471
1051
  resourceLoader,
472
1052
  sessionManager: SessionManager.inMemory(),
473
- tools: this.resolveTools(cwd, settings.tools),
474
- customTools: this.resolveCustomTools(cwd),
1053
+ settingsManager,
1054
+ tools,
1055
+ customTools,
475
1056
  thinkingLevel: this.runtimeConfig.thinkingLevel,
476
1057
  });
477
1058
  return session;
@@ -509,6 +1090,9 @@ class PiSessionRuntime {
509
1090
  record.session = await this.createAgentSession(cwd, input.body.agent);
510
1091
  record.agent = input.body.agent;
511
1092
  record.cwd = cwd;
1093
+ if (this.runtimeConfig.traceCollector) {
1094
+ this.runtimeConfig.traceCollector.attachSession(record.session, record.id);
1095
+ }
512
1096
  }
513
1097
  record.error = undefined;
514
1098
  await record.session.prompt(promptText);
@@ -518,6 +1102,11 @@ class PiSessionRuntime {
518
1102
  record.error = error;
519
1103
  return { ok: false };
520
1104
  }
1105
+ finally {
1106
+ if (this.runtimeConfig.traceCollector && record.session) {
1107
+ this.runtimeConfig.traceCollector.finalizeSession(record.id);
1108
+ }
1109
+ }
521
1110
  }
522
1111
  readMessages(input) {
523
1112
  const record = this.getSessionRecord(input.path.id);
@@ -538,7 +1127,7 @@ class PiSessionRuntime {
538
1127
  id: `${record.id}-error`,
539
1128
  role: 'assistant',
540
1129
  time: { completed: Date.now() },
541
- error: record.error instanceof Error ? record.error.message : String(record.error),
1130
+ error: formatUnknownError(record.error),
542
1131
  },
543
1132
  parts: [{ text: '' }],
544
1133
  });