reasonix 0.49.0 → 0.50.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 (327) hide show
  1. package/dashboard/dist/app.css +1 -0
  2. package/dashboard/dist/app.js +28 -30531
  3. package/dashboard/dist/app.js.map +1 -1
  4. package/dashboard/dist/assets/KaTeX_AMS-Regular.ttf +0 -0
  5. package/dashboard/dist/assets/KaTeX_AMS-Regular.woff +0 -0
  6. package/dashboard/dist/assets/KaTeX_AMS-Regular.woff2 +0 -0
  7. package/dashboard/dist/assets/KaTeX_Caligraphic-Bold.ttf +0 -0
  8. package/dashboard/dist/assets/KaTeX_Caligraphic-Bold.woff +0 -0
  9. package/dashboard/dist/assets/KaTeX_Caligraphic-Bold.woff2 +0 -0
  10. package/dashboard/dist/assets/KaTeX_Caligraphic-Regular.ttf +0 -0
  11. package/dashboard/dist/assets/KaTeX_Caligraphic-Regular.woff +0 -0
  12. package/dashboard/dist/assets/KaTeX_Caligraphic-Regular.woff2 +0 -0
  13. package/dashboard/dist/assets/KaTeX_Fraktur-Bold.ttf +0 -0
  14. package/dashboard/dist/assets/KaTeX_Fraktur-Bold.woff +0 -0
  15. package/dashboard/dist/assets/KaTeX_Fraktur-Bold.woff2 +0 -0
  16. package/dashboard/dist/assets/KaTeX_Fraktur-Regular.ttf +0 -0
  17. package/dashboard/dist/assets/KaTeX_Fraktur-Regular.woff +0 -0
  18. package/dashboard/dist/assets/KaTeX_Fraktur-Regular.woff2 +0 -0
  19. package/dashboard/dist/assets/KaTeX_Main-Bold.ttf +0 -0
  20. package/dashboard/dist/assets/KaTeX_Main-Bold.woff +0 -0
  21. package/dashboard/dist/assets/KaTeX_Main-Bold.woff2 +0 -0
  22. package/dashboard/dist/assets/KaTeX_Main-BoldItalic.ttf +0 -0
  23. package/dashboard/dist/assets/KaTeX_Main-BoldItalic.woff +0 -0
  24. package/dashboard/dist/assets/KaTeX_Main-BoldItalic.woff2 +0 -0
  25. package/dashboard/dist/assets/KaTeX_Main-Italic.ttf +0 -0
  26. package/dashboard/dist/assets/KaTeX_Main-Italic.woff +0 -0
  27. package/dashboard/dist/assets/KaTeX_Main-Italic.woff2 +0 -0
  28. package/dashboard/dist/assets/KaTeX_Main-Regular.ttf +0 -0
  29. package/dashboard/dist/assets/KaTeX_Main-Regular.woff +0 -0
  30. package/dashboard/dist/assets/KaTeX_Main-Regular.woff2 +0 -0
  31. package/dashboard/dist/assets/KaTeX_Math-BoldItalic.ttf +0 -0
  32. package/dashboard/dist/assets/KaTeX_Math-BoldItalic.woff +0 -0
  33. package/dashboard/dist/assets/KaTeX_Math-BoldItalic.woff2 +0 -0
  34. package/dashboard/dist/assets/KaTeX_Math-Italic.ttf +0 -0
  35. package/dashboard/dist/assets/KaTeX_Math-Italic.woff +0 -0
  36. package/dashboard/dist/assets/KaTeX_Math-Italic.woff2 +0 -0
  37. package/dashboard/dist/assets/KaTeX_SansSerif-Bold.ttf +0 -0
  38. package/dashboard/dist/assets/KaTeX_SansSerif-Bold.woff +0 -0
  39. package/dashboard/dist/assets/KaTeX_SansSerif-Bold.woff2 +0 -0
  40. package/dashboard/dist/assets/KaTeX_SansSerif-Italic.ttf +0 -0
  41. package/dashboard/dist/assets/KaTeX_SansSerif-Italic.woff +0 -0
  42. package/dashboard/dist/assets/KaTeX_SansSerif-Italic.woff2 +0 -0
  43. package/dashboard/dist/assets/KaTeX_SansSerif-Regular.ttf +0 -0
  44. package/dashboard/dist/assets/KaTeX_SansSerif-Regular.woff +0 -0
  45. package/dashboard/dist/assets/KaTeX_SansSerif-Regular.woff2 +0 -0
  46. package/dashboard/dist/assets/KaTeX_Script-Regular.ttf +0 -0
  47. package/dashboard/dist/assets/KaTeX_Script-Regular.woff +0 -0
  48. package/dashboard/dist/assets/KaTeX_Script-Regular.woff2 +0 -0
  49. package/dashboard/dist/assets/KaTeX_Size1-Regular.ttf +0 -0
  50. package/dashboard/dist/assets/KaTeX_Size1-Regular.woff +0 -0
  51. package/dashboard/dist/assets/KaTeX_Size1-Regular.woff2 +0 -0
  52. package/dashboard/dist/assets/KaTeX_Size2-Regular.ttf +0 -0
  53. package/dashboard/dist/assets/KaTeX_Size2-Regular.woff +0 -0
  54. package/dashboard/dist/assets/KaTeX_Size2-Regular.woff2 +0 -0
  55. package/dashboard/dist/assets/KaTeX_Size3-Regular.ttf +0 -0
  56. package/dashboard/dist/assets/KaTeX_Size3-Regular.woff +0 -0
  57. package/dashboard/dist/assets/KaTeX_Size4-Regular.ttf +0 -0
  58. package/dashboard/dist/assets/KaTeX_Size4-Regular.woff +0 -0
  59. package/dashboard/dist/assets/KaTeX_Size4-Regular.woff2 +0 -0
  60. package/dashboard/dist/assets/KaTeX_Typewriter-Regular.ttf +0 -0
  61. package/dashboard/dist/assets/KaTeX_Typewriter-Regular.woff +0 -0
  62. package/dashboard/dist/assets/KaTeX_Typewriter-Regular.woff2 +0 -0
  63. package/dashboard/dist/assets/geist-cyrillic-400-normal.woff +0 -0
  64. package/dashboard/dist/assets/geist-cyrillic-400-normal.woff2 +0 -0
  65. package/dashboard/dist/assets/geist-cyrillic-500-normal.woff +0 -0
  66. package/dashboard/dist/assets/geist-cyrillic-500-normal.woff2 +0 -0
  67. package/dashboard/dist/assets/geist-cyrillic-600-normal.woff +0 -0
  68. package/dashboard/dist/assets/geist-cyrillic-600-normal.woff2 +0 -0
  69. package/dashboard/dist/assets/geist-cyrillic-700-normal.woff +0 -0
  70. package/dashboard/dist/assets/geist-cyrillic-700-normal.woff2 +0 -0
  71. package/dashboard/dist/assets/geist-cyrillic-ext-500-normal.woff +0 -0
  72. package/dashboard/dist/assets/geist-cyrillic-ext-600-normal.woff +0 -0
  73. package/dashboard/dist/assets/geist-cyrillic-ext-700-normal.woff +0 -0
  74. package/dashboard/dist/assets/geist-latin-400-normal.woff +0 -0
  75. package/dashboard/dist/assets/geist-latin-400-normal.woff2 +0 -0
  76. package/dashboard/dist/assets/geist-latin-500-normal.woff +0 -0
  77. package/dashboard/dist/assets/geist-latin-500-normal.woff2 +0 -0
  78. package/dashboard/dist/assets/geist-latin-600-normal.woff +0 -0
  79. package/dashboard/dist/assets/geist-latin-600-normal.woff2 +0 -0
  80. package/dashboard/dist/assets/geist-latin-700-normal.woff +0 -0
  81. package/dashboard/dist/assets/geist-latin-700-normal.woff2 +0 -0
  82. package/dashboard/dist/assets/geist-latin-ext-400-normal.woff +0 -0
  83. package/dashboard/dist/assets/geist-latin-ext-400-normal.woff2 +0 -0
  84. package/dashboard/dist/assets/geist-latin-ext-500-normal.woff +0 -0
  85. package/dashboard/dist/assets/geist-latin-ext-500-normal.woff2 +0 -0
  86. package/dashboard/dist/assets/geist-latin-ext-600-normal.woff +0 -0
  87. package/dashboard/dist/assets/geist-latin-ext-600-normal.woff2 +0 -0
  88. package/dashboard/dist/assets/geist-latin-ext-700-normal.woff +0 -0
  89. package/dashboard/dist/assets/geist-latin-ext-700-normal.woff2 +0 -0
  90. package/dashboard/dist/assets/geist-mono-cyrillic-400-normal.woff +0 -0
  91. package/dashboard/dist/assets/geist-mono-cyrillic-400-normal.woff2 +0 -0
  92. package/dashboard/dist/assets/geist-mono-cyrillic-500-normal.woff +0 -0
  93. package/dashboard/dist/assets/geist-mono-cyrillic-500-normal.woff2 +0 -0
  94. package/dashboard/dist/assets/geist-mono-cyrillic-600-normal.woff +0 -0
  95. package/dashboard/dist/assets/geist-mono-cyrillic-600-normal.woff2 +0 -0
  96. package/dashboard/dist/assets/geist-mono-latin-400-normal.woff +0 -0
  97. package/dashboard/dist/assets/geist-mono-latin-400-normal.woff2 +0 -0
  98. package/dashboard/dist/assets/geist-mono-latin-500-normal.woff +0 -0
  99. package/dashboard/dist/assets/geist-mono-latin-500-normal.woff2 +0 -0
  100. package/dashboard/dist/assets/geist-mono-latin-600-normal.woff +0 -0
  101. package/dashboard/dist/assets/geist-mono-latin-600-normal.woff2 +0 -0
  102. package/dashboard/dist/assets/geist-mono-latin-ext-400-normal.woff +0 -0
  103. package/dashboard/dist/assets/geist-mono-latin-ext-400-normal.woff2 +0 -0
  104. package/dashboard/dist/assets/geist-mono-latin-ext-500-normal.woff +0 -0
  105. package/dashboard/dist/assets/geist-mono-latin-ext-500-normal.woff2 +0 -0
  106. package/dashboard/dist/assets/geist-mono-latin-ext-600-normal.woff +0 -0
  107. package/dashboard/dist/assets/geist-mono-latin-ext-600-normal.woff2 +0 -0
  108. package/dashboard/dist/assets/geist-mono-symbols2-400-normal.woff +0 -0
  109. package/dashboard/dist/assets/geist-mono-symbols2-500-normal.woff +0 -0
  110. package/dashboard/dist/assets/geist-mono-symbols2-600-normal.woff +0 -0
  111. package/dashboard/dist/assets/geist-mono-vietnamese-400-normal.woff +0 -0
  112. package/dashboard/dist/assets/geist-mono-vietnamese-500-normal.woff +0 -0
  113. package/dashboard/dist/assets/geist-mono-vietnamese-600-normal.woff +0 -0
  114. package/dashboard/dist/assets/geist-vietnamese-400-normal.woff +0 -0
  115. package/dashboard/dist/assets/geist-vietnamese-500-normal.woff +0 -0
  116. package/dashboard/dist/assets/geist-vietnamese-600-normal.woff +0 -0
  117. package/dashboard/dist/assets/geist-vietnamese-600-normal.woff2 +0 -0
  118. package/dashboard/dist/assets/geist-vietnamese-700-normal.woff +0 -0
  119. package/dashboard/dist/assets/inter-cyrillic-400-normal.woff +0 -0
  120. package/dashboard/dist/assets/inter-cyrillic-400-normal.woff2 +0 -0
  121. package/dashboard/dist/assets/inter-cyrillic-500-normal.woff +0 -0
  122. package/dashboard/dist/assets/inter-cyrillic-500-normal.woff2 +0 -0
  123. package/dashboard/dist/assets/inter-cyrillic-600-normal.woff +0 -0
  124. package/dashboard/dist/assets/inter-cyrillic-600-normal.woff2 +0 -0
  125. package/dashboard/dist/assets/inter-cyrillic-700-normal.woff +0 -0
  126. package/dashboard/dist/assets/inter-cyrillic-700-normal.woff2 +0 -0
  127. package/dashboard/dist/assets/inter-cyrillic-ext-400-normal.woff +0 -0
  128. package/dashboard/dist/assets/inter-cyrillic-ext-400-normal.woff2 +0 -0
  129. package/dashboard/dist/assets/inter-cyrillic-ext-500-normal.woff +0 -0
  130. package/dashboard/dist/assets/inter-cyrillic-ext-500-normal.woff2 +0 -0
  131. package/dashboard/dist/assets/inter-cyrillic-ext-600-normal.woff +0 -0
  132. package/dashboard/dist/assets/inter-cyrillic-ext-600-normal.woff2 +0 -0
  133. package/dashboard/dist/assets/inter-cyrillic-ext-700-normal.woff +0 -0
  134. package/dashboard/dist/assets/inter-cyrillic-ext-700-normal.woff2 +0 -0
  135. package/dashboard/dist/assets/inter-greek-400-normal.woff +0 -0
  136. package/dashboard/dist/assets/inter-greek-400-normal.woff2 +0 -0
  137. package/dashboard/dist/assets/inter-greek-500-normal.woff +0 -0
  138. package/dashboard/dist/assets/inter-greek-500-normal.woff2 +0 -0
  139. package/dashboard/dist/assets/inter-greek-600-normal.woff +0 -0
  140. package/dashboard/dist/assets/inter-greek-600-normal.woff2 +0 -0
  141. package/dashboard/dist/assets/inter-greek-700-normal.woff +0 -0
  142. package/dashboard/dist/assets/inter-greek-700-normal.woff2 +0 -0
  143. package/dashboard/dist/assets/inter-greek-ext-400-normal.woff +0 -0
  144. package/dashboard/dist/assets/inter-greek-ext-400-normal.woff2 +0 -0
  145. package/dashboard/dist/assets/inter-greek-ext-500-normal.woff +0 -0
  146. package/dashboard/dist/assets/inter-greek-ext-500-normal.woff2 +0 -0
  147. package/dashboard/dist/assets/inter-greek-ext-600-normal.woff +0 -0
  148. package/dashboard/dist/assets/inter-greek-ext-600-normal.woff2 +0 -0
  149. package/dashboard/dist/assets/inter-greek-ext-700-normal.woff +0 -0
  150. package/dashboard/dist/assets/inter-greek-ext-700-normal.woff2 +0 -0
  151. package/dashboard/dist/assets/inter-latin-400-normal.woff +0 -0
  152. package/dashboard/dist/assets/inter-latin-400-normal.woff2 +0 -0
  153. package/dashboard/dist/assets/inter-latin-500-normal.woff +0 -0
  154. package/dashboard/dist/assets/inter-latin-500-normal.woff2 +0 -0
  155. package/dashboard/dist/assets/inter-latin-600-normal.woff +0 -0
  156. package/dashboard/dist/assets/inter-latin-600-normal.woff2 +0 -0
  157. package/dashboard/dist/assets/inter-latin-700-normal.woff +0 -0
  158. package/dashboard/dist/assets/inter-latin-700-normal.woff2 +0 -0
  159. package/dashboard/dist/assets/inter-latin-ext-400-normal.woff +0 -0
  160. package/dashboard/dist/assets/inter-latin-ext-400-normal.woff2 +0 -0
  161. package/dashboard/dist/assets/inter-latin-ext-500-normal.woff +0 -0
  162. package/dashboard/dist/assets/inter-latin-ext-500-normal.woff2 +0 -0
  163. package/dashboard/dist/assets/inter-latin-ext-600-normal.woff +0 -0
  164. package/dashboard/dist/assets/inter-latin-ext-600-normal.woff2 +0 -0
  165. package/dashboard/dist/assets/inter-latin-ext-700-normal.woff +0 -0
  166. package/dashboard/dist/assets/inter-latin-ext-700-normal.woff2 +0 -0
  167. package/dashboard/dist/assets/inter-vietnamese-400-normal.woff +0 -0
  168. package/dashboard/dist/assets/inter-vietnamese-400-normal.woff2 +0 -0
  169. package/dashboard/dist/assets/inter-vietnamese-500-normal.woff +0 -0
  170. package/dashboard/dist/assets/inter-vietnamese-500-normal.woff2 +0 -0
  171. package/dashboard/dist/assets/inter-vietnamese-600-normal.woff +0 -0
  172. package/dashboard/dist/assets/inter-vietnamese-600-normal.woff2 +0 -0
  173. package/dashboard/dist/assets/inter-vietnamese-700-normal.woff +0 -0
  174. package/dashboard/dist/assets/inter-vietnamese-700-normal.woff2 +0 -0
  175. package/dashboard/dist/vendor-icons.js +102 -0
  176. package/dashboard/dist/vendor-icons.js.map +1 -0
  177. package/dashboard/dist/vendor-katex.css +1 -0
  178. package/dashboard/dist/vendor-katex.js +258 -0
  179. package/dashboard/dist/vendor-katex.js.map +1 -0
  180. package/dashboard/dist/vendor-markdown.js +36 -0
  181. package/dashboard/dist/vendor-markdown.js.map +1 -0
  182. package/dashboard/dist/vendor-prism.js +15 -0
  183. package/dashboard/dist/vendor-prism.js.map +1 -0
  184. package/dashboard/dist/vendor-react.js +50 -0
  185. package/dashboard/dist/vendor-react.js.map +1 -0
  186. package/dashboard/index.html +4 -3
  187. package/dist/cli/{acp-WFQIC6SO.js → acp-6B25WIFF.js} +48 -49
  188. package/dist/cli/acp-6B25WIFF.js.map +1 -0
  189. package/dist/cli/chat-7WASPB4O.js +50 -0
  190. package/dist/cli/{chunk-QF32ROX2.js → chunk-3KRRTLC5.js} +955 -788
  191. package/dist/cli/chunk-3KRRTLC5.js.map +1 -0
  192. package/dist/cli/{chunk-TEDWJKEI.js → chunk-3RNFYDDM.js} +11 -27
  193. package/dist/cli/chunk-3RNFYDDM.js.map +1 -0
  194. package/dist/cli/{chunk-ZWHSHFDP.js → chunk-6IUMTRFP.js} +35 -7
  195. package/dist/cli/chunk-6IUMTRFP.js.map +1 -0
  196. package/dist/cli/{chunk-GNS7BAT2.js → chunk-7WITYWKN.js} +2 -2
  197. package/dist/cli/{chunk-HIYTRCSW.js → chunk-7YPMTE3U.js} +65 -28
  198. package/dist/cli/chunk-7YPMTE3U.js.map +1 -0
  199. package/dist/cli/{chunk-DFX5ZH5L.js → chunk-AAHB2PFX.js} +2 -2
  200. package/dist/cli/{chunk-PB3MAFEI.js → chunk-AJIZ5KFK.js} +3 -3
  201. package/dist/cli/{chunk-U5XQDCK7.js → chunk-ALCOQP6R.js} +10 -9
  202. package/dist/cli/chunk-ALCOQP6R.js.map +1 -0
  203. package/dist/cli/{chunk-6OWJV3YW.js → chunk-CAGKEGNE.js} +1 -2
  204. package/dist/cli/{chunk-JNTMOX7G.js → chunk-ENFBF6HI.js} +15 -3
  205. package/dist/cli/chunk-ENFBF6HI.js.map +1 -0
  206. package/dist/cli/{chunk-J2IHQGPQ.js → chunk-EZ57UEZQ.js} +2 -2
  207. package/dist/cli/{chunk-QX5TWXRZ.js → chunk-FQSQFCBI.js} +41 -2
  208. package/dist/cli/chunk-FQSQFCBI.js.map +1 -0
  209. package/dist/cli/{chunk-ZAEJWKXB.js → chunk-GMSAB2TC.js} +2 -2
  210. package/dist/cli/{chunk-MQWO32ZD.js → chunk-GPUH2BNM.js} +123 -286
  211. package/dist/cli/chunk-GPUH2BNM.js.map +1 -0
  212. package/dist/cli/{chunk-7AST3QQ3.js → chunk-I4Q3QT4W.js} +2 -2
  213. package/dist/cli/{chunk-O5LIHAMP.js → chunk-I6FBSTTR.js} +3 -3
  214. package/dist/cli/{chunk-AWEULQG6.js → chunk-IBRTU5WO.js} +25 -15
  215. package/dist/cli/{chunk-AWEULQG6.js.map → chunk-IBRTU5WO.js.map} +1 -1
  216. package/dist/cli/{chunk-RRXUIPWG.js → chunk-IK6WWRIX.js} +1 -1
  217. package/dist/cli/chunk-IK6WWRIX.js.map +1 -0
  218. package/dist/cli/{chunk-WMTMMSXU.js → chunk-MXWPAPZW.js} +315 -233
  219. package/dist/cli/chunk-MXWPAPZW.js.map +1 -0
  220. package/dist/cli/{chunk-7JTKBJ2G.js → chunk-NLRC3DWQ.js} +3 -3
  221. package/dist/cli/{chunk-PXBQ6IZ7.js → chunk-OPGWCKKU.js} +2 -2
  222. package/dist/cli/{chunk-23ZPCIPR.js → chunk-OWA42BKS.js} +21 -20
  223. package/dist/cli/chunk-OWA42BKS.js.map +1 -0
  224. package/dist/cli/{chunk-YEF7C4XI.js → chunk-PYIZZAVQ.js} +102 -94
  225. package/dist/cli/chunk-PYIZZAVQ.js.map +1 -0
  226. package/dist/cli/{chunk-EQATK2L2.js → chunk-SVD4UPRQ.js} +4 -3
  227. package/dist/cli/chunk-SVD4UPRQ.js.map +1 -0
  228. package/dist/cli/{chunk-PEMG6CUB.js → chunk-TX652NBA.js} +2 -2
  229. package/dist/cli/{chunk-W46ZMNKO.js → chunk-VVMY4M7J.js} +21 -2
  230. package/dist/cli/chunk-VVMY4M7J.js.map +1 -0
  231. package/dist/cli/{chunk-TAIKVL35.js → chunk-WSBFVOCO.js} +2 -2
  232. package/dist/cli/{chunk-ASOLXV67.js → chunk-X2BQZQEE.js} +3 -3
  233. package/dist/cli/{chunk-E5WCLUIU.js → chunk-XJZWMU5P.js} +2 -2
  234. package/dist/cli/{chunk-MGTBP7GG.js → chunk-XWPZHWC2.js} +20 -7
  235. package/dist/cli/chunk-XWPZHWC2.js.map +1 -0
  236. package/dist/cli/{chunk-JGTX4RRQ.js → chunk-ZAXMJANP.js} +2 -2
  237. package/dist/cli/{code-R4IHI7SR.js → code-TBK2TASK.js} +49 -57
  238. package/dist/cli/code-TBK2TASK.js.map +1 -0
  239. package/dist/cli/{commands-DRHFCYMO.js → commands-NXTKSQTN.js} +4 -4
  240. package/dist/cli/{commit-AG5KB4YP.js → commit-IR5SPP7A.js} +7 -8
  241. package/dist/cli/commit-IR5SPP7A.js.map +1 -0
  242. package/dist/cli/config-XK5WQGTS.js +194 -0
  243. package/dist/cli/{desktop-JGL6GORA.js → desktop-5NTQBADL.js} +200 -113
  244. package/dist/cli/desktop-5NTQBADL.js.map +1 -0
  245. package/dist/cli/{diff-4Z7ETWZO.js → diff-JNYX5BSZ.js} +8 -8
  246. package/dist/cli/{doctor-VA3RHQLB.js → doctor-IKYLUFXX.js} +11 -11
  247. package/dist/cli/{events-VRYXOSKI.js → events-HSC57ONU.js} +12 -8
  248. package/dist/cli/{events-VRYXOSKI.js.map → events-HSC57ONU.js.map} +1 -1
  249. package/dist/cli/index.js +87 -84
  250. package/dist/cli/index.js.map +1 -1
  251. package/dist/cli/{mcp-LZO4HXFA.js → mcp-BDJJWOCD.js} +3 -3
  252. package/dist/cli/{mcp-browse-C3GXVMYZ.js → mcp-browse-NJRZDI6V.js} +8 -8
  253. package/dist/cli/{mcp-inspect-ZMYUNFDS.js → mcp-inspect-Y62NWZQL.js} +7 -6
  254. package/dist/cli/mcp-inspect-Y62NWZQL.js.map +1 -0
  255. package/dist/cli/{prompt-MC3U5KRP.js → prompt-UTOIFUQC.js} +5 -5
  256. package/dist/cli/{prune-sessions-OEPFH4N6.js → prune-sessions-UCUD4XAP.js} +4 -4
  257. package/dist/cli/{replay-4TP7ZUMZ.js → replay-VVIN64MN.js} +10 -19
  258. package/dist/cli/replay-VVIN64MN.js.map +1 -0
  259. package/dist/cli/{run-6MXQYBOE.js → run-76OBDZFB.js} +28 -25
  260. package/dist/cli/run-76OBDZFB.js.map +1 -0
  261. package/dist/cli/{server-Z3IMJNNI.js → server-SZZDKTH2.js} +404 -163
  262. package/dist/cli/server-SZZDKTH2.js.map +1 -0
  263. package/dist/cli/{sessions-NXQ5SAV7.js → sessions-FZTGRCM5.js} +18 -18
  264. package/dist/cli/{setup-LHZELI6I.js → setup-4UNENGOE.js} +14 -40
  265. package/dist/cli/setup-4UNENGOE.js.map +1 -0
  266. package/dist/cli/{stats-SUIJ3QWY.js → stats-F4NDOD7D.js} +6 -6
  267. package/dist/cli/stats-F4NDOD7D.js.map +1 -0
  268. package/dist/cli/version-LUVTWHLL.js +33 -0
  269. package/dist/index.d.ts +325 -299
  270. package/dist/index.js +438 -528
  271. package/dist/index.js.map +1 -1
  272. package/package.json +6 -3
  273. package/scripts/postinstall.mjs +12 -0
  274. package/dist/cli/acp-WFQIC6SO.js.map +0 -1
  275. package/dist/cli/chat-D32JGNVH.js +0 -51
  276. package/dist/cli/chunk-23ZPCIPR.js.map +0 -1
  277. package/dist/cli/chunk-EQATK2L2.js.map +0 -1
  278. package/dist/cli/chunk-HIYTRCSW.js.map +0 -1
  279. package/dist/cli/chunk-JNTMOX7G.js.map +0 -1
  280. package/dist/cli/chunk-LGEKVMMV.js +0 -59
  281. package/dist/cli/chunk-LGEKVMMV.js.map +0 -1
  282. package/dist/cli/chunk-MGTBP7GG.js.map +0 -1
  283. package/dist/cli/chunk-MQWO32ZD.js.map +0 -1
  284. package/dist/cli/chunk-QF32ROX2.js.map +0 -1
  285. package/dist/cli/chunk-QX5TWXRZ.js.map +0 -1
  286. package/dist/cli/chunk-RRXUIPWG.js.map +0 -1
  287. package/dist/cli/chunk-TEDWJKEI.js.map +0 -1
  288. package/dist/cli/chunk-U5XQDCK7.js.map +0 -1
  289. package/dist/cli/chunk-W46ZMNKO.js.map +0 -1
  290. package/dist/cli/chunk-WMTMMSXU.js.map +0 -1
  291. package/dist/cli/chunk-YEF7C4XI.js.map +0 -1
  292. package/dist/cli/chunk-ZWHSHFDP.js.map +0 -1
  293. package/dist/cli/code-R4IHI7SR.js.map +0 -1
  294. package/dist/cli/commit-AG5KB4YP.js.map +0 -1
  295. package/dist/cli/desktop-JGL6GORA.js.map +0 -1
  296. package/dist/cli/mcp-inspect-ZMYUNFDS.js.map +0 -1
  297. package/dist/cli/replay-4TP7ZUMZ.js.map +0 -1
  298. package/dist/cli/run-6MXQYBOE.js.map +0 -1
  299. package/dist/cli/server-Z3IMJNNI.js.map +0 -1
  300. package/dist/cli/setup-LHZELI6I.js.map +0 -1
  301. package/dist/cli/version-BIFONEUB.js +0 -33
  302. /package/dist/cli/{chat-D32JGNVH.js.map → chat-7WASPB4O.js.map} +0 -0
  303. /package/dist/cli/{chunk-GNS7BAT2.js.map → chunk-7WITYWKN.js.map} +0 -0
  304. /package/dist/cli/{chunk-DFX5ZH5L.js.map → chunk-AAHB2PFX.js.map} +0 -0
  305. /package/dist/cli/{chunk-PB3MAFEI.js.map → chunk-AJIZ5KFK.js.map} +0 -0
  306. /package/dist/cli/{chunk-6OWJV3YW.js.map → chunk-CAGKEGNE.js.map} +0 -0
  307. /package/dist/cli/{chunk-J2IHQGPQ.js.map → chunk-EZ57UEZQ.js.map} +0 -0
  308. /package/dist/cli/{chunk-ZAEJWKXB.js.map → chunk-GMSAB2TC.js.map} +0 -0
  309. /package/dist/cli/{chunk-7AST3QQ3.js.map → chunk-I4Q3QT4W.js.map} +0 -0
  310. /package/dist/cli/{chunk-O5LIHAMP.js.map → chunk-I6FBSTTR.js.map} +0 -0
  311. /package/dist/cli/{chunk-7JTKBJ2G.js.map → chunk-NLRC3DWQ.js.map} +0 -0
  312. /package/dist/cli/{chunk-PXBQ6IZ7.js.map → chunk-OPGWCKKU.js.map} +0 -0
  313. /package/dist/cli/{chunk-PEMG6CUB.js.map → chunk-TX652NBA.js.map} +0 -0
  314. /package/dist/cli/{chunk-TAIKVL35.js.map → chunk-WSBFVOCO.js.map} +0 -0
  315. /package/dist/cli/{chunk-ASOLXV67.js.map → chunk-X2BQZQEE.js.map} +0 -0
  316. /package/dist/cli/{chunk-E5WCLUIU.js.map → chunk-XJZWMU5P.js.map} +0 -0
  317. /package/dist/cli/{chunk-JGTX4RRQ.js.map → chunk-ZAXMJANP.js.map} +0 -0
  318. /package/dist/cli/{commands-DRHFCYMO.js.map → commands-NXTKSQTN.js.map} +0 -0
  319. /package/dist/cli/{doctor-VA3RHQLB.js.map → config-XK5WQGTS.js.map} +0 -0
  320. /package/dist/cli/{diff-4Z7ETWZO.js.map → diff-JNYX5BSZ.js.map} +0 -0
  321. /package/dist/cli/{prompt-MC3U5KRP.js.map → doctor-IKYLUFXX.js.map} +0 -0
  322. /package/dist/cli/{mcp-LZO4HXFA.js.map → mcp-BDJJWOCD.js.map} +0 -0
  323. /package/dist/cli/{mcp-browse-C3GXVMYZ.js.map → mcp-browse-NJRZDI6V.js.map} +0 -0
  324. /package/dist/cli/{stats-SUIJ3QWY.js.map → prompt-UTOIFUQC.js.map} +0 -0
  325. /package/dist/cli/{prune-sessions-OEPFH4N6.js.map → prune-sessions-UCUD4XAP.js.map} +0 -0
  326. /package/dist/cli/{sessions-NXQ5SAV7.js.map → sessions-FZTGRCM5.js.map} +0 -0
  327. /package/dist/cli/{version-BIFONEUB.js.map → version-LUVTWHLL.js.map} +0 -0
package/dist/index.js CHANGED
@@ -2,14 +2,8 @@
2
2
  import { createParser } from "eventsource-parser";
3
3
 
4
4
  // src/config.ts
5
- import {
6
- appendFileSync,
7
- chmodSync,
8
- mkdirSync,
9
- readFileSync,
10
- renameSync,
11
- writeFileSync
12
- } from "fs";
5
+ import { randomBytes } from "crypto";
6
+ import { chmodSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "fs";
13
7
  import { homedir } from "os";
14
8
  import { dirname, isAbsolute, join, resolve } from "path";
15
9
  import { z } from "zod";
@@ -39,39 +33,6 @@ function card(fg, tone) {
39
33
  function defineTheme(base) {
40
34
  return { ...base, card: card(base.fg, base.tone) };
41
35
  }
42
- var githubDark = defineTheme({
43
- fg: {
44
- strong: "#e6edf3",
45
- body: "#c9d1d9",
46
- sub: "#8b949e",
47
- meta: "#6e7681",
48
- faint: "#484f58"
49
- },
50
- tone: {
51
- brand: "#79c0ff",
52
- accent: "#d2a8ff",
53
- violet: "#b395f5",
54
- ok: "#7ee787",
55
- warn: "#f0b07d",
56
- err: "#ff8b81",
57
- info: "#79c0ff"
58
- },
59
- toneActive: {
60
- brand: "#a5d6ff",
61
- accent: "#e2c5ff",
62
- violet: "#c8aaff",
63
- ok: "#a8f5ad",
64
- warn: "#ffc99e",
65
- err: "#ffaba3",
66
- info: "#a5d6ff"
67
- },
68
- surface: {
69
- bg: "#0a0c10",
70
- bgInput: "#0d1015",
71
- bgCode: "#06080c",
72
- bgElev: "#11141a"
73
- }
74
- });
75
36
  var dark = defineTheme({
76
37
  fg: {
77
38
  strong: "#f4f7fb",
@@ -100,7 +61,7 @@ var dark = defineTheme({
100
61
  },
101
62
  surface: {
102
63
  bg: "#0b1020",
103
- bgInput: "#111827",
64
+ bgInput: "#0f172a",
104
65
  bgCode: "#080c16",
105
66
  bgElev: "#151d2f"
106
67
  }
@@ -133,12 +94,12 @@ var light = defineTheme({
133
94
  },
134
95
  surface: {
135
96
  bg: "#ffffff",
136
- bgInput: "#f8fafc",
97
+ bgInput: "#f1f5f9",
137
98
  bgCode: "#f3f4f6",
138
99
  bgElev: "#eef2f7"
139
100
  }
140
101
  });
141
- var tokyoNight = defineTheme({
102
+ var midnight = defineTheme({
142
103
  fg: {
143
104
  strong: "#c0caf5",
144
105
  body: "#a9b1d6",
@@ -171,37 +132,37 @@ var tokyoNight = defineTheme({
171
132
  bgElev: "#24283b"
172
133
  }
173
134
  });
174
- var githubLight = defineTheme({
135
+ var deepBlue = defineTheme({
175
136
  fg: {
176
- strong: "#1f2328",
177
- body: "#24292f",
178
- sub: "#57606a",
179
- meta: "#6e7781",
180
- faint: "#8c959f"
137
+ strong: "#ffffff",
138
+ body: "#e0e0e0",
139
+ sub: "#b0b0b0",
140
+ meta: "#808080",
141
+ faint: "#606060"
181
142
  },
182
143
  tone: {
183
- brand: "#0969da",
184
- accent: "#8250df",
185
- violet: "#6639ba",
186
- ok: "#1a7f37",
187
- warn: "#9a6700",
188
- err: "#cf222e",
189
- info: "#0969da"
144
+ brand: "#0153e5",
145
+ accent: "#4d94ff",
146
+ violet: "#7b68ee",
147
+ ok: "#4caf50",
148
+ warn: "#ff9800",
149
+ err: "#f44336",
150
+ info: "#2196f3"
190
151
  },
191
152
  toneActive: {
192
- brand: "#0550ae",
193
- accent: "#6639ba",
194
- violet: "#512a97",
195
- ok: "#116329",
196
- warn: "#7d4e00",
197
- err: "#a40e26",
198
- info: "#0550ae"
153
+ brand: "#4d94ff",
154
+ accent: "#80b3ff",
155
+ violet: "#9b8bff",
156
+ ok: "#66bb6a",
157
+ warn: "#ffb74d",
158
+ err: "#ef5350",
159
+ info: "#42a5f5"
199
160
  },
200
161
  surface: {
201
- bg: "#ffffff",
202
- bgInput: "#f6f8fa",
203
- bgCode: "#f6f8fa",
204
- bgElev: "#eaeef2"
162
+ bg: "#0a0a0a",
163
+ bgInput: "#1e1e1e",
164
+ bgCode: "#141414",
165
+ bgElev: "#252525"
205
166
  }
206
167
  });
207
168
  var highContrast = defineTheme({
@@ -238,15 +199,13 @@ var highContrast = defineTheme({
238
199
  }
239
200
  });
240
201
  var THEMES = {
241
- default: githubDark,
242
202
  dark,
243
203
  light,
244
- "tokyo-night": tokyoNight,
245
- "github-dark": githubDark,
246
- "github-light": githubLight,
204
+ midnight,
205
+ "deep-blue": deepBlue,
247
206
  "high-contrast": highContrast
248
207
  };
249
- var DEFAULT_THEME_NAME = "default";
208
+ var DEFAULT_THEME_NAME = "dark";
250
209
  var DEFAULT_THEME = THEMES[DEFAULT_THEME_NAME];
251
210
  var activeTheme = DEFAULT_THEME;
252
211
  function proxyTokens(select) {
@@ -660,7 +619,6 @@ function readConfig(path2 = defaultConfigPath()) {
660
619
  return {};
661
620
  }
662
621
  function writeConfig(cfg, path2 = defaultConfigPath()) {
663
- debugLogConfigWrite(cfg, path2);
664
622
  mkdirSync(dirname(path2), { recursive: true });
665
623
  const tmp = `${path2}.${process.pid}.tmp`;
666
624
  writeFileSync(tmp, JSON.stringify(cfg, null, 2), "utf8");
@@ -670,33 +628,24 @@ function writeConfig(cfg, path2 = defaultConfigPath()) {
670
628
  }
671
629
  renameSync(tmp, path2);
672
630
  }
673
- function debugLogConfigWrite(cfg, configPath) {
674
- const debugPath = process.env.REASONIX_DEBUG_PRESET;
675
- if (!debugPath) return;
676
- try {
677
- const stack = new Error("trace").stack ?? "";
678
- const keys = Object.keys(cfg).sort().join(",");
679
- const presetField = cfg.preset === void 0 ? "(absent)" : JSON.stringify(cfg.preset);
680
- const line = `${(/* @__PURE__ */ new Date()).toISOString()} writeConfig pid=${process.pid} \u2192 ${configPath}
681
- keys=[${keys}]
682
- preset=${presetField}
683
- ${stack.split("\n").slice(1, 10).map((l) => ` ${l.trim()}`).join("\n")}
684
-
685
- `;
686
- appendFileSync(debugPath, line);
687
- } catch {
688
- }
689
- }
690
631
  function loadLanguage(path2 = defaultConfigPath()) {
691
632
  return readConfig(path2).lang;
692
633
  }
634
+ function loadEndpoint(path2 = defaultConfigPath()) {
635
+ if (process.env.DEEPSEEK_BASE_URL) {
636
+ return { baseUrl: process.env.DEEPSEEK_BASE_URL, apiKey: process.env.DEEPSEEK_API_KEY };
637
+ }
638
+ const cfg = readConfig(path2);
639
+ if (cfg.baseUrl) {
640
+ return { baseUrl: cfg.baseUrl, apiKey: cfg.apiKey };
641
+ }
642
+ return { baseUrl: void 0, apiKey: process.env.DEEPSEEK_API_KEY ?? cfg.apiKey };
643
+ }
693
644
  function loadApiKey(path2 = defaultConfigPath()) {
694
- if (process.env.DEEPSEEK_API_KEY) return process.env.DEEPSEEK_API_KEY;
695
- return readConfig(path2).apiKey;
645
+ return loadEndpoint(path2).apiKey;
696
646
  }
697
647
  function loadBaseUrl(path2 = defaultConfigPath()) {
698
- if (process.env.DEEPSEEK_BASE_URL) return process.env.DEEPSEEK_BASE_URL;
699
- return readConfig(path2).baseUrl;
648
+ return loadEndpoint(path2).baseUrl;
700
649
  }
701
650
  function isNonNegativeNumber(value) {
702
651
  return typeof value === "number" && Number.isFinite(value) && value >= 0;
@@ -891,8 +840,8 @@ function computeWait(attempt, initial, cap, retryAfter) {
891
840
  }
892
841
  function sleep(ms, signal) {
893
842
  if (ms <= 0) return Promise.resolve();
894
- return new Promise((resolve14, reject) => {
895
- const timer = setTimeout(resolve14, ms);
843
+ return new Promise((resolve15, reject) => {
844
+ const timer = setTimeout(resolve15, ms);
896
845
  if (signal) {
897
846
  const onAbort = () => {
898
847
  clearTimeout(timer);
@@ -980,8 +929,8 @@ var DeepSeekClient = class {
980
929
  const waitMs = Math.max(0, this.nextChatRequestAt - now);
981
930
  this.nextChatRequestAt = Math.max(now, this.nextChatRequestAt) + this.minChatIntervalMs;
982
931
  if (waitMs <= 0) return;
983
- await new Promise((resolve14, reject) => {
984
- const timer = setTimeout(resolve14, waitMs);
932
+ await new Promise((resolve15, reject) => {
933
+ const timer = setTimeout(resolve15, waitMs);
985
934
  signal?.addEventListener(
986
935
  "abort",
987
936
  () => {
@@ -1197,10 +1146,10 @@ var PauseGate = class {
1197
1146
  `${kind}: no confirmation listener registered \u2014 cannot prompt the user. This tool can only be used inside an interactive Reasonix session.`
1198
1147
  );
1199
1148
  }
1200
- return new Promise((resolve14) => {
1149
+ return new Promise((resolve15) => {
1201
1150
  const id = this._nextId++;
1202
1151
  const request = { id, kind, payload };
1203
- this._pending.set(id, { resolve: resolve14, request });
1152
+ this._pending.set(id, { resolve: resolve15, request });
1204
1153
  for (const fn of this._listeners) {
1205
1154
  try {
1206
1155
  fn(request);
@@ -1330,7 +1279,7 @@ var EN = {
1330
1279
  cli: {
1331
1280
  description: "DeepSeek-native agent framework \u2014 built for cache hits and cheap tokens.",
1332
1281
  continue: "Resume the most recently used chat session without showing the picker.",
1333
- setup: "Interactive wizard \u2014 API key, preset, MCP servers. Re-run any time to reconfigure.",
1282
+ setup: "Interactive wizard \u2014 API key, MCP servers. Re-run any time to reconfigure.",
1334
1283
  code: "Code-editing chat \u2014 filesystem tools rooted at <dir> (default: cwd), coding system prompt, v4-flash baseline.",
1335
1284
  chat: "Interactive Ink TUI with live cache/cost panel.",
1336
1285
  run: "Run a single task non-interactively, streaming output.",
@@ -1502,13 +1451,13 @@ var EN = {
1502
1451
  budgetHint: "session USD cap \u2014 warns at 80%, refuses next turn at 100%",
1503
1452
  modelIdHint: "DeepSeek model id (e.g. deepseek-v4-flash)",
1504
1453
  systemPromptHint: "override the default system prompt",
1505
- presetHint: "model bundle \u2014 auto|flash|pro",
1454
+ effortHint: "reasoning effort \u2014 low|medium|high|max",
1506
1455
  sessionNameHint: "session name (default: 'default')",
1507
1456
  ephemeralHint: "disable session persistence for this run",
1508
1457
  mcpSpecHint: "MCP server spec (repeatable)",
1509
1458
  mcpPrefixHint: "prefix MCP tool names with this string",
1510
1459
  noConfigHint: "ignore ~/.reasonix/config.json for this run",
1511
- presetHintShort: "model bundle \u2014 auto|flash|pro",
1460
+ effortHintShort: "reasoning effort \u2014 low|medium|high|max",
1512
1461
  budgetHintShort: "session USD cap",
1513
1462
  transcriptHintShort: "JSONL transcript path",
1514
1463
  mcpSpecHintShort: "MCP server spec (repeatable)",
@@ -1560,15 +1509,15 @@ var EN = {
1560
1509
  slash: {
1561
1510
  help: { description: "show the full command reference" },
1562
1511
  status: { description: "current model, flags, context, session" },
1563
- preset: {
1564
- description: "model bundle \u2014 auto escalates flash \u2192 pro, flash/pro lock",
1565
- argsHint: "<auto|flash|pro>"
1512
+ effort: {
1513
+ description: "reasoning_effort cap (low|medium|high|max); high is the safe default for vLLM/Azure",
1514
+ argsHint: "<low|medium|high|max>"
1566
1515
  },
1567
1516
  model: { description: "switch DeepSeek model id", argsHint: "<id>" },
1568
1517
  models: { description: "list available models fetched from DeepSeek /models" },
1569
1518
  theme: {
1570
1519
  description: "show or persist the terminal theme preference. Bare opens picker.",
1571
- argsHint: "[auto|default|dark|light|tokyo-night|github-dark|github-light|high-contrast]"
1520
+ argsHint: "[auto|dark|light|midnight|deep-blue|high-contrast]"
1572
1521
  },
1573
1522
  language: {
1574
1523
  description: "switch the runtime language",
@@ -1576,10 +1525,6 @@ var EN = {
1576
1525
  success: "Language switched to English.",
1577
1526
  unsupported: "Unsupported language code: {code}. Supported: {supported}."
1578
1527
  },
1579
- pro: {
1580
- description: "arm v4-pro for the NEXT turn only (one-shot \xB7 auto-disarms after turn)",
1581
- argsHint: "[off]"
1582
- },
1583
1528
  budget: {
1584
1529
  description: "session USD cap \u2014 warns at 80%, refuses next turn at 100%. Off by default. /budget alone shows status",
1585
1530
  argsHint: "[usd|off]"
@@ -1732,16 +1677,13 @@ var EN = {
1732
1677
  themeSampleHeading: "Sample",
1733
1678
  themeFooter: "[\u2191\u2193] navigate \xB7 [Enter] confirm \xB7 [Esc] cancel",
1734
1679
  themeCaption: {
1735
- default: "GitHub dark (default)",
1736
- dark: "Cool dark tones",
1680
+ dark: "Cool dark tones (default)",
1737
1681
  light: "Clean light mode",
1738
- "tokyo-night": "Tokyo Night palette",
1739
- "github-dark": "GitHub dark",
1740
- "github-light": "GitHub light",
1682
+ midnight: "Tokyo Night palette",
1683
+ "deep-blue": "Deep blue on black",
1741
1684
  "high-contrast": "Accessibility"
1742
1685
  },
1743
1686
  reviewLabelTheme: "Theme",
1744
- presetTitle: "Pick a preset",
1745
1687
  mcpTitle: "Which MCP servers should Reasonix wire up for you?",
1746
1688
  mcpUserArgsHint: "(you'll provide {arg})",
1747
1689
  mcpFooterMulti: "[\u2191\u2193] navigate \xB7 [Space] toggle \xB7 [Enter] confirm \xB7 [Esc] cancel \xB7 empty = skip",
@@ -1755,7 +1697,6 @@ var EN = {
1755
1697
  reviewTitle: "Ready to save",
1756
1698
  reviewLabelApiKey: "API key",
1757
1699
  reviewLabelLanguage: "Language",
1758
- reviewLabelPreset: "Preset",
1759
1700
  reviewLabelMcp: "MCP",
1760
1701
  reviewMcpNone: "(none)",
1761
1702
  reviewMcpServers: "{count} server(s)",
@@ -1923,7 +1864,17 @@ var EN = {
1923
1864
  mcpFailed: "MCP {name} failed",
1924
1865
  mcpWarn: "MCP {name} warn",
1925
1866
  unknownTheme: "unknown theme: {name}\navailable: {choices}",
1926
- themeSaved: "theme saved: {name}\nactive on next launch: {active}"
1867
+ themeSaved: "theme saved: {name}\nactive on next launch: {active}",
1868
+ noPendingEdits: "nothing pending \u2014 the model hasn\u2019t proposed edits since the last /apply or /discard.",
1869
+ noMatchedApply: "\u25B8 no edits matched those indices \u2014 nothing applied. Use /apply with no args to commit them all.",
1870
+ noPendingDiscard: "nothing pending to discard.",
1871
+ noMatchedDiscard: "\u25B8 no edits matched those indices \u2014 nothing discarded.",
1872
+ blocksStillPending: "\u25B8 {count} edit block(s) still pending \u2014 /apply or /discard to clear them.",
1873
+ nothingWritten: ". Nothing was written to disk.",
1874
+ discardedCount: "\u25B8 discarded {count} pending edit block(s)",
1875
+ noEventsFor: 'no events for session "{name}"',
1876
+ lookedAtFile: "looked at: {path}",
1877
+ sidecarHint: "(sessions auto-create the sidecar on first turn \u2014 has this session run yet?)"
1927
1878
  },
1928
1879
  hooks: {
1929
1880
  head: "hook {tag} `{cmd}` {decision}{truncTag}",
@@ -1943,13 +1894,9 @@ var EN = {
1943
1894
  budgetExhausted: "session budget exhausted \u2014 spent ${spent} \u2265 cap ${cap}. Bump the cap with /budget <usd>, clear it with /budget off, or end the session.",
1944
1895
  budget80Pct: "\u25B2 budget 80% used \u2014 ${spent} of ${cap}. Next turn or two likely trips the cap.",
1945
1896
  proArmed: "\u21E7 /pro armed \u2014 this turn runs on deepseek-v4-pro (one-shot \xB7 disarms after turn)",
1946
- abortedAtIter: "aborted at iter {iter} \u2014 stopped without producing a summary (press \u2191 + Enter or /retry to resume)",
1947
1897
  toolUploadStatus: "tool result uploaded \xB7 model thinking before next response\u2026",
1948
- preflightTruncateStatus: "preflight: context near full, truncating oldest history\u2026",
1949
- preflightTruncated: "preflight: request ~{estimate}/{ctxMax} tokens ({pct}%) \xB7 body {bodyKB} KB \u2014 truncated {beforeMessages} messages \u2192 {afterMessages}. Sending.",
1950
- preflightTruncatedStillFull: "preflight: request still ~{estimate}/{ctxMax} tokens ({pct}%) \xB7 body {bodyKB} KB after truncating {beforeMessages} messages \u2192 {afterMessages}. DeepSeek will likely 400. Run /clear or /new to start fresh.",
1951
- preflightNoFold: "preflight: request ~{estimate}/{ctxMax} tokens ({pct}%) \xB7 body {bodyKB} KB and nothing left to truncate \u2014 DeepSeek will likely 400. Run /clear or /new to start fresh.",
1952
- flashEscalation: "\u21E7 flash requested escalation \u2014 retrying this turn on {model}{reasonSuffix}",
1898
+ turnStartFoldStatus: "turn start: context approaching limit, compacting history\u2026",
1899
+ turnStartFolded: "turn start: request ~{estimate}/{ctxMax} tokens ({pct}%) \u2014 compacted {beforeMessages} messages \u2192 {afterMessages}. Sending.",
1953
1900
  harvestStatus: "extracting plan state from reasoning\u2026",
1954
1901
  repeatToolCallWarning: "Caught a repeated tool call \u2014 let the model see the issue and retry with a different approach.",
1955
1902
  stormStuck: "Stopped a stuck retry loop \u2014 the model kept calling the same tool with identical args after a self-correction nudge. Try /retry, rephrase, or rule out the underlying blocker.",
@@ -1972,7 +1919,7 @@ var EN = {
1972
1919
  deepseek5xxReachable: " DeepSeek's main API answered our health check, but /chat/completions is failing \u2014 partial outage on their side.",
1973
1920
  deepseek5xxUnreachable: " DeepSeek API is unreachable from your network \u2014 could be a wider DS outage or a local network issue.",
1974
1921
  deepseek5xxActionNetwork: " Try: (1) check your network, (2) wait 30s and retry, (3) status page: https://status.deepseek.com.",
1975
- deepseek5xxActionRetry: " Try: (1) wait 30s and retry, (2) /preset to switch model, (3) status page: https://status.deepseek.com.",
1922
+ deepseek5xxActionRetry: " Try: (1) wait 30s and retry, (2) /model to switch model, (3) status page: https://status.deepseek.com.",
1976
1923
  innerNoMessage: "(no message)",
1977
1924
  reasonAborted: "[aborted by user (Esc) \u2014 summarizing what I found so far]",
1978
1925
  reasonContextGuard: "[context budget running low \u2014 summarizing before the next call would overflow]",
@@ -2010,10 +1957,6 @@ var EN = {
2010
1957
  helpUrl: " @https://example.com fetch the URL, strip HTML, inline under [Referenced URLs].",
2011
1958
  helpUrlCache: " Same URL twice in one session fetches once (in-mem cache).",
2012
1959
  helpUrlPunct: " Trailing sentence punctuation (./,/)) is stripped automatically.",
2013
- helpPresetsTitle: "Presets (branch + harvest are NEVER auto-enabled \u2014 opt-in only):",
2014
- helpPresetAuto: " auto v4-flash \u2192 v4-pro on hard turns \u2190 default \xB7 cheap when easy, smart when hard",
2015
- helpPresetFlash: " flash v4-flash always cheapest \xB7 predictable per-turn cost",
2016
- helpPresetPro: " pro v4-pro always ~3\xD7 flash (5/31) \xB7 hard multi-turn work",
2017
1960
  helpSessionsTitle: "Sessions (auto-enabled by default, named 'default'):",
2018
1961
  helpSessionCustom: " reasonix chat --session <name> use a different named session",
2019
1962
  helpSessionNone: " reasonix chat --no-session disable persistence for this run",
@@ -2155,14 +2098,9 @@ var EN = {
2155
2098
  modelUsage: "usage: /model <id> ({hint})",
2156
2099
  modelNotInCatalog: "model \u2192 {id} (\u26A0 not in the fetched catalog: {list}. If this is wrong the next call will 400 \u2014 run /models to refresh.)",
2157
2100
  modelSet: "model \u2192 {id}",
2158
- presetAuto: "preset \u2192 auto (v4-flash \u2192 v4-pro on hard turns \xB7 default)",
2159
- presetFlash: "preset \u2192 flash (v4-flash always \xB7 cheapest \xB7 /pro still bumps one turn)",
2160
- presetPro: "preset \u2192 pro (v4-pro always \xB7 ~3\xD7 flash \xB7 for hard multi-turn work)",
2161
- presetUsage: "usage: /preset <auto|flash|pro>",
2162
- proNothingArmed: "nothing armed \u2014 /pro with no args will arm pro for your next turn",
2163
- proDisarmed: "\u25B8 /pro disarmed \u2014 next turn falls back to the current preset",
2164
- proUsage: "usage: /pro arm pro for the next turn (one-shot, auto-disarms after)\n /pro off cancel armed state before the next turn",
2165
- proArmed: "\u25B8 /pro armed \u2014 your NEXT message runs on {model} regardless of preset. Auto-disarms after one turn. Use /preset max for a persistent switch.",
2101
+ effortStatus: "effort \u2192 {current} (pick: {list})",
2102
+ effortUsage: "usage: /effort <{list}> (high is the safe default; max is a DeepSeek extension)",
2103
+ effortSet: "effort \u2192 {effort}",
2166
2104
  budgetNoCap: "no session budget set \u2014 Reasonix will keep going until you stop it. Set one with: /budget <usd> (e.g. /budget 5)",
2167
2105
  budgetStatus: "budget: ${spent} of ${cap} ({pct}%) \xB7 /budget off to clear, /budget <usd> to change",
2168
2106
  budgetOff: "budget \u2192 off (no cap)",
@@ -2208,7 +2146,10 @@ var EN = {
2208
2146
  ready: "\u25B8 dashboard ready:",
2209
2147
  readyHint: "127.0.0.1 only \xB7 token-gated. Type `/dashboard stop` to shut down.",
2210
2148
  failed: "\u25B8 dashboard failed to start: {reason}",
2211
- starting: "\u25B8 starting dashboard server\u2026"
2149
+ starting: "\u25B8 starting dashboard server\u2026",
2150
+ copied: "\u25B8 dashboard URL copied to clipboard: {url}",
2151
+ tokenResetting: "\u25B8 rotating dashboard token \u2014 restarting server\u2026",
2152
+ tokenReset: "\u25B8 dashboard token rotated. New URL:"
2212
2153
  },
2213
2154
  observability: {
2214
2155
  contextInfo: "context: ~{total} of {max} ({pct}%) \xB7 system {sys} \xB7 tools {tools} \xB7 log {log}",
@@ -2448,7 +2389,10 @@ var EN = {
2448
2389
  editorExited: "editor exited with code {code}",
2449
2390
  typeaheadStaged: "\u25B8 {count} line(s) staged \xB7 esc recall",
2450
2391
  steerPlaceholder: "type to steer the current task \u2014 commands are disabled while busy",
2451
- steerHint: "send \u2014 injected mid-turn"
2392
+ steerHint: "send \u2014 injected mid-turn",
2393
+ stashNothing: "Nothing to stash",
2394
+ stashSaved: "Stashed",
2395
+ stashRecall: "Recalled"
2452
2396
  },
2453
2397
  pathConfirm: {
2454
2398
  title: "Outside-sandbox path",
@@ -2562,8 +2506,14 @@ var EN = {
2562
2506
  loading: " \xB7 loading catalog\u2026",
2563
2507
  catalogEmpty: " \xB7 catalog empty \u2014 using known fallbacks",
2564
2508
  modelsAvailable: " \xB7 {count} models available",
2565
- presetsHeader: " PRESETS \xB7 recommended \u2014 model + effort + auto-escalate",
2566
- modelsHeader: " MODELS \xB7 raw pick \u2014 auto-escalate stays as-is",
2509
+ effortHeader: " EFFORT \xB7 reasoning_effort cap",
2510
+ modelsHeader: " MODELS \xB7 DeepSeek-compatible ids",
2511
+ effortDesc: {
2512
+ low: "fastest \u2014 minimal reasoning",
2513
+ medium: "balanced",
2514
+ high: "default \u2014 safe for vLLM / Azure",
2515
+ max: "DeepSeek extension; rejected by stock OpenAI / vLLM"
2516
+ },
2567
2517
  pickerFooter: " \u2191\u2193 pick \xB7 \u23CE confirm \xB7 [r] refresh \xB7 esc cancel",
2568
2518
  currentLabel: " \xB7 current"
2569
2519
  },
@@ -2720,8 +2670,10 @@ var EN = {
2720
2670
  hitsPlural: "{count} hits \xB7 {files} files",
2721
2671
  moreHitSingular: "\u22EE +{count} more hit",
2722
2672
  moreHitsPlural: "\u22EE +{count} more hits",
2723
- earlierLine: "\u22EE {count} earlier line (use /tool to read full)",
2724
- earlierLines: "\u22EE {count} earlier lines (use /tool to read full)",
2673
+ earlierLine: "\u22EE {count} hidden line (Ctrl+R for full output)",
2674
+ earlierLines: "\u22EE {count} hidden lines (Ctrl+R for full output)",
2675
+ hiddenLine: "\u22EE {count} hidden line",
2676
+ hiddenLines: "\u22EE {count} hidden lines",
2725
2677
  earlierStackLine: "\u22EE {count} earlier stack line hidden",
2726
2678
  earlierStackLines: "\u22EE {count} earlier stack lines hidden",
2727
2679
  agent: "agent \xB7 {name}",
@@ -2927,14 +2879,15 @@ var EN = {
2927
2879
  descNewSession: "New session",
2928
2880
  descListSessions: "List sessions",
2929
2881
  descSwitchModel: "Switch model",
2930
- descSwitchPreset: "Switch preset",
2882
+ descSwitchEffort: "Switch reasoning effort",
2931
2883
  descSwitchTheme: "Switch theme",
2932
2884
  descCtrlC: "Quit",
2933
2885
  descEsc: "Stop / Cancel",
2934
2886
  descCtrlR: "Toggle verbose",
2935
2887
  descCtrlO: "Expand reply (streaming only)",
2936
2888
  descHelp: "Show all commands",
2937
- descShiftTab: "Switch edit mode"
2889
+ descShiftTab: "Switch edit mode",
2890
+ descAltS: "Stash / recall input"
2938
2891
  },
2939
2892
  mcpCli: {
2940
2893
  bundledCatalog: "Bundled MCP servers (offline catalog):",
@@ -2977,7 +2930,7 @@ var zhCN = {
2977
2930
  cli: {
2978
2931
  description: "DeepSeek \u539F\u751F\u667A\u80FD\u4F53\u6846\u67B6 \u2014 \u4E13\u4E3A\u7F13\u5B58\u547D\u4E2D\u548C\u4F4E\u6210\u672C\u4EE4\u724C\u6784\u5EFA\u3002",
2979
2932
  continue: "\u6062\u590D\u6700\u8FD1\u4F7F\u7528\u7684\u804A\u5929\u4F1A\u8BDD\uFF0C\u4E0D\u663E\u793A\u9009\u62E9\u5668\u3002",
2980
- setup: "\u4EA4\u4E92\u5F0F\u5411\u5BFC \u2014 API \u5BC6\u94A5\u3001\u9884\u8BBE\u3001MCP \u670D\u52A1\u5668\u3002\u968F\u65F6\u91CD\u65B0\u8FD0\u884C\u4EE5\u91CD\u65B0\u914D\u7F6E\u3002",
2933
+ setup: "\u4EA4\u4E92\u5F0F\u5411\u5BFC \u2014 API \u5BC6\u94A5\u3001MCP \u670D\u52A1\u5668\u3002\u968F\u65F6\u91CD\u65B0\u8FD0\u884C\u4EE5\u91CD\u65B0\u914D\u7F6E\u3002",
2981
2934
  code: "\u4EE3\u7801\u7F16\u8F91\u804A\u5929 \u2014 \u4EE5 <dir>\uFF08\u9ED8\u8BA4\uFF1Acwd\uFF09\u4E3A\u6839\u7684\u6587\u4EF6\u7CFB\u7EDF\u5DE5\u5177\uFF0C\u7F16\u7801\u7CFB\u7EDF\u63D0\u793A\u8BCD\uFF0Cv4-flash \u57FA\u7EBF\u3002",
2982
2935
  chat: "\u5177\u6709\u5B9E\u65F6\u7F13\u5B58/\u6210\u672C\u9762\u677F\u7684\u4EA4\u4E92\u5F0F Ink TUI\u3002",
2983
2936
  run: "\u4EE5\u975E\u4EA4\u4E92\u65B9\u5F0F\u8FD0\u884C\u5355\u4E2A\u4EFB\u52A1\uFF0C\u6D41\u5F0F\u8F93\u51FA\u3002",
@@ -3143,13 +3096,13 @@ var zhCN = {
3143
3096
  budgetHint: "\u4F1A\u8BDD\u7F8E\u5143\u4E0A\u9650 \u2014 80% \u65F6\u8B66\u544A\uFF0C100% \u65F6\u62D2\u7EDD\u4E0B\u4E00\u8F6E",
3144
3097
  modelIdHint: "DeepSeek \u6A21\u578B ID\uFF08\u4F8B\u5982 deepseek-v4-flash\uFF09",
3145
3098
  systemPromptHint: "\u8986\u76D6\u9ED8\u8BA4\u7CFB\u7EDF\u63D0\u793A\u8BCD",
3146
- presetHint: "\u6A21\u578B\u7EC4\u5408 \u2014 auto|flash|pro",
3099
+ effortHint: "\u63A8\u7406\u5F3A\u5EA6 \u2014 low|medium|high|max",
3147
3100
  sessionNameHint: "\u4F1A\u8BDD\u540D\u79F0\uFF08\u9ED8\u8BA4\uFF1A'default'\uFF09",
3148
3101
  ephemeralHint: "\u7981\u7528\u672C\u6B21\u8FD0\u884C\u7684\u4F1A\u8BDD\u6301\u4E45\u5316",
3149
3102
  mcpSpecHint: "MCP \u670D\u52A1\u5668\u89C4\u683C\uFF08\u53EF\u91CD\u590D\uFF09",
3150
3103
  mcpPrefixHint: "\u7528\u6B64\u5B57\u7B26\u4E32\u4E3A MCP \u5DE5\u5177\u540D\u6DFB\u52A0\u524D\u7F00",
3151
3104
  noConfigHint: "\u672C\u6B21\u8FD0\u884C\u5FFD\u7565 ~/.reasonix/config.json",
3152
- presetHintShort: "\u6A21\u578B\u7EC4\u5408 \u2014 auto|flash|pro",
3105
+ effortHintShort: "\u63A8\u7406\u5F3A\u5EA6 \u2014 low|medium|high|max",
3153
3106
  budgetHintShort: "\u4F1A\u8BDD\u7F8E\u5143\u4E0A\u9650",
3154
3107
  transcriptHintShort: "JSONL \u8F6C\u5F55\u7A3F\u8DEF\u5F84",
3155
3108
  mcpSpecHintShort: "MCP \u670D\u52A1\u5668\u89C4\u683C\uFF08\u53EF\u91CD\u590D\uFF09",
@@ -3201,15 +3154,15 @@ var zhCN = {
3201
3154
  slash: {
3202
3155
  help: { description: "\u663E\u793A\u5B8C\u6574\u547D\u4EE4\u53C2\u8003" },
3203
3156
  status: { description: "\u5F53\u524D\u6A21\u578B\u3001\u6807\u5FD7\u3001\u4E0A\u4E0B\u6587\u3001\u4F1A\u8BDD" },
3204
- preset: {
3205
- description: "\u6A21\u578B\u7EC4\u5408 \u2014 \u81EA\u52A8\u5728 flash \u2192 pro \u4E4B\u95F4\u5207\u6362\uFF0C\u6216\u9501\u5B9A flash/pro",
3206
- argsHint: "<auto|flash|pro>"
3157
+ effort: {
3158
+ description: "\u63A8\u7406\u5F3A\u5EA6\u4E0A\u9650\uFF08low|medium|high|max\uFF09\uFF1Bhigh \u662F vLLM/Azure \u5B89\u5168\u9ED8\u8BA4",
3159
+ argsHint: "<low|medium|high|max>"
3207
3160
  },
3208
3161
  model: { description: "\u5207\u6362 DeepSeek \u6A21\u578B ID", argsHint: "<id>" },
3209
3162
  models: { description: "\u5217\u51FA\u4ECE DeepSeek /models \u83B7\u53D6\u7684\u53EF\u7528\u6A21\u578B" },
3210
3163
  theme: {
3211
3164
  description: "\u663E\u793A\u6216\u6301\u4E45\u5316\u7EC8\u7AEF\u4E3B\u9898\u504F\u597D\u3002\u65E0\u53C2\u6570\u65F6\u6253\u5F00\u9009\u62E9\u5668\u3002",
3212
- argsHint: "[auto|default|dark|light|tokyo-night|github-dark|github-light|high-contrast]"
3165
+ argsHint: "[auto|dark|light|midnight|deep-blue|high-contrast]"
3213
3166
  },
3214
3167
  language: {
3215
3168
  description: "\u5207\u6362\u8FD0\u884C\u65F6\u8BED\u8A00",
@@ -3217,10 +3170,6 @@ var zhCN = {
3217
3170
  success: "\u8BED\u8A00\u5DF2\u5207\u6362\u4E3A\u7B80\u4F53\u4E2D\u6587\u3002",
3218
3171
  unsupported: "\u4E0D\u652F\u6301\u7684\u8BED\u8A00\u4EE3\u7801\uFF1A{code}\u3002\u652F\u6301\u7684\u8BED\u8A00\uFF1A{supported}\u3002"
3219
3172
  },
3220
- pro: {
3221
- description: "\u4EC5\u4E3A\u4E0B\u4E00\u8F6E\u542F\u7528 v4-pro\uFF08\u4E00\u6B21\u6027 \xB7 \u81EA\u52A8\u89E3\u9664\uFF09",
3222
- argsHint: "[off]"
3223
- },
3224
3173
  budget: {
3225
3174
  description: "\u4F1A\u8BDD\u7F8E\u5143\u4E0A\u9650 \u2014 80% \u65F6\u8B66\u544A\uFF0C100% \u65F6\u62D2\u7EDD\u4E0B\u4E00\u8F6E\u3002\u9ED8\u8BA4\u5173\u95ED\u3002\u5355\u72EC /budget \u663E\u793A\u72B6\u6001",
3226
3175
  argsHint: "[usd|off]"
@@ -3377,16 +3326,13 @@ var zhCN = {
3377
3326
  themeSampleHeading: "\u793A\u4F8B",
3378
3327
  themeFooter: "[\u2191\u2193] \u79FB\u52A8 \xB7 [Enter] \u786E\u8BA4 \xB7 [Esc] \u53D6\u6D88",
3379
3328
  themeCaption: {
3380
- default: "GitHub \u6DF1\u8272\uFF08\u9ED8\u8BA4\uFF09",
3381
- dark: "\u6DF1\u8272\u8C03",
3329
+ dark: "\u6DF1\u8272\u8C03\uFF08\u9ED8\u8BA4\uFF09",
3382
3330
  light: "\u6E05\u723D\u6D45\u8272",
3383
- "tokyo-night": "\u4E1C\u4EAC\u591C\u8272",
3384
- "github-dark": "GitHub \u6DF1\u8272",
3385
- "github-light": "GitHub \u6D45\u8272",
3331
+ midnight: "\u4E1C\u4EAC\u591C\u8272",
3332
+ "deep-blue": "\u6DF1\u84DD\u7EAF\u9ED1",
3386
3333
  "high-contrast": "\u9AD8\u5BF9\u6BD4\u5EA6\uFF08\u65E0\u969C\u788D\uFF09"
3387
3334
  },
3388
3335
  reviewLabelTheme: "\u4E3B\u9898",
3389
- presetTitle: "\u9009\u62E9\u9884\u8BBE",
3390
3336
  mcpTitle: "Reasonix \u8981\u4E3A\u4F60\u63A5\u5165\u54EA\u4E9B MCP \u670D\u52A1\u5668\uFF1F",
3391
3337
  mcpUserArgsHint: "\uFF08\u9700\u8981\u4F60\u63D0\u4F9B {arg}\uFF09",
3392
3338
  mcpFooterMulti: "[\u2191\u2193] \u79FB\u52A8 \xB7 [\u7A7A\u683C] \u9009\u62E9 \xB7 [Enter] \u786E\u8BA4 \xB7 [Esc] \u53D6\u6D88 \xB7 \u5168\u4E0D\u9009 = \u8DF3\u8FC7",
@@ -3400,7 +3346,6 @@ var zhCN = {
3400
3346
  reviewTitle: "\u786E\u8BA4\u4FDD\u5B58",
3401
3347
  reviewLabelApiKey: "API key",
3402
3348
  reviewLabelLanguage: "\u8BED\u8A00",
3403
- reviewLabelPreset: "\u9884\u8BBE",
3404
3349
  reviewLabelMcp: "MCP",
3405
3350
  reviewMcpNone: "\uFF08\u65E0\uFF09",
3406
3351
  reviewMcpServers: "{count} \u4E2A\u670D\u52A1\u5668",
@@ -3568,7 +3513,17 @@ var zhCN = {
3568
3513
  mcpFailed: "MCP {name} \u5931\u8D25",
3569
3514
  mcpWarn: "MCP {name} \u8B66\u544A",
3570
3515
  unknownTheme: "\u672A\u77E5\u4E3B\u9898\uFF1A{name}\n\u53EF\u7528\u4E3B\u9898\uFF1A{choices}",
3571
- themeSaved: "\u4E3B\u9898\u5DF2\u4FDD\u5B58\uFF1A{name}\n\u4E0B\u6B21\u542F\u52A8\u751F\u6548\uFF1A{active}"
3516
+ themeSaved: "\u4E3B\u9898\u5DF2\u4FDD\u5B58\uFF1A{name}\n\u4E0B\u6B21\u542F\u52A8\u751F\u6548\uFF1A{active}",
3517
+ noPendingEdits: "\u6CA1\u6709\u5F85\u5904\u7406\u7684\u7F16\u8F91 \u2014 \u81EA\u4E0A\u6B21 /apply \u6216 /discard \u4EE5\u6765\u6A21\u578B\u672A\u63D0\u51FA\u4FEE\u6539\u3002",
3518
+ noMatchedApply: "\u25B8 \u6CA1\u6709\u5339\u914D\u8FD9\u4E9B\u7D22\u5F15\u7684\u7F16\u8F91 \u2014 \u4EC0\u4E48\u90FD\u6CA1\u5E94\u7528\u3002\u4E0D\u5E26\u53C2\u6570\u4F7F\u7528 /apply \u63D0\u4EA4\u5168\u90E8\u3002",
3519
+ noPendingDiscard: "\u6CA1\u6709\u53EF\u4E22\u5F03\u7684\u5F85\u5904\u7406\u7F16\u8F91\u3002",
3520
+ noMatchedDiscard: "\u25B8 \u6CA1\u6709\u5339\u914D\u8FD9\u4E9B\u7D22\u5F15\u7684\u7F16\u8F91 \u2014 \u4EC0\u4E48\u90FD\u6CA1\u4E22\u5F03\u3002",
3521
+ blocksStillPending: "\u25B8 \u8FD8\u6709 {count} \u4E2A\u5F85\u5904\u7406\u7F16\u8F91 \u2014 \u4F7F\u7528 /apply \u6216 /discard \u5904\u7406\u3002",
3522
+ nothingWritten: "\u3002\u6CA1\u6709\u5199\u5165\u78C1\u76D8\u3002",
3523
+ discardedCount: "\u25B8 \u5DF2\u4E22\u5F03 {count} \u4E2A\u5F85\u5904\u7406\u7F16\u8F91",
3524
+ noEventsFor: '\u6CA1\u6709\u4F1A\u8BDD "{name}" \u7684\u4E8B\u4EF6',
3525
+ lookedAtFile: "\u4F4D\u7F6E\uFF1A{path}",
3526
+ sidecarHint: "\uFF08\u4F1A\u8BDD\u4F1A\u5728\u7B2C\u4E00\u8F6E\u65F6\u81EA\u52A8\u521B\u5EFA sidecar \u2014 \u6B64\u4F1A\u8BDD\u662F\u5426\u8FD0\u884C\u8FC7\uFF1F\uFF09"
3572
3527
  },
3573
3528
  hooks: {
3574
3529
  head: "\u94A9\u5B50 {tag} `{cmd}` {decision}{truncTag}",
@@ -3588,13 +3543,9 @@ var zhCN = {
3588
3543
  budgetExhausted: "\u4F1A\u8BDD\u9884\u7B97\u5DF2\u7528\u5B8C \u2014 \u5DF2\u82B1\u8D39 ${spent} \u2265 \u4E0A\u9650 ${cap}\u3002\u7528 /budget <usd> \u63D0\u9AD8\u4E0A\u9650\uFF0C/budget off \u6E05\u9664\u4E0A\u9650\uFF0C\u6216\u7ED3\u675F\u4F1A\u8BDD\u3002",
3589
3544
  budget80Pct: "\u25B2 \u9884\u7B97\u5DF2\u7528 80% \u2014 ${spent} / ${cap}\u3002\u4E0B\u4E00\u4E24\u8F6E\u53EF\u80FD\u5C31\u89E6\u9876\u3002",
3590
3545
  proArmed: "\u21E7 /pro \u5DF2\u88C5\u5907 \u2014 \u672C\u8F6E\u4F7F\u7528 deepseek-v4-pro\uFF08\u4E00\u6B21\u6027 \xB7 \u672C\u8F6E\u540E\u81EA\u52A8\u89E3\u9664\uFF09",
3591
- abortedAtIter: "\u5728\u7B2C {iter} \u6B21\u5DE5\u5177\u8C03\u7528\u5904\u4E2D\u65AD \u2014 \u672A\u751F\u6210\u603B\u7ED3\u5373\u505C\u6B62\uFF08\u6309 \u2191 + Enter \u6216 /retry \u6062\u590D\uFF09",
3592
3546
  toolUploadStatus: "\u5DE5\u5177\u7ED3\u679C\u5DF2\u4E0A\u4F20 \xB7 \u6A21\u578B\u5728\u751F\u6210\u4E0B\u4E00\u6761\u54CD\u5E94\u524D\u601D\u8003\u4E2D\u2026",
3593
- preflightTruncateStatus: "\u9884\u68C0\uFF1A\u4E0A\u4E0B\u6587\u63A5\u8FD1\u4E0A\u9650\uFF0C\u6B63\u5728\u88C1\u526A\u6700\u65E9\u5386\u53F2\u2026",
3594
- preflightTruncated: "\u9884\u68C0\uFF1A\u8BF7\u6C42\u7EA6 {estimate}/{ctxMax} tokens\uFF08{pct}%\uFF09\xB7 body {bodyKB} KB \u2014 \u5DF2\u88C1\u526A {beforeMessages} \u6761\u6D88\u606F \u2192 {afterMessages}\u3002\u53D1\u9001\u4E2D\u3002",
3595
- preflightTruncatedStillFull: "\u9884\u68C0\uFF1A\u88C1\u526A {beforeMessages} \u6761\u6D88\u606F \u2192 {afterMessages} \u540E\uFF0C\u8BF7\u6C42\u4ECD\u7EA6 {estimate}/{ctxMax} tokens\uFF08{pct}%\uFF09\xB7 body {bodyKB} KB \u2014 DeepSeek \u5927\u6982\u7387\u4F1A\u8FD4\u56DE 400\u3002\u8BF7\u8FD0\u884C /clear \u6216 /new \u91CD\u65B0\u5F00\u59CB\u3002",
3596
- preflightNoFold: "\u9884\u68C0\uFF1A\u8BF7\u6C42\u7EA6 {estimate}/{ctxMax} tokens\uFF08{pct}%\uFF09\xB7 body {bodyKB} KB \u4E14\u6CA1\u6709\u53EF\u88C1\u526A\u7684\u5185\u5BB9 \u2014 DeepSeek \u5927\u6982\u7387\u4F1A\u8FD4\u56DE 400\u3002\u8BF7\u8FD0\u884C /clear \u6216 /new \u91CD\u65B0\u5F00\u59CB\u3002",
3597
- flashEscalation: "\u21E7 flash \u8BF7\u6C42\u5347\u7EA7 \u2014 \u672C\u8F6E\u6539\u7528 {model}{reasonSuffix}",
3547
+ turnStartFoldStatus: "\u56DE\u5408\u5F00\u59CB\uFF1A\u4E0A\u4E0B\u6587\u63A5\u8FD1\u4E0A\u9650\uFF0C\u6B63\u5728\u538B\u7F29\u5386\u53F2\u2026",
3548
+ turnStartFolded: "\u56DE\u5408\u5F00\u59CB\uFF1A\u8BF7\u6C42\u7EA6 {estimate}/{ctxMax} tokens\uFF08{pct}%\uFF09\u2014 \u5DF2\u538B\u7F29 {beforeMessages} \u6761\u6D88\u606F \u2192 {afterMessages}\u3002\u53D1\u9001\u4E2D\u3002",
3598
3549
  harvestStatus: "\u6B63\u5728\u4ECE\u63A8\u7406\u8FC7\u7A0B\u63D0\u53D6\u8BA1\u5212\u72B6\u6001\u2026",
3599
3550
  repeatToolCallWarning: "\u62E6\u622A\u5230\u91CD\u590D\u5DE5\u5177\u8C03\u7528 \u2014 \u8BA9\u6A21\u578B\u5BDF\u89C9\u95EE\u9898\u5E76\u6362\u79CD\u65B9\u5F0F\u91CD\u8BD5\u3002",
3600
3551
  stormStuck: "\u5DF2\u505C\u6B62\u5361\u6B7B\u7684\u91CD\u8BD5\u5FAA\u73AF \u2014 \u6A21\u578B\u5728\u81EA\u7EA0\u63D0\u793A\u540E\u4ECD\u4EE5\u76F8\u540C\u53C2\u6570\u91CD\u590D\u8C03\u7528\u540C\u4E00\u5DE5\u5177\u3002\u8BF7\u5C1D\u8BD5 /retry\u3001\u6362\u79CD\u8BF4\u6CD5\uFF0C\u6216\u6392\u67E5\u5E95\u5C42\u963B\u585E\u3002",
@@ -3617,7 +3568,7 @@ var zhCN = {
3617
3568
  deepseek5xxReachable: " DeepSeek \u4E3B API \u5065\u5EB7\u68C0\u67E5\u901A\u8FC7\uFF0C\u4F46 /chat/completions \u5728\u6302 \u2014 \u4ED6\u4EEC\u90A3\u8FB9\u90E8\u5206\u670D\u52A1\u5F02\u5E38\u3002",
3618
3569
  deepseek5xxUnreachable: " \u65E0\u6CD5\u4ECE\u4F60\u7684\u7F51\u7EDC\u8BBF\u95EE DeepSeek API \u2014 \u53EF\u80FD\u662F DS \u6574\u4F53\u6545\u969C\uFF0C\u4E5F\u53EF\u80FD\u662F\u672C\u5730\u7F51\u7EDC\u95EE\u9898\u3002",
3619
3570
  deepseek5xxActionNetwork: " \u5EFA\u8BAE\uFF1A(1) \u68C0\u67E5\u7F51\u7EDC\uFF0C(2) \u7B49 30 \u79D2\u540E\u91CD\u8BD5\uFF0C(3) \u67E5\u770B\u72B6\u6001\u9875 https://status.deepseek.com\u3002",
3620
- deepseek5xxActionRetry: " \u5EFA\u8BAE\uFF1A(1) \u7B49 30 \u79D2\u540E\u91CD\u8BD5\uFF0C(2) \u7528 /preset \u5207\u6362\u6A21\u578B\uFF0C(3) \u67E5\u770B\u72B6\u6001\u9875 https://status.deepseek.com\u3002",
3571
+ deepseek5xxActionRetry: " \u5EFA\u8BAE\uFF1A(1) \u7B49 30 \u79D2\u540E\u91CD\u8BD5\uFF0C(2) \u7528 /model \u5207\u6362\u6A21\u578B\uFF0C(3) \u67E5\u770B\u72B6\u6001\u9875 https://status.deepseek.com\u3002",
3621
3572
  innerNoMessage: "\uFF08\u65E0\u9519\u8BEF\u4FE1\u606F\uFF09",
3622
3573
  reasonAborted: "[\u7528\u6237\u5DF2\u4E2D\u65AD\uFF08Esc\uFF09 \u2014 \u6B63\u5728\u603B\u7ED3\u5230\u76EE\u524D\u4E3A\u6B62\u7684\u53D1\u73B0]",
3623
3574
  reasonContextGuard: "[\u4E0A\u4E0B\u6587\u989D\u5EA6\u5373\u5C06\u8017\u5C3D \u2014 \u5728\u4E0B\u4E00\u6B21\u8C03\u7528\u6EA2\u51FA\u4E4B\u524D\u5148\u603B\u7ED3]",
@@ -3655,10 +3606,6 @@ var zhCN = {
3655
3606
  helpUrl: " @https://example.com \u83B7\u53D6 URL\uFF0C\u5265\u79BB HTML\uFF0C\u5185\u8054\u5230 [Referenced URLs] \u4E0B\u3002",
3656
3607
  helpUrlCache: " \u540C\u4E00\u4F1A\u8BDD\u4E2D\u76F8\u540C URL \u53EA\u83B7\u53D6\u4E00\u6B21\uFF08\u5185\u5B58\u7F13\u5B58\uFF09\u3002",
3657
3608
  helpUrlPunct: " \u81EA\u52A8\u5265\u79BB\u5C3E\u90E8\u6807\u70B9\u7B26\u53F7\uFF08./,/\uFF09\uFF09\u3002",
3658
- helpPresetsTitle: "\u9884\u8BBE\uFF08branch + harvest \u6C38\u8FDC\u4E0D\u4F1A\u81EA\u52A8\u542F\u7528 \u2014 \u4EC5\u624B\u52A8\u9009\u62E9\uFF09\uFF1A",
3659
- helpPresetAuto: " auto v4-flash \u2192 v4-pro \u5728\u56F0\u96BE\u8F6E\u6B21\u5207\u6362 \u2190 \u9ED8\u8BA4 \xB7 \u7B80\u5355\u65F6\u4FBF\u5B9C\uFF0C\u56F0\u96BE\u65F6\u667A\u80FD",
3660
- helpPresetFlash: " flash \u59CB\u7EC8\u4F7F\u7528 v4-flash \u6700\u4FBF\u5B9C \xB7 \u6BCF\u8F6E\u6210\u672C\u53EF\u9884\u6D4B",
3661
- helpPresetPro: " pro \u59CB\u7EC8\u4F7F\u7528 v4-pro \u7EA6 3 \u500D flash \xB7 \u7528\u4E8E\u56F0\u96BE\u7684\u591A\u8F6E\u5DE5\u4F5C",
3662
3609
  helpSessionsTitle: "\u4F1A\u8BDD\uFF08\u9ED8\u8BA4\u81EA\u52A8\u542F\u7528\uFF0C\u547D\u540D\u4E3A 'default'\uFF09\uFF1A",
3663
3610
  helpSessionCustom: " reasonix chat --session <name> \u4F7F\u7528\u4E0D\u540C\u7684\u547D\u540D\u4F1A\u8BDD",
3664
3611
  helpSessionNone: " reasonix chat --no-session \u7981\u7528\u672C\u6B21\u8FD0\u884C\u7684\u6301\u4E45\u5316",
@@ -3800,14 +3747,9 @@ var zhCN = {
3800
3747
  modelUsage: "\u7528\u6CD5\uFF1A/model <id> \uFF08{hint}\uFF09",
3801
3748
  modelNotInCatalog: "model \u2192 {id} \uFF08\u26A0 \u4E0D\u5728\u83B7\u53D6\u7684\u76EE\u5F55\u4E2D\uFF1A{list}\u3002\u5982\u679C\u8FD9\u662F\u9519\u8BEF\u7684\uFF0C\u4E0B\u6B21\u8C03\u7528\u5C06\u8FD4\u56DE 400 \u2014 \u8FD0\u884C /models \u5237\u65B0\u3002\uFF09",
3802
3749
  modelSet: "model \u2192 {id}",
3803
- presetAuto: "preset \u2192 auto \uFF08v4-flash \u2192 v4-pro \u5728\u56F0\u96BE\u8F6E\u6B21\u5207\u6362 \xB7 \u9ED8\u8BA4\uFF09",
3804
- presetFlash: "preset \u2192 flash \uFF08\u59CB\u7EC8\u4F7F\u7528 v4-flash \xB7 \u6700\u4FBF\u5B9C \xB7 /pro \u4ECD\u53EF\u4E34\u65F6\u63D0\u5347\u4E00\u8F6E\uFF09",
3805
- presetPro: "preset \u2192 pro \uFF08\u59CB\u7EC8\u4F7F\u7528 v4-pro \xB7 \u7EA6 3 \u500D flash \xB7 \u7528\u4E8E\u56F0\u96BE\u7684\u591A\u8F6E\u5DE5\u4F5C\uFF09",
3806
- presetUsage: "\u7528\u6CD5\uFF1A/preset <auto|flash|pro>",
3807
- proNothingArmed: "\u672A\u542F\u7528 \u2014 /pro \u4E0D\u5E26\u53C2\u6570\u5C06\u4E3A\u4E0B\u4E00\u8F6E\u542F\u7528 pro",
3808
- proDisarmed: "\u25B8 /pro \u5DF2\u89E3\u9664 \u2014 \u4E0B\u4E00\u8F6E\u56DE\u9000\u5230\u5F53\u524D\u9884\u8BBE",
3809
- proUsage: "\u7528\u6CD5\uFF1A/pro \u4E3A\u4E0B\u4E00\u8F6E\u542F\u7528 pro\uFF08\u4E00\u6B21\u6027\uFF0C\u81EA\u52A8\u89E3\u9664\uFF09\n /pro off \u5728\u4E0B\u4E00\u8F6E\u524D\u53D6\u6D88\u542F\u7528\u72B6\u6001",
3810
- proArmed: "\u25B8 /pro \u5DF2\u542F\u7528 \u2014 \u60A8\u7684\u4E0B\u4E00\u6761\u6D88\u606F\u5C06\u5728 {model} \u4E0A\u8FD0\u884C\uFF0C\u65E0\u8BBA\u9884\u8BBE\u5982\u4F55\u3002\u4E00\u8F6E\u540E\u81EA\u52A8\u89E3\u9664\u3002\u4F7F\u7528 /preset max \u8FDB\u884C\u6301\u4E45\u5207\u6362\u3002",
3750
+ effortStatus: "effort \u2192 {current} \uFF08\u53EF\u9009\uFF1A{list}\uFF09",
3751
+ effortUsage: "\u7528\u6CD5\uFF1A/effort <{list}> \uFF08high \u4E3A\u5B89\u5168\u9ED8\u8BA4\uFF1Bmax \u662F DeepSeek \u6269\u5C55\uFF09",
3752
+ effortSet: "effort \u2192 {effort}",
3811
3753
  budgetNoCap: "\u672A\u8BBE\u7F6E\u4F1A\u8BDD\u9884\u7B97 \u2014 Reasonix \u5C06\u6301\u7EED\u8FD0\u884C\u76F4\u5230\u60A8\u505C\u6B62\u3002\u4F7F\u7528\u4EE5\u4E0B\u65B9\u5F0F\u8BBE\u7F6E\uFF1A/budget <usd> \uFF08\u4F8B\u5982 /budget 5\uFF09",
3812
3754
  budgetStatus: "\u9884\u7B97\uFF1A${spent} / ${cap}\uFF08{pct}%\uFF09\xB7 /budget off \u6E05\u9664\uFF0C/budget <usd> \u66F4\u6539",
3813
3755
  budgetOff: "budget \u2192 \u5173\u95ED\uFF08\u65E0\u4E0A\u9650\uFF09",
@@ -3853,7 +3795,10 @@ var zhCN = {
3853
3795
  ready: "\u25B8 \u4EEA\u8868\u677F\u5C31\u7EEA\uFF1A",
3854
3796
  readyHint: "\u4EC5 127.0.0.1 \xB7 token \u4FDD\u62A4\u3002\u8F93\u5165 `/dashboard stop` \u5173\u95ED\u3002",
3855
3797
  failed: "\u25B8 \u4EEA\u8868\u677F\u542F\u52A8\u5931\u8D25\uFF1A{reason}",
3856
- starting: "\u25B8 \u6B63\u5728\u542F\u52A8\u4EEA\u8868\u677F\u670D\u52A1\u5668\u2026"
3798
+ starting: "\u25B8 \u6B63\u5728\u542F\u52A8\u4EEA\u8868\u677F\u670D\u52A1\u5668\u2026",
3799
+ copied: "\u25B8 \u4EEA\u8868\u677F URL \u5DF2\u590D\u5236\u5230\u526A\u8D34\u677F\uFF1A{url}",
3800
+ tokenResetting: "\u25B8 \u6B63\u5728\u8F6E\u6362\u4EEA\u8868\u677F token \u5E76\u91CD\u542F\u670D\u52A1\u2026",
3801
+ tokenReset: "\u25B8 \u4EEA\u8868\u677F token \u5DF2\u8F6E\u6362\u3002\u65B0 URL\uFF1A"
3857
3802
  },
3858
3803
  observability: {
3859
3804
  contextInfo: "\u4E0A\u4E0B\u6587\uFF1A~{total} / {max}\uFF08{pct}%\uFF09\xB7 \u7CFB\u7EDF {sys} \xB7 \u5DE5\u5177 {tools} \xB7 \u65E5\u5FD7 {log}",
@@ -4093,7 +4038,10 @@ var zhCN = {
4093
4038
  editorExited: "\u7F16\u8F91\u5668\u5F02\u5E38\u9000\u51FA\uFF0C\u8FD4\u56DE\u7801 {code}",
4094
4039
  typeaheadStaged: "\u25B8 {count} \u884C\u5DF2\u6682\u5B58 \xB7 esc \u53EC\u56DE",
4095
4040
  steerPlaceholder: "\u8F93\u5165\u6D88\u606F\u4EE5\u5F15\u5BFC\u5F53\u524D\u4EFB\u52A1 \u2014 \u5FD9\u788C\u65F6\u4E0D\u652F\u6301\u547D\u4EE4",
4096
- steerHint: "\u53D1\u9001 \u2014 \u56DE\u5408\u5185\u6CE8\u5165"
4041
+ steerHint: "\u53D1\u9001 \u2014 \u56DE\u5408\u5185\u6CE8\u5165",
4042
+ stashNothing: "\u6CA1\u6709\u53EF\u6682\u5B58\u7684\u5185\u5BB9",
4043
+ stashSaved: "\u5DF2\u6682\u5B58",
4044
+ stashRecall: "\u5DF2\u6062\u590D"
4097
4045
  },
4098
4046
  pathConfirm: {
4099
4047
  title: "\u6C99\u7BB1\u5916\u8DEF\u5F84",
@@ -4207,8 +4155,14 @@ var zhCN = {
4207
4155
  loading: " \xB7 \u52A0\u8F7D\u76EE\u5F55\u2026",
4208
4156
  catalogEmpty: " \xB7 \u76EE\u5F55\u4E3A\u7A7A \u2014 \u4F7F\u7528\u5DF2\u77E5\u5907\u9009",
4209
4157
  modelsAvailable: " \xB7 {count} \u4E2A\u6A21\u578B\u53EF\u7528",
4210
- presetsHeader: " \u9884\u8BBE \xB7 \u63A8\u8350 \u2014 \u6A21\u578B + \u5F3A\u5EA6 + \u81EA\u52A8\u5347\u7EA7",
4211
- modelsHeader: " \u6A21\u578B \xB7 \u76F4\u63A5\u9009\u62E9 \u2014 \u81EA\u52A8\u5347\u7EA7\u4FDD\u6301\u4E0D\u53D8",
4158
+ effortHeader: " \u5F3A\u5EA6 \xB7 reasoning_effort \u4E0A\u9650",
4159
+ modelsHeader: " \u6A21\u578B \xB7 DeepSeek \u517C\u5BB9 ID",
4160
+ effortDesc: {
4161
+ low: "\u6700\u5FEB \u2014 \u6781\u5C11\u63A8\u7406",
4162
+ medium: "\u5E73\u8861",
4163
+ high: "\u9ED8\u8BA4 \u2014 vLLM / Azure \u5B89\u5168",
4164
+ max: "DeepSeek \u6269\u5C55\uFF1BOpenAI / vLLM \u4F1A\u62D2\u7EDD"
4165
+ },
4212
4166
  pickerFooter: " \u2191\u2193 \u9009\u62E9 \xB7 \u23CE \u786E\u8BA4 \xB7 [r] \u5237\u65B0 \xB7 Esc \u53D6\u6D88",
4213
4167
  currentLabel: " \xB7 \u5F53\u524D"
4214
4168
  },
@@ -4365,8 +4319,10 @@ var zhCN = {
4365
4319
  hitsPlural: "{count} \u6761\u7ED3\u679C \xB7 {files} \u4E2A\u6587\u4EF6",
4366
4320
  moreHitSingular: "\u22EE +{count} \u6761\u7ED3\u679C",
4367
4321
  moreHitsPlural: "\u22EE +{count} \u6761\u7ED3\u679C",
4368
- earlierLine: "\u22EE \u524D {count} \u884C\uFF08\u4F7F\u7528 /tool \u9605\u8BFB\u5168\u6587\uFF09",
4369
- earlierLines: "\u22EE \u524D {count} \u884C\uFF08\u4F7F\u7528 /tool \u9605\u8BFB\u5168\u6587\uFF09",
4322
+ earlierLine: "\u22EE {count} \u884C\u5DF2\u9690\u85CF\uFF08Ctrl+R \u67E5\u770B\u5B8C\u6574\u8F93\u51FA\uFF09",
4323
+ earlierLines: "\u22EE {count} \u884C\u5DF2\u9690\u85CF\uFF08Ctrl+R \u67E5\u770B\u5B8C\u6574\u8F93\u51FA\uFF09",
4324
+ hiddenLine: "\u22EE {count} \u884C\u5DF2\u9690\u85CF",
4325
+ hiddenLines: "\u22EE {count} \u884C\u5DF2\u9690\u85CF",
4370
4326
  earlierStackLine: "\u22EE \u524D {count} \u884C\u5806\u6808\u5DF2\u9690\u85CF",
4371
4327
  earlierStackLines: "\u22EE \u524D {count} \u884C\u5806\u6808\u5DF2\u9690\u85CF",
4372
4328
  agent: "\u4EE3\u7406 \xB7 {name}",
@@ -4572,14 +4528,15 @@ var zhCN = {
4572
4528
  descNewSession: "\u65B0\u5EFA\u4F1A\u8BDD",
4573
4529
  descListSessions: "\u5217\u51FA\u4F1A\u8BDD",
4574
4530
  descSwitchModel: "\u5207\u6362\u6A21\u578B",
4575
- descSwitchPreset: "\u5207\u6362\u9884\u8BBE",
4531
+ descSwitchEffort: "\u5207\u6362\u63A8\u7406\u5F3A\u5EA6",
4576
4532
  descSwitchTheme: "\u5207\u6362\u4E3B\u9898",
4577
4533
  descCtrlC: "\u9000\u51FA",
4578
4534
  descEsc: "\u505C\u6B62/\u53D6\u6D88",
4579
4535
  descCtrlR: "\u5207\u6362\u8BE6\u7EC6\u6A21\u5F0F",
4580
4536
  descCtrlO: "\u5C55\u5F00\u56DE\u590D\uFF08\u4EC5\u6D41\u5F0F\u8F93\u51FA\u671F\u95F4\uFF09",
4581
4537
  descHelp: "\u663E\u793A\u6240\u6709\u547D\u4EE4",
4582
- descShiftTab: "\u5207\u6362\u7F16\u8F91\u6A21\u5F0F"
4538
+ descShiftTab: "\u5207\u6362\u7F16\u8F91\u6A21\u5F0F",
4539
+ descAltS: "\u6682\u5B58/\u6062\u590D\u8F93\u5165"
4583
4540
  },
4584
4541
  mcpCli: {
4585
4542
  bundledCatalog: "\u5DF2\u6253\u5305\u7684 MCP \u670D\u52A1\u5668\uFF08\u79BB\u7EBF\u76EE\u5F55\uFF09\uFF1A",
@@ -4710,7 +4667,7 @@ function matchesTool(hook, toolName) {
4710
4667
  }
4711
4668
  var HOOK_OUTPUT_CAP_BYTES = 256 * 1024;
4712
4669
  function defaultSpawner(input) {
4713
- return new Promise((resolve14) => {
4670
+ return new Promise((resolve15) => {
4714
4671
  const child = spawn(input.command, {
4715
4672
  cwd: input.cwd,
4716
4673
  shell: true,
@@ -4755,7 +4712,7 @@ function defaultSpawner(input) {
4755
4712
  child.stderr.on("data", (chunk) => onChunk("stderr", chunk));
4756
4713
  child.once("error", (err) => {
4757
4714
  clearTimeout(timer);
4758
- resolve14({
4715
+ resolve15({
4759
4716
  exitCode: null,
4760
4717
  stdout: Buffer.concat(stdoutChunks).toString("utf8"),
4761
4718
  stderr: Buffer.concat(stderrChunks).toString("utf8"),
@@ -4766,7 +4723,7 @@ function defaultSpawner(input) {
4766
4723
  });
4767
4724
  child.once("close", (code) => {
4768
4725
  clearTimeout(timer);
4769
- resolve14({
4726
+ resolve15({
4770
4727
  exitCode: code,
4771
4728
  stdout: Buffer.concat(stdoutChunks).toString("utf8").trim(),
4772
4729
  stderr: Buffer.concat(stderrChunks).toString("utf8").trim(),
@@ -5531,6 +5488,9 @@ function plainTextRejectedReason(name, result) {
5531
5488
  if ((name === "edit_file" || name === "write_file") && /rejected this edit/i.test(result)) {
5532
5489
  return "edit-gate";
5533
5490
  }
5491
+ if ((name === "edit_file" || name === "write_file" || name === "multi_edit") && /queued \d+ edits? for review/i.test(result)) {
5492
+ return "edit-gate";
5493
+ }
5534
5494
  if ((name === "edit_file" || name === "multi_edit") && /read_file first/i.test(result)) {
5535
5495
  return "read-before-edit";
5536
5496
  }
@@ -5673,12 +5633,12 @@ async function waitForReady(ready, timeoutMs, serverName, signal) {
5673
5633
  let timer;
5674
5634
  let onAbort;
5675
5635
  try {
5676
- await new Promise((resolve14, reject) => {
5636
+ await new Promise((resolve15, reject) => {
5677
5637
  ready.then(
5678
5638
  () => {
5679
5639
  if (settled) return;
5680
5640
  settled = true;
5681
- resolve14();
5641
+ resolve15();
5682
5642
  },
5683
5643
  (err) => {
5684
5644
  if (settled) return;
@@ -5858,6 +5818,12 @@ function blockToString(block) {
5858
5818
  return `[unknown block: ${JSON.stringify(block)}]`;
5859
5819
  }
5860
5820
 
5821
+ // packages/core-utils/src/compaction.ts
5822
+ var COMPACTION_SUMMARY_MARKER = "[CONVERSATION HISTORY SUMMARY \u2014 earlier turns folded for context efficiency]\n\n";
5823
+
5824
+ // packages/core-utils/src/tildeify.ts
5825
+ import { homedir as homedir3 } from "os";
5826
+
5861
5827
  // src/loop/thinking.ts
5862
5828
  function isThinkingModeModel(model) {
5863
5829
  if (model.includes("reasoner")) return true;
@@ -5895,7 +5861,7 @@ function buildSyntheticAssistantMessage(content, fallbackModel) {
5895
5861
  // src/memory/session.ts
5896
5862
  import { execFileSync } from "child_process";
5897
5863
  import {
5898
- appendFileSync as appendFileSync2,
5864
+ appendFileSync,
5899
5865
  chmodSync as chmodSync2,
5900
5866
  copyFileSync,
5901
5867
  existsSync as existsSync3,
@@ -5907,7 +5873,7 @@ import {
5907
5873
  unlinkSync,
5908
5874
  writeFileSync as writeFileSync2
5909
5875
  } from "fs";
5910
- import { homedir as homedir3 } from "os";
5876
+ import { homedir as homedir4 } from "os";
5911
5877
  import { dirname as dirname3, join as join4, posix as posixPath, win32 as win32Path } from "path";
5912
5878
  var SESSION_SIDECAR_EXTS = [
5913
5879
  ".events.jsonl",
@@ -5917,7 +5883,7 @@ var SESSION_SIDECAR_EXTS = [
5917
5883
  ".jsonl.bak"
5918
5884
  ];
5919
5885
  function sessionsDir() {
5920
- return join4(homedir3(), ".reasonix", "sessions");
5886
+ return join4(homedir4(), ".reasonix", "sessions");
5921
5887
  }
5922
5888
  function sessionPath(name) {
5923
5889
  return join4(sessionsDir(), `${sanitizeName(name)}.jsonl`);
@@ -5959,7 +5925,7 @@ function readSessionMessages(path2) {
5959
5925
  function appendSessionMessage(name, message) {
5960
5926
  const path2 = sessionPath(name);
5961
5927
  mkdirSync2(dirname3(path2), { recursive: true });
5962
- appendFileSync2(path2, `${JSON.stringify(message)}
5928
+ appendFileSync(path2, `${JSON.stringify(message)}
5963
5929
  `, "utf8");
5964
5930
  try {
5965
5931
  chmodSync2(path2, 384);
@@ -6011,6 +5977,18 @@ function loadSessionMeta(name) {
6011
5977
  return {};
6012
5978
  }
6013
5979
  }
5980
+ function patchSessionMeta(name, patch) {
5981
+ const cur = loadSessionMeta(name);
5982
+ const next = { ...cur, ...patch };
5983
+ const p = metaPath(name);
5984
+ mkdirSync2(dirname3(p), { recursive: true });
5985
+ writeFileSync2(p, JSON.stringify(next), "utf8");
5986
+ try {
5987
+ chmodSync2(p, 384);
5988
+ } catch {
5989
+ }
5990
+ return next;
5991
+ }
6014
5992
  function renameSession(oldName, newName) {
6015
5993
  const safeOld = sanitizeName(oldName);
6016
5994
  const safeNew = sanitizeName(newName);
@@ -6134,6 +6112,7 @@ var DEEPSEEK_CONTEXT_TOKENS = {
6134
6112
  "deepseek-reasoner": 1e6
6135
6113
  };
6136
6114
  var DEFAULT_CONTEXT_TOKENS = 131072;
6115
+ var MAX_TURNS = 200;
6137
6116
  function costUsd(model, usage, path2) {
6138
6117
  const p = pricingFor(model, path2);
6139
6118
  if (!p) return 0;
@@ -6166,6 +6145,7 @@ var SessionStats = class {
6166
6145
  _carryoverTurns = 0;
6167
6146
  _carryoverCacheHit = 0;
6168
6147
  _carryoverCacheMiss = 0;
6148
+ _carryoverCompletion = 0;
6169
6149
  /** Last turn's promptTokens before exit — surfaced via summary() until the next live turn lands. */
6170
6150
  _carryoverLastPromptTokens = 0;
6171
6151
  /** Seed totals from a resumed session's persisted meta — only call once at construction. */
@@ -6182,16 +6162,38 @@ var SessionStats = class {
6182
6162
  if (typeof opts.cacheMissTokens === "number" && opts.cacheMissTokens > 0) {
6183
6163
  this._carryoverCacheMiss = opts.cacheMissTokens;
6184
6164
  }
6165
+ if (typeof opts.totalCompletionTokens === "number" && opts.totalCompletionTokens > 0) {
6166
+ this._carryoverCompletion = opts.totalCompletionTokens;
6167
+ }
6185
6168
  if (typeof opts.lastPromptTokens === "number" && opts.lastPromptTokens > 0) {
6186
6169
  this._carryoverLastPromptTokens = opts.lastPromptTokens;
6187
6170
  }
6188
6171
  }
6172
+ /** Cumulative cache hit tokens across carryover + current turns. */
6173
+ get cumulativeCacheHitTokens() {
6174
+ let hit = this._carryoverCacheHit;
6175
+ for (const t2 of this.turns) hit += t2.usage.promptCacheHitTokens;
6176
+ return hit;
6177
+ }
6178
+ /** Cumulative cache miss tokens across carryover + current turns. */
6179
+ get cumulativeCacheMissTokens() {
6180
+ let miss = this._carryoverCacheMiss;
6181
+ for (const t2 of this.turns) miss += t2.usage.promptCacheMissTokens;
6182
+ return miss;
6183
+ }
6184
+ /** Cumulative completion (output) tokens across carryover + current turns. */
6185
+ get cumulativeCompletionTokens() {
6186
+ let comp = this._carryoverCompletion;
6187
+ for (const t2 of this.turns) comp += t2.usage.completionTokens;
6188
+ return comp;
6189
+ }
6189
6190
  reset() {
6190
6191
  this.turns.length = 0;
6191
6192
  this._carryoverCost = 0;
6192
6193
  this._carryoverTurns = 0;
6193
6194
  this._carryoverCacheHit = 0;
6194
6195
  this._carryoverCacheMiss = 0;
6196
+ this._carryoverCompletion = 0;
6195
6197
  this._carryoverLastPromptTokens = 0;
6196
6198
  }
6197
6199
  record(turn, model, usage) {
@@ -6204,8 +6206,23 @@ var SessionStats = class {
6204
6206
  cacheHitRatio: usage.cacheHitRatio
6205
6207
  };
6206
6208
  this.turns.push(stats);
6209
+ this.trimOldTurns();
6207
6210
  return stats;
6208
6211
  }
6212
+ /** Drop oldest turns beyond MAX_TURNS, folding their costs into carryover so
6213
+ * session totals remain accurate even after trimming. */
6214
+ trimOldTurns() {
6215
+ if (this.turns.length <= MAX_TURNS) return;
6216
+ const excess = this.turns.length - MAX_TURNS;
6217
+ const dropped = this.turns.splice(0, excess);
6218
+ for (const t2 of dropped) {
6219
+ this._carryoverCost += t2.cost;
6220
+ this._carryoverCacheHit += t2.usage.promptCacheHitTokens;
6221
+ this._carryoverCacheMiss += t2.usage.promptCacheMissTokens;
6222
+ this._carryoverCompletion += t2.usage.completionTokens;
6223
+ }
6224
+ this._carryoverTurns += excess;
6225
+ }
6209
6226
  get totalCost() {
6210
6227
  return this._carryoverCost + this.turns.reduce((sum, t2) => sum + t2.cost, 0);
6211
6228
  }
@@ -6263,12 +6280,9 @@ var HISTORY_FOLD_AGGRESSIVE_THRESHOLD = 0.78;
6263
6280
  var HISTORY_FOLD_AGGRESSIVE_TAIL_FRACTION = 0.1;
6264
6281
  var HISTORY_FOLD_MIN_SAVINGS_FRACTION = 0.3;
6265
6282
  var FORCE_SUMMARY_THRESHOLD = 0.8;
6266
- var PREFLIGHT_EMERGENCY_THRESHOLD = 0.95;
6267
- var PREFLIGHT_MECHANICAL_TARGET_FRACTION = 0.7;
6268
- var MAX_BODY_BYTES = 7e5;
6269
- var MAX_BODY_BYTES_TARGET = 5e5;
6283
+ var TURN_START_FOLD_THRESHOLD = 0.9;
6270
6284
  var HISTORY_FOLD_SUMMARY_TIMEOUT_MS = 15e3;
6271
- var HISTORY_FOLD_MARKER = "[CONVERSATION HISTORY SUMMARY \u2014 earlier turns folded for context efficiency]\n\n";
6285
+ var HISTORY_FOLD_MARKER = COMPACTION_SUMMARY_MARKER;
6272
6286
  var SKILL_PIN_MEMO_HEADER = "[Active skill memos \u2014 preserved verbatim across the fold:]";
6273
6287
  var SKILL_PIN_REGEX = /<skill-pin name="([^"]+)">\n[\s\S]*?\n<\/skill-pin>/g;
6274
6288
  function buildFoldSummaryInstruction(pinnedSkillNames) {
@@ -6338,28 +6352,13 @@ var ContextManager = class {
6338
6352
  }
6339
6353
  return { kind: "none", ...base };
6340
6354
  }
6341
- /** Local-side preflight before sending a request catches oversized payloads early.
6342
- * Two independent signals trip mechanical truncate: token estimate above the context-window
6343
- * fraction, OR JSON body bytes above the gateway limit (see `MAX_BODY_BYTES`). */
6344
- decidePreflight(messages, toolSpecs, model) {
6355
+ /** Turn-start estimate vs ctxMax caller folds if the ratio crosses
6356
+ * TURN_START_FOLD_THRESHOLD. Replaces the old preflight/mechanical pair. */
6357
+ estimateTurnStart(messages, toolSpecs, model) {
6345
6358
  const ctxMax = DEEPSEEK_CONTEXT_TOKENS[model] ?? DEFAULT_CONTEXT_TOKENS;
6346
6359
  const estimate = estimateRequestTokens(messages, toolSpecs ?? null, true);
6347
- const estimateBytes = Buffer.byteLength(JSON.stringify(messages), "utf8");
6348
- const tokensOver = estimate / ctxMax > PREFLIGHT_EMERGENCY_THRESHOLD;
6349
- const bytesOver = estimateBytes > MAX_BODY_BYTES;
6350
- let trigger = "none";
6351
- if (tokensOver && bytesOver) trigger = "both";
6352
- else if (tokensOver) trigger = "tokens";
6353
- else if (bytesOver) trigger = "bytes";
6354
- return {
6355
- needsAction: tokensOver || bytesOver,
6356
- estimateTokens: estimate,
6357
- estimateBytes,
6358
- ctxMax,
6359
- trigger
6360
- };
6360
+ return { estimateTokens: estimate, ctxMax, ratio: estimate / ctxMax };
6361
6361
  }
6362
- /** Replace older turns with one summary message; keep tail within keepRecentTokens budget. */
6363
6362
  async fold(model, opts) {
6364
6363
  const ctxMax = DEEPSEEK_CONTEXT_TOKENS[model] ?? DEFAULT_CONTEXT_TOKENS;
6365
6364
  const tailBudget = opts?.keepRecentTokens ?? Math.floor(ctxMax * HISTORY_FOLD_TAIL_FRACTION);
@@ -6371,7 +6370,13 @@ var ContextManager = class {
6371
6370
  summaryChars: 0
6372
6371
  };
6373
6372
  if (all.length === 0) return noop;
6374
- const tokenCounts = all.map((m) => countTokensBounded(m.content ?? ""));
6373
+ const tokenCounts = all.map((m) => {
6374
+ let n = countTokensBounded(typeof m.content === "string" ? m.content : "");
6375
+ if (m.role === "assistant" && Array.isArray(m.tool_calls) && m.tool_calls.length > 0) {
6376
+ n += countTokensBounded(JSON.stringify(m.tool_calls));
6377
+ }
6378
+ return n;
6379
+ });
6375
6380
  const totalTokens = tokenCounts.reduce((a, b) => a + b, 0);
6376
6381
  let cumTokens = 0;
6377
6382
  let boundary = all.length;
@@ -6381,6 +6386,7 @@ var ContextManager = class {
6381
6386
  if (all[i].role === "user") boundary = i;
6382
6387
  }
6383
6388
  if (boundary <= 0) return noop;
6389
+ if (opts?.requireTailBoundary && boundary >= all.length) return noop;
6384
6390
  const head = all.slice(0, boundary);
6385
6391
  const tail = all.slice(boundary);
6386
6392
  const headTokens = totalTokens - cumTokens;
@@ -6416,58 +6422,6 @@ ${constraints}` : "";
6416
6422
  summaryChars: summary.content.length
6417
6423
  };
6418
6424
  }
6419
- /** Pure local emergency compaction for preflight: drop oldest log entries and keep a valid tail.
6420
- * Bounded by tokens AND bytes — bytes matter because DeepSeek's gateway 400s on bodies past
6421
- * `MAX_BODY_BYTES` even when the token budget is far from exhausted. */
6422
- mechanicalTruncate(model, opts) {
6423
- const ctxMax = DEEPSEEK_CONTEXT_TOKENS[model] ?? DEFAULT_CONTEXT_TOKENS;
6424
- const targetTokens = opts?.targetTokens ?? Math.floor(ctxMax * PREFLIGHT_MECHANICAL_TARGET_FRACTION);
6425
- const targetBytes = opts?.targetBytes ?? MAX_BODY_BYTES_TARGET;
6426
- const all = this.deps.log.toMessages();
6427
- const noop = {
6428
- folded: false,
6429
- beforeMessages: all.length,
6430
- afterMessages: all.length,
6431
- summaryChars: 0
6432
- };
6433
- if (all.length === 0) return noop;
6434
- const tokenCounts = all.map((m) => estimateConversationTokens([m], true));
6435
- const byteCounts = all.map((m) => Buffer.byteLength(JSON.stringify(m), "utf8"));
6436
- let latestUserBoundary = -1;
6437
- for (let i = all.length - 1; i >= 0; i--) {
6438
- if (all[i].role === "user") {
6439
- latestUserBoundary = i;
6440
- break;
6441
- }
6442
- }
6443
- let cumTokens = 0;
6444
- let cumBytes = 0;
6445
- let boundary = all.length;
6446
- let foundSafeBoundary = false;
6447
- for (let i = all.length - 1; i >= 0; i--) {
6448
- const nextTokens = cumTokens + tokenCounts[i];
6449
- const nextBytes = cumBytes + byteCounts[i];
6450
- if (nextTokens > targetTokens || nextBytes > targetBytes) break;
6451
- cumTokens = nextTokens;
6452
- cumBytes = nextBytes;
6453
- if (all[i].role === "user") {
6454
- boundary = i;
6455
- foundSafeBoundary = true;
6456
- }
6457
- }
6458
- if (boundary <= 0) return noop;
6459
- const replacement = foundSafeBoundary ? all.slice(boundary) : opts?.allowEmpty ? [] : latestUserBoundary >= 0 ? all.slice(latestUserBoundary) : all;
6460
- if (replacement.length === all.length) return noop;
6461
- this.deps.log.compactInPlace(replacement);
6462
- this.persistRewrite(replacement);
6463
- this.deps.onLogRewrite?.();
6464
- return {
6465
- folded: true,
6466
- beforeMessages: all.length,
6467
- afterMessages: replacement.length,
6468
- summaryChars: 0
6469
- };
6470
- }
6471
6425
  /** Drop a trailing in-flight assistant-with-tool_calls before a forced summary. Tail-only mutation; prefix cache safe. */
6472
6426
  trimTrailingToolCalls() {
6473
6427
  const tail = this.deps.log.entries[this.deps.log.entries.length - 1];
@@ -6654,31 +6608,6 @@ function extractDeepSeekErrorMessage(body) {
6654
6608
  return trimmed;
6655
6609
  }
6656
6610
 
6657
- // src/loop/escalation.ts
6658
- var NEEDS_PRO_MARKER_PREFIX = "<<<NEEDS_PRO";
6659
- var NEEDS_PRO_MARKER_RE = /^<<<NEEDS_PRO(?::\s*([^>]*))?>>>/;
6660
- var NEEDS_PRO_BUFFER_CHARS = 256;
6661
- function parseEscalationMarker(content) {
6662
- const m = NEEDS_PRO_MARKER_RE.exec(content.trimStart());
6663
- if (!m) return { matched: false };
6664
- const reason = m[1]?.trim();
6665
- return { matched: true, reason: reason || void 0 };
6666
- }
6667
- function isEscalationRequest(content) {
6668
- return parseEscalationMarker(content).matched;
6669
- }
6670
- function looksLikePartialEscalationMarker(buf) {
6671
- const t2 = buf.trimStart();
6672
- if (t2.length === 0) return true;
6673
- if (t2.length <= NEEDS_PRO_MARKER_PREFIX.length) {
6674
- return NEEDS_PRO_MARKER_PREFIX.startsWith(t2);
6675
- }
6676
- if (!t2.startsWith(NEEDS_PRO_MARKER_PREFIX)) return false;
6677
- const rest = t2.slice(NEEDS_PRO_MARKER_PREFIX.length);
6678
- if (rest[0] !== ">" && rest[0] !== ":") return false;
6679
- return true;
6680
- }
6681
-
6682
6611
  // src/loop/force-summary.ts
6683
6612
  async function* forceSummaryAfterIterLimit(ctx, opts) {
6684
6613
  try {
@@ -7321,7 +7250,6 @@ var ReadTracker = class _ReadTracker {
7321
7250
  };
7322
7251
 
7323
7252
  // src/loop.ts
7324
- var ESCALATION_MODEL = "deepseek-v4-pro";
7325
7253
  var MID_TURN_STEER_WRAPPER = "[Mid-turn steer queued by the user. Do not treat this as a new task; use it only as additional guidance for the current task after completing the current step.]";
7326
7254
  function formatSteerUserMessage(content) {
7327
7255
  return [MID_TURN_STEER_WRAPPER, content].join("\n");
@@ -7341,7 +7269,6 @@ var CacheFirstLoop = class {
7341
7269
  model;
7342
7270
  stream;
7343
7271
  reasoningEffort;
7344
- autoEscalate = true;
7345
7272
  budgetUsd;
7346
7273
  /** One-shot 80% warning latch — cleared by setBudget so a bump re-arms at the new boundary. */
7347
7274
  _budgetWarned = false;
@@ -7357,6 +7284,7 @@ var CacheFirstLoop = class {
7357
7284
  _streamPreference;
7358
7285
  /** Threaded through HTTP + every tool dispatch so Esc cancels in-flight work, not after. */
7359
7286
  _turnAbort = new AbortController();
7287
+ _discardAbortRequested = false;
7360
7288
  /** Authoritative running-id set — UI cards consult this instead of trusting end-event delivery. Insert at dispatch entry, delete in finally. */
7361
7289
  _inflight = new InflightSet();
7362
7290
  /** Typeahead steer messages set by the UI; step() consumes one at each iter boundary. */
@@ -7377,8 +7305,6 @@ var CacheFirstLoop = class {
7377
7305
  get steerConsumed() {
7378
7306
  return this._steerConsumed;
7379
7307
  }
7380
- _proArmedForNextTurn = false;
7381
- _escalateThisTurn = false;
7382
7308
  _turnSelfCorrected = false;
7383
7309
  _foldedThisTurn = false;
7384
7310
  context;
@@ -7394,8 +7320,7 @@ var CacheFirstLoop = class {
7394
7320
  this.prefix = opts.prefix;
7395
7321
  this.tools = opts.tools ?? new ToolRegistry();
7396
7322
  this.model = opts.model ?? "deepseek-v4-flash";
7397
- this.reasoningEffort = opts.reasoningEffort ?? "max";
7398
- if (opts.autoEscalate !== void 0) this.autoEscalate = opts.autoEscalate;
7323
+ this.reasoningEffort = opts.reasoningEffort ?? "high";
7399
7324
  this.budgetUsd = typeof opts.budgetUsd === "number" && opts.budgetUsd > 0 ? opts.budgetUsd : null;
7400
7325
  this.hooks = opts.hooks ?? [];
7401
7326
  this.hookCwd = opts.hookCwd ?? process.cwd();
@@ -7435,6 +7360,7 @@ var CacheFirstLoop = class {
7435
7360
  turnCount: meta.turnCount,
7436
7361
  cacheHitTokens: meta.cacheHitTokens,
7437
7362
  cacheMissTokens: meta.cacheMissTokens,
7363
+ totalCompletionTokens: meta.totalCompletionTokens,
7438
7364
  lastPromptTokens: meta.lastPromptTokens
7439
7365
  });
7440
7366
  }
@@ -7552,35 +7478,15 @@ var CacheFirstLoop = class {
7552
7478
  this.stream = opts.stream;
7553
7479
  }
7554
7480
  if (opts.reasoningEffort !== void 0) this.reasoningEffort = opts.reasoningEffort;
7555
- if (opts.autoEscalate !== void 0) this.autoEscalate = opts.autoEscalate;
7556
7481
  }
7557
7482
  /** `null` disables the cap; any change re-arms the 80% warning. */
7558
7483
  setBudget(usd) {
7559
7484
  this.budgetUsd = typeof usd === "number" && usd > 0 ? usd : null;
7560
7485
  this._budgetWarned = false;
7561
7486
  }
7562
- /** Single-turn upgrade consumed at next step() distinct from `/preset max` (persistent). */
7563
- armProForNextTurn() {
7564
- this._proArmedForNextTurn = true;
7565
- }
7566
- /** Cancel `/pro` arming before the next turn starts. */
7567
- disarmPro() {
7568
- this._proArmedForNextTurn = false;
7569
- }
7570
- /** UI surface — true while `/pro` is queued but hasn't fired yet. */
7571
- get proArmed() {
7572
- return this._proArmedForNextTurn;
7573
- }
7574
- /** UI surface — true while the current turn is running on pro (armed or auto-escalated). */
7575
- get escalatedThisTurn() {
7576
- return this._escalateThisTurn;
7577
- }
7578
- /** UI surface — model id of the call about to run (or running) right now, including escalation. */
7487
+ /** UI surface model id of the call about to run (or running) right now. */
7579
7488
  get currentCallModel() {
7580
- return this.modelForCurrentCall();
7581
- }
7582
- modelForCurrentCall() {
7583
- return this._escalateThisTurn ? ESCALATION_MODEL : this.model;
7489
+ return this.model;
7584
7490
  }
7585
7491
  /** A call counts as mutating when its definition reports `readOnly !== true` and any dynamic `readOnlyCheck` doesn't override that for these args. */
7586
7492
  isMutating(call) {
@@ -7678,9 +7584,24 @@ ${reason}`
7678
7584
  }
7679
7585
  return healed.messages;
7680
7586
  }
7681
- abort() {
7587
+ abort(opts = {}) {
7588
+ if (opts.discardCurrentTurn) this._discardAbortRequested = true;
7682
7589
  this._turnAbort.abort();
7683
7590
  }
7591
+ resetAbortState() {
7592
+ this._turnAbort = new AbortController();
7593
+ this._discardAbortRequested = false;
7594
+ }
7595
+ discardLogFrom(index) {
7596
+ const preserved = this.log.entries.slice(0, index).map((m) => ({ ...m }));
7597
+ this.log.compactInPlace(preserved);
7598
+ if (this.sessionName) {
7599
+ try {
7600
+ rewriteSession(this.sessionName, preserved);
7601
+ } catch {
7602
+ }
7603
+ }
7604
+ }
7684
7605
  /** Drop the last user message + everything after; caller re-sends. Persists to session file. */
7685
7606
  retryLastUser() {
7686
7607
  const entries = this.log.entries;
@@ -7763,38 +7684,54 @@ ${reason}`
7763
7684
  this.scratch.reset();
7764
7685
  this.repair.resetStorm();
7765
7686
  this._turnSelfCorrected = false;
7766
- this._escalateThisTurn = false;
7767
7687
  this._foldedThisTurn = false;
7768
- let armedConsumed = false;
7769
- if (this._proArmedForNextTurn) {
7770
- this._escalateThisTurn = true;
7771
- this._proArmedForNextTurn = false;
7772
- armedConsumed = true;
7773
- }
7774
7688
  const carryAbort = this._turnAbort.signal.aborted;
7775
7689
  this._turnAbort = new AbortController();
7776
7690
  if (carryAbort) this._turnAbort.abort();
7777
7691
  const signal = this._turnAbort.signal;
7778
- if (armedConsumed) {
7779
- yield {
7780
- turn: this._turn,
7781
- role: "warning",
7782
- content: t("loop.proArmed")
7783
- };
7784
- }
7692
+ const turnStartLogIndex = this.log.length;
7785
7693
  this.appendAndPersist({ role: "user", content: userInput });
7786
7694
  const toolSpecs = this.prefix.tools();
7787
7695
  let rateLimitWarningShown = false;
7788
- for (let iter = 0; ; iter++) {
7789
- if (signal.aborted) {
7790
- try {
7696
+ {
7697
+ const turnStart = this.context.estimateTurnStart(
7698
+ this.buildMessages(),
7699
+ this.prefix.toolSpecs,
7700
+ this.model
7701
+ );
7702
+ if (turnStart.ratio > TURN_START_FOLD_THRESHOLD) {
7703
+ yield {
7704
+ turn: this._turn,
7705
+ role: "status",
7706
+ content: t("loop.turnStartFoldStatus")
7707
+ };
7708
+ const result = await this.context.fold(this.model, { requireTailBoundary: true });
7709
+ if (result.folded) {
7710
+ this._foldedThisTurn = true;
7791
7711
  yield {
7792
7712
  turn: this._turn,
7793
7713
  role: "warning",
7794
- content: t("loop.abortedAtIter", { iter })
7714
+ content: t("loop.turnStartFolded", {
7715
+ estimate: turnStart.estimateTokens.toLocaleString(),
7716
+ ctxMax: turnStart.ctxMax.toLocaleString(),
7717
+ pct: Math.round(turnStart.ratio * 100),
7718
+ beforeMessages: result.beforeMessages,
7719
+ afterMessages: result.afterMessages
7720
+ })
7795
7721
  };
7796
- const stoppedMsg = "[aborted by user (Esc) \u2014 no summary produced. Ask again or /retry when ready; prior tool output is still in the log.]";
7797
- this.appendAndPersist(buildSyntheticAssistantMessage(stoppedMsg, this.model));
7722
+ }
7723
+ }
7724
+ }
7725
+ for (let iter = 0; ; iter++) {
7726
+ if (signal.aborted) {
7727
+ try {
7728
+ const discardTurn = this._discardAbortRequested;
7729
+ const stoppedMsg = discardTurn ? "[aborted by user (Esc) \u2014 interrupted turn discarded. Ask again when ready.]" : "[aborted by user (Esc) \u2014 no summary produced. Ask again or /retry when ready; prior tool output is still in the log.]";
7730
+ if (discardTurn) {
7731
+ this.discardLogFrom(turnStartLogIndex);
7732
+ } else {
7733
+ this.appendAndPersist(buildSyntheticAssistantMessage(stoppedMsg, this.model));
7734
+ }
7798
7735
  yield {
7799
7736
  turn: this._turn,
7800
7737
  role: "assistant_final",
@@ -7803,7 +7740,7 @@ ${reason}`
7803
7740
  };
7804
7741
  yield { turn: this._turn, role: "done", content: stoppedMsg };
7805
7742
  } finally {
7806
- this._turnAbort = new AbortController();
7743
+ this.resetAbortState();
7807
7744
  }
7808
7745
  this._steerQueue.length = 0;
7809
7746
  return;
@@ -7830,51 +7767,6 @@ ${reason}`
7830
7767
  content: steer
7831
7768
  };
7832
7769
  }
7833
- {
7834
- const decision2 = this.context.decidePreflight(messages, this.prefix.toolSpecs, this.model);
7835
- if (decision2.needsAction) {
7836
- const { estimateTokens: estimate, estimateBytes, ctxMax } = decision2;
7837
- yield {
7838
- turn: this._turn,
7839
- role: "status",
7840
- content: t("loop.preflightTruncateStatus")
7841
- };
7842
- const result = this.context.mechanicalTruncate(this.model, {
7843
- allowEmpty: false
7844
- });
7845
- if (result.folded) {
7846
- messages = this.buildMessages();
7847
- const after = this.context.decidePreflight(messages, this.prefix.toolSpecs, this.model);
7848
- const stillFull = after.needsAction;
7849
- yield {
7850
- turn: this._turn,
7851
- role: "warning",
7852
- content: t(
7853
- stillFull ? "loop.preflightTruncatedStillFull" : "loop.preflightTruncated",
7854
- {
7855
- estimate: after.estimateTokens.toLocaleString(),
7856
- ctxMax: after.ctxMax.toLocaleString(),
7857
- pct: Math.round(after.estimateTokens / after.ctxMax * 100),
7858
- bodyKB: Math.round(after.estimateBytes / 1024).toLocaleString(),
7859
- beforeMessages: result.beforeMessages,
7860
- afterMessages: result.afterMessages
7861
- }
7862
- )
7863
- };
7864
- } else {
7865
- yield {
7866
- turn: this._turn,
7867
- role: "warning",
7868
- content: t("loop.preflightNoFold", {
7869
- estimate: estimate.toLocaleString(),
7870
- ctxMax: ctxMax.toLocaleString(),
7871
- pct: Math.round(estimate / ctxMax * 100),
7872
- bodyKB: Math.round(estimateBytes / 1024).toLocaleString()
7873
- })
7874
- };
7875
- }
7876
- }
7877
- }
7878
7770
  let assistantContent = "";
7879
7771
  let reasoningContent = "";
7880
7772
  let toolCalls = [];
@@ -7883,10 +7775,7 @@ ${reason}`
7883
7775
  if (this.stream) {
7884
7776
  const callBuf = /* @__PURE__ */ new Map();
7885
7777
  const readyIndices = /* @__PURE__ */ new Set();
7886
- const callModel = this.modelForCurrentCall();
7887
- const bufferForEscalation = this.autoEscalate && callModel !== ESCALATION_MODEL;
7888
- let escalationBuf = "";
7889
- let escalationBufFlushed = false;
7778
+ const callModel = this.model;
7890
7779
  for await (const chunk of this.client.stream({
7891
7780
  model: callModel,
7892
7781
  messages,
@@ -7906,27 +7795,11 @@ ${reason}`
7906
7795
  }
7907
7796
  if (chunk.contentDelta) {
7908
7797
  assistantContent += chunk.contentDelta;
7909
- if (bufferForEscalation && !escalationBufFlushed) {
7910
- escalationBuf += chunk.contentDelta;
7911
- if (isEscalationRequest(escalationBuf)) {
7912
- break;
7913
- }
7914
- if (escalationBuf.length >= NEEDS_PRO_BUFFER_CHARS || !looksLikePartialEscalationMarker(escalationBuf)) {
7915
- escalationBufFlushed = true;
7916
- yield {
7917
- turn: this._turn,
7918
- role: "assistant_delta",
7919
- content: escalationBuf
7920
- };
7921
- escalationBuf = "";
7922
- }
7923
- } else {
7924
- yield {
7925
- turn: this._turn,
7926
- role: "assistant_delta",
7927
- content: chunk.contentDelta
7928
- };
7929
- }
7798
+ yield {
7799
+ turn: this._turn,
7800
+ role: "assistant_delta",
7801
+ content: chunk.contentDelta
7802
+ };
7930
7803
  }
7931
7804
  if (chunk.toolCallDelta) {
7932
7805
  const d = chunk.toolCallDelta;
@@ -7958,17 +7831,8 @@ ${reason}`
7958
7831
  if (chunk.usage) usage = chunk.usage;
7959
7832
  }
7960
7833
  toolCalls = [...callBuf.values()];
7961
- if (bufferForEscalation && !escalationBufFlushed && escalationBuf.length > 0) {
7962
- if (!isEscalationRequest(escalationBuf)) {
7963
- yield {
7964
- turn: this._turn,
7965
- role: "assistant_delta",
7966
- content: escalationBuf
7967
- };
7968
- }
7969
- }
7970
7834
  } else {
7971
- const callModel = this.modelForCurrentCall();
7835
+ const callModel = this.model;
7972
7836
  const resp = await this.client.chat({
7973
7837
  model: callModel,
7974
7838
  messages,
@@ -7984,10 +7848,11 @@ ${reason}`
7984
7848
  }
7985
7849
  } catch (err) {
7986
7850
  if (signal.aborted) {
7851
+ if (this._discardAbortRequested) this.discardLogFrom(turnStartLogIndex);
7987
7852
  try {
7988
7853
  yield { turn: this._turn, role: "done", content: "" };
7989
7854
  } finally {
7990
- this._turnAbort = new AbortController();
7855
+ this.resetAbortState();
7991
7856
  }
7992
7857
  this._steerQueue.length = 0;
7993
7858
  return;
@@ -8002,27 +7867,20 @@ ${reason}`
8002
7867
  this._steerQueue.length = 0;
8003
7868
  return;
8004
7869
  }
8005
- if (this.autoEscalate && this.modelForCurrentCall() !== ESCALATION_MODEL && isEscalationRequest(assistantContent)) {
8006
- const { reason } = parseEscalationMarker(assistantContent);
8007
- this._escalateThisTurn = true;
8008
- const reasonSuffix = reason ? ` \u2014 ${reason}` : "";
8009
- yield {
8010
- turn: this._turn,
8011
- role: "warning",
8012
- content: t("loop.flashEscalation", { model: ESCALATION_MODEL, reasonSuffix })
8013
- };
8014
- assistantContent = "";
8015
- reasoningContent = "";
8016
- toolCalls = [];
8017
- usage = null;
8018
- iter--;
8019
- continue;
7870
+ const turnStats = this.stats.record(this._turn, this.model, usage ?? new Usage());
7871
+ if (this.sessionName) {
7872
+ try {
7873
+ const last = this.stats.turns.length > 0 ? this.stats.turns[this.stats.turns.length - 1] : null;
7874
+ patchSessionMeta(this.sessionName, {
7875
+ totalCostUsd: this.stats.totalCost,
7876
+ cacheHitTokens: this.stats.cumulativeCacheHitTokens,
7877
+ cacheMissTokens: this.stats.cumulativeCacheMissTokens,
7878
+ totalCompletionTokens: this.stats.cumulativeCompletionTokens,
7879
+ lastPromptTokens: last?.usage.promptTokens
7880
+ });
7881
+ } catch {
7882
+ }
8020
7883
  }
8021
- const turnStats = this.stats.record(
8022
- this._turn,
8023
- this.modelForCurrentCall(),
8024
- usage ?? new Usage()
8025
- );
8026
7884
  this.scratch.reasoning = reasoningContent || null;
8027
7885
  const { calls: repairedCalls, report } = this.repair.process(
8028
7886
  toolCalls,
@@ -8030,12 +7888,7 @@ ${reason}`
8030
7888
  assistantContent || null
8031
7889
  );
8032
7890
  this.appendAndPersist(
8033
- buildAssistantMessage(
8034
- assistantContent,
8035
- repairedCalls,
8036
- this.modelForCurrentCall(),
8037
- reasoningContent
8038
- )
7891
+ buildAssistantMessage(assistantContent, repairedCalls, this.model, reasoningContent)
8039
7892
  );
8040
7893
  yield {
8041
7894
  turn: this._turn,
@@ -8048,12 +7901,7 @@ ${reason}`
8048
7901
  if (allSuppressed && !this._turnSelfCorrected) {
8049
7902
  this._turnSelfCorrected = true;
8050
7903
  this.replaceTailAssistantMessage(
8051
- buildAssistantMessage(
8052
- assistantContent,
8053
- toolCalls,
8054
- this.modelForCurrentCall(),
8055
- reasoningContent
8056
- )
7904
+ buildAssistantMessage(assistantContent, toolCalls, this.model, reasoningContent)
8057
7905
  );
8058
7906
  for (const call of toolCalls) {
8059
7907
  this.appendAndPersist({
@@ -8066,6 +7914,7 @@ ${reason}`
8066
7914
  yield {
8067
7915
  turn: this._turn,
8068
7916
  role: "warning",
7917
+ severity: "low",
8069
7918
  content: t("loop.repeatToolCallWarning")
8070
7919
  };
8071
7920
  continue;
@@ -8076,6 +7925,7 @@ ${reason}`
8076
7925
  yield {
8077
7926
  turn: this._turn,
8078
7927
  role: "warning",
7928
+ severity: allSuppressed ? "high" : "low",
8079
7929
  content: `${phrase}${noteTail}`
8080
7930
  };
8081
7931
  }
@@ -8788,7 +8638,7 @@ import {
8788
8638
  unlinkSync as unlinkSync2,
8789
8639
  writeFileSync as writeFileSync4
8790
8640
  } from "fs";
8791
- import { homedir as homedir5 } from "os";
8641
+ import { homedir as homedir6 } from "os";
8792
8642
  import { join as join8, resolve as resolve5 } from "path";
8793
8643
 
8794
8644
  // src/frontmatter.ts
@@ -8849,7 +8699,7 @@ import {
8849
8699
  writeFileSync as writeFileSync3
8850
8700
  } from "fs";
8851
8701
  import { accessSync } from "fs";
8852
- import { homedir as homedir4 } from "os";
8702
+ import { homedir as homedir5 } from "os";
8853
8703
  import { dirname as dirname4, isAbsolute as isAbsolute3, join as join7, resolve as resolve4 } from "path";
8854
8704
 
8855
8705
  // src/prompt-fragments.ts
@@ -8895,19 +8745,24 @@ function parseAllowedTools(raw) {
8895
8745
  const names = raw.split(",").map((s) => s.trim()).filter(Boolean);
8896
8746
  return names.length > 0 ? Object.freeze(names) : void 0;
8897
8747
  }
8748
+ function subagentModelForPreset(preset) {
8749
+ return preset === "pro" ? "deepseek-v4-pro" : "deepseek-v4-flash";
8750
+ }
8898
8751
  var SkillStore = class {
8899
8752
  homeDir;
8900
8753
  projectRoot;
8901
8754
  customSkillPaths;
8902
8755
  disableBuiltins;
8756
+ subagentModels;
8903
8757
  constructor(opts = {}) {
8904
- this.homeDir = opts.homeDir ?? homedir4();
8758
+ this.homeDir = opts.homeDir ?? homedir5();
8905
8759
  this.projectRoot = opts.projectRoot ? resolve4(opts.projectRoot) : void 0;
8906
8760
  const baseDir = this.projectRoot ?? process.cwd();
8907
8761
  this.customSkillPaths = dedupePaths(
8908
8762
  opts.customSkillPaths?.map((p) => resolveCustomSkillPath(p, baseDir, this.homeDir)) ?? []
8909
8763
  );
8910
8764
  this.disableBuiltins = opts.disableBuiltins === true;
8765
+ this.subagentModels = opts.subagentModels ?? {};
8911
8766
  }
8912
8767
  /** True iff this store was configured with a project root. */
8913
8768
  hasProjectScope() {
@@ -8961,7 +8816,14 @@ var SkillStore = class {
8961
8816
  if (!byName.has(skill.name)) byName.set(skill.name, skill);
8962
8817
  }
8963
8818
  }
8964
- return [...byName.values()].sort((a, b) => a.name.localeCompare(b.name));
8819
+ return [...byName.values()].map((s) => this.applyModelOverride(s)).sort((a, b) => a.name.localeCompare(b.name));
8820
+ }
8821
+ /** Apply `subagentModels` config override on top of frontmatter `model:`. Inline skills are unaffected. */
8822
+ applyModelOverride(skill) {
8823
+ if (skill.runAs !== "subagent") return skill;
8824
+ const override = this.subagentModels[skill.name];
8825
+ if (!override) return skill;
8826
+ return { ...skill, model: subagentModelForPreset(override) };
8965
8827
  }
8966
8828
  /** Scaffold a new skill stub at the chosen scope. Refuses to overwrite. */
8967
8829
  create(name, scope) {
@@ -9390,7 +9252,7 @@ var MemoryStore = class {
9390
9252
  homeDir;
9391
9253
  projectRoot;
9392
9254
  constructor(opts = {}) {
9393
- this.homeDir = opts.homeDir ?? join8(homedir5(), ".reasonix");
9255
+ this.homeDir = opts.homeDir ?? join8(homedir6(), ".reasonix");
9394
9256
  this.projectRoot = opts.projectRoot ? resolve5(opts.projectRoot) : void 0;
9395
9257
  }
9396
9258
  /** Directory this store writes `scope` files into, creating it if needed. */
@@ -9542,7 +9404,7 @@ var MemoryStore = class {
9542
9404
  `, "utf8");
9543
9405
  }
9544
9406
  };
9545
- function readGlobalReasonixMemory(homeDir = join8(homedir5(), ".reasonix")) {
9407
+ function readGlobalReasonixMemory(homeDir = join8(homedir6(), ".reasonix")) {
9546
9408
  const path2 = join8(homeDir, "REASONIX.md");
9547
9409
  if (!existsSync7(path2)) return null;
9548
9410
  let raw;
@@ -9561,7 +9423,7 @@ function readGlobalReasonixMemory(homeDir = join8(homedir5(), ".reasonix")) {
9561
9423
  }
9562
9424
  function applyGlobalReasonixMemory(basePrompt, homeDir) {
9563
9425
  if (!memoryEnabled()) return basePrompt;
9564
- const dir = homeDir ?? join8(homedir5(), ".reasonix");
9426
+ const dir = homeDir ?? join8(homedir6(), ".reasonix");
9565
9427
  const mem = readGlobalReasonixMemory(dir);
9566
9428
  if (!mem) return basePrompt;
9567
9429
  return [
@@ -10199,7 +10061,7 @@ var RegexRunner = class {
10199
10061
  this.defaultTimeoutMs = opts.defaultTimeoutMs ?? DEFAULT_TIMEOUT_MS;
10200
10062
  }
10201
10063
  testLines(text, source, flags, opts = {}) {
10202
- return new Promise((resolve14, reject) => {
10064
+ return new Promise((resolve15, reject) => {
10203
10065
  if (opts.signal?.aborted) {
10204
10066
  reject(new Error("regex evaluation aborted"));
10205
10067
  return;
@@ -10212,7 +10074,7 @@ var RegexRunner = class {
10212
10074
  this.killWorker();
10213
10075
  reject(new Error(`regex evaluation exceeded ${timeoutMs}ms`));
10214
10076
  }, timeoutMs);
10215
- const entry = { resolve: resolve14, reject, timer };
10077
+ const entry = { resolve: resolve15, reject, timer };
10216
10078
  if (opts.signal) {
10217
10079
  entry.signal = opts.signal;
10218
10080
  entry.onAbort = () => {
@@ -12443,9 +12305,11 @@ var READY_SIGNALS = [
12443
12305
  // Generic
12444
12306
  /\bstartup (?:complete|finished)\b/i
12445
12307
  ];
12446
- var JobRegistry = class {
12308
+ var JobRegistry = class _JobRegistry {
12447
12309
  jobs = /* @__PURE__ */ new Map();
12448
12310
  nextId = 1;
12311
+ /** Max completed jobs to retain for list_jobs / job_output lookups. */
12312
+ static MAX_COMPLETED_JOBS = 20;
12449
12313
  /** Resolves on (a) ready signal, (b) early exit, or (c) waitSec deadline — child keeps running regardless. */
12450
12314
  async start(command, opts) {
12451
12315
  const trimmed = command.trim();
@@ -12581,6 +12445,7 @@ ${job.output.slice(start)}`;
12581
12445
  job.exitCode = code;
12582
12446
  job.signalReady();
12583
12447
  job.signalClosed();
12448
+ this.maybeCleanup();
12584
12449
  };
12585
12450
  child.on("exit", settleClosed);
12586
12451
  child.on("close", settleClosed);
@@ -12647,16 +12512,16 @@ ${job.output.slice(start)}`;
12647
12512
  let wakeOutput = null;
12648
12513
  if (waitFor === "output-or-exit") {
12649
12514
  racers.push(
12650
- new Promise((resolve14) => {
12651
- wakeOutput = resolve14;
12652
- job.outputWaiters.add(resolve14);
12515
+ new Promise((resolve15) => {
12516
+ wakeOutput = resolve15;
12517
+ job.outputWaiters.add(resolve15);
12653
12518
  })
12654
12519
  );
12655
12520
  }
12656
12521
  let timer = null;
12657
12522
  racers.push(
12658
- new Promise((resolve14) => {
12659
- timer = setTimeout(resolve14, timeoutMs);
12523
+ new Promise((resolve15) => {
12524
+ timer = setTimeout(resolve15, timeoutMs);
12660
12525
  })
12661
12526
  );
12662
12527
  await Promise.race(racers);
@@ -12743,6 +12608,19 @@ ${job.output.slice(start)}`;
12743
12608
  for (const job of this.jobs.values()) if (job.running) n++;
12744
12609
  return n;
12745
12610
  }
12611
+ /** Evict oldest completed jobs when the map exceeds MAX_COMPLETED_JOBS. */
12612
+ maybeCleanup() {
12613
+ const completed = [];
12614
+ for (const [id, job] of this.jobs) {
12615
+ if (!job.running) completed.push({ id, startedAt: job.startedAt });
12616
+ }
12617
+ if (completed.length <= _JobRegistry.MAX_COMPLETED_JOBS) return;
12618
+ completed.sort((a, b) => a.startedAt - b.startedAt);
12619
+ const toRemove = completed.length - _JobRegistry.MAX_COMPLETED_JOBS;
12620
+ for (let i = 0; i < toRemove; i++) {
12621
+ this.jobs.delete(completed[i].id);
12622
+ }
12623
+ }
12746
12624
  };
12747
12625
  function snapshot(job) {
12748
12626
  return {
@@ -13195,9 +13073,9 @@ async function runPipeGroup(segments, opts) {
13195
13073
  }
13196
13074
  const exits = await Promise.all(
13197
13075
  children.map(
13198
- (c) => new Promise((resolve14) => {
13199
- c.once("error", () => resolve14(null));
13200
- c.once("close", (code) => resolve14(code));
13076
+ (c) => new Promise((resolve15) => {
13077
+ c.once("error", () => resolve15(null));
13078
+ c.once("close", (code) => resolve15(code));
13201
13079
  })
13202
13080
  )
13203
13081
  );
@@ -13243,11 +13121,6 @@ var OutputBuffer = class {
13243
13121
  // src/tools/shell/parse.ts
13244
13122
  import { homedir as homedir7 } from "os";
13245
13123
  import * as pathMod9 from "path";
13246
-
13247
- // packages/core-utils/src/tildeify.ts
13248
- import { homedir as homedir6 } from "os";
13249
-
13250
- // src/tools/shell/parse.ts
13251
13124
  var BUILTIN_ALLOWLIST = [
13252
13125
  // Repo inspection
13253
13126
  "git status",
@@ -13625,7 +13498,7 @@ async function runCommand(cmd, opts) {
13625
13498
  };
13626
13499
  const { bin, args, spawnOverrides } = prepareSpawn(argv, { env: normalizedEnv });
13627
13500
  const effectiveSpawnOpts = { ...spawnOpts, ...spawnOverrides };
13628
- return await new Promise((resolve14, reject) => {
13501
+ return await new Promise((resolve15, reject) => {
13629
13502
  let child;
13630
13503
  try {
13631
13504
  child = spawn4(bin, args, effectiveSpawnOpts);
@@ -13679,7 +13552,7 @@ async function runCommand(cmd, opts) {
13679
13552
  const output = buf.length > maxChars ? `${buf.slice(0, maxChars)}
13680
13553
 
13681
13554
  [\u2026 truncated ${buf.length - maxChars} chars \u2026]` : buf;
13682
- resolve14({ exitCode: code, output, timedOut });
13555
+ resolve15({ exitCode: code, output, timedOut });
13683
13556
  });
13684
13557
  });
13685
13558
  }
@@ -15255,6 +15128,10 @@ function truncate(s, n) {
15255
15128
  return s.length > n ? `${s.slice(0, n)}\u2026` : s;
15256
15129
  }
15257
15130
 
15131
+ // src/mcp/client.ts
15132
+ import { basename as basename3, resolve as resolve13 } from "path";
15133
+ import { pathToFileURL } from "url";
15134
+
15258
15135
  // src/version.ts
15259
15136
  import { existsSync as existsSync10, mkdirSync as mkdirSync5, readFileSync as readFileSync14, writeFileSync as writeFileSync6 } from "fs";
15260
15137
  import { homedir as homedir8 } from "os";
@@ -15385,6 +15262,8 @@ function isJsonRpcError(msg) {
15385
15262
  var McpClient = class {
15386
15263
  transport;
15387
15264
  clientInfo;
15265
+ workspaceDir;
15266
+ workspaceRoot;
15388
15267
  requestTimeoutMs;
15389
15268
  pending = /* @__PURE__ */ new Map();
15390
15269
  nextId = 1;
@@ -15404,6 +15283,14 @@ var McpClient = class {
15404
15283
  constructor(opts) {
15405
15284
  this.transport = opts.transport;
15406
15285
  this.clientInfo = opts.clientInfo ?? { name: "reasonix", version: VERSION };
15286
+ const workspaceDir = opts.workspaceDir?.trim();
15287
+ if (workspaceDir) {
15288
+ this.workspaceDir = resolve13(workspaceDir);
15289
+ this.workspaceRoot = {
15290
+ uri: pathToFileURL(this.workspaceDir).href,
15291
+ name: basename3(this.workspaceDir) || this.workspaceDir
15292
+ };
15293
+ }
15407
15294
  this.requestTimeoutMs = opts.requestTimeoutMs ?? 6e4;
15408
15295
  }
15409
15296
  /** Server's advertised capabilities, available after initialize(). */
@@ -15422,24 +15309,29 @@ var McpClient = class {
15422
15309
  get serverInstructions() {
15423
15310
  return this._instructions;
15424
15311
  }
15312
+ get workspaceRootDir() {
15313
+ return this.workspaceDir;
15314
+ }
15425
15315
  /** Compliant servers reject other methods until this completes. */
15426
15316
  async initialize(opts = {}) {
15427
15317
  if (this.initialized) throw new Error("MCP client already initialized");
15428
15318
  this.startReaderIfNeeded();
15429
- const result = await this.request(
15430
- "initialize",
15431
- {
15432
- protocolVersion: MCP_PROTOCOL_VERSION,
15433
- // Advertise every method the client can consume so servers know
15434
- // they can send listChanged notifications etc. Sub-feature flags
15435
- // (e.g. `resources.subscribe`) are omitted — we don't implement
15436
- // those yet and the empty object means "method-level support, no
15437
- // sub-features."
15438
- capabilities: { tools: {}, resources: {}, prompts: {} },
15439
- clientInfo: this.clientInfo
15440
- },
15441
- opts.signal
15442
- );
15319
+ const capabilities = {
15320
+ tools: {},
15321
+ resources: {},
15322
+ prompts: {},
15323
+ ...this.workspaceRoot ? { roots: {} } : {}
15324
+ };
15325
+ const params = {
15326
+ protocolVersion: MCP_PROTOCOL_VERSION,
15327
+ capabilities,
15328
+ clientInfo: this.clientInfo,
15329
+ ...this.workspaceRoot ? {
15330
+ rootUri: this.workspaceRoot.uri,
15331
+ workspaceFolders: [this.workspaceRoot]
15332
+ } : {}
15333
+ };
15334
+ const result = await this.request("initialize", params, opts.signal);
15443
15335
  this._serverCapabilities = result.capabilities ?? {};
15444
15336
  this._serverInfo = result.serverInfo ?? { name: "", version: "" };
15445
15337
  this._protocolVersion = result.protocolVersion ?? "";
@@ -15516,7 +15408,7 @@ var McpClient = class {
15516
15408
  const id = this.nextId++;
15517
15409
  const frame = { jsonrpc: "2.0", id, method, params };
15518
15410
  let abortHandler = null;
15519
- const promise = new Promise((resolve14, reject) => {
15411
+ const promise = new Promise((resolve15, reject) => {
15520
15412
  const timeout = setTimeout(() => {
15521
15413
  this.pending.delete(id);
15522
15414
  if (abortHandler && signal) signal.removeEventListener("abort", abortHandler);
@@ -15525,7 +15417,7 @@ var McpClient = class {
15525
15417
  );
15526
15418
  }, this.requestTimeoutMs);
15527
15419
  this.pending.set(id, {
15528
- resolve: resolve14,
15420
+ resolve: resolve15,
15529
15421
  reject,
15530
15422
  timeout
15531
15423
  });
@@ -15599,7 +15491,10 @@ var McpClient = class {
15599
15491
  }
15600
15492
  return;
15601
15493
  }
15602
- if (!("result" in msg) && !("error" in msg)) return;
15494
+ if (!("result" in msg) && !("error" in msg)) {
15495
+ this.handleServerRequest(msg);
15496
+ return;
15497
+ }
15603
15498
  const pending = this.pending.get(msg.id);
15604
15499
  if (!pending) return;
15605
15500
  this.pending.delete(msg.id);
@@ -15611,6 +15506,21 @@ var McpClient = class {
15611
15506
  pending.resolve(resp.result);
15612
15507
  }
15613
15508
  }
15509
+ handleServerRequest(req) {
15510
+ if (req.method === "roots/list" && this.workspaceRoot) {
15511
+ void this.transport.send({
15512
+ jsonrpc: "2.0",
15513
+ id: req.id,
15514
+ result: { roots: [this.workspaceRoot] }
15515
+ }).catch(() => void 0);
15516
+ return;
15517
+ }
15518
+ void this.transport.send({
15519
+ jsonrpc: "2.0",
15520
+ id: req.id,
15521
+ error: { code: -32601, message: `method not found: ${req.method}` }
15522
+ }).catch(() => void 0);
15523
+ }
15614
15524
  };
15615
15525
 
15616
15526
  // src/mcp/stdio.ts
@@ -15657,12 +15567,12 @@ var StdioTransport = class {
15657
15567
  }
15658
15568
  async send(message) {
15659
15569
  if (this.closed) throw new Error("MCP transport is closed");
15660
- return new Promise((resolve14, reject) => {
15570
+ return new Promise((resolve15, reject) => {
15661
15571
  const line = `${JSON.stringify(message)}
15662
15572
  `;
15663
15573
  this.child.stdin.write(line, "utf8", (err) => {
15664
15574
  if (err) reject(err);
15665
- else resolve14();
15575
+ else resolve15();
15666
15576
  });
15667
15577
  });
15668
15578
  }
@@ -15673,8 +15583,8 @@ var StdioTransport = class {
15673
15583
  continue;
15674
15584
  }
15675
15585
  if (this.closed) return;
15676
- const next = await new Promise((resolve14) => {
15677
- this.waiters.push(resolve14);
15586
+ const next = await new Promise((resolve15) => {
15587
+ this.waiters.push(resolve15);
15678
15588
  });
15679
15589
  if (next === null) return;
15680
15590
  yield next;
@@ -15754,8 +15664,8 @@ var SseTransport = class {
15754
15664
  constructor(opts) {
15755
15665
  this.url = opts.url;
15756
15666
  this.headers = opts.headers ?? {};
15757
- this.endpointReady = new Promise((resolve14, reject) => {
15758
- this.resolveEndpoint = resolve14;
15667
+ this.endpointReady = new Promise((resolve15, reject) => {
15668
+ this.resolveEndpoint = resolve15;
15759
15669
  this.rejectEndpoint = reject;
15760
15670
  });
15761
15671
  this.endpointReady.catch(() => void 0);
@@ -15782,8 +15692,8 @@ var SseTransport = class {
15782
15692
  continue;
15783
15693
  }
15784
15694
  if (this.closed) return;
15785
- const next = await new Promise((resolve14) => {
15786
- this.waiters.push(resolve14);
15695
+ const next = await new Promise((resolve15) => {
15696
+ this.waiters.push(resolve15);
15787
15697
  });
15788
15698
  if (next === null) return;
15789
15699
  yield next;
@@ -15969,8 +15879,8 @@ var StreamableHttpTransport = class {
15969
15879
  continue;
15970
15880
  }
15971
15881
  if (this.closed) return;
15972
- const next = await new Promise((resolve14) => {
15973
- this.waiters.push(resolve14);
15882
+ const next = await new Promise((resolve15) => {
15883
+ this.waiters.push(resolve15);
15974
15884
  });
15975
15885
  if (next === null) return;
15976
15886
  yield next;
@@ -16074,7 +15984,7 @@ import {
16074
15984
  writeFileSync as writeFileSync7,
16075
15985
  writeSync
16076
15986
  } from "fs";
16077
- import { dirname as dirname9, isAbsolute as isAbsolute9, relative as relative10, resolve as resolve13 } from "path";
15987
+ import { dirname as dirname9, isAbsolute as isAbsolute9, relative as relative10, resolve as resolve14 } from "path";
16078
15988
  var BLOCK_RE = /^(\S[^\n]*)\n<{7} SEARCH\n([\s\S]*?)\n?={7}\n([\s\S]*?)\n?>{7} REPLACE/gm;
16079
15989
  function parseEditBlocks(text) {
16080
15990
  const out = [];
@@ -16092,15 +16002,15 @@ function parseEditBlocks(text) {
16092
16002
  return out;
16093
16003
  }
16094
16004
  function resolveEditPath(rootDir, rawPath) {
16095
- const absRoot = resolve13(rootDir);
16005
+ const absRoot = resolve14(rootDir);
16096
16006
  if (/^[A-Za-z]:[\\/]/.test(rawPath) || looksLikeAbsoluteSystemPath2(rawPath)) {
16097
- return resolve13(rawPath);
16007
+ return resolve14(rawPath);
16098
16008
  }
16099
16009
  let rooted = rawPath;
16100
16010
  while (rooted.startsWith("/") || rooted.startsWith("\\")) {
16101
16011
  rooted = rooted.slice(1);
16102
16012
  }
16103
- return resolve13(absRoot, rooted || ".");
16013
+ return resolve14(absRoot, rooted || ".");
16104
16014
  }
16105
16015
  function looksLikeAbsoluteSystemPath2(rawPath) {
16106
16016
  return /^\/(?:home|Users|etc|var|opt|tmp|usr|mnt|Library|Volumes|proc|sys|dev|run|srv|media|Applications|System|root|boot|private)(?:[/\\]|$)/.test(
@@ -16112,7 +16022,7 @@ function pathIsUnder4(child, parent) {
16112
16022
  return rel === "" || !rel.startsWith("..") && !isAbsolute9(rel);
16113
16023
  }
16114
16024
  function applyEditBlock(block, rootDir) {
16115
- const absRoot = resolve13(rootDir);
16025
+ const absRoot = resolve14(rootDir);
16116
16026
  const absTarget = resolveEditPath(rootDir, block.path);
16117
16027
  if (!pathIsUnder4(absTarget, absRoot)) {
16118
16028
  return {
@@ -16208,7 +16118,7 @@ function applyEditBlocks(blocks, rootDir) {
16208
16118
  return blocks.map((b) => applyEditBlock(b, rootDir));
16209
16119
  }
16210
16120
  function snapshotBeforeEdits(blocks, rootDir) {
16211
- const absRoot = resolve13(rootDir);
16121
+ const absRoot = resolve14(rootDir);
16212
16122
  const seen = /* @__PURE__ */ new Set();
16213
16123
  const snapshots = [];
16214
16124
  for (const b of blocks) {
@@ -16230,7 +16140,7 @@ function snapshotBeforeEdits(blocks, rootDir) {
16230
16140
  return snapshots;
16231
16141
  }
16232
16142
  function restoreSnapshots(snapshots, rootDir) {
16233
- const absRoot = resolve13(rootDir);
16143
+ const absRoot = resolve14(rootDir);
16234
16144
  return snapshots.map((snap) => {
16235
16145
  const abs = resolveEditPath(rootDir, snap.path);
16236
16146
  if (!pathIsUnder4(abs, absRoot)) {
@@ -16432,7 +16342,7 @@ ${appendParts.join("\n\n")}`;
16432
16342
 
16433
16343
  // src/telemetry/usage.ts
16434
16344
  import {
16435
- appendFileSync as appendFileSync3,
16345
+ appendFileSync as appendFileSync2,
16436
16346
  closeSync as closeSync3,
16437
16347
  existsSync as existsSync13,
16438
16348
  fstatSync as fstatSync2,
@@ -16514,7 +16424,7 @@ function appendUsage(input) {
16514
16424
  const path2 = input.path ?? defaultUsageLogPath();
16515
16425
  try {
16516
16426
  mkdirSync7(dirname10(path2), { recursive: true });
16517
- appendFileSync3(path2, `${JSON.stringify(record)}
16427
+ appendFileSync2(path2, `${JSON.stringify(record)}
16518
16428
  `, "utf8");
16519
16429
  compactUsageLogIfLarge(path2, record.ts);
16520
16430
  } catch {