@researai/deepscientist 1.5.16 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (896) hide show
  1. package/AGENTS.md +309 -130
  2. package/AISB/catalog/aisb.b1.agentic_coding.yaml +244 -0
  3. package/AISB/catalog/aisb.b10.climate_earth.yaml +235 -0
  4. package/AISB/catalog/aisb.b11.model_efficiency.yaml +231 -0
  5. package/AISB/catalog/aisb.b12.embodied_ai.yaml +238 -0
  6. package/AISB/catalog/aisb.b2.agent_systems.yaml +229 -0
  7. package/AISB/catalog/aisb.b3.self_evolving_rl.yaml +237 -0
  8. package/AISB/catalog/aisb.b4.lm_reasoning.yaml +240 -0
  9. package/AISB/catalog/aisb.b5.math_proof.yaml +235 -0
  10. package/AISB/catalog/aisb.b6.research_process.yaml +243 -0
  11. package/AISB/catalog/aisb.b7.multimodal_fusion.yaml +232 -0
  12. package/AISB/catalog/aisb.b8.lifesci_drug.yaml +275 -0
  13. package/AISB/catalog/aisb.b9.material_science.yaml +237 -0
  14. package/AISB/catalog/aisb.t3.001_savvy.yaml +159 -0
  15. package/AISB/catalog/aisb.t3.001_savvy.zh.yaml +121 -0
  16. package/AISB/catalog/aisb.t3.002_pinet.yaml +189 -0
  17. package/AISB/catalog/aisb.t3.002_pinet.zh.yaml +130 -0
  18. package/AISB/catalog/aisb.t3.004_decentralattn.yaml +184 -0
  19. package/AISB/catalog/aisb.t3.004_decentralattn.zh.yaml +153 -0
  20. package/AISB/catalog/aisb.t3.005_tsae.yaml +193 -0
  21. package/AISB/catalog/aisb.t3.005_tsae.zh.yaml +139 -0
  22. package/AISB/catalog/aisb.t3.006_physense.yaml +194 -0
  23. package/AISB/catalog/aisb.t3.006_physense.zh.yaml +118 -0
  24. package/AISB/catalog/aisb.t3.007_reasoningiqa.yaml +169 -0
  25. package/AISB/catalog/aisb.t3.007_reasoningiqa.zh.yaml +133 -0
  26. package/AISB/catalog/aisb.t3.008_meanflows.yaml +188 -0
  27. package/AISB/catalog/aisb.t3.008_meanflows.zh.yaml +140 -0
  28. package/AISB/catalog/aisb.t3.009_scoremissing.yaml +179 -0
  29. package/AISB/catalog/aisb.t3.009_scoremissing.zh.yaml +119 -0
  30. package/AISB/catalog/aisb.t3.010_suitabilityfilter.yaml +221 -0
  31. package/AISB/catalog/aisb.t3.010_suitabilityfilter.zh.yaml +141 -0
  32. package/AISB/catalog/aisb.t3.011_osd.yaml +206 -0
  33. package/AISB/catalog/aisb.t3.011_osd.zh.yaml +163 -0
  34. package/AISB/catalog/aisb.t3.012_efficientqat.yaml +206 -0
  35. package/AISB/catalog/aisb.t3.012_efficientqat.zh.yaml +159 -0
  36. package/AISB/catalog/aisb.t3.013_appl.yaml +152 -0
  37. package/AISB/catalog/aisb.t3.013_appl.zh.yaml +126 -0
  38. package/AISB/catalog/aisb.t3.014_piguard.yaml +207 -0
  39. package/AISB/catalog/aisb.t3.014_piguard.zh.yaml +164 -0
  40. package/AISB/catalog/aisb.t3.015_frspec.yaml +209 -0
  41. package/AISB/catalog/aisb.t3.015_frspec.zh.yaml +163 -0
  42. package/AISB/catalog/aisb.t3.016_mathfusion.yaml +166 -0
  43. package/AISB/catalog/aisb.t3.016_mathfusion.zh.yaml +145 -0
  44. package/AISB/catalog/aisb.t3.017_multimodalglp.yaml +171 -0
  45. package/AISB/catalog/aisb.t3.017_multimodalglp.zh.yaml +122 -0
  46. package/AISB/catalog/aisb.t3.018_cotsynth.yaml +206 -0
  47. package/AISB/catalog/aisb.t3.018_cotsynth.zh.yaml +162 -0
  48. package/AISB/catalog/aisb.t3.019_dyscaleut.yaml +211 -0
  49. package/AISB/catalog/aisb.t3.019_dyscaleut.zh.yaml +148 -0
  50. package/AISB/catalog/aisb.t3.020_aristotle.yaml +173 -0
  51. package/AISB/catalog/aisb.t3.020_aristotle.zh.yaml +119 -0
  52. package/AISB/catalog/aisb.t3.021_tokenrecycling.yaml +160 -0
  53. package/AISB/catalog/aisb.t3.021_tokenrecycling.zh.yaml +129 -0
  54. package/AISB/catalog/aisb.t3.022_chainofreasoning.yaml +204 -0
  55. package/AISB/catalog/aisb.t3.022_chainofreasoning.zh.yaml +161 -0
  56. package/AISB/catalog/aisb.t3.023_guidedembed.yaml +211 -0
  57. package/AISB/catalog/aisb.t3.023_guidedembed.zh.yaml +189 -0
  58. package/AISB/catalog/aisb.t3.024_outputcentric.yaml +148 -0
  59. package/AISB/catalog/aisb.t3.024_outputcentric.zh.yaml +131 -0
  60. package/AISB/catalog/aisb.t3.025_deeper.yaml +143 -0
  61. package/AISB/catalog/aisb.t3.025_deeper.zh.yaml +116 -0
  62. package/AISB/catalog/aisb.t3.026_gartkg.yaml +195 -0
  63. package/AISB/catalog/aisb.t3.026_gartkg.zh.yaml +127 -0
  64. package/AISB/catalog/aisb.t3.027_citeeval.yaml +182 -0
  65. package/AISB/catalog/aisb.t3.027_citeeval.zh.yaml +135 -0
  66. package/AISB/catalog/aisb.t3.028_sbam.yaml +206 -0
  67. package/AISB/catalog/aisb.t3.028_sbam.zh.yaml +166 -0
  68. package/AISB/catalog/aisb.t3.029_cdqgeoembed.yaml +224 -0
  69. package/AISB/catalog/aisb.t3.029_cdqgeoembed.zh.yaml +142 -0
  70. package/AISB/catalog/aisb.t3.030_processrm.yaml +211 -0
  71. package/AISB/catalog/aisb.t3.030_processrm.zh.yaml +166 -0
  72. package/AISB/catalog/aisb.t3.031_circuitstability.yaml +172 -0
  73. package/AISB/catalog/aisb.t3.031_circuitstability.zh.yaml +134 -0
  74. package/AISB/catalog/aisb.t3.032_ptsolver.yaml +169 -0
  75. package/AISB/catalog/aisb.t3.032_ptsolver.zh.yaml +135 -0
  76. package/AISB/catalog/aisb.t3.033_gcse.yaml +144 -0
  77. package/AISB/catalog/aisb.t3.033_gcse.zh.yaml +126 -0
  78. package/AISB/catalog/aisb.t3.034_ensemblewm.yaml +183 -0
  79. package/AISB/catalog/aisb.t3.034_ensemblewm.zh.yaml +146 -0
  80. package/AISB/catalog/aisb.t3.035_moralvalueswa.yaml +207 -0
  81. package/AISB/catalog/aisb.t3.035_moralvalueswa.zh.yaml +165 -0
  82. package/AISB/catalog/aisb.t3.036_weakstrongpref.yaml +210 -0
  83. package/AISB/catalog/aisb.t3.036_weakstrongpref.zh.yaml +194 -0
  84. package/AISB/catalog/aisb.t3.037_dementiamask.yaml +172 -0
  85. package/AISB/catalog/aisb.t3.037_dementiamask.zh.yaml +132 -0
  86. package/AISB/catalog/aisb.t3.038_tinysam.yaml +284 -0
  87. package/AISB/catalog/aisb.t3.038_tinysam.zh.yaml +240 -0
  88. package/AISB/catalog/aisb.t3.039_calf.yaml +224 -0
  89. package/AISB/catalog/aisb.t3.039_calf.zh.yaml +194 -0
  90. package/AISB/catalog/aisb.t3.040_graniteguardian.yaml +199 -0
  91. package/AISB/catalog/aisb.t3.040_graniteguardian.zh.yaml +174 -0
  92. package/AISB/catalog/aisb.t3.041_amdm.yaml +149 -0
  93. package/AISB/catalog/aisb.t3.041_amdm.zh.yaml +137 -0
  94. package/AISB/catalog/aisb.t3.042_xpatch.yaml +216 -0
  95. package/AISB/catalog/aisb.t3.042_xpatch.zh.yaml +182 -0
  96. package/AISB/catalog/aisb.t3.043_vhm.yaml +268 -0
  97. package/AISB/catalog/aisb.t3.043_vhm.zh.yaml +193 -0
  98. package/AISB/catalog/aisb.t3.044_rgvi.yaml +224 -0
  99. package/AISB/catalog/aisb.t3.044_rgvi.zh.yaml +176 -0
  100. package/AISB/catalog/aisb.t3.045_pslstm.yaml +203 -0
  101. package/AISB/catalog/aisb.t3.045_pslstm.zh.yaml +179 -0
  102. package/AISB/catalog/aisb.t3.046_nonstatts.yaml +208 -0
  103. package/AISB/catalog/aisb.t3.046_nonstatts.zh.yaml +194 -0
  104. package/AISB/catalog/aisb.t3.047_timepfn.yaml +156 -0
  105. package/AISB/catalog/aisb.t3.047_timepfn.zh.yaml +124 -0
  106. package/AISB/catalog/aisb.t3.048_proxyspex.yaml +148 -0
  107. package/AISB/catalog/aisb.t3.048_proxyspex.zh.yaml +125 -0
  108. package/AISB/catalog/aisb.t3.049_hogwildinference.yaml +183 -0
  109. package/AISB/catalog/aisb.t3.049_hogwildinference.zh.yaml +138 -0
  110. package/AISB/catalog/aisb.t3.050_causalpfn.yaml +214 -0
  111. package/AISB/catalog/aisb.t3.050_causalpfn.zh.yaml +190 -0
  112. package/AISB/catalog/aisb.t3.051_flashtp.yaml +169 -0
  113. package/AISB/catalog/aisb.t3.051_flashtp.zh.yaml +124 -0
  114. package/AISB/catalog/aisb.t3.052_nsdiff.yaml +155 -0
  115. package/AISB/catalog/aisb.t3.052_nsdiff.zh.yaml +138 -0
  116. package/AISB/catalog/aisb.t3.053_k2vae.yaml +158 -0
  117. package/AISB/catalog/aisb.t3.053_k2vae.zh.yaml +132 -0
  118. package/AISB/catalog/aisb.t3.054_timebase.yaml +178 -0
  119. package/AISB/catalog/aisb.t3.054_timebase.zh.yaml +158 -0
  120. package/AISB/catalog/aisb.t3.055_csbrain.yaml +238 -0
  121. package/AISB/catalog/aisb.t3.055_csbrain.zh.yaml +184 -0
  122. package/AISB/catalog/aisb.t3.056_infosam.yaml +224 -0
  123. package/AISB/catalog/aisb.t3.056_infosam.zh.yaml +189 -0
  124. package/AISB/catalog/aisb.t3.057_mdreid.yaml +129 -0
  125. package/AISB/catalog/aisb.t3.057_mdreid.zh.yaml +117 -0
  126. package/AISB/catalog/aisb.t3.058_mindglitch.yaml +171 -0
  127. package/AISB/catalog/aisb.t3.058_mindglitch.zh.yaml +145 -0
  128. package/AISB/catalog/aisb.t3.059_selfsupervised.yaml +154 -0
  129. package/AISB/catalog/aisb.t3.059_selfsupervised.zh.yaml +125 -0
  130. package/AISB/catalog/aisb.t3.060_iaggad.yaml +121 -0
  131. package/AISB/catalog/aisb.t3.060_iaggad.zh.yaml +100 -0
  132. package/AISB/catalog/aisb.t3.061_hsgkn.yaml +136 -0
  133. package/AISB/catalog/aisb.t3.061_hsgkn.zh.yaml +113 -0
  134. package/AISB/catalog/aisb.t3.062_visionts.yaml +237 -0
  135. package/AISB/catalog/aisb.t3.062_visionts.zh.yaml +216 -0
  136. package/AISB/catalog/aisb.t3.063_tsrag.yaml +162 -0
  137. package/AISB/catalog/aisb.t3.063_tsrag.zh.yaml +138 -0
  138. package/AISB/catalog/aisb.t3.064_pir.yaml +221 -0
  139. package/AISB/catalog/aisb.t3.064_pir.zh.yaml +197 -0
  140. package/AISB/catalog/aisb.t3.065_proteinbinding.yaml +234 -0
  141. package/AISB/catalog/aisb.t3.065_proteinbinding.zh.yaml +167 -0
  142. package/AISB/catalog/aisb.t3.066_tropicalattention.yaml +267 -0
  143. package/AISB/catalog/aisb.t3.066_tropicalattention.zh.yaml +229 -0
  144. package/AISB/catalog/aisb.t3.067_kanad.yaml +193 -0
  145. package/AISB/catalog/aisb.t3.067_kanad.zh.yaml +167 -0
  146. package/AISB/catalog/aisb.t3.068_sempo.yaml +187 -0
  147. package/AISB/catalog/aisb.t3.068_sempo.zh.yaml +148 -0
  148. package/AISB/catalog/aisb.t3.069_treehfd.yaml +129 -0
  149. package/AISB/catalog/aisb.t3.069_treehfd.zh.yaml +111 -0
  150. package/AISB/catalog/aisb.t3.070_certifiedunlearning.yaml +224 -0
  151. package/AISB/catalog/aisb.t3.070_certifiedunlearning.zh.yaml +171 -0
  152. package/AISB/catalog/aisb.t3.071_neuralmjd.yaml +142 -0
  153. package/AISB/catalog/aisb.t3.071_neuralmjd.zh.yaml +120 -0
  154. package/AISB/catalog/aisb.t3.072_fedgmt.yaml +181 -0
  155. package/AISB/catalog/aisb.t3.072_fedgmt.zh.yaml +158 -0
  156. package/AISB/catalog/aisb.t3.073_rld.yaml +161 -0
  157. package/AISB/catalog/aisb.t3.073_rld.zh.yaml +129 -0
  158. package/AISB/catalog/aisb.t3.074_lsvi.yaml +163 -0
  159. package/AISB/catalog/aisb.t3.074_lsvi.zh.yaml +129 -0
  160. package/AISB/catalog/aisb.t3.075_treeslicedentropy.yaml +201 -0
  161. package/AISB/catalog/aisb.t3.075_treeslicedentropy.zh.yaml +148 -0
  162. package/AISB/catalog/aisb.t3.076_aanet.yaml +169 -0
  163. package/AISB/catalog/aisb.t3.076_aanet.zh.yaml +129 -0
  164. package/AISB/catalog/aisb.t3.077_cmnn.yaml +199 -0
  165. package/AISB/catalog/aisb.t3.077_cmnn.zh.yaml +165 -0
  166. package/AISB/catalog/aisb.t3.078_conformalanomaly.yaml +146 -0
  167. package/AISB/catalog/aisb.t3.078_conformalanomaly.zh.yaml +117 -0
  168. package/AISB/catalog/aisb.t3.079_dpfkmeans.yaml +131 -0
  169. package/AISB/catalog/aisb.t3.079_dpfkmeans.zh.yaml +104 -0
  170. package/AISB/catalog/aisb.t3.080_latentscorereweight.yaml +169 -0
  171. package/AISB/catalog/aisb.t3.080_latentscorereweight.zh.yaml +123 -0
  172. package/AISB/catalog/aisb.t3.081_qmamba.yaml +150 -0
  173. package/AISB/catalog/aisb.t3.081_qmamba.zh.yaml +117 -0
  174. package/AISB/catalog/aisb.t3.082_onlinellmrouting.yaml +160 -0
  175. package/AISB/catalog/aisb.t3.082_onlinellmrouting.zh.yaml +133 -0
  176. package/AISB/catalog/aisb.t3.083_starformer.yaml +178 -0
  177. package/AISB/catalog/aisb.t3.083_starformer.zh.yaml +140 -0
  178. package/AISB/catalog/aisb.t3.084_ift.yaml +139 -0
  179. package/AISB/catalog/aisb.t3.084_ift.zh.yaml +111 -0
  180. package/AISB/catalog/aisb.t3.085_neuralsurv.yaml +183 -0
  181. package/AISB/catalog/aisb.t3.085_neuralsurv.zh.yaml +143 -0
  182. package/AISB/catalog/aisb.t3.086_stella.yaml +197 -0
  183. package/AISB/catalog/aisb.t3.086_stella.zh.yaml +142 -0
  184. package/AISB/catalog/aisb.t3.087_moses.yaml +167 -0
  185. package/AISB/catalog/aisb.t3.087_moses.zh.yaml +132 -0
  186. package/AISB/catalog/aisb.t3.088_channelnorm.yaml +140 -0
  187. package/AISB/catalog/aisb.t3.088_channelnorm.zh.yaml +109 -0
  188. package/AISB/catalog/aisb.t3.089_causalvelocity.yaml +730 -0
  189. package/AISB/catalog/aisb.t3.089_causalvelocity.zh.yaml +668 -0
  190. package/AISB/catalog/aisb.t3.090_rstib.yaml +144 -0
  191. package/AISB/catalog/aisb.t3.090_rstib.zh.yaml +109 -0
  192. package/AISB/catalog/aisb.t3.091_timeawarecausal.yaml +132 -0
  193. package/AISB/catalog/aisb.t3.091_timeawarecausal.zh.yaml +107 -0
  194. package/AISB/catalog/aisb.t3.092_kmeanslocalopt.yaml +138 -0
  195. package/AISB/catalog/aisb.t3.092_kmeanslocalopt.zh.yaml +110 -0
  196. package/AISB/catalog/aisb.t3.093_fedwmsam.yaml +134 -0
  197. package/AISB/catalog/aisb.t3.093_fedwmsam.zh.yaml +106 -0
  198. package/AISB/catalog/aisb.t3.094_boundre.yaml +147 -0
  199. package/AISB/catalog/aisb.t3.094_boundre.zh.yaml +114 -0
  200. package/AISB/catalog/aisb.t3.095_fastfeaturecp.yaml +153 -0
  201. package/AISB/catalog/aisb.t3.095_fastfeaturecp.zh.yaml +118 -0
  202. package/AISB/catalog/aisb.t3.096_m3svm.yaml +189 -0
  203. package/AISB/catalog/aisb.t3.096_m3svm.zh.yaml +149 -0
  204. package/AISB/catalog/aisb.t3.097_wassersteintl.yaml +212 -0
  205. package/AISB/catalog/aisb.t3.097_wassersteintl.zh.yaml +169 -0
  206. package/AISB/catalog/aisb.t3.098_xmahalanobis.yaml +171 -0
  207. package/AISB/catalog/aisb.t3.098_xmahalanobis.zh.yaml +127 -0
  208. package/AISB/catalog/aisb.t3.099_ollalanding.yaml +248 -0
  209. package/AISB/catalog/aisb.t3.099_ollalanding.zh.yaml +182 -0
  210. package/AISB/catalog/aisb.t3.100_invmissingdata.yaml +179 -0
  211. package/AISB/catalog/aisb.t3.100_invmissingdata.zh.yaml +150 -0
  212. package/AISB/catalog/aisb.t3.101_acia.yaml +164 -0
  213. package/AISB/catalog/aisb.t3.101_acia.zh.yaml +109 -0
  214. package/AISB/catalog/aisb.t3.102_stochasticff.yaml +178 -0
  215. package/AISB/catalog/aisb.t3.102_stochasticff.zh.yaml +130 -0
  216. package/AISB/catalog/aisb.t3.103_qdcp.yaml +150 -0
  217. package/AISB/catalog/aisb.t3.103_qdcp.zh.yaml +116 -0
  218. package/AISB/catalog/aisb.t3.104_balancedactiveinf.yaml +137 -0
  219. package/AISB/catalog/aisb.t3.104_balancedactiveinf.zh.yaml +104 -0
  220. package/AISB/catalog/aisb.t3.105_binaryclasseval.yaml +161 -0
  221. package/AISB/catalog/aisb.t3.105_binaryclasseval.zh.yaml +130 -0
  222. package/AISB/image/001_aisb.t3.001_savvy.jpg +0 -0
  223. package/AISB/image/002_aisb.t3.002_pinet.jpg +0 -0
  224. package/AISB/image/003_aisb.t3.003_dmsqd.jpg +0 -0
  225. package/AISB/image/004_aisb.t3.004_decentralattn.jpg +0 -0
  226. package/AISB/image/005_aisb.t3.005_tsae.jpg +0 -0
  227. package/AISB/image/006_aisb.t3.006_physense.jpg +0 -0
  228. package/AISB/image/007_aisb.t3.007_reasoningiqa.jpg +0 -0
  229. package/AISB/image/008_aisb.t3.008_meanflows.jpg +0 -0
  230. package/AISB/image/009_aisb.t3.009_scoremissing.jpg +0 -0
  231. package/AISB/image/010_aisb.t3.010_suitabilityfilter.jpg +0 -0
  232. package/AISB/image/011_aisb.t3.011_osd.jpg +0 -0
  233. package/AISB/image/012_aisb.t3.012_efficientqat.jpg +0 -0
  234. package/AISB/image/013_aisb.t3.013_appl.jpg +0 -0
  235. package/AISB/image/014_aisb.t3.014_piguard.jpg +0 -0
  236. package/AISB/image/015_aisb.t3.015_frspec.jpg +0 -0
  237. package/AISB/image/016_aisb.t3.016_mathfusion.jpg +0 -0
  238. package/AISB/image/017_aisb.t3.017_multimodalglp.jpg +0 -0
  239. package/AISB/image/018_aisb.t3.018_cotsynth.jpg +0 -0
  240. package/AISB/image/019_aisb.t3.019_dyscaleut.jpg +0 -0
  241. package/AISB/image/020_aisb.t3.020_aristotle.jpg +0 -0
  242. package/AISB/image/021_aisb.t3.021_tokenrecycling.jpg +0 -0
  243. package/AISB/image/022_aisb.t3.022_chainofreasoning.jpg +0 -0
  244. package/AISB/image/023_aisb.t3.023_guidedembed.jpg +0 -0
  245. package/AISB/image/024_aisb.t3.024_outputcentric.jpg +0 -0
  246. package/AISB/image/025_aisb.t3.025_deeper.jpg +0 -0
  247. package/AISB/image/026_aisb.t3.026_gartkg.jpg +0 -0
  248. package/AISB/image/027_aisb.t3.027_citeeval.jpg +0 -0
  249. package/AISB/image/028_aisb.t3.028_sbam.jpg +0 -0
  250. package/AISB/image/029_aisb.t3.029_cdqgeoembed.jpg +0 -0
  251. package/AISB/image/030_aisb.t3.030_processrm.jpg +0 -0
  252. package/AISB/image/031_aisb.t3.031_circuitstability.jpg +0 -0
  253. package/AISB/image/032_aisb.t3.032_ptsolver.jpg +0 -0
  254. package/AISB/image/033_aisb.t3.033_gcse.jpg +0 -0
  255. package/AISB/image/034_aisb.t3.034_ensemblewm.jpg +0 -0
  256. package/AISB/image/035_aisb.t3.035_moralvalueswa.jpg +0 -0
  257. package/AISB/image/036_aisb.t3.036_weakstrongpref.jpg +0 -0
  258. package/AISB/image/037_aisb.t3.037_dementiamask.jpg +0 -0
  259. package/AISB/image/038_aisb.t3.038_tinysam.jpg +0 -0
  260. package/AISB/image/039_aisb.t3.039_calf.jpg +0 -0
  261. package/AISB/image/040_aisb.t3.040_graniteguardian.jpg +0 -0
  262. package/AISB/image/041_aisb.t3.041_amdm.jpg +0 -0
  263. package/AISB/image/042_aisb.t3.042_xpatch.jpg +0 -0
  264. package/AISB/image/043_aisb.t3.043_vhm.jpg +0 -0
  265. package/AISB/image/044_aisb.t3.044_rgvi.jpg +0 -0
  266. package/AISB/image/045_aisb.t3.045_pslstm.jpg +0 -0
  267. package/AISB/image/046_aisb.t3.046_nonstatts.jpg +0 -0
  268. package/AISB/image/047_aisb.t3.047_timepfn.jpg +0 -0
  269. package/AISB/image/048_aisb.t3.048_proxyspex.jpg +0 -0
  270. package/AISB/image/049_aisb.t3.049_hogwildinference.jpg +0 -0
  271. package/AISB/image/050_aisb.t3.050_causalpfn.jpg +0 -0
  272. package/AISB/image/051_aisb.t3.051_flashtp.jpg +0 -0
  273. package/AISB/image/052_aisb.t3.052_nsdiff.jpg +0 -0
  274. package/AISB/image/053_aisb.t3.053_k2vae.jpg +0 -0
  275. package/AISB/image/054_aisb.t3.054_timebase.jpg +0 -0
  276. package/AISB/image/055_aisb.t3.055_csbrain.jpg +0 -0
  277. package/AISB/image/056_aisb.t3.056_infosam.jpg +0 -0
  278. package/AISB/image/057_aisb.t3.057_mdreid.jpg +0 -0
  279. package/AISB/image/058_aisb.t3.058_mindglitch.jpg +0 -0
  280. package/AISB/image/059_aisb.t3.059_selfsupervised.jpg +0 -0
  281. package/AISB/image/060_aisb.t3.060_iaggad.jpg +0 -0
  282. package/AISB/image/061_aisb.t3.061_hsgkn.jpg +0 -0
  283. package/AISB/image/062_aisb.t3.062_visionts.jpg +0 -0
  284. package/AISB/image/063_aisb.t3.063_tsrag.jpg +0 -0
  285. package/AISB/image/064_aisb.t3.064_pir.jpg +0 -0
  286. package/AISB/image/065_aisb.t3.065_proteinbinding.jpg +0 -0
  287. package/AISB/image/066_aisb.t3.066_tropicalattention.jpg +0 -0
  288. package/AISB/image/067_aisb.t3.067_kanad.jpg +0 -0
  289. package/AISB/image/068_aisb.t3.068_sempo.jpg +0 -0
  290. package/AISB/image/069_aisb.t3.069_treehfd.jpg +0 -0
  291. package/AISB/image/070_aisb.t3.070_certifiedunlearning.jpg +0 -0
  292. package/AISB/image/071_aisb.t3.071_neuralmjd.jpg +0 -0
  293. package/AISB/image/072_aisb.t3.072_fedgmt.jpg +0 -0
  294. package/AISB/image/073_aisb.t3.073_rld.jpg +0 -0
  295. package/AISB/image/074_aisb.t3.074_lsvi.jpg +0 -0
  296. package/AISB/image/075_aisb.t3.075_treeslicedentropy.jpg +0 -0
  297. package/AISB/image/076_aisb.t3.076_aanet.jpg +0 -0
  298. package/AISB/image/077_aisb.t3.077_cmnn.jpg +0 -0
  299. package/AISB/image/078_aisb.t3.078_conformalanomaly.jpg +0 -0
  300. package/AISB/image/079_aisb.t3.079_dpfkmeans.jpg +0 -0
  301. package/AISB/image/080_aisb.t3.080_latentscorereweight.jpg +0 -0
  302. package/AISB/image/081_aisb.t3.081_qmamba.jpg +0 -0
  303. package/AISB/image/082_aisb.t3.082_onlinellmrouting.jpg +0 -0
  304. package/AISB/image/083_aisb.t3.083_starformer.jpg +0 -0
  305. package/AISB/image/084_aisb.t3.084_ift.jpg +0 -0
  306. package/AISB/image/085_aisb.t3.085_neuralsurv.jpg +0 -0
  307. package/AISB/image/086_aisb.t3.086_stella.jpg +0 -0
  308. package/AISB/image/087_aisb.t3.087_moses.jpg +0 -0
  309. package/AISB/image/088_aisb.t3.088_channelnorm.jpg +0 -0
  310. package/AISB/image/089_aisb.t3.089_causalvelocity.jpg +0 -0
  311. package/AISB/image/090_aisb.t3.090_rstib.jpg +0 -0
  312. package/AISB/image/091_aisb.t3.091_timeawarecausal.jpg +0 -0
  313. package/AISB/image/092_aisb.t3.092_kmeanslocalopt.jpg +0 -0
  314. package/AISB/image/093_aisb.t3.093_fedwmsam.jpg +0 -0
  315. package/AISB/image/094_aisb.t3.094_boundre.jpg +0 -0
  316. package/AISB/image/095_aisb.t3.095_fastfeaturecp.jpg +0 -0
  317. package/AISB/image/096_aisb.t3.096_m3svm.jpg +0 -0
  318. package/AISB/image/097_aisb.t3.097_wassersteintl.jpg +0 -0
  319. package/AISB/image/098_aisb.t3.098_xmahalanobis.jpg +0 -0
  320. package/AISB/image/099_aisb.t3.099_ollalanding.jpg +0 -0
  321. package/AISB/image/100_aisb.t3.100_invmissingdata.jpg +0 -0
  322. package/AISB/image/101_aisb.t3.101_acia.jpg +0 -0
  323. package/AISB/image/102_aisb.t3.102_stochasticff.jpg +0 -0
  324. package/AISB/image/103_aisb.t3.103_qdcp.jpg +0 -0
  325. package/AISB/image/104_aisb.t3.104_balancedactiveinf.jpg +0 -0
  326. package/AISB/image/105_aisb.t3.105_binaryclasseval.jpg +0 -0
  327. package/AISB/image/106_aisb.t1.reasoning_lite.jpg +0 -0
  328. package/AISB/image/107_aisb.t2.paper_audit.jpg +0 -0
  329. package/AISB/image/108_aisb.t3.multi_gpu_search.jpg +0 -0
  330. package/AISB/image/109_aisb.t3.tdc_admet.jpg +0 -0
  331. package/AISB/image/aisb.b1.agentic_coding.svg +16 -0
  332. package/AISB/image/aisb.b10.climate_earth.svg +16 -0
  333. package/AISB/image/aisb.b11.model_efficiency.svg +16 -0
  334. package/AISB/image/aisb.b12.embodied_ai.svg +16 -0
  335. package/AISB/image/aisb.b2.agent_systems.svg +16 -0
  336. package/AISB/image/aisb.b3.self_evolving_rl.svg +16 -0
  337. package/AISB/image/aisb.b4.lm_reasoning.svg +16 -0
  338. package/AISB/image/aisb.b5.math_proof.svg +16 -0
  339. package/AISB/image/aisb.b6.research_process.svg +16 -0
  340. package/AISB/image/aisb.b7.multimodal_fusion.svg +16 -0
  341. package/AISB/image/aisb.b8.lifesci_drug.svg +16 -0
  342. package/AISB/image/aisb.b9.material_science.svg +16 -0
  343. package/README.md +196 -32
  344. package/bin/ds.js +924 -66
  345. package/docs/en/00_QUICK_START.md +195 -18
  346. package/docs/en/01_SETTINGS_REFERENCE.md +468 -96
  347. package/docs/en/02_START_RESEARCH_GUIDE.md +26 -5
  348. package/docs/en/03_QQ_CONNECTOR_GUIDE.md +14 -3
  349. package/docs/en/04_LINGZHU_CONNECTOR_GUIDE.md +2 -0
  350. package/docs/en/05_TUI_GUIDE.md +171 -2
  351. package/docs/en/07_MEMORY_AND_MCP.md +38 -2
  352. package/docs/en/09_DOCTOR.md +78 -7
  353. package/docs/en/10_WEIXIN_CONNECTOR_GUIDE.md +38 -1
  354. package/docs/en/11_LICENSE_AND_RISK.md +4 -0
  355. package/docs/en/12_GUIDED_WORKFLOW_TOUR.md +15 -0
  356. package/docs/en/14_PROMPT_SKILLS_AND_MCP_GUIDE.md +9 -0
  357. package/docs/en/15_CODEX_PROVIDER_SETUP.md +624 -180
  358. package/docs/en/16_TELEGRAM_CONNECTOR_GUIDE.md +14 -0
  359. package/docs/en/17_WHATSAPP_CONNECTOR_GUIDE.md +14 -0
  360. package/docs/en/18_FEISHU_CONNECTOR_GUIDE.md +14 -0
  361. package/docs/en/21_LOCAL_MODEL_BACKENDS_GUIDE.md +386 -0
  362. package/docs/en/22_BENCHSTORE_YAML_REFERENCE.md +469 -0
  363. package/docs/en/23_BENCHSTORE_GITHUB_RELEASES_SPEC.md +316 -0
  364. package/docs/en/24_CLAUDE_CODE_PROVIDER_SETUP.md +469 -0
  365. package/docs/en/25_OPENCODE_PROVIDER_SETUP.md +653 -0
  366. package/docs/en/26_CITATION_AND_ATTRIBUTION.md +119 -0
  367. package/docs/en/27_KIMI_CODE_PROVIDER_SETUP.md +180 -0
  368. package/docs/en/28_DISCORD_CONNECTOR_GUIDE.md +61 -0
  369. package/docs/en/29_SLACK_CONNECTOR_GUIDE.md +60 -0
  370. package/docs/en/30_SETTINGS_CONTROL_CENTER_GUIDE.md +371 -0
  371. package/docs/en/{19_LOCAL_BROWSER_AUTH.md → 31_LOCAL_BROWSER_AUTH.md} +1 -1
  372. package/docs/en/32_WINDOWS_WSL2_DEPLOYMENT_GUIDE.md +273 -0
  373. package/docs/en/33_WORKSPACE_EXPLORER_QA.md +121 -0
  374. package/docs/en/91_DEVELOPMENT.md +266 -0
  375. package/docs/en/99_ACKNOWLEDGEMENTS.md +24 -19
  376. package/docs/en/README.md +48 -7
  377. package/docs/images/admin/admin-connectors-health-en.png +0 -0
  378. package/docs/images/admin/admin-controllers-en.png +0 -0
  379. package/docs/images/admin/admin-diagnostics-en.png +0 -0
  380. package/docs/images/admin/admin-errors-en.png +0 -0
  381. package/docs/images/admin/admin-issues-en.png +0 -0
  382. package/docs/images/admin/admin-logs-en.png +0 -0
  383. package/docs/images/admin/admin-quest-detail-en.png +0 -0
  384. package/docs/images/admin/admin-quests-en.png +0 -0
  385. package/docs/images/admin/admin-repairs-en.png +0 -0
  386. package/docs/images/admin/admin-runtime-en.png +0 -0
  387. package/docs/images/admin/admin-search-en.png +0 -0
  388. package/docs/images/admin/admin-stats-en.png +0 -0
  389. package/docs/images/admin/admin-summary-en.png +0 -0
  390. package/docs/images/connectors/connector-discord-en.png +0 -0
  391. package/docs/images/connectors/connector-feishu-en.png +0 -0
  392. package/docs/images/connectors/connector-lingzhu-en.png +0 -0
  393. package/docs/images/connectors/connector-qq-en.png +0 -0
  394. package/docs/images/connectors/connector-slack-en.png +0 -0
  395. package/docs/images/connectors/connector-telegram-en.png +0 -0
  396. package/docs/images/connectors/connector-weixin-en.png +0 -0
  397. package/docs/images/connectors/connector-whatsapp-en.png +0 -0
  398. package/docs/images/settings/settings-baselines-en.png +0 -0
  399. package/docs/images/settings/settings-config-en.png +0 -0
  400. package/docs/images/settings/settings-connectors-overview-en.png +0 -0
  401. package/docs/images/settings/settings-deepxiv-en.png +0 -0
  402. package/docs/images/settings/settings-mcp-servers-en.png +0 -0
  403. package/docs/images/settings/settings-plugins-en.png +0 -0
  404. package/docs/images/settings/settings-runners-en.png +0 -0
  405. package/docs/zh/00_QUICK_START.md +142 -18
  406. package/docs/zh/01_SETTINGS_REFERENCE.md +219 -98
  407. package/docs/zh/02_START_RESEARCH_GUIDE.md +26 -5
  408. package/docs/zh/05_TUI_GUIDE.md +171 -2
  409. package/docs/zh/07_MEMORY_AND_MCP.md +29 -2
  410. package/docs/zh/09_DOCTOR.md +54 -8
  411. package/docs/zh/10_WEIXIN_CONNECTOR_GUIDE.md +24 -1
  412. package/docs/zh/11_LICENSE_AND_RISK.md +4 -0
  413. package/docs/zh/12_GUIDED_WORKFLOW_TOUR.md +15 -0
  414. package/docs/zh/14_PROMPT_SKILLS_AND_MCP_GUIDE.md +9 -0
  415. package/docs/zh/15_CODEX_PROVIDER_SETUP.md +552 -181
  416. package/docs/zh/21_LOCAL_MODEL_BACKENDS_GUIDE.md +384 -0
  417. package/docs/zh/22_BENCHSTORE_YAML_REFERENCE.md +459 -0
  418. package/docs/zh/23_BENCHSTORE_GITHUB_RELEASES_SPEC.md +287 -0
  419. package/docs/zh/23_CLAUDE_RUNNER_GUIDE.md +103 -0
  420. package/docs/zh/24_CLAUDE_CODE_PROVIDER_SETUP.md +460 -0
  421. package/docs/zh/25_OPENCODE_PROVIDER_SETUP.md +660 -0
  422. package/docs/zh/26_CITATION_AND_ATTRIBUTION.md +102 -0
  423. package/docs/zh/27_KIMI_CODE_PROVIDER_SETUP.md +51 -0
  424. package/docs/zh/{19_LOCAL_BROWSER_AUTH.md → 31_LOCAL_BROWSER_AUTH.md} +1 -1
  425. package/docs/zh/32_WINDOWS_WSL2_DEPLOYMENT_GUIDE.md +264 -0
  426. package/docs/zh/33_WORKSPACE_EXPLORER_QA.md +127 -0
  427. package/docs/zh/99_ACKNOWLEDGEMENTS.md +23 -19
  428. package/docs/zh/README.md +33 -7
  429. package/install.sh +168 -20
  430. package/package.json +5 -1
  431. package/pyproject.toml +2 -1
  432. package/src/deepscientist/__init__.py +1 -1
  433. package/src/deepscientist/acp/envelope.py +13 -0
  434. package/src/deepscientist/admin/__init__.py +3 -0
  435. package/src/deepscientist/admin/charts.py +681 -0
  436. package/src/deepscientist/admin/logs.py +119 -0
  437. package/src/deepscientist/admin/repairs.py +217 -0
  438. package/src/deepscientist/admin/service.py +1310 -0
  439. package/src/deepscientist/admin/system_info.py +700 -0
  440. package/src/deepscientist/admin/tasks.py +465 -0
  441. package/src/deepscientist/admin/tool_metrics.py +600 -0
  442. package/src/deepscientist/artifact/guidance.py +8 -4
  443. package/src/deepscientist/artifact/schemas.py +115 -0
  444. package/src/deepscientist/artifact/service.py +4268 -260
  445. package/src/deepscientist/bash_exec/monitor.py +30 -3
  446. package/src/deepscientist/bash_exec/service.py +134 -1
  447. package/src/deepscientist/benchstore/__init__.py +4 -0
  448. package/src/deepscientist/benchstore/prompt_builder.py +224 -0
  449. package/src/deepscientist/benchstore/service.py +1716 -0
  450. package/src/deepscientist/bridges/connectors.py +8 -2
  451. package/src/deepscientist/channels/weixin_ilink.py +8 -1
  452. package/src/deepscientist/cli.py +92 -17
  453. package/src/deepscientist/codex_cli_compat.py +187 -74
  454. package/src/deepscientist/config/models.py +82 -11
  455. package/src/deepscientist/config/service.py +1077 -93
  456. package/src/deepscientist/connector/weixin_support.py +48 -17
  457. package/src/deepscientist/daemon/api/handlers.py +827 -235
  458. package/src/deepscientist/daemon/api/router.py +81 -1
  459. package/src/deepscientist/daemon/app.py +1512 -85
  460. package/src/deepscientist/diagnostics/__init__.py +6 -0
  461. package/src/deepscientist/diagnostics/runner_failures.py +277 -0
  462. package/src/deepscientist/doctor.py +407 -56
  463. package/src/deepscientist/evidence_packets.py +590 -0
  464. package/src/deepscientist/home.py +52 -4
  465. package/src/deepscientist/kimi_cli_compat.py +50 -0
  466. package/src/deepscientist/latex_runtime.py +2 -2
  467. package/src/deepscientist/mcp/context.py +2 -0
  468. package/src/deepscientist/mcp/schemas.py +114 -0
  469. package/src/deepscientist/mcp/server.py +1566 -126
  470. package/src/deepscientist/memory/service.py +203 -16
  471. package/src/deepscientist/process_control.py +8 -1
  472. package/src/deepscientist/prompts/builder.py +850 -88
  473. package/src/deepscientist/quest/__init__.py +2 -2
  474. package/src/deepscientist/quest/layout.py +12 -1
  475. package/src/deepscientist/quest/node_traces.py +10 -0
  476. package/src/deepscientist/quest/service.py +1852 -161
  477. package/src/deepscientist/quest/stage_views.py +1 -1
  478. package/src/deepscientist/runners/__init__.py +18 -0
  479. package/src/deepscientist/runners/base.py +89 -1
  480. package/src/deepscientist/runners/builtins.py +13 -1
  481. package/src/deepscientist/runners/claude.py +391 -0
  482. package/src/deepscientist/runners/codex.py +480 -35
  483. package/src/deepscientist/runners/codex_telemetry.py +127 -0
  484. package/src/deepscientist/runners/kimi.py +334 -0
  485. package/src/deepscientist/runners/metadata.py +68 -0
  486. package/src/deepscientist/runners/opencode.py +414 -0
  487. package/src/deepscientist/runners/runtime_overrides.py +100 -0
  488. package/src/deepscientist/runners/simple_cli.py +538 -0
  489. package/src/deepscientist/runtime_storage.py +303 -0
  490. package/src/deepscientist/shared.py +80 -16
  491. package/src/deepscientist/skills/installer.py +37 -0
  492. package/src/deepscientist/skills/registry.py +2 -0
  493. package/src/deepscientist/tinytex.py +2 -2
  494. package/src/deepscientist/tui.py +10 -3
  495. package/src/prompts/benchstore/system.md +77 -0
  496. package/src/prompts/connectors/qq.md +33 -2
  497. package/src/prompts/connectors/weixin.md +208 -23
  498. package/src/prompts/contracts/admin_ops.md +74 -0
  499. package/src/prompts/contracts/admin_ops_knowledge.md +138 -0
  500. package/src/prompts/contracts/shared_interaction.md +5 -10
  501. package/src/prompts/start_setup/system.md +422 -0
  502. package/src/prompts/system.md +411 -304
  503. package/src/prompts/system_copilot.md +89 -0
  504. package/src/skills/analysis-campaign/SKILL.md +239 -578
  505. package/src/skills/analysis-campaign/references/artifact-flow-examples.md +102 -0
  506. package/src/skills/analysis-campaign/references/boundary-cases.md +98 -0
  507. package/src/skills/analysis-campaign/references/campaign-checklist-template.md +39 -24
  508. package/src/skills/analysis-campaign/references/campaign-design.md +26 -10
  509. package/src/skills/analysis-campaign/references/campaign-plan-template.md +53 -54
  510. package/src/skills/analysis-campaign/references/operational-guidance.md +97 -0
  511. package/src/skills/analysis-campaign/references/writing-facing-slice-examples.md +10 -20
  512. package/src/skills/baseline/SKILL.md +183 -461
  513. package/src/skills/baseline/references/artifact-flow-examples.md +106 -0
  514. package/src/skills/baseline/references/artifact-payload-examples.md +1 -1
  515. package/src/skills/baseline/references/baseline-checklist-template.md +27 -35
  516. package/src/skills/baseline/references/baseline-plan-template.md +37 -76
  517. package/src/skills/baseline/references/boundary-cases.md +86 -0
  518. package/src/skills/baseline/references/codebase-audit-checklist.md +2 -6
  519. package/src/skills/baseline/references/comparability-contract.md +7 -12
  520. package/src/skills/baseline/references/operational-guidance.md +56 -0
  521. package/src/skills/baseline/references/route-selection.md +5 -25
  522. package/src/skills/decision/SKILL.md +113 -306
  523. package/src/skills/decision/references/checkpoint-memory-template.md +47 -0
  524. package/src/skills/decision/references/operational-guidance.md +94 -0
  525. package/src/skills/decision/references/research-route-criteria.md +7 -8
  526. package/src/skills/decision/references/strategic-decision-template.md +13 -26
  527. package/src/skills/experiment/SKILL.md +132 -670
  528. package/src/skills/experiment/references/execution-playbook.md +374 -0
  529. package/src/skills/experiment/references/main-experiment-checklist-template.md +26 -2
  530. package/src/skills/experiment/references/main-experiment-plan-template.md +28 -17
  531. package/src/skills/experiment/references/operational-guidance.md +108 -0
  532. package/src/skills/finalize/SKILL.md +62 -0
  533. package/src/skills/finalize/references/checkpoint-memory-template.md +49 -0
  534. package/src/skills/finalize/references/resume-packet-template.md +7 -0
  535. package/src/skills/idea/SKILL.md +228 -15
  536. package/src/skills/idea/references/controlled-brainstorming-playbook.md +78 -0
  537. package/src/skills/idea/references/current-board-packet-template.md +61 -0
  538. package/src/skills/idea/references/high-value-idea-sourcing.md +119 -0
  539. package/src/skills/idea/references/idea-generation-playbook.md +21 -0
  540. package/src/skills/idea/references/idea-thinking-flow.md +6 -0
  541. package/src/skills/idea/references/literature-survey-template.md +3 -0
  542. package/src/skills/idea/references/objective-contract-template.md +54 -0
  543. package/src/skills/idea/references/outline-seeding-example.md +56 -0
  544. package/src/skills/idea/references/pre-idea-draft-template.md +105 -0
  545. package/src/skills/idea/references/related-work-playbook.md +75 -2
  546. package/src/skills/idea/references/research-history-playbook.md +114 -0
  547. package/src/skills/idea/references/selection-gate.md +58 -6
  548. package/src/skills/intake-audit/SKILL.md +43 -2
  549. package/src/skills/intake-audit/references/state-audit-template.md +10 -0
  550. package/src/skills/nature-data/SKILL.md +128 -0
  551. package/src/skills/nature-data/UPSTREAM_LICENSE.txt +21 -0
  552. package/src/skills/nature-data/agents/openai.yaml +4 -0
  553. package/src/skills/nature-data/references/chinese-author-alignment.md +84 -0
  554. package/src/skills/nature-data/references/fair-metadata-checklist.md +105 -0
  555. package/src/skills/nature-data/references/policy-principles.md +103 -0
  556. package/src/skills/nature-data/references/repository-and-identifiers.md +96 -0
  557. package/src/skills/nature-data/references/source-basis.md +54 -0
  558. package/src/skills/nature-data/references/statement-patterns.md +153 -0
  559. package/src/skills/nature-figure/SKILL.md +197 -0
  560. package/src/skills/nature-figure/UPSTREAM_LICENSE.txt +21 -0
  561. package/src/skills/nature-figure/agents/openai.yaml +4 -0
  562. package/src/skills/nature-figure/evals/evals.json +37 -0
  563. package/src/skills/nature-figure/references/api.md +428 -0
  564. package/src/skills/nature-figure/references/backend-selection.md +100 -0
  565. package/src/skills/nature-figure/references/chart-types.md +281 -0
  566. package/src/skills/nature-figure/references/common-patterns.md +349 -0
  567. package/src/skills/nature-figure/references/design-theory.md +436 -0
  568. package/src/skills/nature-figure/references/figure-contract.md +93 -0
  569. package/src/skills/nature-figure/references/nature-2026-observations.md +112 -0
  570. package/src/skills/nature-figure/references/qa-contract.md +119 -0
  571. package/src/skills/nature-figure/references/r-template-index.md +66 -0
  572. package/src/skills/nature-figure/references/r-workflow.md +161 -0
  573. package/src/skills/nature-figure/references/tutorials.md +250 -0
  574. package/src/skills/nature-paper2ppt/SKILL.md +507 -0
  575. package/src/skills/nature-paper2ppt/UPSTREAM_LICENSE.txt +21 -0
  576. package/src/skills/nature-paper2ppt/agents/openai.yaml +4 -0
  577. package/src/skills/nature-polishing/SKILL.md +385 -0
  578. package/src/skills/nature-polishing/UPSTREAM_LICENSE.txt +21 -0
  579. package/src/skills/nature-polishing/agents/openai.yaml +4 -0
  580. package/src/skills/nature-polishing/references/phrasebank-playbook.md +162 -0
  581. package/src/skills/nature-polishing/references/section-moves.md +240 -0
  582. package/src/skills/nature-polishing/references/style-guardrails.md +94 -0
  583. package/src/skills/nature-polishing/references/writing-strategy.md +148 -0
  584. package/src/skills/optimize/SKILL.md +177 -1568
  585. package/src/skills/optimize/references/brief-shaping-playbook.md +95 -0
  586. package/src/skills/optimize/references/candidate-board-template.md +13 -0
  587. package/src/skills/optimize/references/candidate-ranking-template.md +51 -0
  588. package/src/skills/optimize/references/codegen-route-playbook.md +50 -0
  589. package/src/skills/optimize/references/debug-response-template.md +29 -0
  590. package/src/skills/optimize/references/frontier-review-template.md +32 -0
  591. package/src/skills/optimize/references/fusion-playbook.md +36 -0
  592. package/src/skills/optimize/references/method-brief-template.md +73 -0
  593. package/src/skills/optimize/references/operational-guidance.md +621 -0
  594. package/src/skills/optimize/references/optimization-memory-template.md +30 -0
  595. package/src/skills/optimize/references/optimize-checklist-template.md +18 -0
  596. package/src/skills/optimize/references/plateau-response-playbook.md +28 -0
  597. package/src/skills/optimize/references/prompt-patterns.md +49 -0
  598. package/src/skills/paper-outline/SKILL.md +227 -0
  599. package/src/skills/paper-outline/references/outline-patterns.md +87 -0
  600. package/src/skills/paper-plot/SKILL.md +79 -0
  601. package/src/skills/paper-plot/agents/openai.yaml +4 -0
  602. package/src/skills/paper-plot/references/bar_grouped_hatch.md +96 -0
  603. package/src/skills/paper-plot/references/bar_paired_delta.md +72 -0
  604. package/src/skills/paper-plot/references/line_confidence_band.md +75 -0
  605. package/src/skills/paper-plot/references/line_loss_with_inset.md +65 -0
  606. package/src/skills/paper-plot/references/line_training_curve.md +44 -0
  607. package/src/skills/paper-plot/references/radar_dual_series.md +59 -0
  608. package/src/skills/paper-plot/references/scatter_broken_axis.md +59 -0
  609. package/src/skills/paper-plot/references/scatter_tsne_cluster.md +72 -0
  610. package/src/skills/paper-plot/scripts/bar_memevolve.py +109 -0
  611. package/src/skills/paper-plot/scripts/bar_spice.py +166 -0
  612. package/src/skills/paper-plot/scripts/line_aime.py +94 -0
  613. package/src/skills/paper-plot/scripts/line_loss_inset.py +157 -0
  614. package/src/skills/paper-plot/scripts/line_selfdistill.py +168 -0
  615. package/src/skills/paper-plot/scripts/radar_dora.py +151 -0
  616. package/src/skills/paper-plot/scripts/scatter_break.py +169 -0
  617. package/src/skills/paper-plot/scripts/scatter_tsne.py +133 -0
  618. package/src/skills/rebuttal/SKILL.md +9 -0
  619. package/src/skills/references/tool-usage-by-stage.md +438 -0
  620. package/src/skills/review/SKILL.md +105 -7
  621. package/src/skills/science/PROVENANCE.md +44 -0
  622. package/src/skills/science/SKILL.md +137 -0
  623. package/src/skills/science/references/artifact-science-tool.md +110 -0
  624. package/src/skills/science/references/claim-type-discipline.md +56 -0
  625. package/src/skills/science/references/domain-index.md +422 -0
  626. package/src/skills/science/references/hpc-via-bash-exec.md +42 -0
  627. package/src/skills/science/references/package-check-playbook.md +64 -0
  628. package/src/skills/science/references/package-index.min.json +3616 -0
  629. package/src/skills/science/references/packages/abinit.md +80 -0
  630. package/src/skills/science/references/packages/acts.md +73 -0
  631. package/src/skills/science/references/packages/aiida-core.md +80 -0
  632. package/src/skills/science/references/packages/alamode.md +80 -0
  633. package/src/skills/science/references/packages/amuse.md +88 -0
  634. package/src/skills/science/references/packages/anndata.md +88 -0
  635. package/src/skills/science/references/packages/arbor.md +80 -0
  636. package/src/skills/science/references/packages/arc.md +73 -0
  637. package/src/skills/science/references/packages/astropy.md +88 -0
  638. package/src/skills/science/references/packages/astroquery.md +88 -0
  639. package/src/skills/science/references/packages/atomate2.md +80 -0
  640. package/src/skills/science/references/packages/atomsmltr.md +73 -0
  641. package/src/skills/science/references/packages/awkward.md +73 -0
  642. package/src/skills/science/references/packages/batman.md +88 -0
  643. package/src/skills/science/references/packages/biopython.md +88 -0
  644. package/src/skills/science/references/packages/bloqade.md +73 -0
  645. package/src/skills/science/references/packages/brian2.md +73 -0
  646. package/src/skills/science/references/packages/bullet3.md +73 -0
  647. package/src/skills/science/references/packages/calculix.md +80 -0
  648. package/src/skills/science/references/packages/cantera.md +73 -0
  649. package/src/skills/science/references/packages/cavity-md-ipi.md +80 -0
  650. package/src/skills/science/references/packages/ccdproc.md +88 -0
  651. package/src/skills/science/references/packages/celerite2.md +88 -0
  652. package/src/skills/science/references/packages/cellrank.md +73 -0
  653. package/src/skills/science/references/packages/cesm.md +80 -0
  654. package/src/skills/science/references/packages/chemicals.md +73 -0
  655. package/src/skills/science/references/packages/chempy.md +73 -0
  656. package/src/skills/science/references/packages/cirq.md +73 -0
  657. package/src/skills/science/references/packages/coffea.md +73 -0
  658. package/src/skills/science/references/packages/cp2k.md +88 -0
  659. package/src/skills/science/references/packages/custodian.md +80 -0
  660. package/src/skills/science/references/packages/dart.md +73 -0
  661. package/src/skills/science/references/packages/datamol.md +88 -0
  662. package/src/skills/science/references/packages/dd4hep.md +73 -0
  663. package/src/skills/science/references/packages/dealii.md +80 -0
  664. package/src/skills/science/references/packages/deepchem.md +88 -0
  665. package/src/skills/science/references/packages/delphes.md +73 -0
  666. package/src/skills/science/references/packages/devito.md +80 -0
  667. package/src/skills/science/references/packages/dftb.md +88 -0
  668. package/src/skills/science/references/packages/dftd4.md +88 -0
  669. package/src/skills/science/references/packages/dftk-jl.md +80 -0
  670. package/src/skills/science/references/packages/dolfinx.md +80 -0
  671. package/src/skills/science/references/packages/drake.md +73 -0
  672. package/src/skills/science/references/packages/dumux.md +73 -0
  673. package/src/skills/science/references/packages/elk.md +80 -0
  674. package/src/skills/science/references/packages/elmerfem.md +80 -0
  675. package/src/skills/science/references/packages/enzo-e.md +88 -0
  676. package/src/skills/science/references/packages/espresso.md +80 -0
  677. package/src/skills/science/references/packages/exoplanet.md +88 -0
  678. package/src/skills/science/references/packages/fairroot.md +73 -0
  679. package/src/skills/science/references/packages/fbpic.md +80 -0
  680. package/src/skills/science/references/packages/fdtdbath-meep.md +80 -0
  681. package/src/skills/science/references/packages/geant4.md +73 -0
  682. package/src/skills/science/references/packages/geosx.md +80 -0
  683. package/src/skills/science/references/packages/gprmax.md +80 -0
  684. package/src/skills/science/references/packages/gromacs.md +80 -0
  685. package/src/skills/science/references/packages/gwaslab.md +73 -0
  686. package/src/skills/science/references/packages/gz-sim.md +73 -0
  687. package/src/skills/science/references/packages/hail.md +88 -0
  688. package/src/skills/science/references/packages/hiphive.md +80 -0
  689. package/src/skills/science/references/packages/hoomd-blue.md +80 -0
  690. package/src/skills/science/references/packages/itensor.md +73 -0
  691. package/src/skills/science/references/packages/itensors-jl.md +73 -0
  692. package/src/skills/science/references/packages/jdftx.md +73 -0
  693. package/src/skills/science/references/packages/jobflow.md +80 -0
  694. package/src/skills/science/references/packages/kadanoffbaym-jl.md +73 -0
  695. package/src/skills/science/references/packages/kite.md +80 -0
  696. package/src/skills/science/references/packages/kratos.md +80 -0
  697. package/src/skills/science/references/packages/kwant.md +73 -0
  698. package/src/skills/science/references/packages/lammps.md +80 -0
  699. package/src/skills/science/references/packages/lightkurve.md +88 -0
  700. package/src/skills/science/references/packages/limix.md +73 -0
  701. package/src/skills/science/references/packages/maxwelllink.md +80 -0
  702. package/src/skills/science/references/packages/mcdc.md +73 -0
  703. package/src/skills/science/references/packages/meep.md +80 -0
  704. package/src/skills/science/references/packages/mfem.md +80 -0
  705. package/src/skills/science/references/packages/mitgcm.md +73 -0
  706. package/src/skills/science/references/packages/modflow6.md +73 -0
  707. package/src/skills/science/references/packages/molecool.md +73 -0
  708. package/src/skills/science/references/packages/mom6.md +73 -0
  709. package/src/skills/science/references/packages/moose.md +80 -0
  710. package/src/skills/science/references/packages/mpas-model.md +73 -0
  711. package/src/skills/science/references/packages/mujoco.md +73 -0
  712. package/src/skills/science/references/packages/mumax3.md +73 -0
  713. package/src/skills/science/references/packages/nekrs.md +80 -0
  714. package/src/skills/science/references/packages/nessi.md +73 -0
  715. package/src/skills/science/references/packages/nest-simulator.md +73 -0
  716. package/src/skills/science/references/packages/netket.md +73 -0
  717. package/src/skills/science/references/packages/neuron.md +73 -0
  718. package/src/skills/science/references/packages/nextflow.md +88 -0
  719. package/src/skills/science/references/packages/nwchem.md +88 -0
  720. package/src/skills/science/references/packages/openbabel.md +88 -0
  721. package/src/skills/science/references/packages/openems.md +80 -0
  722. package/src/skills/science/references/packages/openff-toolkit.md +88 -0
  723. package/src/skills/science/references/packages/openfoam-dev.md +80 -0
  724. package/src/skills/science/references/packages/openmc.md +73 -0
  725. package/src/skills/science/references/packages/openmm.md +80 -0
  726. package/src/skills/science/references/packages/openmoc.md +73 -0
  727. package/src/skills/science/references/packages/openmx.md +80 -0
  728. package/src/skills/science/references/packages/opensees.md +80 -0
  729. package/src/skills/science/references/packages/opensn.md +80 -0
  730. package/src/skills/science/references/packages/opm-simulators.md +73 -0
  731. package/src/skills/science/references/packages/oqupy.md +73 -0
  732. package/src/skills/science/references/packages/packmol.md +80 -0
  733. package/src/skills/science/references/packages/palabos.md +80 -0
  734. package/src/skills/science/references/packages/parflow.md +80 -0
  735. package/src/skills/science/references/packages/pennylane.md +88 -0
  736. package/src/skills/science/references/packages/perceval.md +73 -0
  737. package/src/skills/science/references/packages/phono3py.md +73 -0
  738. package/src/skills/science/references/packages/phonopy.md +73 -0
  739. package/src/skills/science/references/packages/photutils.md +88 -0
  740. package/src/skills/science/references/packages/picongpu.md +80 -0
  741. package/src/skills/science/references/packages/plink-ng.md +88 -0
  742. package/src/skills/science/references/packages/precice.md +73 -0
  743. package/src/skills/science/references/packages/psc.md +80 -0
  744. package/src/skills/science/references/packages/psi4.md +88 -0
  745. package/src/skills/science/references/packages/pybinding.md +73 -0
  746. package/src/skills/science/references/packages/pyfr.md +80 -0
  747. package/src/skills/science/references/packages/pyhf.md +73 -0
  748. package/src/skills/science/references/packages/pyiron_base.md +80 -0
  749. package/src/skills/science/references/packages/pylcp.md +73 -0
  750. package/src/skills/science/references/packages/pylith.md +80 -0
  751. package/src/skills/science/references/packages/pynbody.md +88 -0
  752. package/src/skills/science/references/packages/pysam.md +88 -0
  753. package/src/skills/science/references/packages/pyscf.md +88 -0
  754. package/src/skills/science/references/packages/q-e.md +73 -0
  755. package/src/skills/science/references/packages/qibo.md +73 -0
  756. package/src/skills/science/references/packages/qiskit.md +73 -0
  757. package/src/skills/science/references/packages/quantica-jl.md +73 -0
  758. package/src/skills/science/references/packages/quantumoptics-jl.md +73 -0
  759. package/src/skills/science/references/packages/quimb.md +73 -0
  760. package/src/skills/science/references/packages/qulacs.md +73 -0
  761. package/src/skills/science/references/packages/qutip.md +73 -0
  762. package/src/skills/science/references/packages/rdkit.md +88 -0
  763. package/src/skills/science/references/packages/rmg-py.md +73 -0
  764. package/src/skills/science/references/packages/root.md +73 -0
  765. package/src/skills/science/references/packages/scanpy.md +88 -0
  766. package/src/skills/science/references/packages/scikit-allel.md +88 -0
  767. package/src/skills/science/references/packages/scikit-bio.md +88 -0
  768. package/src/skills/science/references/packages/scqubits.md +73 -0
  769. package/src/skills/science/references/packages/scuff-em.md +80 -0
  770. package/src/skills/science/references/packages/scvi-tools.md +73 -0
  771. package/src/skills/science/references/packages/seissol.md +73 -0
  772. package/src/skills/science/references/packages/sfepy.md +80 -0
  773. package/src/skills/science/references/packages/sisl.md +73 -0
  774. package/src/skills/science/references/packages/smilei.md +80 -0
  775. package/src/skills/science/references/packages/snakemake.md +88 -0
  776. package/src/skills/science/references/packages/specfem3d-globe.md +80 -0
  777. package/src/skills/science/references/packages/specutils.md +88 -0
  778. package/src/skills/science/references/packages/spglib.md +80 -0
  779. package/src/skills/science/references/packages/squidpy.md +88 -0
  780. package/src/skills/science/references/packages/starry.md +88 -0
  781. package/src/skills/science/references/packages/strawberryfields.md +73 -0
  782. package/src/skills/science/references/packages/su2.md +80 -0
  783. package/src/skills/science/references/packages/sunny-jl.md +73 -0
  784. package/src/skills/science/references/packages/sw4.md +73 -0
  785. package/src/skills/science/references/packages/swift.md +88 -0
  786. package/src/skills/science/references/packages/tdnegf.md +73 -0
  787. package/src/skills/science/references/packages/tenpy.md +73 -0
  788. package/src/skills/science/references/packages/thermo.md +73 -0
  789. package/src/skills/science/references/packages/tkwant.md +73 -0
  790. package/src/skills/science/references/packages/tvb-root.md +73 -0
  791. package/src/skills/science/references/packages/uproot5.md +73 -0
  792. package/src/skills/science/references/packages/vampire.md +80 -0
  793. package/src/skills/science/references/packages/wannier_tools.md +73 -0
  794. package/src/skills/science/references/packages/warpx.md +80 -0
  795. package/src/skills/science/references/packages/wrf.md +73 -0
  796. package/src/skills/science/references/packages/xtb.md +88 -0
  797. package/src/skills/science/references/packages/yt.md +73 -0
  798. package/src/skills/science/references/science-task-brief-template.md +71 -0
  799. package/src/skills/scout/SKILL.md +83 -425
  800. package/src/skills/scout/references/literature-scout-template.md +5 -24
  801. package/src/skills/scout/references/operational-guidance.md +191 -0
  802. package/src/skills/scout/references/paper-triage-playbook.md +11 -35
  803. package/src/skills/write/SKILL.md +744 -1246
  804. package/src/skills/write/references/experiments_analysis_patterns.md +129 -0
  805. package/src/skills/write/references/oral_package_patterns.md +252 -0
  806. package/src/skills/write/references/oral_writing_principles.md +291 -0
  807. package/src/skills/write/references/section_rewrite_checklist.md +234 -0
  808. package/src/tui/dist/app/AppContainer.js +1314 -27
  809. package/src/tui/dist/components/Composer.js +26 -1
  810. package/src/tui/dist/components/ConfigScreen.js +2 -1
  811. package/src/tui/dist/components/InputPrompt.js +25 -9
  812. package/src/tui/dist/components/MainContent.js +18 -3
  813. package/src/tui/dist/components/QuestScreen.js +3 -2
  814. package/src/tui/dist/components/UtilityScreen.js +37 -0
  815. package/src/tui/dist/hooks/useSafeInput.js +10 -0
  816. package/src/tui/dist/index.js +13 -1
  817. package/src/tui/dist/layouts/DefaultAppLayout.js +11 -8
  818. package/src/tui/dist/lib/api.js +89 -1
  819. package/src/tui/package.json +1 -1
  820. package/src/ui/dist/assets/{AnalysisPlugin-DnSm0GZn.js → AnalysisPlugin-CA94NGmI.js} +1 -1
  821. package/src/ui/dist/assets/CliPlugin-DHBzphZU.js +79 -0
  822. package/src/ui/dist/assets/CodeEditorPlugin-BOFwD2rn.js +2 -0
  823. package/src/ui/dist/assets/{CodeViewerPlugin-itb0tltR.js → CodeViewerPlugin-CqDpgjik.js} +4 -4
  824. package/src/ui/dist/assets/{DocViewerPlugin-DqKkiCI6.js → DocViewerPlugin-UDBgt8-4.js} +3 -3
  825. package/src/ui/dist/assets/GitCommitViewerPlugin-BmHtZ0bZ.js +6 -0
  826. package/src/ui/dist/assets/{GitDiffViewerPlugin-DxL2ezFG.js → GitDiffViewerPlugin-CAxjNorQ.js} +2 -2
  827. package/src/ui/dist/assets/{GitSnapshotViewer-B_RQm1YZ.js → GitSnapshotViewer-CweA6VON.js} +2 -2
  828. package/src/ui/dist/assets/{ImageViewerPlugin-tHqlXY3n.js → ImageViewerPlugin-C8wHGvGN.js} +5 -5
  829. package/src/ui/dist/assets/LabPlugin-COyyLUol.js +32 -0
  830. package/src/ui/dist/assets/{LatexPlugin-B495DTXC.js → LatexPlugin-BQjAaA5J.js} +4 -4
  831. package/src/ui/dist/assets/{MarkdownViewerPlugin-DG28-61B.js → MarkdownViewerPlugin-Dy1NE2dI.js} +3 -3
  832. package/src/ui/dist/assets/{MarketplacePlugin-BiOGT-Kj.js → MarketplacePlugin-DMIZtEJ2.js} +2 -2
  833. package/src/ui/dist/assets/NotebookEditor-CFHMq_Qt.js +91 -0
  834. package/src/ui/dist/assets/{NotebookEditor-CVsj8h_T.js → NotebookEditor-WFyd8Ybt.js} +23 -23
  835. package/src/ui/dist/assets/{PdfLoader-CASDQmxJ.js → PdfLoader-CLE5u5TS.js} +3 -3
  836. package/src/ui/dist/assets/{PdfMarkdownPlugin-BFhwoKsY.js → PdfMarkdownPlugin-_iNK_H83.js} +1 -1
  837. package/src/ui/dist/assets/PdfViewerPlugin-DgWsbInT.js +22 -0
  838. package/src/ui/dist/assets/SearchPlugin-DrZmn5iw.js +11 -0
  839. package/src/ui/dist/assets/{TextViewerPlugin-CB4DYfWO.js → TextViewerPlugin-D1-T3aC7.js} +4 -4
  840. package/src/ui/dist/assets/branding/runner-claude.svg +107 -0
  841. package/src/ui/dist/assets/branding/runner-codex.svg +10 -0
  842. package/src/ui/dist/assets/branding/runner-kimi.svg +14 -0
  843. package/src/ui/dist/assets/branding/runner-opencode.svg +7 -0
  844. package/src/ui/dist/assets/cli-store-CoZ-x5Ip.js +1 -0
  845. package/src/ui/dist/assets/{code-DLC6G24T.js → code-DbsmSd3Y.js} +1 -1
  846. package/src/ui/dist/assets/file-diff-panel-DsvyRz47.js +1 -0
  847. package/src/ui/dist/assets/{wrap-text-CwMn-iqb.js → file-jump-queue-DeQBikaw.js} +3 -3
  848. package/src/ui/dist/assets/{file-socket-Cu4Qln7Y.js → file-socket-DA5XIx88.js} +1 -1
  849. package/src/ui/dist/assets/fonts/ds-fonts.css +50 -4
  850. package/src/ui/dist/assets/images/deepxiv/register-guide.png +0 -0
  851. package/src/ui/dist/assets/index-39vY9LmZ.js +1 -0
  852. package/src/ui/dist/assets/{index-wQ7RIIRd.js → index-BsO46tJA.js} +1 -1
  853. package/src/ui/dist/assets/index-CHzJ2xtB.js +3530 -0
  854. package/src/ui/dist/assets/index-DH-zxoZ3.css +33 -0
  855. package/src/ui/dist/assets/{plugin-notebook-HbW2K-1c.js → plugin-notebook-JRhysCqj.js} +2 -2
  856. package/src/ui/dist/assets/{project-sync-CsX08Qno.js → project-sync-DPmWKmKD.js} +1 -1
  857. package/src/ui/dist/assets/{zoom-out-R-GWEhzS.js → zoom-out-DAukFWen.js} +3 -3
  858. package/src/ui/dist/index.html +3 -3
  859. package/src/skills/analysis-campaign/references/artifact-orchestration.md +0 -58
  860. package/src/skills/baseline/references/memory-playbook.md +0 -40
  861. package/src/skills/baseline/references/publishable-baseline-package.md +0 -30
  862. package/src/skills/write/references/outline-evidence-contract-example.md +0 -107
  863. package/src/skills/write/references/paper-experiment-matrix-template.md +0 -131
  864. package/src/skills/write/references/paper-section-playbook.md +0 -64
  865. package/src/skills/write/references/reviewer-first-writing.md +0 -64
  866. package/src/skills/write/references/revision-checklist.md +0 -70
  867. package/src/skills/write/references/section-contracts.md +0 -82
  868. package/src/skills/write/references/sentence-level-proofing.md +0 -49
  869. package/src/ui/dist/assets/AiManusChatView-COFACy7V.js +0 -204
  870. package/src/ui/dist/assets/CliPlugin-CvwCmDQ5.js +0 -109
  871. package/src/ui/dist/assets/CodeEditorPlugin-cOqSa0xq.js +0 -2
  872. package/src/ui/dist/assets/GitCommitViewerPlugin-DVgNHBCS.js +0 -1
  873. package/src/ui/dist/assets/LabCopilotPanel-ClMbq5Yu.js +0 -14
  874. package/src/ui/dist/assets/LabPlugin-L_SuE8ow.js +0 -22
  875. package/src/ui/dist/assets/NotebookEditor-C-4Kt1p9.js +0 -81
  876. package/src/ui/dist/assets/PdfViewerPlugin-DcOzU9vd.js +0 -17
  877. package/src/ui/dist/assets/SearchPlugin-CHj7M58O.js +0 -16
  878. package/src/ui/dist/assets/VNCViewer-CjlbyCB3.js +0 -11
  879. package/src/ui/dist/assets/bot-CFkZY-JP.js +0 -6
  880. package/src/ui/dist/assets/chevron-up-Dq5ofbht.js +0 -6
  881. package/src/ui/dist/assets/file-content-Dv4LoZec.js +0 -1
  882. package/src/ui/dist/assets/file-diff-panel-Denq-lC3.js +0 -1
  883. package/src/ui/dist/assets/file-jump-queue-DA-SdG__.js +0 -1
  884. package/src/ui/dist/assets/git-commit-horizontal-BUh6G52n.js +0 -6
  885. package/src/ui/dist/assets/image-B9HUUddG.js +0 -6
  886. package/src/ui/dist/assets/index-B2B1sg-M.js +0 -1
  887. package/src/ui/dist/assets/index-Cgla8biy.css +0 -33
  888. package/src/ui/dist/assets/index-DRyx7vAc.js +0 -1
  889. package/src/ui/dist/assets/index-Gbl53BNp.js +0 -2496
  890. package/src/ui/dist/assets/pdf-effect-queue-ZtnHFCAi.js +0 -6
  891. package/src/ui/dist/assets/popover-DL6h35vr.js +0 -1
  892. package/src/ui/dist/assets/select-DvmXt1yY.js +0 -11
  893. package/src/ui/dist/assets/sigma-7jpXazui.js +0 -6
  894. package/src/ui/dist/assets/trash-xA7kFt8i.js +0 -11
  895. package/src/ui/dist/assets/useCliAccess-DsMwDjOp.js +0 -1
  896. package/src/ui/dist/assets/useFileDiffOverlay-FuhcnKiw.js +0 -1
@@ -1,7 +1,8 @@
1
1
  import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
2
  import fs from 'node:fs';
3
- import { useApp, useInput } from 'ink';
3
+ import { useApp } from 'ink';
4
4
  import { spawn } from 'node:child_process';
5
+ import { useSafeInput } from '../hooks/useSafeInput.js';
5
6
  import { client } from '../lib/api.js';
6
7
  import { CONNECTOR_ORDER, connectorLabel, connectorSubtitle, createLingzhuAk, looksLikeWeixinQrImageUrl, resolveLingzhuAuthAk, supportsGuidedConnector, } from '../lib/connectorConfig.js';
7
8
  import { connectorTargetLabel, normalizeConnectorTargets, qqProfileDisplayLabel, qqProfileStatus, selectQqProfileTarget, } from '../lib/connectors.js';
@@ -9,6 +10,7 @@ import { renderQrAscii } from '../lib/qr.js';
9
10
  import { buildToolOperationContent, extractToolSubject } from '../lib/toolOperations.js';
10
11
  import { DefaultAppLayout } from '../layouts/DefaultAppLayout.js';
11
12
  const LOCAL_USER_SOURCE = 'tui-local';
13
+ const TUI_RECENT_HISTORY_LIMIT = 160;
12
14
  const CONFIG_ROOT_ENTRIES = [
13
15
  {
14
16
  id: 'connectors',
@@ -55,6 +57,712 @@ const parseSlashCommand = (text) => {
55
57
  arg: trimmed.slice(firstSpace + 1).trim(),
56
58
  };
57
59
  };
60
+ const BACKEND_SLASH_COMMANDS = new Set([
61
+ '/status',
62
+ '/summary',
63
+ '/metrics',
64
+ '/graph',
65
+ '/terminal',
66
+ '/approve',
67
+ '/note',
68
+ ]);
69
+ const firstLine = (value) => String(value ?? '').split('\n')[0]?.trim() || '';
70
+ const splitCommandTokens = (value) => value.split(/\s+/).map((item) => item.trim()).filter(Boolean);
71
+ const stripKnownFlags = (value, flags) => {
72
+ let next = value;
73
+ for (const flag of flags) {
74
+ next = next.replace(new RegExp(`(^|\\s)${flag.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}(?=\\s|$)`, 'g'), ' ');
75
+ }
76
+ return next.replace(/\s+/g, ' ').trim();
77
+ };
78
+ const parseLocaleFlag = (tokens) => {
79
+ for (let index = 0; index < tokens.length; index += 1) {
80
+ const token = tokens[index];
81
+ if (token === '--locale') {
82
+ const value = tokens[index + 1]?.toLowerCase();
83
+ if (value === 'en' || value === 'zh')
84
+ return value;
85
+ }
86
+ if (token.startsWith('--locale=')) {
87
+ const value = token.slice('--locale='.length).toLowerCase();
88
+ if (value === 'en' || value === 'zh')
89
+ return value;
90
+ }
91
+ }
92
+ return undefined;
93
+ };
94
+ const stringifyBrief = (value, maxLength = 280) => {
95
+ if (typeof value === 'string') {
96
+ return value.length > maxLength ? `${value.slice(0, maxLength).trimEnd()}...` : value;
97
+ }
98
+ if (value == null) {
99
+ return '';
100
+ }
101
+ try {
102
+ const text = JSON.stringify(value);
103
+ return text.length > maxLength ? `${text.slice(0, maxLength).trimEnd()}...` : text;
104
+ }
105
+ catch {
106
+ return String(value);
107
+ }
108
+ };
109
+ const buildHelpPanel = () => ({
110
+ kind: 'help',
111
+ title: 'TUI Help',
112
+ subtitle: 'Local commands are handled by TUI before anything is forwarded to the daemon command endpoint.',
113
+ sections: [
114
+ {
115
+ title: 'Quest',
116
+ lines: [
117
+ '/new <goal> Create and auto-start a quest. Add --no-start to create only.',
118
+ '/projects Browse quests.',
119
+ '/use <quest_id|index> Open a quest.',
120
+ '/pause|/stop|/resume [id] Control a quest.',
121
+ '/delete <id> --yes Delete a quest.',
122
+ ],
123
+ },
124
+ {
125
+ title: 'Run And Workflow',
126
+ lines: [
127
+ '/run <skill> <message> Run one skill on the active quest.',
128
+ '/status /summary /graph Forwarded to the implemented quest command handlers.',
129
+ '/note <text> Store a note and queue it for the active quest.',
130
+ ],
131
+ },
132
+ {
133
+ title: 'BenchStore And Ops',
134
+ lines: [
135
+ '/benchstore List benchmark catalog entries.',
136
+ '/benchstore show <id> Show benchmark detail.',
137
+ '/benchstore install <id> Start the install task.',
138
+ '/benchstore setup <id> Preview the setup packet.',
139
+ '/benchstore launch <id> Launch a benchmark quest.',
140
+ '/doctor Start a system doctor task.',
141
+ '/tasks [task_id] List or inspect system tasks.',
142
+ ],
143
+ },
144
+ {
145
+ title: 'Diagnostics',
146
+ lines: [
147
+ '/debug Open the local debug inspector.',
148
+ 'Ctrl+D Open the debug inspector from any TUI screen.',
149
+ '/debug is local only and shows the current route, screen, and web analog.',
150
+ ],
151
+ },
152
+ {
153
+ title: 'Config And Baseline',
154
+ lines: [
155
+ '/config Open config workspace.',
156
+ '/config validate [name] Validate config, runners, connectors, plugins, or mcp_servers.',
157
+ '/config test <name> Run config test. Add --live for live probes.',
158
+ '/config deepxiv-test Test DeepXiv using current config.',
159
+ '/baseline List archived baselines.',
160
+ '/baseline attach <id> Attach a baseline to the active quest.',
161
+ '/baseline unbind Clear baseline binding on the active quest.',
162
+ ],
163
+ },
164
+ ],
165
+ footer: 'Esc closes this panel. Unknown slash commands are blocked locally instead of hitting the skeleton fallback.',
166
+ });
167
+ const buildBenchCatalogPanel = (payload) => {
168
+ const items = payload.items.slice(0, 30).map((entry, index) => {
169
+ const title = entry.name || entry.id;
170
+ const summary = entry.one_line || entry.task_description || entry.snapshot_status || '';
171
+ return `${index + 1}. ${entry.id} · ${title}${summary ? ` · ${summary}` : ''}`;
172
+ });
173
+ return {
174
+ kind: 'benchstore',
175
+ title: 'BenchStore',
176
+ subtitle: `${payload.total ?? payload.items.length} benchmark entries${payload.device_summary ? ` · ${payload.device_summary}` : ''}`,
177
+ lines: items.length > 0 ? items : ['No benchmark entries are available.'],
178
+ footer: 'Use /benchstore show <id>, /benchstore install <id>, or /benchstore launch <id>.',
179
+ };
180
+ };
181
+ const buildBenchEntryPanel = (entry) => ({
182
+ kind: 'benchstore',
183
+ title: entry.name || entry.id,
184
+ subtitle: entry.id,
185
+ sections: [
186
+ {
187
+ title: 'Summary',
188
+ lines: [
189
+ entry.one_line || entry.task_description || 'No summary.',
190
+ `status: ${entry.snapshot_status || 'unknown'}`,
191
+ `support: ${entry.support_level || 'unknown'}`,
192
+ `cost/time/difficulty: ${[entry.cost_band, entry.time_band, entry.difficulty].filter(Boolean).join(' / ') || 'unknown'}`,
193
+ ],
194
+ },
195
+ {
196
+ title: 'Compatibility',
197
+ lines: [
198
+ stringifyBrief(entry.compatibility || entry.recommendation || 'No compatibility payload.'),
199
+ ],
200
+ },
201
+ {
202
+ title: 'Risk',
203
+ lines: [
204
+ ...(entry.risk_flags?.length ? [`flags: ${entry.risk_flags.join(', ')}`] : []),
205
+ ...(entry.risk_notes?.length ? entry.risk_notes : ['No risk notes.']),
206
+ ],
207
+ },
208
+ ],
209
+ footer: 'Use /benchstore setup <id>, /benchstore install <id>, or /benchstore launch <id>.',
210
+ });
211
+ const buildTaskLine = (task) => {
212
+ const progress = typeof task.progress_percent === 'number'
213
+ ? `${Math.round(task.progress_percent)}%`
214
+ : task.progress_current != null && task.progress_total
215
+ ? `${task.progress_current}/${task.progress_total}`
216
+ : '';
217
+ return [task.task_id, task.kind, task.status, progress, task.current_step || task.message || task.error]
218
+ .filter(Boolean)
219
+ .join(' · ');
220
+ };
221
+ const buildTasksPanel = (tasks, title = 'System Tasks') => ({
222
+ kind: 'tasks',
223
+ title,
224
+ subtitle: `${tasks.length} task(s)`,
225
+ lines: tasks.length > 0 ? tasks.map(buildTaskLine) : ['No system tasks found.'],
226
+ footer: 'Use /tasks <task_id> to inspect one task, or /doctor to start a doctor task.',
227
+ });
228
+ const buildTaskPanel = (task) => ({
229
+ kind: 'tasks',
230
+ title: `Task ${task.task_id}`,
231
+ subtitle: `${task.kind} · ${task.status}`,
232
+ lines: [
233
+ { label: 'step', value: task.current_step || 'none', tone: 'muted' },
234
+ { label: 'message', value: task.message || 'none' },
235
+ { label: 'progress', value: buildTaskLine(task) },
236
+ ...(task.result_path ? [{ label: 'result', value: task.result_path, tone: 'link' }] : []),
237
+ ...(task.error ? [{ label: 'error', value: task.error, tone: 'error' }] : []),
238
+ ],
239
+ footer: 'Use /tasks to refresh recent tasks.',
240
+ });
241
+ const buildBaselinesPanel = (entries) => ({
242
+ kind: 'baselines',
243
+ title: 'Baselines',
244
+ subtitle: `${entries.length} archived baseline(s)`,
245
+ lines: entries.length > 0
246
+ ? entries.slice(0, 40).map((entry, index) => {
247
+ const variantCount = Array.isArray(entry.variants) ? entry.variants.length : 0;
248
+ return `${index + 1}. ${entry.baseline_id}${entry.summary ? ` · ${entry.summary}` : ''}${variantCount ? ` · variants ${variantCount}` : ''}`;
249
+ })
250
+ : ['No archived baselines are available.'],
251
+ footer: 'Use /baseline attach <baseline_id> [variant_id] after opening a quest.',
252
+ });
253
+ const buildConfigResultPanel = (title, name, payload) => ({
254
+ kind: 'config',
255
+ title,
256
+ subtitle: `${name} · ${payload.ok ? 'ok' : 'failed'}`,
257
+ sections: [
258
+ {
259
+ title: 'Summary',
260
+ lines: [
261
+ { value: payload.summary || (payload.ok ? 'OK' : 'Failed'), tone: payload.ok ? 'success' : 'error' },
262
+ ],
263
+ },
264
+ {
265
+ title: 'Errors',
266
+ lines: payload.errors?.length ? payload.errors.map((value) => ({ value, tone: 'error' })) : ['No errors.'],
267
+ },
268
+ {
269
+ title: 'Warnings',
270
+ lines: payload.warnings?.length ? payload.warnings.map((value) => ({ value, tone: 'warning' })) : ['No warnings.'],
271
+ },
272
+ ...(Array.isArray(payload.items)
273
+ ? [
274
+ {
275
+ title: 'Items',
276
+ lines: (payload.items || []).map((item) => `${item.name || 'item'} · ${item.ok === false ? 'failed' : 'ok'} · ${item.summary || firstLine(item.errors?.[0]) || 'checked'}`),
277
+ },
278
+ ]
279
+ : []),
280
+ ...(payload.preview
281
+ ? [
282
+ {
283
+ title: 'Preview',
284
+ lines: [String(payload.preview)],
285
+ },
286
+ ]
287
+ : []),
288
+ ],
289
+ });
290
+ const compactDebugText = (value, maxLength = 140) => {
291
+ const text = stringifyBrief(value, maxLength);
292
+ const flattened = text.replace(/\r?\n+/g, ' ⏎ ').replace(/\s+/g, ' ').trim();
293
+ return flattened || '—';
294
+ };
295
+ const SENSITIVE_DEBUG_KEY_PATTERN = /(secret|token|api[_-]?key|auth[_-]?ak|password|credential|app[_-]?secret)/i;
296
+ const redactedDebugText = (reason, value) => {
297
+ const length = String(value ?? '').length;
298
+ return `[redacted: ${reason}; ${length} chars]`;
299
+ };
300
+ const resolveDebugInputRedaction = (args) => {
301
+ if (args.configMode === 'edit') {
302
+ if (args.configEditor?.kind === 'connector-field') {
303
+ if (args.configEditor.fieldKind === 'password' ||
304
+ SENSITIVE_DEBUG_KEY_PATTERN.test(args.configEditor.fieldKey) ||
305
+ SENSITIVE_DEBUG_KEY_PATTERN.test(args.configEditor.fieldLabel)) {
306
+ return 'connector secret field';
307
+ }
308
+ return 'connector field editor';
309
+ }
310
+ return 'config editor buffer';
311
+ }
312
+ if (SENSITIVE_DEBUG_KEY_PATTERN.test(args.input)) {
313
+ return 'secret-like input';
314
+ }
315
+ return null;
316
+ };
317
+ const compactMaybeRedacted = (value, reason, maxLength = 140) => reason ? redactedDebugText(reason, value) : compactDebugText(value, maxLength);
318
+ const countUtilityPanelLines = (panel) => {
319
+ if (!panel) {
320
+ return 0;
321
+ }
322
+ const sectionLines = panel.sections?.reduce((total, section) => total + section.lines.length + 1, 0) ?? 0;
323
+ return (panel.lines?.length ?? 0) + sectionLines;
324
+ };
325
+ const describeDebugSurface = (args) => {
326
+ if (args.utilityPanel) {
327
+ return `utility:${args.utilityPanel.kind}`;
328
+ }
329
+ if (args.configMode) {
330
+ return `config:${args.configView || 'root'}:${args.configMode}`;
331
+ }
332
+ if (args.questPanelMode) {
333
+ return `quest-panel:${args.questPanelMode}`;
334
+ }
335
+ if (args.activeQuestId) {
336
+ return `quest:${args.activeQuestId}`;
337
+ }
338
+ if (args.browseQuestId) {
339
+ return `home:browse:${args.browseQuestId}`;
340
+ }
341
+ return 'home';
342
+ };
343
+ const describeDebugWebAnalog = (args) => {
344
+ if (args.utilityPanel) {
345
+ if (args.utilityPanel.kind === 'benchstore') {
346
+ return 'Web BenchStore page';
347
+ }
348
+ if (args.utilityPanel.kind === 'tasks') {
349
+ return 'Web admin tasks';
350
+ }
351
+ if (args.utilityPanel.kind === 'baselines') {
352
+ return 'Web baselines page';
353
+ }
354
+ if (args.utilityPanel.kind === 'config') {
355
+ return 'Web Settings > diagnostics / DeepXiv test';
356
+ }
357
+ if (args.utilityPanel.kind === 'run') {
358
+ return 'Web workspace run drawer';
359
+ }
360
+ if (args.utilityPanel.kind === 'status') {
361
+ return 'Web quest status surface';
362
+ }
363
+ if (args.utilityPanel.kind === 'debug') {
364
+ return 'Web Settings > diagnostics / audit';
365
+ }
366
+ return 'Web utility surface';
367
+ }
368
+ if (args.configMode) {
369
+ if (args.configView === 'root') {
370
+ return 'Web Settings';
371
+ }
372
+ if (args.configView === 'files') {
373
+ const selected = args.configPanel?.kind === 'files' ? args.configPanel.items[args.configPanel.selectedIndex] ?? null : null;
374
+ if (selected?.title === 'config.yaml' || selected?.name === 'config') {
375
+ return 'Web Settings > DeepXiv / runtime defaults';
376
+ }
377
+ if (selected?.title === 'connectors.yaml' || selected?.name === 'connectors') {
378
+ return 'Web Settings > Connectors';
379
+ }
380
+ if (selected?.scope === 'quest') {
381
+ return 'Web quest settings';
382
+ }
383
+ return 'Web Settings > config files';
384
+ }
385
+ if (args.configView === 'connector-list' || args.configView === 'connector-detail') {
386
+ if (args.selectedConnectorName === 'weixin') {
387
+ return 'Web Settings > Weixin connector';
388
+ }
389
+ if (args.selectedConnectorName === 'qq') {
390
+ return 'Web Settings > QQ connector';
391
+ }
392
+ if (args.selectedConnectorName === 'lingzhu') {
393
+ return 'Web Settings > Lingzhu connector';
394
+ }
395
+ return 'Web Settings > Connectors';
396
+ }
397
+ if (args.configView === 'weixin-qr') {
398
+ return 'Web Settings > Weixin QR login dialog';
399
+ }
400
+ }
401
+ if (args.questPanelMode) {
402
+ return 'Web projects / quest picker';
403
+ }
404
+ if (args.activeQuestId) {
405
+ return 'Web quest workspace';
406
+ }
407
+ if (args.browseQuestId) {
408
+ return 'Web home / quest picker';
409
+ }
410
+ return 'Web home';
411
+ };
412
+ const previewDebugRoute = (args) => {
413
+ const trimmed = args.input.trim();
414
+ const slash = parseSlashCommand(args.input);
415
+ const redactionReason = args.redactionReason || null;
416
+ const visibleArg = (value, maxLength = 120) => compactMaybeRedacted(value, redactionReason, maxLength);
417
+ const parsedCommand = slash
418
+ ? `${slash.name}${slash.arg ? ` ${redactionReason ? '[redacted]' : slash.arg}` : ''}`
419
+ : trimmed
420
+ ? visibleArg(trimmed, 120)
421
+ : 'none';
422
+ if (args.configMode === 'edit') {
423
+ return {
424
+ kind: 'config-save',
425
+ target: 'save config draft',
426
+ reason: 'Enter saves the current editor buffer.',
427
+ command: 'editor',
428
+ arg: redactedDebugText(redactionReason || 'config editor buffer', args.input),
429
+ parsedCommand: 'editor-buffer',
430
+ };
431
+ }
432
+ if (args.configMode === 'browse' && !trimmed) {
433
+ return {
434
+ kind: 'config-select',
435
+ target: 'open highlighted config item',
436
+ reason: 'Enter opens the selected config item.',
437
+ command: 'browse',
438
+ arg: 'selection',
439
+ parsedCommand,
440
+ };
441
+ }
442
+ if (args.questPanelMode && !trimmed) {
443
+ return {
444
+ kind: `quest-${args.questPanelMode}`,
445
+ target: `confirm ${args.questPanelMode} selection`,
446
+ reason: 'Enter confirms the highlighted quest.',
447
+ command: 'quest-panel',
448
+ arg: args.questPanelMode,
449
+ parsedCommand,
450
+ };
451
+ }
452
+ if (!trimmed) {
453
+ return {
454
+ kind: 'idle',
455
+ target: 'no-op',
456
+ reason: 'Input is empty.',
457
+ command: 'none',
458
+ arg: 'empty',
459
+ parsedCommand,
460
+ };
461
+ }
462
+ if (slash?.name === '/help') {
463
+ return {
464
+ kind: 'local-help',
465
+ target: 'help panel',
466
+ reason: 'Handled locally by the TUI command registry.',
467
+ command: slash.name,
468
+ arg: slash.arg || 'none',
469
+ parsedCommand,
470
+ };
471
+ }
472
+ if (slash?.name === '/debug') {
473
+ return {
474
+ kind: 'local-debug',
475
+ target: 'debug inspector',
476
+ reason: 'Handled locally by the TUI command registry.',
477
+ command: slash.name,
478
+ arg: slash.arg || 'none',
479
+ parsedCommand,
480
+ };
481
+ }
482
+ if (slash?.name === '/home') {
483
+ return {
484
+ kind: 'local-home',
485
+ target: 'home request mode',
486
+ reason: 'Handled locally by the TUI command registry.',
487
+ command: slash.name,
488
+ arg: 'none',
489
+ parsedCommand,
490
+ };
491
+ }
492
+ if (slash?.name === '/benchstore') {
493
+ return {
494
+ kind: 'local-benchstore',
495
+ target: slash.arg ? `benchstore ${visibleArg(slash.arg)}` : 'benchstore catalog',
496
+ reason: 'Handled locally by the TUI command registry.',
497
+ command: slash.name,
498
+ arg: slash.arg ? visibleArg(slash.arg) : 'list',
499
+ parsedCommand,
500
+ };
501
+ }
502
+ if (slash?.name === '/doctor') {
503
+ return {
504
+ kind: 'local-doctor',
505
+ target: 'system doctor task',
506
+ reason: 'Handled locally by the TUI command registry.',
507
+ command: slash.name,
508
+ arg: slash.arg || 'none',
509
+ parsedCommand,
510
+ };
511
+ }
512
+ if (slash?.name === '/tasks') {
513
+ return {
514
+ kind: 'local-tasks',
515
+ target: slash.arg ? `task ${visibleArg(slash.arg)}` : 'task list',
516
+ reason: 'Handled locally by the TUI command registry.',
517
+ command: slash.name,
518
+ arg: slash.arg ? visibleArg(slash.arg) : 'list',
519
+ parsedCommand,
520
+ };
521
+ }
522
+ if (slash?.name === '/baseline') {
523
+ return {
524
+ kind: 'local-baseline',
525
+ target: slash.arg ? `baseline ${visibleArg(slash.arg)}` : 'baseline list',
526
+ reason: 'Handled locally by the TUI command registry.',
527
+ command: slash.name,
528
+ arg: slash.arg ? visibleArg(slash.arg) : 'list',
529
+ parsedCommand,
530
+ };
531
+ }
532
+ if (slash?.name === '/run') {
533
+ return {
534
+ kind: 'local-run',
535
+ target: 'quest run endpoint',
536
+ reason: 'Handled locally by the TUI command registry.',
537
+ command: slash.name,
538
+ arg: slash.arg ? visibleArg(slash.arg) : 'usage',
539
+ parsedCommand,
540
+ };
541
+ }
542
+ if (slash?.name === '/projects' || slash?.name === '/pause' || slash?.name === '/stop' || slash?.name === '/resume' || slash?.name === '/use') {
543
+ return {
544
+ kind: 'local-quest',
545
+ target: slash.name === '/projects' ? 'quest browser' : 'quest control',
546
+ reason: 'Handled locally by the TUI command registry.',
547
+ command: slash.name,
548
+ arg: slash.arg ? visibleArg(slash.arg) : 'none',
549
+ parsedCommand,
550
+ };
551
+ }
552
+ if (slash?.name === '/config') {
553
+ return {
554
+ kind: 'local-config',
555
+ target: slash.arg ? `config ${visibleArg(slash.arg)}` : 'config workspace',
556
+ reason: 'Handled locally by the TUI command registry.',
557
+ command: slash.name,
558
+ arg: slash.arg ? visibleArg(slash.arg) : 'workspace',
559
+ parsedCommand,
560
+ };
561
+ }
562
+ if (slash?.name === '/new') {
563
+ return {
564
+ kind: 'local-new',
565
+ target: 'create quest and auto-start',
566
+ reason: 'Handled locally by the TUI command registry.',
567
+ command: slash.name,
568
+ arg: slash.arg ? visibleArg(slash.arg) : 'usage',
569
+ parsedCommand,
570
+ };
571
+ }
572
+ if (slash?.name === '/delete') {
573
+ return {
574
+ kind: 'local-delete',
575
+ target: 'delete quest',
576
+ reason: 'Handled locally by the TUI command registry.',
577
+ command: slash.name,
578
+ arg: slash.arg ? visibleArg(slash.arg) : 'usage',
579
+ parsedCommand,
580
+ };
581
+ }
582
+ if (args.activeQuestId) {
583
+ if (trimmed.startsWith('/') && BACKEND_SLASH_COMMANDS.has(slash?.name || '')) {
584
+ return {
585
+ kind: 'backend-command',
586
+ target: `/api/quests/${args.activeQuestId}/commands`,
587
+ reason: 'Forwarded to the daemon quest command endpoint.',
588
+ command: slash?.name || 'command',
589
+ arg: slash?.arg ? visibleArg(slash.arg) : 'none',
590
+ parsedCommand,
591
+ };
592
+ }
593
+ if (trimmed.startsWith('/')) {
594
+ return {
595
+ kind: 'blocked',
596
+ target: 'local block',
597
+ reason: 'Unknown slash command is blocked before it can hit the daemon fallback.',
598
+ command: slash?.name || 'unknown',
599
+ arg: slash?.arg ? visibleArg(slash.arg) : 'none',
600
+ parsedCommand,
601
+ };
602
+ }
603
+ return {
604
+ kind: 'quest-chat',
605
+ target: `/api/quests/${args.activeQuestId}/chat`,
606
+ reason: 'Sent as a user message to the active quest.',
607
+ command: 'chat',
608
+ arg: visibleArg(trimmed, 120),
609
+ parsedCommand,
610
+ };
611
+ }
612
+ if (trimmed.startsWith('/')) {
613
+ if (!slash || !BACKEND_SLASH_COMMANDS.has(slash.name)) {
614
+ return {
615
+ kind: 'blocked',
616
+ target: 'local block',
617
+ reason: 'Unknown slash command is blocked before it can hit the daemon fallback.',
618
+ command: slash?.name || 'unknown',
619
+ arg: slash?.arg ? visibleArg(slash.arg) : 'none',
620
+ parsedCommand,
621
+ };
622
+ }
623
+ return {
624
+ kind: 'needs-quest',
625
+ target: 'open a quest first',
626
+ reason: 'Open a quest before sending quest commands.',
627
+ command: slash.name,
628
+ arg: slash.arg ? visibleArg(slash.arg) : 'none',
629
+ parsedCommand,
630
+ };
631
+ }
632
+ return {
633
+ kind: 'home-message',
634
+ target: 'bind or create a quest',
635
+ reason: 'No active quest is bound yet.',
636
+ command: 'chat',
637
+ arg: visibleArg(trimmed, 120),
638
+ parsedCommand,
639
+ };
640
+ };
641
+ const selectedDebugLabel = (panel) => {
642
+ if (!panel) {
643
+ return null;
644
+ }
645
+ if (panel.kind === 'root') {
646
+ return panel.items[panel.selectedIndex]?.title ?? null;
647
+ }
648
+ if (panel.kind === 'files') {
649
+ return panel.items[panel.selectedIndex]?.title ?? null;
650
+ }
651
+ if (panel.kind === 'connector-list') {
652
+ return panel.items[panel.selectedIndex]?.label ?? null;
653
+ }
654
+ if (panel.kind === 'connector-detail') {
655
+ return panel.items[panel.selectedIndex]?.label ?? null;
656
+ }
657
+ if (panel.kind === 'document-editor') {
658
+ return panel.item.title;
659
+ }
660
+ if (panel.kind === 'connector-field-editor') {
661
+ return `${panel.connectorName} · ${panel.fieldLabel}`;
662
+ }
663
+ if (panel.kind === 'weixin-qr') {
664
+ return panel.status || 'weixin qr';
665
+ }
666
+ return null;
667
+ };
668
+ const describeDebugScreen = (args) => {
669
+ const selected = args.utilityPanel?.title || selectedDebugLabel(args.configPanel);
670
+ let main = 'Home quest list';
671
+ if (args.utilityPanel) {
672
+ main = `Utility panel: ${args.utilityPanel.title}`;
673
+ }
674
+ else if (args.configMode === 'edit') {
675
+ main = selected ? `Config editor: ${selected}` : 'Config editor';
676
+ }
677
+ else if (args.configMode === 'browse') {
678
+ main = `Config browser: ${args.configView || 'root'}`;
679
+ }
680
+ else if (args.questPanelMode) {
681
+ main = `Quest browser: ${args.questPanelMode}`;
682
+ }
683
+ else if (args.activeQuestId) {
684
+ main = `Quest workspace: ${args.activeQuestId}`;
685
+ }
686
+ else if (args.browseQuestId) {
687
+ main = `Home quest picker: ${args.browseQuestId}`;
688
+ }
689
+ const composer = args.utilityPanel
690
+ ? 'utility command input'
691
+ : args.configMode === 'edit'
692
+ ? 'config editor input'
693
+ : args.configMode === 'browse'
694
+ ? 'config navigation input disabled'
695
+ : args.questPanelMode
696
+ ? 'quest selection input disabled'
697
+ : args.activeQuestId
698
+ ? 'quest chat input'
699
+ : 'home command input';
700
+ return {
701
+ main,
702
+ composer,
703
+ selected,
704
+ input_visible: args.configMode !== 'browse' && !args.questPanelMode,
705
+ input_redacted: args.inputRedacted,
706
+ debug_strip_visible: args.debugStripVisible,
707
+ };
708
+ };
709
+ const buildDebugPanel = (snapshot) => ({
710
+ kind: 'debug',
711
+ title: 'TUI Debug',
712
+ subtitle: `${snapshot.surface} · ${snapshot.connection_state} · ${snapshot.web_analog}`,
713
+ sections: [
714
+ {
715
+ title: 'Submitted Route',
716
+ lines: [
717
+ `kind: ${snapshot.route.kind}`,
718
+ `target: ${snapshot.route.target}`,
719
+ `reason: ${snapshot.route.reason}`,
720
+ `command: ${snapshot.route.command || 'none'}${snapshot.route.arg ? ` ${snapshot.route.arg}` : ''}`,
721
+ ],
722
+ },
723
+ {
724
+ title: 'Input',
725
+ lines: [
726
+ `raw: ${compactDebugText(snapshot.input.raw, 220)}`,
727
+ `parsed: ${snapshot.input.parsed}`,
728
+ `preview: ${snapshot.input.preview}`,
729
+ `redacted: ${snapshot.input.redacted ? `yes · ${snapshot.input.redaction_reason || 'policy'}` : 'no'}`,
730
+ `length: ${snapshot.input.length ?? snapshot.input.raw.length}`,
731
+ ],
732
+ },
733
+ {
734
+ title: 'Screen',
735
+ lines: [
736
+ `main: ${snapshot.screen.main}`,
737
+ `composer: ${snapshot.screen.composer}`,
738
+ `selected: ${snapshot.screen.selected || 'none'}`,
739
+ `input visible: ${snapshot.screen.input_visible ? 'yes' : 'no'}`,
740
+ `debug strip: ${snapshot.screen.debug_strip_visible ? 'yes' : 'no'}`,
741
+ ],
742
+ },
743
+ {
744
+ title: 'Render',
745
+ lines: [
746
+ `active quest: ${snapshot.active_quest_id || 'none'}`,
747
+ `browse quest: ${snapshot.browse_quest_id || 'none'}`,
748
+ `config view: ${snapshot.config_view || 'none'}`,
749
+ `quest panel: ${snapshot.quest_panel_mode || 'none'}`,
750
+ `utility panel: ${snapshot.utility_panel_kind || 'none'}`,
751
+ `counts: quests ${snapshot.counts.quests}, history ${snapshot.counts.history}, pending ${snapshot.counts.pending}, config items ${snapshot.counts.config_items}, selection ${snapshot.counts.selected_index}, suggestions ${snapshot.counts.suggestions}, utility lines ${snapshot.counts.utility_lines}`,
752
+ ],
753
+ },
754
+ {
755
+ title: 'Capture',
756
+ lines: [
757
+ `status: ${snapshot.status_line}`,
758
+ `session: ${snapshot.session_id || 'none'}`,
759
+ `log path: ${snapshot.log_path || 'disabled'}`,
760
+ `signature: ${snapshot.signature}`,
761
+ ],
762
+ },
763
+ ],
764
+ footer: 'Esc closes this panel. Compare the route preview and web analog before retrying the action.',
765
+ });
58
766
  const getPanelQuests = (mode, quests) => {
59
767
  if (mode === 'pause') {
60
768
  return quests.filter((quest) => !['stopped', 'paused'].includes(String(quest.status || '')));
@@ -509,7 +1217,7 @@ function buildProjectUrl(baseUrl, questId, authToken) {
509
1217
  }
510
1218
  return target.toString();
511
1219
  }
512
- export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null, }) => {
1220
+ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null, debugEnabled = false, debugLogPath = null, }) => {
513
1221
  const { exit } = useApp();
514
1222
  const [quests, setQuests] = useState([]);
515
1223
  const [connectors, setConnectors] = useState([]);
@@ -523,6 +1231,8 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
523
1231
  const [configEditor, setConfigEditor] = useState(null);
524
1232
  const [connectorsDocument, setConnectorsDocument] = useState(null);
525
1233
  const [selectedConnectorName, setSelectedConnectorName] = useState(null);
1234
+ const [utilityPanel, setUtilityPanel] = useState(null);
1235
+ const [utilityPanelOverlay, setUtilityPanelOverlay] = useState(false);
526
1236
  const [weixinQrState, setWeixinQrState] = useState(null);
527
1237
  const [questPanelMode, setQuestPanelMode] = useState(null);
528
1238
  const [questPanelIndex, setQuestPanelIndex] = useState(0);
@@ -541,6 +1251,7 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
541
1251
  const refreshRequestRef = useRef(0);
542
1252
  const streamAbortRef = useRef(null);
543
1253
  const reconnectTimerRef = useRef(null);
1254
+ const debugSnapshotSignatureRef = useRef('');
544
1255
  const activeQuest = useMemo(() => quests.find((quest) => quest.quest_id === activeQuestId) ?? null, [quests, activeQuestId]);
545
1256
  const browseQuest = useMemo(() => quests.find((quest) => quest.quest_id === browseQuestId) ?? null, [quests, browseQuestId]);
546
1257
  const panelQuests = useMemo(() => (questPanelMode ? getPanelQuests(questPanelMode, quests) : []), [questPanelMode, quests]);
@@ -844,6 +1555,9 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
844
1555
  ? 'Persist the generated Lingzhu values into connectors.yaml and reload the runtime.'
845
1556
  : 'Set a public base URL and a Custom agent AK first. The Web Rokid popup applies the same save gate.',
846
1557
  disabled: !saveReady,
1558
+ disabledReason: !saveReady
1559
+ ? 'Save is disabled because Lingzhu requires a public HTTP(S) base URL and a Custom agent AK.'
1560
+ : undefined,
847
1561
  },
848
1562
  {
849
1563
  type: 'action',
@@ -1172,10 +1886,17 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
1172
1886
  const slashSuggestions = useMemo(() => {
1173
1887
  const slashCommands = session?.acp_session?.slash_commands ?? [];
1174
1888
  const localCommands = [
1889
+ { name: '/help', description: 'Show TUI command help.' },
1890
+ { name: '/debug', description: 'Open the local TUI debug inspector.' },
1175
1891
  { name: '/home', description: 'Return to home request mode.' },
1176
1892
  { name: '/projects', description: 'Open the quest browser.' },
1177
1893
  { name: '/use', description: 'Bind a quest, for example `/use 001`.' },
1178
- { name: '/new', description: 'Create a new quest explicitly.' },
1894
+ { name: '/new', description: 'Create and auto-start a new quest.' },
1895
+ { name: '/run', description: 'Run a skill in the active quest.' },
1896
+ { name: '/benchstore', description: 'List, install, setup, or launch benchmark entries.' },
1897
+ { name: '/doctor', description: 'Start a system doctor task.' },
1898
+ { name: '/tasks', description: 'List or inspect system tasks.' },
1899
+ { name: '/baseline', description: 'List, attach, or clear quest baselines.' },
1179
1900
  { name: '/delete', description: 'Delete a quest (requires --yes).' },
1180
1901
  { name: '/pause', description: 'Pause a running quest.' },
1181
1902
  { name: '/resume', description: 'Resume a stopped quest.' },
@@ -1183,6 +1904,9 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
1183
1904
  { name: '/status', description: 'Show the current quest status.' },
1184
1905
  { name: '/graph', description: 'Show the quest graph.' },
1185
1906
  { name: '/config', description: 'Open the local config workspace.' },
1907
+ { name: '/config validate', description: 'Validate a config file.' },
1908
+ { name: '/config test', description: 'Run config tests.' },
1909
+ { name: '/config deepxiv-test', description: 'Run a DeepXiv test using current config.' },
1186
1910
  { name: '/config connectors', description: 'Open the connector list inside config.' },
1187
1911
  { name: '/config qq', description: 'Open the QQ connector setup.' },
1188
1912
  { name: '/config weixin', description: 'Open the Weixin connector setup.' },
@@ -1307,6 +2031,136 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
1307
2031
  }
1308
2032
  return 0;
1309
2033
  }, [configMode, configPanel]);
2034
+ const debugSnapshot = useMemo(() => {
2035
+ const redactionReason = resolveDebugInputRedaction({
2036
+ input,
2037
+ configMode,
2038
+ configEditor,
2039
+ });
2040
+ const routePreview = previewDebugRoute({
2041
+ input,
2042
+ activeQuestId,
2043
+ configMode,
2044
+ questPanelMode,
2045
+ redactionReason,
2046
+ });
2047
+ const selectedIndex = configMode ? configIndex : questPanelMode ? questPanelIndex : 0;
2048
+ const surface = describeDebugSurface({
2049
+ activeQuestId,
2050
+ browseQuestId,
2051
+ configMode,
2052
+ configView,
2053
+ questPanelMode,
2054
+ utilityPanel,
2055
+ });
2056
+ const webAnalog = describeDebugWebAnalog({
2057
+ activeQuestId,
2058
+ browseQuestId,
2059
+ configMode,
2060
+ configView,
2061
+ configPanel,
2062
+ questPanelMode,
2063
+ utilityPanel,
2064
+ selectedConnectorName,
2065
+ });
2066
+ const parsedCommand = routePreview.parsedCommand || routePreview.command || 'none';
2067
+ const route = {
2068
+ kind: routePreview.kind,
2069
+ target: routePreview.target,
2070
+ reason: routePreview.reason,
2071
+ command: routePreview.command,
2072
+ arg: routePreview.arg,
2073
+ };
2074
+ const inputSnapshot = {
2075
+ raw: redactionReason ? redactedDebugText(redactionReason, input) : input,
2076
+ parsed: redactionReason && configMode === 'edit' ? 'editor-buffer' : parsedCommand,
2077
+ preview: compactMaybeRedacted(input || 'empty', redactionReason, 180),
2078
+ redacted: Boolean(redactionReason),
2079
+ redaction_reason: redactionReason,
2080
+ length: input.length,
2081
+ };
2082
+ const counts = {
2083
+ quests: quests.length,
2084
+ history: history.length,
2085
+ pending: pendingHistoryItems.length,
2086
+ config_items: configSelectionCount,
2087
+ selected_index: selectedIndex,
2088
+ suggestions: slashSuggestions.length,
2089
+ utility_lines: countUtilityPanelLines(utilityPanel),
2090
+ };
2091
+ const screen = describeDebugScreen({
2092
+ activeQuestId,
2093
+ browseQuestId,
2094
+ configMode,
2095
+ configView,
2096
+ configPanel,
2097
+ questPanelMode,
2098
+ utilityPanel,
2099
+ inputRedacted: inputSnapshot.redacted,
2100
+ debugStripVisible: debugEnabled || utilityPanel?.kind === 'debug',
2101
+ });
2102
+ const signature = JSON.stringify({
2103
+ surface,
2104
+ webAnalog,
2105
+ route,
2106
+ input: inputSnapshot,
2107
+ screen,
2108
+ statusLine: compactDebugText(statusLine, 120),
2109
+ connectionState,
2110
+ activeQuestId,
2111
+ browseQuestId,
2112
+ configView,
2113
+ configMode,
2114
+ questPanelMode,
2115
+ utilityPanelKind: utilityPanel?.kind ?? null,
2116
+ selectedIndex,
2117
+ counts,
2118
+ sessionId: session?.acp_session?.session_id ?? null,
2119
+ logPath: debugEnabled ? debugLogPath : null,
2120
+ });
2121
+ return {
2122
+ surface,
2123
+ web_analog: webAnalog,
2124
+ route,
2125
+ input: inputSnapshot,
2126
+ screen,
2127
+ status_line: compactDebugText(statusLine, 180),
2128
+ connection_state: connectionState,
2129
+ active_quest_id: activeQuestId,
2130
+ browse_quest_id: browseQuestId,
2131
+ config_view: configView,
2132
+ config_mode: configMode,
2133
+ quest_panel_mode: questPanelMode,
2134
+ utility_panel_kind: utilityPanel?.kind ?? null,
2135
+ session_id: session?.acp_session?.session_id ?? null,
2136
+ counts,
2137
+ log_path: debugEnabled ? debugLogPath : null,
2138
+ signature,
2139
+ };
2140
+ }, [
2141
+ activeQuestId,
2142
+ browseQuestId,
2143
+ configIndex,
2144
+ configEditor,
2145
+ configMode,
2146
+ configPanel,
2147
+ configSelectionCount,
2148
+ configView,
2149
+ connectionState,
2150
+ debugEnabled,
2151
+ debugLogPath,
2152
+ history.length,
2153
+ input,
2154
+ pendingHistoryItems.length,
2155
+ questPanelIndex,
2156
+ questPanelMode,
2157
+ selectedConnectorName,
2158
+ session?.acp_session?.session_id,
2159
+ slashSuggestions.length,
2160
+ statusLine,
2161
+ utilityPanel,
2162
+ quests.length,
2163
+ ]);
1310
2164
  useEffect(() => {
1311
2165
  activeQuestIdRef.current = activeQuestId;
1312
2166
  }, [activeQuestId]);
@@ -1319,6 +2173,28 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
1319
2173
  useEffect(() => {
1320
2174
  pendingHistoryItemsRef.current = pendingHistoryItems;
1321
2175
  }, [pendingHistoryItems]);
2176
+ useEffect(() => {
2177
+ if (!debugEnabled) {
2178
+ debugSnapshotSignatureRef.current = '';
2179
+ return;
2180
+ }
2181
+ if (debugSnapshot.signature === debugSnapshotSignatureRef.current) {
2182
+ return;
2183
+ }
2184
+ debugSnapshotSignatureRef.current = debugSnapshot.signature;
2185
+ if (!debugLogPath) {
2186
+ return;
2187
+ }
2188
+ try {
2189
+ fs.appendFileSync(debugLogPath, `${JSON.stringify({
2190
+ recorded_at: new Date().toISOString(),
2191
+ ...debugSnapshot,
2192
+ })}\n`, 'utf8');
2193
+ }
2194
+ catch {
2195
+ // Debug logging should never break the TUI flow.
2196
+ }
2197
+ }, [debugEnabled, debugLogPath, debugSnapshot]);
1322
2198
  const enterQuest = useCallback((questId) => {
1323
2199
  activeQuestIdRef.current = questId;
1324
2200
  setActiveQuestId(questId);
@@ -1334,6 +2210,8 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
1334
2210
  setConfigIndex(0);
1335
2211
  setConnectorsDocument(null);
1336
2212
  setSelectedConnectorName(null);
2213
+ setUtilityPanel(null);
2214
+ setUtilityPanelOverlay(false);
1337
2215
  setWeixinQrState(null);
1338
2216
  setQuestPanelMode(null);
1339
2217
  historyRef.current = [];
@@ -1356,6 +2234,8 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
1356
2234
  setConfigIndex(0);
1357
2235
  setConnectorsDocument(null);
1358
2236
  setSelectedConnectorName(null);
2237
+ setUtilityPanel(null);
2238
+ setUtilityPanelOverlay(false);
1359
2239
  setWeixinQrState(null);
1360
2240
  setQuestPanelMode(null);
1361
2241
  setSession(null);
@@ -1366,7 +2246,7 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
1366
2246
  setCursor(0);
1367
2247
  cursorRef.current = 0;
1368
2248
  }, []);
1369
- const refresh = useCallback(async (hard = false, overrideQuestId) => {
2249
+ const refresh = useCallback(async (hard = false, overrideQuestId, options) => {
1370
2250
  const requestId = refreshRequestRef.current + 1;
1371
2251
  refreshRequestRef.current = requestId;
1372
2252
  try {
@@ -1415,16 +2295,24 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
1415
2295
  return;
1416
2296
  }
1417
2297
  const nextCursor = hard || currentQuestId !== activeQuestIdAtStart ? 0 : cursorRef.current;
1418
- const [nextSession, nextEvents] = await Promise.all([
1419
- client.session(baseUrl, currentQuestId),
1420
- client.events(baseUrl, currentQuestId, nextCursor),
1421
- ]);
2298
+ const eventMode = options?.eventMode ??
2299
+ (hard || currentQuestId !== activeQuestIdAtStart ? 'recent' : 'delta');
2300
+ const sessionPromise = client.session(baseUrl, currentQuestId);
2301
+ const eventsPromise = eventMode === 'none'
2302
+ ? Promise.resolve(null)
2303
+ : eventMode === 'recent'
2304
+ ? client.events(baseUrl, currentQuestId, 0, {
2305
+ limit: TUI_RECENT_HISTORY_LIMIT,
2306
+ tail: true,
2307
+ })
2308
+ : client.events(baseUrl, currentQuestId, nextCursor);
2309
+ const [nextSession, nextEvents] = await Promise.all([sessionPromise, eventsPromise]);
1422
2310
  if (requestId !== refreshRequestRef.current) {
1423
2311
  return;
1424
2312
  }
1425
- const normalized = (nextEvents.acp_updates ?? []).map((item) => normalizeUpdate(item.params.update));
2313
+ const normalized = (nextEvents?.acp_updates ?? []).map((item) => normalizeUpdate(item.params.update));
1426
2314
  setSession(nextSession);
1427
- const baseState = hard || currentQuestId !== activeQuestIdAtStart
2315
+ const baseState = eventMode === 'recent'
1428
2316
  ? { history: [], pending: [] }
1429
2317
  : { history: historyRef.current, pending: pendingHistoryItemsRef.current };
1430
2318
  const nextState = applyIncomingFeedUpdates(baseState, normalized);
@@ -1432,7 +2320,7 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
1432
2320
  pendingHistoryItemsRef.current = nextState.pending;
1433
2321
  setHistory(nextState.history);
1434
2322
  setPendingHistoryItems(nextState.pending);
1435
- const resolvedCursor = nextEvents.cursor ?? nextCursor;
2323
+ const resolvedCursor = nextEvents?.cursor ?? nextCursor;
1436
2324
  setCursor(resolvedCursor);
1437
2325
  cursorRef.current = resolvedCursor;
1438
2326
  setConnectionState('connected');
@@ -1456,6 +2344,8 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
1456
2344
  setConfigEditor(null);
1457
2345
  setConnectorsDocument(null);
1458
2346
  setSelectedConnectorName(null);
2347
+ setUtilityPanel(null);
2348
+ setUtilityPanelOverlay(false);
1459
2349
  setWeixinQrState(null);
1460
2350
  const candidates = getPanelQuests(mode, quests);
1461
2351
  setQuestPanelMode(mode);
@@ -1491,12 +2381,61 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
1491
2381
  setConfigIndex(0);
1492
2382
  setConnectorsDocument(null);
1493
2383
  setSelectedConnectorName(null);
2384
+ setUtilityPanel(null);
2385
+ setUtilityPanelOverlay(false);
1494
2386
  setWeixinQrState(null);
1495
2387
  setInput('');
1496
2388
  if (nextStatus) {
1497
2389
  setStatusLine(nextStatus);
1498
2390
  }
1499
2391
  }, []);
2392
+ const showUtilityPanel = useCallback((panel, nextStatus, options) => {
2393
+ const preserveContext = Boolean(options?.preserveContext);
2394
+ setUtilityPanelOverlay(preserveContext);
2395
+ if (!preserveContext) {
2396
+ setConfigView(null);
2397
+ setConfigEditor(null);
2398
+ setConfigItems([]);
2399
+ setConfigSectionTitle('Config');
2400
+ setConfigSectionDescription('');
2401
+ setConfigIndex(0);
2402
+ setConnectorsDocument(null);
2403
+ setSelectedConnectorName(null);
2404
+ setWeixinQrState(null);
2405
+ setQuestPanelMode(null);
2406
+ setInput('');
2407
+ }
2408
+ setUtilityPanel(panel);
2409
+ setStatusLine(nextStatus || panel.subtitle || panel.title);
2410
+ }, []);
2411
+ const closeUtilityPanel = useCallback((nextStatus = 'Panel closed.') => {
2412
+ setUtilityPanel(null);
2413
+ if (!utilityPanelOverlay) {
2414
+ setInput('');
2415
+ }
2416
+ setUtilityPanelOverlay(false);
2417
+ setStatusLine(nextStatus);
2418
+ }, [utilityPanelOverlay]);
2419
+ const validateConfigBeforeSave = useCallback(async (name, input) => {
2420
+ try {
2421
+ const validation = await client.validateConfig(baseUrl, name, input);
2422
+ if (!validation.ok) {
2423
+ showUtilityPanel(buildConfigResultPanel('Config Validation Failed', name, validation), firstLine(validation.errors?.[0]) || validation.summary || 'Config validation failed.');
2424
+ return false;
2425
+ }
2426
+ if (validation.warnings?.length) {
2427
+ setStatusLine(`Config validation warning · ${validation.warnings[0]}`);
2428
+ }
2429
+ return true;
2430
+ }
2431
+ catch (error) {
2432
+ const message = error instanceof Error ? error.message : String(error);
2433
+ if (!message.includes('404')) {
2434
+ setStatusLine(`Config validation unavailable before save · ${firstLine(message)}`);
2435
+ }
2436
+ return true;
2437
+ }
2438
+ }, [baseUrl, showUtilityPanel]);
1500
2439
  const loadConnectorsDocument = useCallback(async () => {
1501
2440
  const payload = await client.configDocument(baseUrl, 'connectors');
1502
2441
  const structured = asRecord(payload.meta?.structured_config);
@@ -1553,6 +2492,8 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
1553
2492
  }
1554
2493
  setQuestPanelMode(null);
1555
2494
  setConfigView('files');
2495
+ setUtilityPanel(null);
2496
+ setUtilityPanelOverlay(false);
1556
2497
  setConfigEditor({
1557
2498
  kind: 'document',
1558
2499
  item,
@@ -1573,6 +2514,8 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
1573
2514
  : buildQuestConfigItems(selectedQuestForConfig?.quest_id ?? null, selectedQuestForConfig?.quest_root);
1574
2515
  setQuestPanelMode(null);
1575
2516
  setConfigView('files');
2517
+ setUtilityPanel(null);
2518
+ setUtilityPanelOverlay(false);
1576
2519
  setConfigItems(nextItems);
1577
2520
  setConfigSectionTitle(scope === 'global' ? 'Global Config Files' : 'Current Quest Files');
1578
2521
  setConfigSectionDescription(scope === 'global'
@@ -1602,6 +2545,8 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
1602
2545
  const openConfigRoot = useCallback((nextStatus = 'Config · choose a section with arrows and Enter.') => {
1603
2546
  setQuestPanelMode(null);
1604
2547
  setConfigView('root');
2548
+ setUtilityPanel(null);
2549
+ setUtilityPanelOverlay(false);
1605
2550
  setConfigEditor(null);
1606
2551
  setConfigItems([]);
1607
2552
  setConfigSectionTitle('Config');
@@ -1622,6 +2567,8 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
1622
2567
  const browseNames = names.length > 0 ? names : CONNECTOR_ORDER;
1623
2568
  setQuestPanelMode(null);
1624
2569
  setConfigView('connector-list');
2570
+ setUtilityPanel(null);
2571
+ setUtilityPanelOverlay(false);
1625
2572
  setConfigEditor(null);
1626
2573
  setConnectorsDocument(document);
1627
2574
  setSelectedConnectorName(null);
@@ -1710,6 +2657,8 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
1710
2657
  setConnectorsDocument(currentDocument);
1711
2658
  setSelectedConnectorName(connectorName);
1712
2659
  setConfigView('connector-detail');
2660
+ setUtilityPanel(null);
2661
+ setUtilityPanelOverlay(false);
1713
2662
  setConfigEditor(null);
1714
2663
  setWeixinQrState(null);
1715
2664
  setConfigIndex(0);
@@ -1738,6 +2687,10 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
1738
2687
  merged[selectedConnectorName] = cloneStructured(asRecord(connectorsDocument.structured[selectedConnectorName]));
1739
2688
  return merged;
1740
2689
  })();
2690
+ const valid = await validateConfigBeforeSave('connectors', { structured: structuredToSave });
2691
+ if (!valid) {
2692
+ return;
2693
+ }
1741
2694
  const payload = await client.saveStructuredConfig(baseUrl, 'connectors', structuredToSave, connectorsDocument.revision);
1742
2695
  if (!payload.ok) {
1743
2696
  setStatusLine(payload.message || payload.errors?.[0] || 'Connector save failed.');
@@ -1751,7 +2704,7 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
1751
2704
  catch (error) {
1752
2705
  setStatusLine(error instanceof Error ? error.message : String(error));
1753
2706
  }
1754
- }, [baseUrl, connectorsDocument, loadConnectorsDocument, refresh, selectedConnectorName]);
2707
+ }, [baseUrl, connectorsDocument, loadConnectorsDocument, refresh, selectedConnectorName, validateConfigBeforeSave]);
1755
2708
  const saveConfigEditor = useCallback(async (content) => {
1756
2709
  if (!configEditor) {
1757
2710
  return;
@@ -1765,6 +2718,10 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
1765
2718
  return;
1766
2719
  }
1767
2720
  if (configEditor.item.scope === 'global' && configEditor.item.configName) {
2721
+ const valid = await validateConfigBeforeSave(configEditor.item.configName, { content });
2722
+ if (!valid) {
2723
+ return;
2724
+ }
1768
2725
  const payload = await client.saveConfig(baseUrl, configEditor.item.configName, content, configEditor.revision);
1769
2726
  if (payload.ok === false) {
1770
2727
  setStatusLine(payload.message || payload.errors?.[0] || 'Config save failed.');
@@ -1786,13 +2743,13 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
1786
2743
  setInput('');
1787
2744
  setConfigEditor(null);
1788
2745
  setConfigView('files');
1789
- setStatusLine(`Saved ${configEditor.item.title}`);
1790
2746
  await refresh(true, activeQuestId);
2747
+ setStatusLine(`Saved ${configEditor.item.title}`);
1791
2748
  }
1792
2749
  catch (error) {
1793
2750
  setStatusLine(error instanceof Error ? error.message : String(error));
1794
2751
  }
1795
- }, [activeQuestId, baseUrl, configEditor, refresh, selectedQuestForConfig, updateConnectorDraft]);
2752
+ }, [activeQuestId, baseUrl, configEditor, refresh, selectedQuestForConfig, updateConnectorDraft, validateConfigBeforeSave]);
1796
2753
  const openConnectorFieldEditor = useCallback((fieldKey, fieldLabel, description, fieldKind) => {
1797
2754
  if (!selectedConnectorName) {
1798
2755
  return;
@@ -1951,9 +2908,11 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
1951
2908
  return;
1952
2909
  }
1953
2910
  if (selected.type === 'action') {
1954
- if (!selected.disabled) {
1955
- await handleConnectorAction(selected.id);
2911
+ if (selected.disabled) {
2912
+ setStatusLine(selected.disabledReason || selected.description || `${selected.label} is not available.`);
2913
+ return;
1956
2914
  }
2915
+ await handleConnectorAction(selected.id);
1957
2916
  return;
1958
2917
  }
1959
2918
  if (selected.type === 'field') {
@@ -2007,6 +2966,237 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
2007
2966
  setStatusLine(String(payload.message ?? `Quest ${selected.quest_id} ${fallbackVerb}.`));
2008
2967
  await focusQuest(selected.quest_id);
2009
2968
  }, [baseUrl, closeQuestPanel, focusQuest, panelQuests, questPanelIndex, questPanelMode]);
2969
+ const handleConfigSlashCommand = useCallback(async (arg) => {
2970
+ const tokens = splitCommandTokens(arg);
2971
+ const action = tokens[0]?.toLowerCase() || '';
2972
+ if (!['validate', 'test', 'deepxiv-test', 'deepxiv'].includes(action)) {
2973
+ return false;
2974
+ }
2975
+ if (action === 'deepxiv' && tokens[1]?.toLowerCase() !== 'test') {
2976
+ return false;
2977
+ }
2978
+ if (action === 'deepxiv-test' || action === 'deepxiv') {
2979
+ const document = await client.configDocument(baseUrl, 'config');
2980
+ const structured = asRecord(document.meta?.structured_config);
2981
+ const payload = await client.deepxivTest(baseUrl, structured);
2982
+ showUtilityPanel(buildConfigResultPanel('DeepXiv Test', 'config.literature.deepxiv', payload), payload.summary || (payload.ok ? 'DeepXiv test completed.' : 'DeepXiv test failed.'));
2983
+ return true;
2984
+ }
2985
+ const name = tokens.find((token, index) => index > 0 && !token.startsWith('--')) || 'config';
2986
+ const document = await client.configDocument(baseUrl, name);
2987
+ const structured = asRecord(document.meta?.structured_config);
2988
+ const input = Object.keys(structured).length > 0 ? { structured } : { content: document.content };
2989
+ if (action === 'validate') {
2990
+ const payload = await client.validateConfig(baseUrl, name, input);
2991
+ showUtilityPanel(buildConfigResultPanel('Config Validation', name, payload), payload.summary || (payload.ok ? `${name} validation passed.` : `${name} validation failed.`));
2992
+ return true;
2993
+ }
2994
+ const payload = await client.testConfig(baseUrl, name, {
2995
+ ...input,
2996
+ live: tokens.includes('--live'),
2997
+ });
2998
+ showUtilityPanel(buildConfigResultPanel('Config Test', name, payload), payload.summary || (payload.ok ? `${name} test passed.` : `${name} test failed.`));
2999
+ return true;
3000
+ }, [baseUrl, showUtilityPanel]);
3001
+ const handleBenchstoreCommand = useCallback(async (arg) => {
3002
+ const tokens = splitCommandTokens(arg);
3003
+ const action = tokens[0]?.toLowerCase() || 'list';
3004
+ const locale = parseLocaleFlag(tokens);
3005
+ if (action === 'list' || action === 'ls') {
3006
+ const payload = await client.benchstoreEntries(baseUrl, locale);
3007
+ showUtilityPanel(buildBenchCatalogPanel(payload), 'BenchStore catalog loaded.');
3008
+ return;
3009
+ }
3010
+ if (action === 'show' || action === 'detail') {
3011
+ const entryId = tokens[1];
3012
+ if (!entryId) {
3013
+ setStatusLine('Usage · /benchstore show <entry_id>');
3014
+ return;
3015
+ }
3016
+ const payload = await client.benchstoreEntry(baseUrl, entryId, locale);
3017
+ showUtilityPanel(buildBenchEntryPanel(payload.entry), `BenchStore · ${entryId}`);
3018
+ return;
3019
+ }
3020
+ if (action === 'setup') {
3021
+ const entryId = tokens[1];
3022
+ if (!entryId) {
3023
+ setStatusLine('Usage · /benchstore setup <entry_id>');
3024
+ return;
3025
+ }
3026
+ const payload = await client.benchstoreSetupPacket(baseUrl, entryId, locale);
3027
+ const packet = payload.setup_packet;
3028
+ showUtilityPanel({
3029
+ kind: 'benchstore',
3030
+ title: `BenchStore Setup · ${entryId}`,
3031
+ subtitle: packet.project_title || packet.assistant_label || undefined,
3032
+ sections: [
3033
+ {
3034
+ title: 'Launch',
3035
+ lines: [
3036
+ `goal: ${packet.launch_payload?.goal || packet.benchmark_goal || 'missing'}`,
3037
+ `initial_message: ${stringifyBrief(packet.launch_payload?.initial_message || packet.startup_instruction || '')}`,
3038
+ `device_fit: ${packet.device_fit || 'unknown'}`,
3039
+ ],
3040
+ },
3041
+ {
3042
+ title: 'Paths',
3043
+ lines: [
3044
+ `benchmark: ${packet.benchmark_local_path || 'not installed'}`,
3045
+ `datasets: ${(packet.local_dataset_paths || []).join(', ') || 'none'}`,
3046
+ ],
3047
+ },
3048
+ {
3049
+ title: 'Suggested Form',
3050
+ lines: [stringifyBrief(packet.suggested_form || {}, 800)],
3051
+ },
3052
+ ],
3053
+ footer: 'Use /benchstore launch <id> to create and start the benchmark quest.',
3054
+ }, `BenchStore setup packet loaded for ${entryId}.`);
3055
+ return;
3056
+ }
3057
+ if (action === 'install') {
3058
+ const entryId = tokens[1];
3059
+ if (!entryId) {
3060
+ setStatusLine('Usage · /benchstore install <entry_id>');
3061
+ return;
3062
+ }
3063
+ const payload = await client.installBenchstoreEntry(baseUrl, entryId);
3064
+ showUtilityPanel(buildTaskPanel(payload.task), `BenchStore install task started · ${payload.task.task_id}`);
3065
+ return;
3066
+ }
3067
+ if (action === 'launch' || action === 'run') {
3068
+ const entryId = tokens[1];
3069
+ if (!entryId) {
3070
+ setStatusLine('Usage · /benchstore launch <entry_id>');
3071
+ return;
3072
+ }
3073
+ const payload = await client.launchBenchstoreEntry(baseUrl, entryId, locale);
3074
+ setStatusLine(`BenchStore launched ${payload.snapshot.quest_id}.`);
3075
+ await focusQuest(payload.snapshot.quest_id);
3076
+ return;
3077
+ }
3078
+ const payload = await client.benchstoreEntries(baseUrl, locale);
3079
+ showUtilityPanel(buildBenchCatalogPanel(payload), `Unknown BenchStore action · ${action}`);
3080
+ }, [baseUrl, focusQuest, showUtilityPanel]);
3081
+ const handleTasksCommand = useCallback(async (arg) => {
3082
+ const token = splitCommandTokens(arg)[0];
3083
+ if (token) {
3084
+ const payload = await client.systemTask(baseUrl, token);
3085
+ showUtilityPanel(buildTaskPanel(payload.task), `Task ${payload.task.task_id}`);
3086
+ return;
3087
+ }
3088
+ const payload = await client.systemTasks(baseUrl, undefined, 50);
3089
+ showUtilityPanel(buildTasksPanel(payload.items), 'System tasks loaded.');
3090
+ }, [baseUrl, showUtilityPanel]);
3091
+ const handleDoctorCommand = useCallback(async () => {
3092
+ const payload = await client.startDoctorTask(baseUrl);
3093
+ showUtilityPanel(buildTaskPanel(payload.task), `Doctor task started · ${payload.task.task_id}`);
3094
+ }, [baseUrl, showUtilityPanel]);
3095
+ const handleBaselineCommand = useCallback(async (arg) => {
3096
+ const tokens = splitCommandTokens(arg);
3097
+ const action = tokens[0]?.toLowerCase() || 'list';
3098
+ if (action === 'list' || action === 'ls') {
3099
+ const entries = await client.baselines(baseUrl);
3100
+ showUtilityPanel(buildBaselinesPanel(entries), 'Baselines loaded.');
3101
+ return;
3102
+ }
3103
+ if (action === 'attach' || action === 'bind') {
3104
+ if (!activeQuestId) {
3105
+ setStatusLine('Open a quest first, then run /baseline attach <baseline_id> [variant_id].');
3106
+ return;
3107
+ }
3108
+ const baselineId = tokens[1];
3109
+ if (!baselineId) {
3110
+ setStatusLine('Usage · /baseline attach <baseline_id> [variant_id]');
3111
+ return;
3112
+ }
3113
+ const payload = await client.attachBaseline(baseUrl, activeQuestId, baselineId, tokens[2] || null);
3114
+ setStatusLine(String(payload.message || `Baseline ${baselineId} attached to ${activeQuestId}.`));
3115
+ await refresh(true, activeQuestId);
3116
+ return;
3117
+ }
3118
+ if (action === 'unbind' || action === 'clear') {
3119
+ if (!activeQuestId) {
3120
+ setStatusLine('Open a quest first, then run /baseline unbind.');
3121
+ return;
3122
+ }
3123
+ const payload = await client.unbindBaseline(baseUrl, activeQuestId);
3124
+ setStatusLine(String(payload.message || `Baseline binding cleared for ${activeQuestId}.`));
3125
+ await refresh(true, activeQuestId);
3126
+ return;
3127
+ }
3128
+ setStatusLine('Usage · /baseline [list] | /baseline attach <baseline_id> [variant_id] | /baseline unbind');
3129
+ }, [activeQuestId, baseUrl, refresh, showUtilityPanel]);
3130
+ const handleRunCommand = useCallback(async (arg) => {
3131
+ if (!activeQuestId) {
3132
+ setStatusLine('Open a quest first, then run /run <skill> <message>.');
3133
+ return;
3134
+ }
3135
+ const tokens = splitCommandTokens(arg);
3136
+ const skillId = tokens[0];
3137
+ if (!skillId) {
3138
+ setStatusLine('Usage · /run <skill_id> <message> [--runner <runner>] [--model <model>] [--effort <level>]');
3139
+ return;
3140
+ }
3141
+ let runner;
3142
+ let model;
3143
+ let effort;
3144
+ const messageParts = [];
3145
+ for (let index = 1; index < tokens.length; index += 1) {
3146
+ const token = tokens[index];
3147
+ if (token === '--runner') {
3148
+ runner = tokens[index + 1];
3149
+ index += 1;
3150
+ continue;
3151
+ }
3152
+ if (token.startsWith('--runner=')) {
3153
+ runner = token.slice('--runner='.length);
3154
+ continue;
3155
+ }
3156
+ if (token === '--model') {
3157
+ model = tokens[index + 1];
3158
+ index += 1;
3159
+ continue;
3160
+ }
3161
+ if (token.startsWith('--model=')) {
3162
+ model = token.slice('--model='.length);
3163
+ continue;
3164
+ }
3165
+ if (token === '--effort') {
3166
+ effort = tokens[index + 1];
3167
+ index += 1;
3168
+ continue;
3169
+ }
3170
+ if (token.startsWith('--effort=')) {
3171
+ effort = token.slice('--effort='.length);
3172
+ continue;
3173
+ }
3174
+ messageParts.push(token);
3175
+ }
3176
+ const message = messageParts.join(' ').trim();
3177
+ const payload = await client.runSkill(baseUrl, activeQuestId, {
3178
+ skill_id: skillId,
3179
+ message,
3180
+ runner,
3181
+ model,
3182
+ model_reasoning_effort: effort,
3183
+ turn_reason: 'tui_run_command',
3184
+ });
3185
+ showUtilityPanel({
3186
+ kind: 'run',
3187
+ title: `Run · ${skillId}`,
3188
+ subtitle: `${String(payload.runner || 'runner')} · ${String(payload.ok) === 'false' ? 'failed' : 'completed'}`,
3189
+ lines: [
3190
+ { label: 'quest', value: activeQuestId },
3191
+ { label: 'run_id', value: String(payload.run_id || 'unknown') },
3192
+ { label: 'model', value: String(payload.model || model || 'default') },
3193
+ ...(payload.output_text ? [{ label: 'output', value: stringifyBrief(payload.output_text, 900) }] : []),
3194
+ ...(payload.stderr_text ? [{ label: 'stderr', value: stringifyBrief(payload.stderr_text, 500), tone: 'warning' }] : []),
3195
+ ],
3196
+ footer: 'The quest feed is refreshed after the run completes.',
3197
+ }, `Run ${String(payload.run_id || skillId)} finished.`);
3198
+ await refresh(false, activeQuestId, { eventMode: 'recent' });
3199
+ }, [activeQuestId, baseUrl, refresh, showUtilityPanel]);
2010
3200
  const cycleQuest = useCallback((direction) => {
2011
3201
  if (configMode === 'browse') {
2012
3202
  if (configSelectionCount === 0) {
@@ -2046,7 +3236,7 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
2046
3236
  }, [initialQuestId, refresh]);
2047
3237
  useEffect(() => {
2048
3238
  const timer = setInterval(() => {
2049
- void refresh(false);
3239
+ void refresh(false, undefined, { eventMode: 'none' });
2050
3240
  }, 20000);
2051
3241
  return () => clearInterval(timer);
2052
3242
  }, [refresh]);
@@ -2115,7 +3305,7 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
2115
3305
  setConnectionState('connected');
2116
3306
  setStatusLine(`Connected · ${activeQuestId} · ${baseUrl}`);
2117
3307
  if (shouldRefreshForUpdate(update)) {
2118
- void refresh(false);
3308
+ void refresh(false, undefined, { eventMode: 'none' });
2119
3309
  }
2120
3310
  },
2121
3311
  onCursor: (nextCursor) => {
@@ -2235,12 +3425,40 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
2235
3425
  setInput('');
2236
3426
  try {
2237
3427
  const slash = parseSlashCommand(text);
3428
+ if (slash?.name === '/help') {
3429
+ showUtilityPanel(buildHelpPanel(), 'TUI help.');
3430
+ return;
3431
+ }
3432
+ if (slash?.name === '/debug') {
3433
+ showUtilityPanel(buildDebugPanel(debugSnapshot), 'TUI debug inspector.');
3434
+ return;
3435
+ }
2238
3436
  if (text === '/home') {
2239
3437
  closeQuestPanel();
2240
3438
  leaveQuest();
2241
3439
  setStatusLine('Home · request mode · quest unbound.');
2242
3440
  return;
2243
3441
  }
3442
+ if (slash?.name === '/benchstore') {
3443
+ await handleBenchstoreCommand(slash.arg);
3444
+ return;
3445
+ }
3446
+ if (slash?.name === '/doctor') {
3447
+ await handleDoctorCommand();
3448
+ return;
3449
+ }
3450
+ if (slash?.name === '/tasks') {
3451
+ await handleTasksCommand(slash.arg);
3452
+ return;
3453
+ }
3454
+ if (slash?.name === '/baseline') {
3455
+ await handleBaselineCommand(slash.arg);
3456
+ return;
3457
+ }
3458
+ if (slash?.name === '/run') {
3459
+ await handleRunCommand(slash.arg);
3460
+ return;
3461
+ }
2244
3462
  if (slash?.name === '/projects') {
2245
3463
  if (!slash.arg) {
2246
3464
  openQuestPanel('projects');
@@ -2320,6 +3538,9 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
2320
3538
  }
2321
3539
  if (slash?.name === '/config') {
2322
3540
  const arg = String(slash.arg || '').trim();
3541
+ if (await handleConfigSlashCommand(arg)) {
3542
+ return;
3543
+ }
2323
3544
  if (!arg) {
2324
3545
  openConfigRoot();
2325
3546
  return;
@@ -2363,8 +3584,19 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
2363
3584
  setStatusLine('Usage · /new <goal>');
2364
3585
  return;
2365
3586
  }
2366
- const payload = await client.createQuest(baseUrl, slash.arg);
2367
- setStatusLine(`Created ${payload.snapshot.quest_id}`);
3587
+ const createOnly = /(^|\s)(--no-start|--create-only)(?=\s|$)/.test(slash.arg);
3588
+ const goal = stripKnownFlags(slash.arg, ['--no-start', '--create-only']);
3589
+ if (!goal) {
3590
+ setStatusLine('Usage · /new <goal> [--no-start]');
3591
+ return;
3592
+ }
3593
+ const payload = await client.createQuestWithOptions(baseUrl, {
3594
+ goal,
3595
+ source: 'tui-ink',
3596
+ auto_start: !createOnly,
3597
+ initial_message: goal,
3598
+ });
3599
+ setStatusLine(createOnly ? `Created ${payload.snapshot.quest_id}` : `Created and started ${payload.snapshot.quest_id}`);
2368
3600
  await focusQuest(payload.snapshot.quest_id);
2369
3601
  return;
2370
3602
  }
@@ -2403,7 +3635,19 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
2403
3635
  }
2404
3636
  if (!activeQuestId) {
2405
3637
  if (text.startsWith('/')) {
2406
- setStatusLine('Home mode · use `/projects`, `/use <quest_id>`, or `/new <goal>` first.');
3638
+ if (!slash || !BACKEND_SLASH_COMMANDS.has(slash.name)) {
3639
+ showUtilityPanel({
3640
+ kind: 'help',
3641
+ title: 'Unknown TUI Command',
3642
+ subtitle: `${slash?.name || text} is not implemented by the TUI command registry.`,
3643
+ lines: [
3644
+ 'This command was blocked locally instead of being forwarded to the daemon skeleton fallback.',
3645
+ 'Use /help to see supported local commands.',
3646
+ ],
3647
+ }, `Unknown command · ${slash?.name || text}`);
3648
+ return;
3649
+ }
3650
+ setStatusLine('Open a quest first, then use that quest command.');
2407
3651
  return;
2408
3652
  }
2409
3653
  if (quests.length === 0) {
@@ -2414,6 +3658,18 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
2414
3658
  return;
2415
3659
  }
2416
3660
  if (text.startsWith('/')) {
3661
+ if (!slash || !BACKEND_SLASH_COMMANDS.has(slash.name)) {
3662
+ showUtilityPanel({
3663
+ kind: 'help',
3664
+ title: 'Unknown TUI Command',
3665
+ subtitle: `${slash?.name || text} is not implemented by the TUI command registry.`,
3666
+ lines: [
3667
+ 'This command was blocked locally instead of being forwarded to the daemon skeleton fallback.',
3668
+ 'Use /help to see supported local commands.',
3669
+ ],
3670
+ }, `Unknown command · ${slash?.name || text}`);
3671
+ return;
3672
+ }
2417
3673
  const payload = await client.sendCommand(baseUrl, activeQuestId, text);
2418
3674
  const messageRecord = (payload.message_record ?? null);
2419
3675
  const commandItems = [
@@ -2464,7 +3720,9 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
2464
3720
  : typeof payload.type === 'string'
2465
3721
  ? `command acknowledged: ${payload.type}`
2466
3722
  : 'command accepted');
2467
- await refresh(false, targetQuestId);
3723
+ await refresh(false, targetQuestId, {
3724
+ eventMode: targetQuestId && targetQuestId !== activeQuestId ? 'recent' : 'none',
3725
+ });
2468
3726
  return;
2469
3727
  }
2470
3728
  const localUserItem = createLocalUserFeedItem(text);
@@ -2492,10 +3750,17 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
2492
3750
  configEditor,
2493
3751
  configIndex,
2494
3752
  configMode,
3753
+ debugSnapshot,
2495
3754
  closeQuestPanel,
2496
3755
  focusQuest,
3756
+ handleBaselineCommand,
3757
+ handleBenchstoreCommand,
2497
3758
  handleConfigBrowseSelection,
3759
+ handleConfigSlashCommand,
3760
+ handleDoctorCommand,
2498
3761
  handleQuestPanelSelection,
3762
+ handleRunCommand,
3763
+ handleTasksCommand,
2499
3764
  input,
2500
3765
  leaveQuest,
2501
3766
  openConfigFiles,
@@ -2508,6 +3773,7 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
2508
3773
  refresh,
2509
3774
  replyTargetId,
2510
3775
  saveConfigEditor,
3776
+ showUtilityPanel,
2511
3777
  ]);
2512
3778
  const backFromConfigBrowse = useCallback(() => {
2513
3779
  if (!configView) {
@@ -2535,7 +3801,7 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
2535
3801
  setStatusLine('Back to Weixin connector details.');
2536
3802
  }
2537
3803
  }, [closeConfigScreen, configView, openConfigRoot]);
2538
- useInput((value, key) => {
3804
+ useSafeInput((value, key) => {
2539
3805
  const canBrowseSelection = configMode === 'browse' || Boolean(questPanelMode);
2540
3806
  const canBrowseHomeQuests = !activeQuestId && input.length === 0;
2541
3807
  const submitRequested = key.return || value === '\r' || value === '\n';
@@ -2555,7 +3821,15 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
2555
3821
  openConfigRoot();
2556
3822
  return;
2557
3823
  }
3824
+ if (key.ctrl && value.toLowerCase() === 'd') {
3825
+ showUtilityPanel(buildDebugPanel(debugSnapshot), 'TUI debug inspector.', { preserveContext: true });
3826
+ return;
3827
+ }
2558
3828
  if (key.ctrl && value.toLowerCase() === 'b') {
3829
+ if (utilityPanel) {
3830
+ closeUtilityPanel();
3831
+ return;
3832
+ }
2559
3833
  if (configMode) {
2560
3834
  closeConfigScreen();
2561
3835
  return;
@@ -2565,6 +3839,10 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
2565
3839
  return;
2566
3840
  }
2567
3841
  if (key.escape) {
3842
+ if (utilityPanel) {
3843
+ closeUtilityPanel();
3844
+ return;
3845
+ }
2568
3846
  if (configMode === 'edit') {
2569
3847
  setConfigEditor(null);
2570
3848
  setInput('');
@@ -2588,22 +3866,27 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
2588
3866
  return;
2589
3867
  }
2590
3868
  }
2591
- if (key.upArrow && ((configMode === 'browse') || canBrowseHomeQuests)) {
3869
+ if (key.upArrow && (configMode === 'browse') && !questPanelMode) {
2592
3870
  cycleQuest(-1);
2593
3871
  return;
2594
3872
  }
2595
- if ((key.downArrow || key.tab) && ((configMode === 'browse') || canBrowseHomeQuests)) {
3873
+ if ((key.downArrow || key.tab) && (configMode === 'browse') && !questPanelMode) {
2596
3874
  cycleQuest(1);
2597
3875
  return;
2598
3876
  }
2599
3877
  });
2600
- return (React.createElement(DefaultAppLayout, { baseUrl: baseUrl, quests: quests, activeQuestId: activeQuestId, browseQuestId: browseQuestId, configMode: configMode, configPanel: configPanel, snapshot: activeQuest, session: session, connectors: connectors, history: history, pendingHistoryItems: pendingHistoryItems, input: input, connectionState: connectionState, statusLine: statusLine, suggestions: slashSuggestions, questPanelMode: questPanelMode, questPanelQuests: panelQuests, questPanelIndex: questPanelIndex, onQuestPanelMove: (direction) => {
3878
+ const utilityOverlayActive = Boolean(utilityPanel && utilityPanelOverlay);
3879
+ const composerInput = utilityOverlayActive ? '' : input;
3880
+ return (React.createElement(DefaultAppLayout, { baseUrl: baseUrl, quests: quests, activeQuestId: activeQuestId, browseQuestId: browseQuestId, configMode: utilityOverlayActive ? null : configMode, configPanel: configPanel, utilityPanel: utilityPanel, snapshot: activeQuest, session: session, connectors: connectors, history: history, pendingHistoryItems: pendingHistoryItems, input: composerInput, connectionState: connectionState, statusLine: statusLine, debugSnapshot: debugEnabled || utilityPanel?.kind === 'debug' ? debugSnapshot : null, suggestions: slashSuggestions, questPanelMode: utilityOverlayActive ? null : questPanelMode, questPanelQuests: panelQuests, questPanelIndex: questPanelIndex, onQuestPanelMove: (direction) => {
2601
3881
  cycleQuest(direction);
2602
3882
  }, onQuestPanelConfirm: () => {
2603
3883
  void handleQuestPanelSelection();
2604
3884
  }, onQuestPanelCancel: () => {
2605
3885
  closeQuestPanel('Quest browser closed.');
2606
- }, onChange: setInput, onSubmit: (override) => {
3886
+ }, onChange: utilityOverlayActive ? () => { } : setInput, onSubmit: (override) => {
3887
+ if (utilityOverlayActive) {
3888
+ return;
3889
+ }
2607
3890
  const submitted = override ?? input;
2608
3891
  if (configMode === 'browse' && !String(submitted).trim()) {
2609
3892
  void handleConfigBrowseSelection();
@@ -2619,6 +3902,10 @@ export const AppContainer = ({ baseUrl, initialQuestId = null, authToken = null,
2619
3902
  }
2620
3903
  void submit(override);
2621
3904
  }, onCancel: () => {
3905
+ if (utilityPanel) {
3906
+ closeUtilityPanel();
3907
+ return;
3908
+ }
2622
3909
  if (configMode === 'edit') {
2623
3910
  setConfigEditor(null);
2624
3911
  setInput('');