@cjhyy/code-shell 0.1.0-alpha.1 → 0.1.0-alpha.2

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 (274) hide show
  1. package/README.md +8 -0
  2. package/dist/anthropic-P5VETAFI.cjs +10 -0
  3. package/dist/{anthropic-NENYS535.js → anthropic-W2GU3D76.js} +3 -2
  4. package/dist/arena/context/context-tools.d.ts +1 -1
  5. package/dist/arena/index.cjs +4 -4
  6. package/dist/arena/index.js +3 -3
  7. package/dist/arena/providers/index.d.ts +19 -3
  8. package/dist/arena/strategies/utils.d.ts +6 -1
  9. package/dist/arena/types.d.ts +10 -1
  10. package/dist/{arena-46QQ6BZQ.js → arena-ENHBHB2W.js} +5 -7
  11. package/dist/{arena-HZZZ2GJH.cjs → arena-HHDYYVHJ.cjs} +19 -21
  12. package/dist/{chunk-BE6IPRDM.js → chunk-2EUAE7AY.js} +1 -1
  13. package/dist/{chunk-WYKNZ54E.cjs → chunk-3CAZIWUA.cjs} +6 -6
  14. package/dist/{chunk-J5XW6UYL.js → chunk-5C5HIOML.js} +63 -4
  15. package/dist/chunk-75E4BBFC.js +224 -0
  16. package/dist/{chunk-ZJV3YSY3.cjs → chunk-BUJ5KYCI.cjs} +53 -11
  17. package/dist/{chunk-BMH65OVB.cjs → chunk-C7C7ZZY4.cjs} +8 -8
  18. package/dist/{chunk-KO2FPF7G.js → chunk-F5BS3GUC.js} +20 -2
  19. package/dist/chunk-FA5KD34T.js +54 -0
  20. package/dist/chunk-FV2ARONZ.cjs +224 -0
  21. package/dist/chunk-G76E5FOB.cjs +54 -0
  22. package/dist/{chunk-DICG4AB7.cjs → chunk-GZBD6QRS.cjs} +42 -3
  23. package/dist/{chunk-FVP7XJGS.cjs → chunk-HOXQLX5R.cjs} +406 -196
  24. package/dist/{chunk-4PKZPFCD.js → chunk-I57ZD5IQ.js} +47 -14
  25. package/dist/{chunk-JUHRV2XF.js → chunk-ID6EJUHP.js} +1703 -438
  26. package/dist/chunk-JHNCK7JP.cjs +202 -0
  27. package/dist/{chunk-MOILS4WE.cjs → chunk-JHXNOB5G.cjs} +3 -3
  28. package/dist/{chunk-UK2SU23S.cjs → chunk-KOGV6PDQ.cjs} +20 -2
  29. package/dist/{chunk-VKGNCYRL.js → chunk-LMEKCQX4.js} +95 -13
  30. package/dist/{chunk-3EAEC566.cjs → chunk-M2QI5X3X.cjs} +51 -18
  31. package/dist/{chunk-YZ25SSWJ.js → chunk-M2SVOKC6.js} +46 -4
  32. package/dist/chunk-OMRGA6TI.js +4753 -0
  33. package/dist/{chunk-NG73UR3L.cjs → chunk-OP57WUWQ.cjs} +23 -1
  34. package/dist/{chunk-ZXYDDJEJ.js → chunk-OUC2DFA7.js} +2 -2
  35. package/dist/{chunk-AP5F6VYE.js → chunk-REFCCVDM.js} +1 -1
  36. package/dist/{chunk-O6F2EF2Z.js → chunk-SCDKLTN3.js} +41 -2
  37. package/dist/{chunk-FECTK5KJ.js → chunk-SW3L7HIM.js} +1 -1
  38. package/dist/chunk-TATCTZSB.cjs +4753 -0
  39. package/dist/{chunk-Q6BYFYGD.cjs → chunk-VWFET3MG.cjs} +1886 -621
  40. package/dist/{chunk-3EUDE77E.cjs → chunk-X2DNIMPC.cjs} +19 -19
  41. package/dist/{chunk-SQZHPD3S.js → chunk-Y7TSCDF6.js} +297 -87
  42. package/dist/{chunk-WHRTARDJ.cjs → chunk-YAFCN7ZW.cjs} +112 -30
  43. package/dist/{chunk-LRAY5IYC.cjs → chunk-YD7XTI7T.cjs} +65 -6
  44. package/dist/{chunk-S74VVJBF.js → chunk-ZLPJJZUW.js} +23 -1
  45. package/dist/chunk-ZRVPCXI7.js +202 -0
  46. package/dist/cli/commands/builtin/advanced-commands.d.ts +1 -1
  47. package/dist/cli/commands/builtin/extra-commands.d.ts +2 -2
  48. package/dist/cli/commands/builtin/more-commands.d.ts +1 -3
  49. package/dist/cli/commands/registry.d.ts +8 -0
  50. package/dist/cli/cost-tracker.d.ts +6 -0
  51. package/dist/cli/main.cjs +3534 -1996
  52. package/dist/cli/main.js +3646 -2108
  53. package/dist/cli/onboarding.d.ts +67 -14
  54. package/dist/client-base-TOVE25FA.js +9 -0
  55. package/dist/client-base-VDDIADAC.cjs +9 -0
  56. package/dist/compaction-D3KV2NWY.cjs +31 -0
  57. package/dist/{compaction-CCHWA4G6.js → compaction-YNWCEF7B.js} +1 -2
  58. package/dist/context/manager.d.ts +9 -0
  59. package/dist/data/openrouter-models.d.ts +35 -0
  60. package/dist/data/openrouter-sync.d.ts +16 -0
  61. package/dist/{devtools-KIY3LWQJ.js → devtools-IRQQPIRY.js} +1 -1
  62. package/dist/{devtools-LRP47DDV.cjs → devtools-WTC3NFNE.cjs} +1 -1
  63. package/dist/engine/engine.d.ts +29 -6
  64. package/dist/engine/turn-loop.d.ts +7 -0
  65. package/dist/engine/turn-state.d.ts +6 -0
  66. package/dist/index.cjs +19 -28
  67. package/dist/index.js +28 -37
  68. package/dist/llm/client-base.d.ts +7 -0
  69. package/dist/llm/model-pool.d.ts +4 -0
  70. package/dist/logging/logger.d.ts +69 -8
  71. package/dist/manager-FWLOVEEK.cjs +7 -0
  72. package/dist/manager-GEXJLOIS.js +7 -0
  73. package/dist/{mcp-manager-OKXHHWYR.js → mcp-manager-37GQLFGX.js} +2 -2
  74. package/dist/mcp-manager-U77NEXBY.cjs +8 -0
  75. package/dist/memory-ADGOWADP.cjs +9 -0
  76. package/dist/memory-EPFDBPII.js +9 -0
  77. package/dist/native-ts/yoga-layout/index.d.ts +2 -2
  78. package/dist/{openai-5HQGBL4L.js → openai-RXU5URYI.js} +3 -2
  79. package/dist/openai-SQW4H2K4.cjs +10 -0
  80. package/dist/openrouter-models-OL725CL6.js +15 -0
  81. package/dist/openrouter-models-UM3AOGZ4.cjs +15 -0
  82. package/dist/openrouter-sync-CWD5VNW2.js +11 -0
  83. package/dist/openrouter-sync-HYZZC6RX.cjs +11 -0
  84. package/dist/product/index.cjs +12 -16
  85. package/dist/product/index.js +11 -15
  86. package/dist/protocol/types.d.ts +11 -3
  87. package/dist/{ink → render}/hooks/use-input.d.ts +1 -1
  88. package/dist/run/index.cjs +12 -16
  89. package/dist/run/index.js +11 -15
  90. package/dist/session/memory.d.ts +23 -3
  91. package/dist/session/session-manager.d.ts +4 -1
  92. package/dist/{session-manager-UQKB564H.cjs → session-manager-HRSKENKB.cjs} +2 -2
  93. package/dist/{session-manager-JIIBCFTC.js → session-manager-NEKFEHF3.js} +1 -1
  94. package/dist/settings/manager.d.ts +9 -0
  95. package/dist/settings/schema.d.ts +48 -39
  96. package/dist/{tool-summary-J2ICNMWP.js → tool-summary-2RUFL5QK.js} +1 -1
  97. package/dist/{tool-summary-5P2GKRA4.cjs → tool-summary-RYNR4DDB.cjs} +2 -2
  98. package/dist/tool-system/builtin/agent.d.ts +3 -26
  99. package/dist/tool-system/builtin/apply-patch/applier.d.ts +26 -0
  100. package/dist/tool-system/builtin/apply-patch/index.d.ts +19 -0
  101. package/dist/tool-system/builtin/apply-patch/parser.d.ts +17 -0
  102. package/dist/tool-system/builtin/apply-patch/seek-sequence.d.ts +18 -0
  103. package/dist/tool-system/builtin/apply-patch/types.d.ts +49 -0
  104. package/dist/tool-system/builtin/arena.d.ts +18 -5
  105. package/dist/tool-system/builtin/ask-user.d.ts +6 -6
  106. package/dist/tool-system/builtin/index.d.ts +11 -1
  107. package/dist/tool-system/builtin/tool-search.d.ts +2 -3
  108. package/dist/tool-system/context.d.ts +74 -0
  109. package/dist/tool-system/executor.d.ts +16 -0
  110. package/dist/tool-system/permission.d.ts +40 -5
  111. package/dist/tool-system/registry.d.ts +2 -0
  112. package/dist/types.d.ts +28 -1
  113. package/dist/ui/App.d.ts +1 -1
  114. package/dist/ui/components/AgentBlock.d.ts +1 -1
  115. package/dist/ui/components/AskUserPrompt.d.ts +7 -0
  116. package/dist/ui/components/MessageContent.d.ts +7 -3
  117. package/dist/ui/components/ModelManager.d.ts +35 -0
  118. package/dist/ui/components/ModelSelector.d.ts +10 -0
  119. package/dist/ui/components/OnboardingPrompt.d.ts +7 -0
  120. package/dist/ui/components/PermissionPrompt.d.ts +5 -2
  121. package/dist/ui/components/SessionPicker.d.ts +14 -0
  122. package/dist/ui/components/StatusLine.d.ts +4 -2
  123. package/dist/ui/components/ThemedBox.d.ts +1 -1
  124. package/dist/ui/components/ToolCall.d.ts +8 -1
  125. package/dist/ui/components/WelcomeTips.d.ts +5 -0
  126. package/dist/ui/onboarding-runner.d.ts +2 -0
  127. package/dist/ui/store.d.ts +1 -0
  128. package/dist/{updater-2N6745WR.cjs → updater-M7L42ASZ.cjs} +4 -4
  129. package/dist/{updater-PV7FKSUI.js → updater-ZRTONIR4.js} +4 -4
  130. package/dist/utils/debug.d.ts +17 -33
  131. package/package.json +4 -4
  132. package/dist/anthropic-XMTTVNSH.cjs +0 -9
  133. package/dist/bridge-4ZRXVWBN.js +0 -98
  134. package/dist/bridge-W476QDFH.cjs +0 -98
  135. package/dist/chunk-4RRUP4MM.js +0 -86
  136. package/dist/chunk-4SFPFHMG.js +0 -132
  137. package/dist/chunk-5LHVI777.cjs +0 -246
  138. package/dist/chunk-6ZIROYXX.js +0 -207
  139. package/dist/chunk-C7JBCO5V.js +0 -80
  140. package/dist/chunk-CSO5EOEP.cjs +0 -132
  141. package/dist/chunk-FGZGCFJX.cjs +0 -207
  142. package/dist/chunk-HD7MT5XU.cjs +0 -86
  143. package/dist/chunk-IMMTBZ33.cjs +0 -63
  144. package/dist/chunk-JT2WSQSR.cjs +0 -335
  145. package/dist/chunk-NZ4DQ72D.cjs +0 -664
  146. package/dist/chunk-OG4MIQJ6.js +0 -335
  147. package/dist/chunk-WRZJUQ5Z.js +0 -664
  148. package/dist/chunk-X4HAERTQ.js +0 -63
  149. package/dist/chunk-XHC2JMEC.cjs +0 -80
  150. package/dist/chunk-ZRSSGYA5.js +0 -246
  151. package/dist/compaction-44I55TLI.cjs +0 -32
  152. package/dist/coordinator-5HY7ALO2.js +0 -7
  153. package/dist/coordinator-INDLPVMF.cjs +0 -7
  154. package/dist/cost-tracker-IWYAUPXH.js +0 -9
  155. package/dist/cost-tracker-JXTJQQWE.cjs +0 -9
  156. package/dist/loader-DXFSUB4R.cjs +0 -91
  157. package/dist/loader-J5UID6CV.js +0 -91
  158. package/dist/manager-ETWDOCHN.cjs +0 -9
  159. package/dist/manager-HGMQNEJB.cjs +0 -11
  160. package/dist/manager-HUAQOORS.js +0 -9
  161. package/dist/manager-VJIZ2CQC.js +0 -11
  162. package/dist/mcp-manager-G4G2QASE.cjs +0 -8
  163. package/dist/memory-AP747G5H.js +0 -7
  164. package/dist/memory-BH3BYUN5.cjs +0 -7
  165. package/dist/onboarding-6WEPV7C2.js +0 -11
  166. package/dist/onboarding-QM5DY2TU.cjs +0 -11
  167. package/dist/openai-656VWUQW.cjs +0 -9
  168. package/dist/skills-63RBYQRX.js +0 -13
  169. package/dist/skills-V3BPLW3D.cjs +0 -13
  170. package/dist/token-counter-CHAXW5O7.cjs +0 -13
  171. package/dist/token-counter-DSOZGZ5Q.js +0 -13
  172. package/dist/utils/log.d.ts +0 -56
  173. package/dist/voice-KTZ7PAGO.js +0 -80
  174. package/dist/voice-KZE25GKB.cjs +0 -80
  175. /package/dist/{ink → render}/Ansi.d.ts +0 -0
  176. /package/dist/{ink → render}/bidi.d.ts +0 -0
  177. /package/dist/{ink → render}/clearTerminal.d.ts +0 -0
  178. /package/dist/{ink → render}/colorize.d.ts +0 -0
  179. /package/dist/{ink → render}/components/AlternateScreen.d.ts +0 -0
  180. /package/dist/{ink → render}/components/App.d.ts +0 -0
  181. /package/dist/{ink → render}/components/AppContext.d.ts +0 -0
  182. /package/dist/{ink → render}/components/Box.d.ts +0 -0
  183. /package/dist/{ink → render}/components/Button.d.ts +0 -0
  184. /package/dist/{ink → render}/components/ClockContext.d.ts +0 -0
  185. /package/dist/{ink → render}/components/CursorDeclarationContext.d.ts +0 -0
  186. /package/dist/{ink → render}/components/ErrorOverview.d.ts +0 -0
  187. /package/dist/{ink → render}/components/Link.d.ts +0 -0
  188. /package/dist/{ink → render}/components/Newline.d.ts +0 -0
  189. /package/dist/{ink → render}/components/NoSelect.d.ts +0 -0
  190. /package/dist/{ink → render}/components/RawAnsi.d.ts +0 -0
  191. /package/dist/{ink → render}/components/ScrollBox.d.ts +0 -0
  192. /package/dist/{ink → render}/components/Spacer.d.ts +0 -0
  193. /package/dist/{ink → render}/components/StdinContext.d.ts +0 -0
  194. /package/dist/{ink → render}/components/TerminalFocusContext.d.ts +0 -0
  195. /package/dist/{ink → render}/components/TerminalSizeContext.d.ts +0 -0
  196. /package/dist/{ink → render}/components/Text.d.ts +0 -0
  197. /package/dist/{ink → render}/constants.d.ts +0 -0
  198. /package/dist/{ink → render}/cursor.d.ts +0 -0
  199. /package/dist/{ink → render}/devtools.d.ts +0 -0
  200. /package/dist/{ink → render}/dom.d.ts +0 -0
  201. /package/dist/{ink → render}/events/click-event.d.ts +0 -0
  202. /package/dist/{ink → render}/events/dispatcher.d.ts +0 -0
  203. /package/dist/{ink → render}/events/emitter.d.ts +0 -0
  204. /package/dist/{ink → render}/events/event-handlers.d.ts +0 -0
  205. /package/dist/{ink → render}/events/event.d.ts +0 -0
  206. /package/dist/{ink → render}/events/focus-event.d.ts +0 -0
  207. /package/dist/{ink → render}/events/input-event.d.ts +0 -0
  208. /package/dist/{ink → render}/events/keyboard-event.d.ts +0 -0
  209. /package/dist/{ink → render}/events/paste-event.d.ts +0 -0
  210. /package/dist/{ink → render}/events/resize-event.d.ts +0 -0
  211. /package/dist/{ink → render}/events/terminal-event.d.ts +0 -0
  212. /package/dist/{ink → render}/events/terminal-focus-event.d.ts +0 -0
  213. /package/dist/{ink → render}/focus.d.ts +0 -0
  214. /package/dist/{ink → render}/frame.d.ts +0 -0
  215. /package/dist/{ink → render}/get-max-width.d.ts +0 -0
  216. /package/dist/{ink → render}/hit-test.d.ts +0 -0
  217. /package/dist/{ink → render}/hooks/use-animation-frame.d.ts +0 -0
  218. /package/dist/{ink → render}/hooks/use-app.d.ts +0 -0
  219. /package/dist/{ink → render}/hooks/use-declared-cursor.d.ts +0 -0
  220. /package/dist/{ink → render}/hooks/use-interval.d.ts +0 -0
  221. /package/dist/{ink → render}/hooks/use-search-highlight.d.ts +0 -0
  222. /package/dist/{ink → render}/hooks/use-selection.d.ts +0 -0
  223. /package/dist/{ink → render}/hooks/use-stdin.d.ts +0 -0
  224. /package/dist/{ink → render}/hooks/use-tab-status.d.ts +0 -0
  225. /package/dist/{ink → render}/hooks/use-terminal-focus.d.ts +0 -0
  226. /package/dist/{ink → render}/hooks/use-terminal-title.d.ts +0 -0
  227. /package/dist/{ink → render}/hooks/use-terminal-viewport.d.ts +0 -0
  228. /package/dist/{ink → render}/index.d.ts +0 -0
  229. /package/dist/{ink → render}/ink.d.ts +0 -0
  230. /package/dist/{ink → render}/instances.d.ts +0 -0
  231. /package/dist/{ink → render}/layout/engine.d.ts +0 -0
  232. /package/dist/{ink → render}/layout/geometry.d.ts +0 -0
  233. /package/dist/{ink → render}/layout/node.d.ts +0 -0
  234. /package/dist/{ink → render}/layout/yoga.d.ts +0 -0
  235. /package/dist/{ink → render}/line-width-cache.d.ts +0 -0
  236. /package/dist/{ink → render}/log-update.d.ts +0 -0
  237. /package/dist/{ink → render}/measure-element.d.ts +0 -0
  238. /package/dist/{ink → render}/measure-text.d.ts +0 -0
  239. /package/dist/{ink → render}/node-cache.d.ts +0 -0
  240. /package/dist/{ink → render}/optimizer.d.ts +0 -0
  241. /package/dist/{ink → render}/output.d.ts +0 -0
  242. /package/dist/{ink → render}/parse-keypress.d.ts +0 -0
  243. /package/dist/{ink → render}/reconciler.d.ts +0 -0
  244. /package/dist/{ink → render}/render-border.d.ts +0 -0
  245. /package/dist/{ink → render}/render-node-to-output.d.ts +0 -0
  246. /package/dist/{ink → render}/render-to-screen.d.ts +0 -0
  247. /package/dist/{ink → render}/renderer.d.ts +0 -0
  248. /package/dist/{ink → render}/root.d.ts +0 -0
  249. /package/dist/{ink → render}/screen.d.ts +0 -0
  250. /package/dist/{ink → render}/searchHighlight.d.ts +0 -0
  251. /package/dist/{ink → render}/selection.d.ts +0 -0
  252. /package/dist/{ink → render}/squash-text-nodes.d.ts +0 -0
  253. /package/dist/{ink → render}/stringWidth.d.ts +0 -0
  254. /package/dist/{ink → render}/styles.d.ts +0 -0
  255. /package/dist/{ink → render}/supports-hyperlinks.d.ts +0 -0
  256. /package/dist/{ink → render}/tabstops.d.ts +0 -0
  257. /package/dist/{ink → render}/terminal-focus-state.d.ts +0 -0
  258. /package/dist/{ink → render}/terminal-querier.d.ts +0 -0
  259. /package/dist/{ink → render}/terminal.d.ts +0 -0
  260. /package/dist/{ink → render}/termio/ansi.d.ts +0 -0
  261. /package/dist/{ink → render}/termio/csi.d.ts +0 -0
  262. /package/dist/{ink → render}/termio/dec.d.ts +0 -0
  263. /package/dist/{ink → render}/termio/esc.d.ts +0 -0
  264. /package/dist/{ink → render}/termio/osc.d.ts +0 -0
  265. /package/dist/{ink → render}/termio/parser.d.ts +0 -0
  266. /package/dist/{ink → render}/termio/sgr.d.ts +0 -0
  267. /package/dist/{ink → render}/termio/tokenize.d.ts +0 -0
  268. /package/dist/{ink → render}/termio/types.d.ts +0 -0
  269. /package/dist/{ink → render}/termio.d.ts +0 -0
  270. /package/dist/{ink → render}/useTerminalNotification.d.ts +0 -0
  271. /package/dist/{ink → render}/warn.d.ts +0 -0
  272. /package/dist/{ink → render}/widest-line.d.ts +0 -0
  273. /package/dist/{ink → render}/wrap-text.d.ts +0 -0
  274. /package/dist/{ink → render}/wrapAnsi.d.ts +0 -0
@@ -1,9 +1,9 @@
1
- import {
2
- logger
3
- } from "./chunk-X4HAERTQ.js";
4
1
  import {
5
2
  LLMError
6
3
  } from "./chunk-FUOKLKR2.js";
4
+ import {
5
+ logger
6
+ } from "./chunk-ZRVPCXI7.js";
7
7
  import {
8
8
  init_esm_shims
9
9
  } from "./chunk-DI7RDLOS.js";
@@ -18,11 +18,11 @@ async function createLLMClient(config) {
18
18
  let Cls = PROVIDER_REGISTRY.get(config.provider);
19
19
  if (!Cls) {
20
20
  if (config.provider === "anthropic") {
21
- const { AnthropicClient } = await import("./anthropic-NENYS535.js");
21
+ const { AnthropicClient } = await import("./anthropic-W2GU3D76.js");
22
22
  registerProvider("anthropic", AnthropicClient);
23
23
  Cls = AnthropicClient;
24
24
  } else if (config.provider === "openai") {
25
- const { OpenAIClient } = await import("./openai-5HQGBL4L.js");
25
+ const { OpenAIClient } = await import("./openai-RXU5URYI.js");
26
26
  registerProvider("openai", OpenAIClient);
27
27
  Cls = OpenAIClient;
28
28
  }
@@ -158,6 +158,8 @@ function parseReport(participant, text) {
158
158
  findings: []
159
159
  };
160
160
  }
161
+ const xmlReport = tryParseReportXml(participant, text);
162
+ if (xmlReport && xmlReport.findings.length > 0) return xmlReport;
161
163
  try {
162
164
  const json = extractJSON(text);
163
165
  const parsed = JSON.parse(json);
@@ -172,22 +174,82 @@ function parseReport(participant, text) {
172
174
  contextSummary: parsed.contextSummary ?? parsed.context_summary ?? "",
173
175
  findings: Array.isArray(findings) ? findings.map(parseFinding) : []
174
176
  };
175
- if (report.findings.length === 0) {
176
- logger.warn("arena.parse_report_no_findings", {
177
- participant,
178
- textPreview: text.slice(0, 200)
179
- });
180
- }
181
- return report;
177
+ if (report.findings.length > 0) return report;
182
178
  } catch (err) {
183
179
  logger.warn("arena.parse_report_json_fail", {
184
180
  participant,
185
181
  error: err.message,
186
182
  textLength: text.length,
187
- text: text.slice(0, 2e3)
183
+ text: text.slice(0, 500)
188
184
  });
189
- return extractFindingsFromFreeText(participant, text);
190
185
  }
186
+ if (xmlReport) {
187
+ logger.warn("arena.parse_report_no_findings", {
188
+ participant,
189
+ textPreview: text.slice(0, 200)
190
+ });
191
+ return xmlReport;
192
+ }
193
+ return extractFindingsFromFreeText(participant, text);
194
+ }
195
+ function tryParseReportXml(participant, text) {
196
+ const reportMatch = text.match(/<report\b[^>]*>([\s\S]*?)<\/report>/i);
197
+ if (!reportMatch) return void 0;
198
+ const body = reportMatch[1];
199
+ const contextSummary = decodeXmlText(extractTag(body, "contextSummary") ?? "");
200
+ const findingsBlock = extractTag(body, "findings") ?? "";
201
+ const findings = [];
202
+ let i = 0;
203
+ for (const match of findingsBlock.matchAll(/<finding\b([^>]*)>([\s\S]*?)<\/finding>/gi)) {
204
+ const attrs = parseAttrs(match[1]);
205
+ const inner = match[2];
206
+ const title = decodeXmlText(extractTag(inner, "title") ?? "");
207
+ const summary = decodeXmlText(extractTag(inner, "summary") ?? "");
208
+ const evidence = [];
209
+ for (const ev of inner.matchAll(/<evidence\b([^>]*)>([\s\S]*?)<\/evidence>/gi)) {
210
+ const evAttrs = parseAttrs(ev[1]);
211
+ evidence.push({
212
+ type: evAttrs.type ?? "doc",
213
+ ref: evAttrs.ref ?? "",
214
+ note: decodeXmlText(ev[2].trim())
215
+ });
216
+ }
217
+ const affectedFilesBlock = extractTag(inner, "affectedFiles") ?? "";
218
+ const affectedFiles = [];
219
+ for (const f of affectedFilesBlock.matchAll(/<file>([\s\S]*?)<\/file>/gi)) {
220
+ affectedFiles.push(decodeXmlText(f[1].trim()));
221
+ }
222
+ const suggestedChange = decodeXmlText(extractTag(inner, "suggestedChange") ?? "").trim();
223
+ const confidence = Number(attrs.confidence);
224
+ findings.push({
225
+ id: attrs.id || `f${i + 1}`,
226
+ kind: validateFindingKind(attrs.kind),
227
+ title: title || "Untitled",
228
+ summary,
229
+ severity: attrs.severity || void 0,
230
+ confidence: Number.isFinite(confidence) ? confidence : 0.5,
231
+ evidence,
232
+ affectedFiles,
233
+ suggestedChange: suggestedChange || void 0
234
+ });
235
+ i++;
236
+ }
237
+ return { participant, contextSummary, findings };
238
+ }
239
+ function extractTag(xml, tag) {
240
+ const re = new RegExp(`<${tag}\\b[^>]*>([\\s\\S]*?)<\\/${tag}>`, "i");
241
+ const m = xml.match(re);
242
+ return m?.[1];
243
+ }
244
+ function parseAttrs(attrString) {
245
+ const out = {};
246
+ for (const m of attrString.matchAll(/(\w+)\s*=\s*"([^"]*)"/g)) {
247
+ out[m[1]] = m[2];
248
+ }
249
+ return out;
250
+ }
251
+ function decodeXmlText(s) {
252
+ return s.replace(/<!\[CDATA\[([\s\S]*?)\]\]>/g, "$1").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&apos;/g, "'").replace(/&amp;/g, "&").trim();
191
253
  }
192
254
  function parseFinding(raw, index) {
193
255
  return {
@@ -564,13 +626,32 @@ var ReviewStrategy = class {
564
626
  You may have access to read-only tools to fetch additional context. The base context is intentionally lean \u2014 use tools to inspect details as needed.
565
627
 
566
628
  IMPORTANT RULES:
567
- - Limit yourself to 3-5 tool rounds. Do NOT exhaustively read every file.
629
+ - Limit yourself to AT MOST 3 tool rounds. Do NOT exhaustively read every file.
568
630
  - Focus on the HIGHEST-IMPACT findings. Quality over quantity.
569
- - Output as many findings as the topic warrants \u2014 typically 5-15 for a non-trivial subject. Each finding's "summary" should be 80+ words with concrete evidence and rationale, not a one-liner. Rank by confidence.
631
+ - Output as many findings as the topic warrants \u2014 typically 5-15 for a non-trivial subject. Each <summary> should be 80+ words with concrete evidence and rationale, not a one-liner. Rank by confidence.
570
632
  - Prioritize: risks > improvements > questions. Strengths are optional.
571
633
 
572
- When ready, respond ONLY with JSON (no markdown fences):
573
- {"contextSummary": "brief summary of what you investigated", "findings": [{"id": "unique-id", "kind": "risk|improvement|question|strength", "title": "short title", "summary": "detailed explanation", "severity": "high|medium|low", "confidence": 0.0-1.0, "evidence": [{"type": "file|diff|grep|git|doc", "ref": "path", "note": "what it shows"}], "affectedFiles": ["paths"], "suggestedChange": "optional"}]}`;
634
+ When ready, respond ONLY with the following XML structure (no markdown fences, no commentary outside the root element):
635
+
636
+ <report>
637
+ <contextSummary>brief summary of what you investigated</contextSummary>
638
+ <findings>
639
+ <finding id="unique-id" kind="risk|improvement|question|strength" severity="high|medium|low" confidence="0.0-1.0">
640
+ <title>short title</title>
641
+ <summary>detailed explanation, 80+ words, citing specific files/lines</summary>
642
+ <evidence type="file|diff|grep|git|doc" ref="path">what it shows</evidence>
643
+ <evidence type="file" ref="another/path">\u2026</evidence>
644
+ <affectedFiles>
645
+ <file>src/foo.ts</file>
646
+ <file>src/bar.ts</file>
647
+ </affectedFiles>
648
+ <suggestedChange>optional concrete fix</suggestedChange>
649
+ </finding>
650
+ <!-- repeat <finding> blocks as needed -->
651
+ </findings>
652
+ </report>
653
+
654
+ XML is preferred over JSON because thinking-mode models produce more reliable output here. Do not wrap the XML in code fences. Do not include text outside <report>\u2026</report>.`;
574
655
  }
575
656
  researchUserPrompt(topic, baseContext) {
576
657
  return `## Review Topic
@@ -578,7 +659,7 @@ ${topic}
578
659
 
579
660
  ${formatBaseContext(baseContext)}
580
661
 
581
- Use tools to read specific files from the diff. Then output 3-6 highest-confidence findings as JSON.`;
662
+ Use tools to read specific files from the diff. Then output 3-6 highest-confidence findings as a single <report> XML element.`;
582
663
  }
583
664
  parseResearchResponse(participant, text) {
584
665
  return parseReport(participant, text);
@@ -716,7 +797,14 @@ ${debateSummary}
716
797
  ## Evidence Digest
717
798
  ${formatDigestForPrompt(digest)}
718
799
 
719
- As moderator, adjudicate this claim based on all available evidence.
800
+ As moderator, you MUST issue a verdict \u2014 "unresolved" is reserved ONLY for the rare case where the debate produced genuinely irreconcilable interpretations of the same evidence. Default to deciding.
801
+
802
+ Decision rule:
803
+ - "accepted": claim is correct as stated AND has direct evidence (file/line refs).
804
+ - "accepted_with_revision": core insight is correct but the challenge surfaced a real refinement (scope/severity/wording). Issue a corrected finalSummary.
805
+ - "rejected": the challenger demonstrated the claim is factually wrong or already addressed in the code under review.
806
+ - "unresolved": ONLY when no amount of further evidence could break the tie \u2014 e.g., taste-level disagreement on design philosophy. Using this on a verifiable code claim is a failure of adjudication.
807
+
720
808
  Respond ONLY with JSON:
721
809
  {"outcome": "accepted|accepted_with_revision|rejected|unresolved", "rationale": "...", "finalSummary": "revised claim summary if needed", "supportingEvidenceRefs": ["..."]}`;
722
810
  }
@@ -1852,15 +1940,15 @@ var gitProvider = {
1852
1940
  });
1853
1941
  }
1854
1942
  const statArgs = isCompare ? ["diff", "--stat", `${baseRef}...${headRef}`] : ["diff", "--stat", "HEAD"];
1855
- let stat = git(statArgs);
1856
- if (!stat && !isCompare) stat = git(["diff", "--stat", "--cached"]);
1857
- if (stat) {
1943
+ let stat2 = git(statArgs);
1944
+ if (!stat2 && !isCompare) stat2 = git(["diff", "--stat", "--cached"]);
1945
+ if (stat2) {
1858
1946
  artifacts.push({
1859
1947
  id: "git-diffstat",
1860
1948
  kind: "doc",
1861
1949
  source: "git",
1862
1950
  title: "Diff Stat",
1863
- preview: stat
1951
+ preview: stat2
1864
1952
  });
1865
1953
  }
1866
1954
  const filesArgs = isCompare ? ["diff", "--name-status", `${baseRef}...${headRef}`] : ["diff", "--name-status", "HEAD"];
@@ -1909,7 +1997,7 @@ var gitProvider = {
1909
1997
  metadata: { totalChars: diff.length, truncated }
1910
1998
  });
1911
1999
  }
1912
- if (!diff && !stat) {
2000
+ if (!diff && !stat2) {
1913
2001
  const status = git(["status", "--short"]);
1914
2002
  if (status) {
1915
2003
  artifacts.push({
@@ -1957,16 +2045,21 @@ function clusterByDirectory(paths) {
1957
2045
 
1958
2046
  // src/arena/providers/repo.ts
1959
2047
  init_esm_shims();
1960
- import { existsSync, readdirSync, statSync, readFileSync } from "fs";
2048
+ import { existsSync, readFileSync, statSync } from "fs";
2049
+ import { readdir, stat } from "fs/promises";
1961
2050
  import { join } from "path";
1962
- import { execFileSync as execFileSync2 } from "child_process";
2051
+ import { execFile } from "child_process";
2052
+ import { promisify } from "util";
1963
2053
  var MAX_FILE_CHARS = 8e3;
2054
+ var GREP_TIMEOUT_MS = 3e3;
2055
+ var MAX_TREE_NODES = 400;
2056
+ var execFileAsync = promisify(execFile);
1964
2057
  var repoProvider = {
1965
2058
  kind: "repo",
1966
- collect(plan, topic) {
2059
+ async collect(plan, topic) {
1967
2060
  const artifacts = [];
1968
2061
  const targets = plan.sources.find((s) => s.kind === "repo")?.targets ?? [];
1969
- const tree = buildTree(".", 2);
2062
+ const tree = await buildTree(".", 2);
1970
2063
  if (tree) {
1971
2064
  artifacts.push({
1972
2065
  id: "repo-tree",
@@ -1980,7 +2073,7 @@ var repoProvider = {
1980
2073
  if (!existsSync(target)) continue;
1981
2074
  const st = statSync(target);
1982
2075
  if (st.isDirectory()) {
1983
- const dirTree = buildTree(target, 3);
2076
+ const dirTree = await buildTree(target, 3);
1984
2077
  if (dirTree) {
1985
2078
  artifacts.push({
1986
2079
  id: `repo-tree-${target}`,
@@ -1990,7 +2083,7 @@ var repoProvider = {
1990
2083
  preview: dirTree
1991
2084
  });
1992
2085
  }
1993
- for (const file of collectEntryFiles(target).slice(0, 3)) {
2086
+ for (const file of (await collectEntryFiles(target)).slice(0, 3)) {
1994
2087
  const content = safeReadFile(file);
1995
2088
  if (content) {
1996
2089
  artifacts.push({
@@ -2018,29 +2111,30 @@ var repoProvider = {
2018
2111
  }
2019
2112
  }
2020
2113
  if (targets.length === 0) {
2021
- const hints = extractSearchHints(topic);
2022
- for (const hint of hints.slice(0, 5)) {
2023
- const grepResult = safeGrep(hint);
2024
- if (grepResult) {
2025
- const files = grepResult.split("\n").filter(Boolean).slice(0, 10);
2026
- for (const file of files) {
2027
- if (!artifacts.some((a) => a.ref === file)) {
2028
- artifacts.push({
2029
- id: `repo-grep-${hint}-${file}`,
2030
- kind: "grep",
2031
- source: "repo",
2032
- title: `Match: ${hint} \u2192 ${file}`,
2033
- ref: file,
2034
- preview: file
2035
- });
2036
- }
2114
+ const hints = extractSearchHints(topic).slice(0, 5);
2115
+ const grepResults = await Promise.all(hints.map((h) => safeGrep(h)));
2116
+ for (let i = 0; i < hints.length; i++) {
2117
+ const hint = hints[i];
2118
+ const result = grepResults[i] ?? "";
2119
+ if (!result) continue;
2120
+ const files = result.split("\n").filter(Boolean).slice(0, 10);
2121
+ for (const file of files) {
2122
+ if (!artifacts.some((a) => a.ref === file)) {
2123
+ artifacts.push({
2124
+ id: `repo-grep-${hint}-${file}`,
2125
+ kind: "grep",
2126
+ source: "repo",
2127
+ title: `Match: ${hint} \u2192 ${file}`,
2128
+ ref: file,
2129
+ preview: file
2130
+ });
2037
2131
  }
2038
2132
  }
2039
2133
  }
2040
2134
  }
2041
2135
  const hasGitSource = plan.sources.some((s) => s.kind === "git");
2042
2136
  if (!hasGitSource) {
2043
- const recentLog = gitLog();
2137
+ const recentLog = await gitLog();
2044
2138
  if (recentLog) {
2045
2139
  artifacts.push({
2046
2140
  id: "repo-recent-activity",
@@ -2055,30 +2149,43 @@ var repoProvider = {
2055
2149
  return artifacts;
2056
2150
  }
2057
2151
  };
2058
- function buildTree(dir, maxDepth, depth = 0, prefix = "") {
2059
- if (depth >= maxDepth) return "";
2152
+ async function buildTree(dir, maxDepth) {
2153
+ const lines = [];
2154
+ const counter = { n: 0 };
2155
+ await walkTree(dir, maxDepth, 0, "", lines, counter);
2156
+ return lines.filter(Boolean).join("\n");
2157
+ }
2158
+ async function walkTree(dir, maxDepth, depth, prefix, out, counter) {
2159
+ if (depth >= maxDepth) return;
2160
+ if (counter.n >= MAX_TREE_NODES) return;
2161
+ let entries;
2060
2162
  try {
2061
- const entries = readdirSync(dir).filter(
2163
+ entries = (await readdir(dir)).filter(
2062
2164
  (e) => !e.startsWith(".") && e !== "node_modules" && e !== "dist" && e !== "__pycache__"
2063
2165
  );
2064
- const lines = [];
2065
- for (const entry of entries.slice(0, 30)) {
2066
- const fullPath = join(dir, entry);
2067
- const isDir = statSync(fullPath).isDirectory();
2068
- lines.push(`${prefix}${isDir ? "/" : ""} ${entry}`);
2069
- if (isDir && depth < maxDepth - 1) {
2070
- lines.push(buildTree(fullPath, maxDepth, depth + 1, prefix + " "));
2071
- }
2072
- }
2073
- return lines.filter(Boolean).join("\n");
2074
2166
  } catch {
2075
- return "";
2167
+ return;
2168
+ }
2169
+ for (const entry of entries.slice(0, 30)) {
2170
+ if (counter.n >= MAX_TREE_NODES) return;
2171
+ counter.n++;
2172
+ const fullPath = join(dir, entry);
2173
+ let isDir = false;
2174
+ try {
2175
+ isDir = (await stat(fullPath)).isDirectory();
2176
+ } catch {
2177
+ continue;
2178
+ }
2179
+ out.push(`${prefix}${isDir ? "/" : ""} ${entry}`);
2180
+ if (isDir && depth < maxDepth - 1) {
2181
+ await walkTree(fullPath, maxDepth, depth + 1, prefix + " ", out, counter);
2182
+ }
2076
2183
  }
2077
2184
  }
2078
- function collectEntryFiles(dir) {
2185
+ async function collectEntryFiles(dir) {
2079
2186
  const files = [];
2080
2187
  try {
2081
- const entries = readdirSync(dir);
2188
+ const entries = await readdir(dir);
2082
2189
  const priority = ["index.ts", "index.js", "main.ts", "main.js", "mod.ts", "__init__.py"];
2083
2190
  for (const p of priority) {
2084
2191
  if (entries.includes(p)) files.push(join(dir, p));
@@ -2110,9 +2217,9 @@ function truncate(content) {
2110
2217
  return t.slice(0, lastNl) + `
2111
2218
  ... (truncated, ${content.length} chars total)`;
2112
2219
  }
2113
- function safeGrep(pattern) {
2220
+ async function safeGrep(pattern) {
2114
2221
  try {
2115
- const result = execFileSync2("grep", [
2222
+ const { stdout } = await execFileAsync("grep", [
2116
2223
  "-rl",
2117
2224
  "--include=*.ts",
2118
2225
  "--include=*.js",
@@ -2121,19 +2228,28 @@ function safeGrep(pattern) {
2121
2228
  "-i",
2122
2229
  pattern,
2123
2230
  "."
2124
- ], { encoding: "utf-8", maxBuffer: 1024 * 1024, timeout: 1e4 });
2125
- return result.trim();
2126
- } catch {
2231
+ ], { encoding: "utf-8", maxBuffer: 1024 * 1024, timeout: GREP_TIMEOUT_MS });
2232
+ return stdout.trim();
2233
+ } catch (err) {
2234
+ const e = err;
2235
+ if (e?.code === 1) return "";
2236
+ logger.warn("arena.provider.grep_failed", {
2237
+ pattern,
2238
+ code: e?.code,
2239
+ killed: e?.killed,
2240
+ signal: e?.signal
2241
+ });
2127
2242
  return "";
2128
2243
  }
2129
2244
  }
2130
- function gitLog() {
2245
+ async function gitLog() {
2131
2246
  try {
2132
- return execFileSync2("git", ["log", "--oneline", "-10"], {
2247
+ const { stdout } = await execFileAsync("git", ["log", "--oneline", "-10"], {
2133
2248
  encoding: "utf-8",
2134
2249
  maxBuffer: 1024 * 1024,
2135
2250
  timeout: 1e4
2136
- }).trim();
2251
+ });
2252
+ return stdout.trim();
2137
2253
  } catch {
2138
2254
  return "";
2139
2255
  }
@@ -2204,7 +2320,7 @@ function extractSearchHints(topic) {
2204
2320
 
2205
2321
  // src/arena/providers/docs.ts
2206
2322
  init_esm_shims();
2207
- import { existsSync as existsSync2, readFileSync as readFileSync2, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
2323
+ import { existsSync as existsSync2, readFileSync as readFileSync2, readdirSync, statSync as statSync2 } from "fs";
2208
2324
  import { join as join2, extname } from "path";
2209
2325
  var MAX_DOC_CHARS = 1e4;
2210
2326
  var DOC_EXTENSIONS = /* @__PURE__ */ new Set([".md", ".txt", ".rst", ".adoc", ".org"]);
@@ -2264,7 +2380,7 @@ function findDocFiles(dir, maxDepth, depth = 0) {
2264
2380
  if (depth >= maxDepth) return [];
2265
2381
  const files = [];
2266
2382
  try {
2267
- const entries = readdirSync2(dir);
2383
+ const entries = readdirSync(dir);
2268
2384
  for (const entry of entries) {
2269
2385
  if (entry.startsWith(".") || entry === "node_modules") continue;
2270
2386
  const full = join2(dir, entry);
@@ -2315,20 +2431,36 @@ var PROVIDER_MAP = {
2315
2431
  // web deferred to Phase 4 — falls back to none for now
2316
2432
  none: noneProvider
2317
2433
  };
2318
- function collectEvidence(plan, topic) {
2434
+ var PROVIDER_TIMEOUT_MS = 8e3;
2435
+ async function collectEvidence(plan, topic, options = {}) {
2319
2436
  const artifacts = [];
2320
2437
  const quickFacts = [];
2321
2438
  const seenSources = /* @__PURE__ */ new Set();
2439
+ const { onProgress, signal } = options;
2440
+ const tasks = [];
2322
2441
  for (const sourceSpec of plan.sources) {
2323
2442
  if (seenSources.has(sourceSpec.kind)) continue;
2324
2443
  seenSources.add(sourceSpec.kind);
2325
2444
  const provider = PROVIDER_MAP[sourceSpec.kind];
2326
2445
  if (!provider) continue;
2327
- const collected = provider.collect(plan, topic);
2328
- artifacts.push(...collected);
2446
+ onProgress?.({ type: "evidence_started", source: sourceSpec.kind });
2447
+ tasks.push(runProviderWithTimeout(provider, plan, topic, signal));
2448
+ }
2449
+ const results = await Promise.all(tasks);
2450
+ for (const r of results) {
2451
+ artifacts.push(...r.artifacts);
2329
2452
  logger.info("arena.evidence_collected", {
2330
- source: sourceSpec.kind,
2331
- count: collected.length
2453
+ source: r.kind,
2454
+ count: r.artifacts.length,
2455
+ durationMs: r.durationMs,
2456
+ timedOut: r.timedOut || void 0
2457
+ });
2458
+ onProgress?.({
2459
+ type: "evidence_collected",
2460
+ source: r.kind,
2461
+ count: r.artifacts.length,
2462
+ durationMs: r.durationMs,
2463
+ timedOut: r.timedOut
2332
2464
  });
2333
2465
  }
2334
2466
  const branchArtifact = artifacts.find((a) => a.id === "git-branch");
@@ -2343,17 +2475,61 @@ function collectEvidence(plan, topic) {
2343
2475
  quickFacts.push({ label: "Lenses", value: plan.lenses.map((l) => l.name).join(", ") });
2344
2476
  return { artifacts, quickFacts };
2345
2477
  }
2478
+ async function runProviderWithTimeout(provider, plan, topic, signal) {
2479
+ const started = Date.now();
2480
+ let timedOut = false;
2481
+ let timer;
2482
+ let abortHandler;
2483
+ const cleanup = () => {
2484
+ if (timer) {
2485
+ clearTimeout(timer);
2486
+ timer = void 0;
2487
+ }
2488
+ if (abortHandler) {
2489
+ signal?.removeEventListener("abort", abortHandler);
2490
+ abortHandler = void 0;
2491
+ }
2492
+ };
2493
+ const work = Promise.resolve().then(() => provider.collect(plan, topic));
2494
+ const timeout = new Promise((resolve2) => {
2495
+ timer = setTimeout(() => {
2496
+ timedOut = true;
2497
+ logger.warn("arena.provider.timeout", { source: provider.kind, ms: PROVIDER_TIMEOUT_MS });
2498
+ resolve2([]);
2499
+ }, PROVIDER_TIMEOUT_MS);
2500
+ if (typeof timer.unref === "function") timer.unref();
2501
+ if (signal) {
2502
+ abortHandler = () => resolve2([]);
2503
+ signal.addEventListener("abort", abortHandler, { once: true });
2504
+ }
2505
+ });
2506
+ let artifacts;
2507
+ try {
2508
+ artifacts = await Promise.race([work, timeout]);
2509
+ } catch (err) {
2510
+ logger.warn("arena.provider.error", { source: provider.kind, error: err.message });
2511
+ artifacts = [];
2512
+ } finally {
2513
+ cleanup();
2514
+ }
2515
+ return {
2516
+ kind: provider.kind,
2517
+ artifacts,
2518
+ durationMs: Date.now() - started,
2519
+ timedOut
2520
+ };
2521
+ }
2346
2522
 
2347
2523
  // src/arena/tools/selector.ts
2348
2524
  init_esm_shims();
2349
2525
 
2350
2526
  // src/arena/context/context-tools.ts
2351
2527
  init_esm_shims();
2352
- import { readFileSync as readFileSync3, existsSync as existsSync3, readdirSync as readdirSync3, statSync as statSync3 } from "fs";
2353
- import { execFileSync as execFileSync3 } from "child_process";
2528
+ import { readFileSync as readFileSync3, existsSync as existsSync3, readdirSync as readdirSync2, statSync as statSync3 } from "fs";
2529
+ import { execFileSync as execFileSync2 } from "child_process";
2354
2530
  import { resolve, join as join3 } from "path";
2355
2531
  var MAX_TOOL_RESULT = 15e3;
2356
- var MAX_TOOL_ROUNDS = 5;
2532
+ var MAX_TOOL_ROUNDS = 3;
2357
2533
  var REPO_ROOT = resolve(".");
2358
2534
  var CONTEXT_TOOLS = [
2359
2535
  {
@@ -2470,7 +2646,7 @@ function executeListFiles(args) {
2470
2646
  const dir = args.path || ".";
2471
2647
  if (!validatePath(dir)) return `Error: path outside repository: ${dir}`;
2472
2648
  try {
2473
- const entries = readdirSync3(dir);
2649
+ const entries = readdirSync2(dir);
2474
2650
  const lines = [];
2475
2651
  for (const entry of entries.slice(0, 50)) {
2476
2652
  const fullPath = join3(dir, entry);
@@ -2514,7 +2690,7 @@ function sanitizeGitRef(ref) {
2514
2690
  }
2515
2691
  function execFileSafe(cmd, args, maxLines) {
2516
2692
  try {
2517
- const raw = execFileSync3(cmd, args, {
2693
+ const raw = execFileSync2(cmd, args, {
2518
2694
  encoding: "utf-8",
2519
2695
  maxBuffer: 512 * 1024,
2520
2696
  timeout: 1e4
@@ -2679,6 +2855,16 @@ async function runParticipantResearchWithDossiers(options) {
2679
2855
  content: result
2680
2856
  });
2681
2857
  }
2858
+ const remaining = MAX_TOOL_ROUNDS - round;
2859
+ const isLastAllowedRound = remaining <= 0;
2860
+ const isPenultimate = remaining === 1;
2861
+ if (isLastAllowedRound || isPenultimate) {
2862
+ const directive = isLastAllowedRound ? "STOP. You have used your tool budget. Your NEXT response MUST be the findings JSON. Do NOT call any more tools \u2014 any further tool_use will be discarded." : "FINAL ROUND. Use the tool results below plus any prior context to output the findings JSON in your NEXT response. Do not call more tools.";
2863
+ resultBlocks.unshift({
2864
+ type: "text",
2865
+ text: `[arena-research:${p.name}] ${directive}`
2866
+ });
2867
+ }
2682
2868
  messages.push({ role: "user", content: resultBlocks });
2683
2869
  }
2684
2870
  if (!finalText) {
@@ -2693,7 +2879,7 @@ async function runParticipantResearchWithDossiers(options) {
2693
2879
  ...messages,
2694
2880
  {
2695
2881
  role: "user",
2696
- content: "You have gathered enough context. Based on ALL the tool results above, output your findings NOW.\n\nRespond ONLY with JSON \u2014 output your highest-confidence findings (typically 5-15 for a substantive topic; each finding's `summary` should be 80+ words with concrete evidence). Do NOT request any more tools. Just output the JSON."
2882
+ content: "You have gathered enough context. Based on ALL the tool results above, output your findings NOW.\n\nRespond ONLY with the <report> XML element specified in the system prompt \u2014 output your highest-confidence findings (typically 5-15 for a substantive topic; each <summary> should be 80+ words with concrete evidence). Do NOT request any more tools. No prose outside the XML."
2697
2883
  }
2698
2884
  ]
2699
2885
  });
@@ -3857,8 +4043,24 @@ var Arena = class {
3857
4043
  this.config.mode = plan.mode;
3858
4044
  }
3859
4045
  signal?.throwIfAborted();
3860
- const { artifacts, quickFacts } = collectEvidence(plan, topic);
3861
- this.config.onProgress?.({ type: "evidence_collected", artifacts });
4046
+ const onProgress = this.config.onProgress;
4047
+ const { artifacts, quickFacts } = await collectEvidence(plan, topic, {
4048
+ signal,
4049
+ onProgress: (e) => {
4050
+ if (e.type === "evidence_started") {
4051
+ onProgress?.({ type: "evidence_started", source: e.source });
4052
+ } else {
4053
+ onProgress?.({
4054
+ type: "evidence_source_done",
4055
+ source: e.source,
4056
+ count: e.count ?? 0,
4057
+ durationMs: e.durationMs ?? 0,
4058
+ timedOut: e.timedOut ?? false
4059
+ });
4060
+ }
4061
+ }
4062
+ });
4063
+ onProgress?.({ type: "evidence_collected", artifacts });
3862
4064
  logger.info("arena.evidence", {
3863
4065
  artifactCount: artifacts.length,
3864
4066
  sources: plan.sources.map((s) => s.kind)
@@ -4299,6 +4501,14 @@ function createProgressRenderer(sink) {
4299
4501
  `Plan: ${event.plan.mode} | lenses: ${event.plan.lenses.map((l) => l.name).join(", ")} | sources: ${event.plan.sources.map((s) => s.kind).join(", ")}` + (event.plan.confidence !== "high" ? ` (${event.plan.confidence} confidence)` : "")
4300
4502
  ));
4301
4503
  break;
4504
+ case "evidence_started":
4505
+ sink(chalk.dim(` \xB7 collecting from ${event.source}\u2026`));
4506
+ break;
4507
+ case "evidence_source_done": {
4508
+ const tag = event.timedOut ? chalk.yellow(" (timed out)") : "";
4509
+ sink(chalk.dim(` \xB7 ${event.source}: ${event.count} artifacts in ${event.durationMs}ms${tag}`));
4510
+ break;
4511
+ }
4302
4512
  case "evidence_collected":
4303
4513
  sink(chalk.dim(`Evidence: ${event.artifacts.length} artifacts collected`));
4304
4514
  break;