@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.
- package/AGENTS.md +309 -130
- package/AISB/catalog/aisb.b1.agentic_coding.yaml +244 -0
- package/AISB/catalog/aisb.b10.climate_earth.yaml +235 -0
- package/AISB/catalog/aisb.b11.model_efficiency.yaml +231 -0
- package/AISB/catalog/aisb.b12.embodied_ai.yaml +238 -0
- package/AISB/catalog/aisb.b2.agent_systems.yaml +229 -0
- package/AISB/catalog/aisb.b3.self_evolving_rl.yaml +237 -0
- package/AISB/catalog/aisb.b4.lm_reasoning.yaml +240 -0
- package/AISB/catalog/aisb.b5.math_proof.yaml +235 -0
- package/AISB/catalog/aisb.b6.research_process.yaml +243 -0
- package/AISB/catalog/aisb.b7.multimodal_fusion.yaml +232 -0
- package/AISB/catalog/aisb.b8.lifesci_drug.yaml +275 -0
- package/AISB/catalog/aisb.b9.material_science.yaml +237 -0
- package/AISB/catalog/aisb.t3.001_savvy.yaml +159 -0
- package/AISB/catalog/aisb.t3.001_savvy.zh.yaml +121 -0
- package/AISB/catalog/aisb.t3.002_pinet.yaml +189 -0
- package/AISB/catalog/aisb.t3.002_pinet.zh.yaml +130 -0
- package/AISB/catalog/aisb.t3.004_decentralattn.yaml +184 -0
- package/AISB/catalog/aisb.t3.004_decentralattn.zh.yaml +153 -0
- package/AISB/catalog/aisb.t3.005_tsae.yaml +193 -0
- package/AISB/catalog/aisb.t3.005_tsae.zh.yaml +139 -0
- package/AISB/catalog/aisb.t3.006_physense.yaml +194 -0
- package/AISB/catalog/aisb.t3.006_physense.zh.yaml +118 -0
- package/AISB/catalog/aisb.t3.007_reasoningiqa.yaml +169 -0
- package/AISB/catalog/aisb.t3.007_reasoningiqa.zh.yaml +133 -0
- package/AISB/catalog/aisb.t3.008_meanflows.yaml +188 -0
- package/AISB/catalog/aisb.t3.008_meanflows.zh.yaml +140 -0
- package/AISB/catalog/aisb.t3.009_scoremissing.yaml +179 -0
- package/AISB/catalog/aisb.t3.009_scoremissing.zh.yaml +119 -0
- package/AISB/catalog/aisb.t3.010_suitabilityfilter.yaml +221 -0
- package/AISB/catalog/aisb.t3.010_suitabilityfilter.zh.yaml +141 -0
- package/AISB/catalog/aisb.t3.011_osd.yaml +206 -0
- package/AISB/catalog/aisb.t3.011_osd.zh.yaml +163 -0
- package/AISB/catalog/aisb.t3.012_efficientqat.yaml +206 -0
- package/AISB/catalog/aisb.t3.012_efficientqat.zh.yaml +159 -0
- package/AISB/catalog/aisb.t3.013_appl.yaml +152 -0
- package/AISB/catalog/aisb.t3.013_appl.zh.yaml +126 -0
- package/AISB/catalog/aisb.t3.014_piguard.yaml +207 -0
- package/AISB/catalog/aisb.t3.014_piguard.zh.yaml +164 -0
- package/AISB/catalog/aisb.t3.015_frspec.yaml +209 -0
- package/AISB/catalog/aisb.t3.015_frspec.zh.yaml +163 -0
- package/AISB/catalog/aisb.t3.016_mathfusion.yaml +166 -0
- package/AISB/catalog/aisb.t3.016_mathfusion.zh.yaml +145 -0
- package/AISB/catalog/aisb.t3.017_multimodalglp.yaml +171 -0
- package/AISB/catalog/aisb.t3.017_multimodalglp.zh.yaml +122 -0
- package/AISB/catalog/aisb.t3.018_cotsynth.yaml +206 -0
- package/AISB/catalog/aisb.t3.018_cotsynth.zh.yaml +162 -0
- package/AISB/catalog/aisb.t3.019_dyscaleut.yaml +211 -0
- package/AISB/catalog/aisb.t3.019_dyscaleut.zh.yaml +148 -0
- package/AISB/catalog/aisb.t3.020_aristotle.yaml +173 -0
- package/AISB/catalog/aisb.t3.020_aristotle.zh.yaml +119 -0
- package/AISB/catalog/aisb.t3.021_tokenrecycling.yaml +160 -0
- package/AISB/catalog/aisb.t3.021_tokenrecycling.zh.yaml +129 -0
- package/AISB/catalog/aisb.t3.022_chainofreasoning.yaml +204 -0
- package/AISB/catalog/aisb.t3.022_chainofreasoning.zh.yaml +161 -0
- package/AISB/catalog/aisb.t3.023_guidedembed.yaml +211 -0
- package/AISB/catalog/aisb.t3.023_guidedembed.zh.yaml +189 -0
- package/AISB/catalog/aisb.t3.024_outputcentric.yaml +148 -0
- package/AISB/catalog/aisb.t3.024_outputcentric.zh.yaml +131 -0
- package/AISB/catalog/aisb.t3.025_deeper.yaml +143 -0
- package/AISB/catalog/aisb.t3.025_deeper.zh.yaml +116 -0
- package/AISB/catalog/aisb.t3.026_gartkg.yaml +195 -0
- package/AISB/catalog/aisb.t3.026_gartkg.zh.yaml +127 -0
- package/AISB/catalog/aisb.t3.027_citeeval.yaml +182 -0
- package/AISB/catalog/aisb.t3.027_citeeval.zh.yaml +135 -0
- package/AISB/catalog/aisb.t3.028_sbam.yaml +206 -0
- package/AISB/catalog/aisb.t3.028_sbam.zh.yaml +166 -0
- package/AISB/catalog/aisb.t3.029_cdqgeoembed.yaml +224 -0
- package/AISB/catalog/aisb.t3.029_cdqgeoembed.zh.yaml +142 -0
- package/AISB/catalog/aisb.t3.030_processrm.yaml +211 -0
- package/AISB/catalog/aisb.t3.030_processrm.zh.yaml +166 -0
- package/AISB/catalog/aisb.t3.031_circuitstability.yaml +172 -0
- package/AISB/catalog/aisb.t3.031_circuitstability.zh.yaml +134 -0
- package/AISB/catalog/aisb.t3.032_ptsolver.yaml +169 -0
- package/AISB/catalog/aisb.t3.032_ptsolver.zh.yaml +135 -0
- package/AISB/catalog/aisb.t3.033_gcse.yaml +144 -0
- package/AISB/catalog/aisb.t3.033_gcse.zh.yaml +126 -0
- package/AISB/catalog/aisb.t3.034_ensemblewm.yaml +183 -0
- package/AISB/catalog/aisb.t3.034_ensemblewm.zh.yaml +146 -0
- package/AISB/catalog/aisb.t3.035_moralvalueswa.yaml +207 -0
- package/AISB/catalog/aisb.t3.035_moralvalueswa.zh.yaml +165 -0
- package/AISB/catalog/aisb.t3.036_weakstrongpref.yaml +210 -0
- package/AISB/catalog/aisb.t3.036_weakstrongpref.zh.yaml +194 -0
- package/AISB/catalog/aisb.t3.037_dementiamask.yaml +172 -0
- package/AISB/catalog/aisb.t3.037_dementiamask.zh.yaml +132 -0
- package/AISB/catalog/aisb.t3.038_tinysam.yaml +284 -0
- package/AISB/catalog/aisb.t3.038_tinysam.zh.yaml +240 -0
- package/AISB/catalog/aisb.t3.039_calf.yaml +224 -0
- package/AISB/catalog/aisb.t3.039_calf.zh.yaml +194 -0
- package/AISB/catalog/aisb.t3.040_graniteguardian.yaml +199 -0
- package/AISB/catalog/aisb.t3.040_graniteguardian.zh.yaml +174 -0
- package/AISB/catalog/aisb.t3.041_amdm.yaml +149 -0
- package/AISB/catalog/aisb.t3.041_amdm.zh.yaml +137 -0
- package/AISB/catalog/aisb.t3.042_xpatch.yaml +216 -0
- package/AISB/catalog/aisb.t3.042_xpatch.zh.yaml +182 -0
- package/AISB/catalog/aisb.t3.043_vhm.yaml +268 -0
- package/AISB/catalog/aisb.t3.043_vhm.zh.yaml +193 -0
- package/AISB/catalog/aisb.t3.044_rgvi.yaml +224 -0
- package/AISB/catalog/aisb.t3.044_rgvi.zh.yaml +176 -0
- package/AISB/catalog/aisb.t3.045_pslstm.yaml +203 -0
- package/AISB/catalog/aisb.t3.045_pslstm.zh.yaml +179 -0
- package/AISB/catalog/aisb.t3.046_nonstatts.yaml +208 -0
- package/AISB/catalog/aisb.t3.046_nonstatts.zh.yaml +194 -0
- package/AISB/catalog/aisb.t3.047_timepfn.yaml +156 -0
- package/AISB/catalog/aisb.t3.047_timepfn.zh.yaml +124 -0
- package/AISB/catalog/aisb.t3.048_proxyspex.yaml +148 -0
- package/AISB/catalog/aisb.t3.048_proxyspex.zh.yaml +125 -0
- package/AISB/catalog/aisb.t3.049_hogwildinference.yaml +183 -0
- package/AISB/catalog/aisb.t3.049_hogwildinference.zh.yaml +138 -0
- package/AISB/catalog/aisb.t3.050_causalpfn.yaml +214 -0
- package/AISB/catalog/aisb.t3.050_causalpfn.zh.yaml +190 -0
- package/AISB/catalog/aisb.t3.051_flashtp.yaml +169 -0
- package/AISB/catalog/aisb.t3.051_flashtp.zh.yaml +124 -0
- package/AISB/catalog/aisb.t3.052_nsdiff.yaml +155 -0
- package/AISB/catalog/aisb.t3.052_nsdiff.zh.yaml +138 -0
- package/AISB/catalog/aisb.t3.053_k2vae.yaml +158 -0
- package/AISB/catalog/aisb.t3.053_k2vae.zh.yaml +132 -0
- package/AISB/catalog/aisb.t3.054_timebase.yaml +178 -0
- package/AISB/catalog/aisb.t3.054_timebase.zh.yaml +158 -0
- package/AISB/catalog/aisb.t3.055_csbrain.yaml +238 -0
- package/AISB/catalog/aisb.t3.055_csbrain.zh.yaml +184 -0
- package/AISB/catalog/aisb.t3.056_infosam.yaml +224 -0
- package/AISB/catalog/aisb.t3.056_infosam.zh.yaml +189 -0
- package/AISB/catalog/aisb.t3.057_mdreid.yaml +129 -0
- package/AISB/catalog/aisb.t3.057_mdreid.zh.yaml +117 -0
- package/AISB/catalog/aisb.t3.058_mindglitch.yaml +171 -0
- package/AISB/catalog/aisb.t3.058_mindglitch.zh.yaml +145 -0
- package/AISB/catalog/aisb.t3.059_selfsupervised.yaml +154 -0
- package/AISB/catalog/aisb.t3.059_selfsupervised.zh.yaml +125 -0
- package/AISB/catalog/aisb.t3.060_iaggad.yaml +121 -0
- package/AISB/catalog/aisb.t3.060_iaggad.zh.yaml +100 -0
- package/AISB/catalog/aisb.t3.061_hsgkn.yaml +136 -0
- package/AISB/catalog/aisb.t3.061_hsgkn.zh.yaml +113 -0
- package/AISB/catalog/aisb.t3.062_visionts.yaml +237 -0
- package/AISB/catalog/aisb.t3.062_visionts.zh.yaml +216 -0
- package/AISB/catalog/aisb.t3.063_tsrag.yaml +162 -0
- package/AISB/catalog/aisb.t3.063_tsrag.zh.yaml +138 -0
- package/AISB/catalog/aisb.t3.064_pir.yaml +221 -0
- package/AISB/catalog/aisb.t3.064_pir.zh.yaml +197 -0
- package/AISB/catalog/aisb.t3.065_proteinbinding.yaml +234 -0
- package/AISB/catalog/aisb.t3.065_proteinbinding.zh.yaml +167 -0
- package/AISB/catalog/aisb.t3.066_tropicalattention.yaml +267 -0
- package/AISB/catalog/aisb.t3.066_tropicalattention.zh.yaml +229 -0
- package/AISB/catalog/aisb.t3.067_kanad.yaml +193 -0
- package/AISB/catalog/aisb.t3.067_kanad.zh.yaml +167 -0
- package/AISB/catalog/aisb.t3.068_sempo.yaml +187 -0
- package/AISB/catalog/aisb.t3.068_sempo.zh.yaml +148 -0
- package/AISB/catalog/aisb.t3.069_treehfd.yaml +129 -0
- package/AISB/catalog/aisb.t3.069_treehfd.zh.yaml +111 -0
- package/AISB/catalog/aisb.t3.070_certifiedunlearning.yaml +224 -0
- package/AISB/catalog/aisb.t3.070_certifiedunlearning.zh.yaml +171 -0
- package/AISB/catalog/aisb.t3.071_neuralmjd.yaml +142 -0
- package/AISB/catalog/aisb.t3.071_neuralmjd.zh.yaml +120 -0
- package/AISB/catalog/aisb.t3.072_fedgmt.yaml +181 -0
- package/AISB/catalog/aisb.t3.072_fedgmt.zh.yaml +158 -0
- package/AISB/catalog/aisb.t3.073_rld.yaml +161 -0
- package/AISB/catalog/aisb.t3.073_rld.zh.yaml +129 -0
- package/AISB/catalog/aisb.t3.074_lsvi.yaml +163 -0
- package/AISB/catalog/aisb.t3.074_lsvi.zh.yaml +129 -0
- package/AISB/catalog/aisb.t3.075_treeslicedentropy.yaml +201 -0
- package/AISB/catalog/aisb.t3.075_treeslicedentropy.zh.yaml +148 -0
- package/AISB/catalog/aisb.t3.076_aanet.yaml +169 -0
- package/AISB/catalog/aisb.t3.076_aanet.zh.yaml +129 -0
- package/AISB/catalog/aisb.t3.077_cmnn.yaml +199 -0
- package/AISB/catalog/aisb.t3.077_cmnn.zh.yaml +165 -0
- package/AISB/catalog/aisb.t3.078_conformalanomaly.yaml +146 -0
- package/AISB/catalog/aisb.t3.078_conformalanomaly.zh.yaml +117 -0
- package/AISB/catalog/aisb.t3.079_dpfkmeans.yaml +131 -0
- package/AISB/catalog/aisb.t3.079_dpfkmeans.zh.yaml +104 -0
- package/AISB/catalog/aisb.t3.080_latentscorereweight.yaml +169 -0
- package/AISB/catalog/aisb.t3.080_latentscorereweight.zh.yaml +123 -0
- package/AISB/catalog/aisb.t3.081_qmamba.yaml +150 -0
- package/AISB/catalog/aisb.t3.081_qmamba.zh.yaml +117 -0
- package/AISB/catalog/aisb.t3.082_onlinellmrouting.yaml +160 -0
- package/AISB/catalog/aisb.t3.082_onlinellmrouting.zh.yaml +133 -0
- package/AISB/catalog/aisb.t3.083_starformer.yaml +178 -0
- package/AISB/catalog/aisb.t3.083_starformer.zh.yaml +140 -0
- package/AISB/catalog/aisb.t3.084_ift.yaml +139 -0
- package/AISB/catalog/aisb.t3.084_ift.zh.yaml +111 -0
- package/AISB/catalog/aisb.t3.085_neuralsurv.yaml +183 -0
- package/AISB/catalog/aisb.t3.085_neuralsurv.zh.yaml +143 -0
- package/AISB/catalog/aisb.t3.086_stella.yaml +197 -0
- package/AISB/catalog/aisb.t3.086_stella.zh.yaml +142 -0
- package/AISB/catalog/aisb.t3.087_moses.yaml +167 -0
- package/AISB/catalog/aisb.t3.087_moses.zh.yaml +132 -0
- package/AISB/catalog/aisb.t3.088_channelnorm.yaml +140 -0
- package/AISB/catalog/aisb.t3.088_channelnorm.zh.yaml +109 -0
- package/AISB/catalog/aisb.t3.089_causalvelocity.yaml +730 -0
- package/AISB/catalog/aisb.t3.089_causalvelocity.zh.yaml +668 -0
- package/AISB/catalog/aisb.t3.090_rstib.yaml +144 -0
- package/AISB/catalog/aisb.t3.090_rstib.zh.yaml +109 -0
- package/AISB/catalog/aisb.t3.091_timeawarecausal.yaml +132 -0
- package/AISB/catalog/aisb.t3.091_timeawarecausal.zh.yaml +107 -0
- package/AISB/catalog/aisb.t3.092_kmeanslocalopt.yaml +138 -0
- package/AISB/catalog/aisb.t3.092_kmeanslocalopt.zh.yaml +110 -0
- package/AISB/catalog/aisb.t3.093_fedwmsam.yaml +134 -0
- package/AISB/catalog/aisb.t3.093_fedwmsam.zh.yaml +106 -0
- package/AISB/catalog/aisb.t3.094_boundre.yaml +147 -0
- package/AISB/catalog/aisb.t3.094_boundre.zh.yaml +114 -0
- package/AISB/catalog/aisb.t3.095_fastfeaturecp.yaml +153 -0
- package/AISB/catalog/aisb.t3.095_fastfeaturecp.zh.yaml +118 -0
- package/AISB/catalog/aisb.t3.096_m3svm.yaml +189 -0
- package/AISB/catalog/aisb.t3.096_m3svm.zh.yaml +149 -0
- package/AISB/catalog/aisb.t3.097_wassersteintl.yaml +212 -0
- package/AISB/catalog/aisb.t3.097_wassersteintl.zh.yaml +169 -0
- package/AISB/catalog/aisb.t3.098_xmahalanobis.yaml +171 -0
- package/AISB/catalog/aisb.t3.098_xmahalanobis.zh.yaml +127 -0
- package/AISB/catalog/aisb.t3.099_ollalanding.yaml +248 -0
- package/AISB/catalog/aisb.t3.099_ollalanding.zh.yaml +182 -0
- package/AISB/catalog/aisb.t3.100_invmissingdata.yaml +179 -0
- package/AISB/catalog/aisb.t3.100_invmissingdata.zh.yaml +150 -0
- package/AISB/catalog/aisb.t3.101_acia.yaml +164 -0
- package/AISB/catalog/aisb.t3.101_acia.zh.yaml +109 -0
- package/AISB/catalog/aisb.t3.102_stochasticff.yaml +178 -0
- package/AISB/catalog/aisb.t3.102_stochasticff.zh.yaml +130 -0
- package/AISB/catalog/aisb.t3.103_qdcp.yaml +150 -0
- package/AISB/catalog/aisb.t3.103_qdcp.zh.yaml +116 -0
- package/AISB/catalog/aisb.t3.104_balancedactiveinf.yaml +137 -0
- package/AISB/catalog/aisb.t3.104_balancedactiveinf.zh.yaml +104 -0
- package/AISB/catalog/aisb.t3.105_binaryclasseval.yaml +161 -0
- package/AISB/catalog/aisb.t3.105_binaryclasseval.zh.yaml +130 -0
- package/AISB/image/001_aisb.t3.001_savvy.jpg +0 -0
- package/AISB/image/002_aisb.t3.002_pinet.jpg +0 -0
- package/AISB/image/003_aisb.t3.003_dmsqd.jpg +0 -0
- package/AISB/image/004_aisb.t3.004_decentralattn.jpg +0 -0
- package/AISB/image/005_aisb.t3.005_tsae.jpg +0 -0
- package/AISB/image/006_aisb.t3.006_physense.jpg +0 -0
- package/AISB/image/007_aisb.t3.007_reasoningiqa.jpg +0 -0
- package/AISB/image/008_aisb.t3.008_meanflows.jpg +0 -0
- package/AISB/image/009_aisb.t3.009_scoremissing.jpg +0 -0
- package/AISB/image/010_aisb.t3.010_suitabilityfilter.jpg +0 -0
- package/AISB/image/011_aisb.t3.011_osd.jpg +0 -0
- package/AISB/image/012_aisb.t3.012_efficientqat.jpg +0 -0
- package/AISB/image/013_aisb.t3.013_appl.jpg +0 -0
- package/AISB/image/014_aisb.t3.014_piguard.jpg +0 -0
- package/AISB/image/015_aisb.t3.015_frspec.jpg +0 -0
- package/AISB/image/016_aisb.t3.016_mathfusion.jpg +0 -0
- package/AISB/image/017_aisb.t3.017_multimodalglp.jpg +0 -0
- package/AISB/image/018_aisb.t3.018_cotsynth.jpg +0 -0
- package/AISB/image/019_aisb.t3.019_dyscaleut.jpg +0 -0
- package/AISB/image/020_aisb.t3.020_aristotle.jpg +0 -0
- package/AISB/image/021_aisb.t3.021_tokenrecycling.jpg +0 -0
- package/AISB/image/022_aisb.t3.022_chainofreasoning.jpg +0 -0
- package/AISB/image/023_aisb.t3.023_guidedembed.jpg +0 -0
- package/AISB/image/024_aisb.t3.024_outputcentric.jpg +0 -0
- package/AISB/image/025_aisb.t3.025_deeper.jpg +0 -0
- package/AISB/image/026_aisb.t3.026_gartkg.jpg +0 -0
- package/AISB/image/027_aisb.t3.027_citeeval.jpg +0 -0
- package/AISB/image/028_aisb.t3.028_sbam.jpg +0 -0
- package/AISB/image/029_aisb.t3.029_cdqgeoembed.jpg +0 -0
- package/AISB/image/030_aisb.t3.030_processrm.jpg +0 -0
- package/AISB/image/031_aisb.t3.031_circuitstability.jpg +0 -0
- package/AISB/image/032_aisb.t3.032_ptsolver.jpg +0 -0
- package/AISB/image/033_aisb.t3.033_gcse.jpg +0 -0
- package/AISB/image/034_aisb.t3.034_ensemblewm.jpg +0 -0
- package/AISB/image/035_aisb.t3.035_moralvalueswa.jpg +0 -0
- package/AISB/image/036_aisb.t3.036_weakstrongpref.jpg +0 -0
- package/AISB/image/037_aisb.t3.037_dementiamask.jpg +0 -0
- package/AISB/image/038_aisb.t3.038_tinysam.jpg +0 -0
- package/AISB/image/039_aisb.t3.039_calf.jpg +0 -0
- package/AISB/image/040_aisb.t3.040_graniteguardian.jpg +0 -0
- package/AISB/image/041_aisb.t3.041_amdm.jpg +0 -0
- package/AISB/image/042_aisb.t3.042_xpatch.jpg +0 -0
- package/AISB/image/043_aisb.t3.043_vhm.jpg +0 -0
- package/AISB/image/044_aisb.t3.044_rgvi.jpg +0 -0
- package/AISB/image/045_aisb.t3.045_pslstm.jpg +0 -0
- package/AISB/image/046_aisb.t3.046_nonstatts.jpg +0 -0
- package/AISB/image/047_aisb.t3.047_timepfn.jpg +0 -0
- package/AISB/image/048_aisb.t3.048_proxyspex.jpg +0 -0
- package/AISB/image/049_aisb.t3.049_hogwildinference.jpg +0 -0
- package/AISB/image/050_aisb.t3.050_causalpfn.jpg +0 -0
- package/AISB/image/051_aisb.t3.051_flashtp.jpg +0 -0
- package/AISB/image/052_aisb.t3.052_nsdiff.jpg +0 -0
- package/AISB/image/053_aisb.t3.053_k2vae.jpg +0 -0
- package/AISB/image/054_aisb.t3.054_timebase.jpg +0 -0
- package/AISB/image/055_aisb.t3.055_csbrain.jpg +0 -0
- package/AISB/image/056_aisb.t3.056_infosam.jpg +0 -0
- package/AISB/image/057_aisb.t3.057_mdreid.jpg +0 -0
- package/AISB/image/058_aisb.t3.058_mindglitch.jpg +0 -0
- package/AISB/image/059_aisb.t3.059_selfsupervised.jpg +0 -0
- package/AISB/image/060_aisb.t3.060_iaggad.jpg +0 -0
- package/AISB/image/061_aisb.t3.061_hsgkn.jpg +0 -0
- package/AISB/image/062_aisb.t3.062_visionts.jpg +0 -0
- package/AISB/image/063_aisb.t3.063_tsrag.jpg +0 -0
- package/AISB/image/064_aisb.t3.064_pir.jpg +0 -0
- package/AISB/image/065_aisb.t3.065_proteinbinding.jpg +0 -0
- package/AISB/image/066_aisb.t3.066_tropicalattention.jpg +0 -0
- package/AISB/image/067_aisb.t3.067_kanad.jpg +0 -0
- package/AISB/image/068_aisb.t3.068_sempo.jpg +0 -0
- package/AISB/image/069_aisb.t3.069_treehfd.jpg +0 -0
- package/AISB/image/070_aisb.t3.070_certifiedunlearning.jpg +0 -0
- package/AISB/image/071_aisb.t3.071_neuralmjd.jpg +0 -0
- package/AISB/image/072_aisb.t3.072_fedgmt.jpg +0 -0
- package/AISB/image/073_aisb.t3.073_rld.jpg +0 -0
- package/AISB/image/074_aisb.t3.074_lsvi.jpg +0 -0
- package/AISB/image/075_aisb.t3.075_treeslicedentropy.jpg +0 -0
- package/AISB/image/076_aisb.t3.076_aanet.jpg +0 -0
- package/AISB/image/077_aisb.t3.077_cmnn.jpg +0 -0
- package/AISB/image/078_aisb.t3.078_conformalanomaly.jpg +0 -0
- package/AISB/image/079_aisb.t3.079_dpfkmeans.jpg +0 -0
- package/AISB/image/080_aisb.t3.080_latentscorereweight.jpg +0 -0
- package/AISB/image/081_aisb.t3.081_qmamba.jpg +0 -0
- package/AISB/image/082_aisb.t3.082_onlinellmrouting.jpg +0 -0
- package/AISB/image/083_aisb.t3.083_starformer.jpg +0 -0
- package/AISB/image/084_aisb.t3.084_ift.jpg +0 -0
- package/AISB/image/085_aisb.t3.085_neuralsurv.jpg +0 -0
- package/AISB/image/086_aisb.t3.086_stella.jpg +0 -0
- package/AISB/image/087_aisb.t3.087_moses.jpg +0 -0
- package/AISB/image/088_aisb.t3.088_channelnorm.jpg +0 -0
- package/AISB/image/089_aisb.t3.089_causalvelocity.jpg +0 -0
- package/AISB/image/090_aisb.t3.090_rstib.jpg +0 -0
- package/AISB/image/091_aisb.t3.091_timeawarecausal.jpg +0 -0
- package/AISB/image/092_aisb.t3.092_kmeanslocalopt.jpg +0 -0
- package/AISB/image/093_aisb.t3.093_fedwmsam.jpg +0 -0
- package/AISB/image/094_aisb.t3.094_boundre.jpg +0 -0
- package/AISB/image/095_aisb.t3.095_fastfeaturecp.jpg +0 -0
- package/AISB/image/096_aisb.t3.096_m3svm.jpg +0 -0
- package/AISB/image/097_aisb.t3.097_wassersteintl.jpg +0 -0
- package/AISB/image/098_aisb.t3.098_xmahalanobis.jpg +0 -0
- package/AISB/image/099_aisb.t3.099_ollalanding.jpg +0 -0
- package/AISB/image/100_aisb.t3.100_invmissingdata.jpg +0 -0
- package/AISB/image/101_aisb.t3.101_acia.jpg +0 -0
- package/AISB/image/102_aisb.t3.102_stochasticff.jpg +0 -0
- package/AISB/image/103_aisb.t3.103_qdcp.jpg +0 -0
- package/AISB/image/104_aisb.t3.104_balancedactiveinf.jpg +0 -0
- package/AISB/image/105_aisb.t3.105_binaryclasseval.jpg +0 -0
- package/AISB/image/106_aisb.t1.reasoning_lite.jpg +0 -0
- package/AISB/image/107_aisb.t2.paper_audit.jpg +0 -0
- package/AISB/image/108_aisb.t3.multi_gpu_search.jpg +0 -0
- package/AISB/image/109_aisb.t3.tdc_admet.jpg +0 -0
- package/AISB/image/aisb.b1.agentic_coding.svg +16 -0
- package/AISB/image/aisb.b10.climate_earth.svg +16 -0
- package/AISB/image/aisb.b11.model_efficiency.svg +16 -0
- package/AISB/image/aisb.b12.embodied_ai.svg +16 -0
- package/AISB/image/aisb.b2.agent_systems.svg +16 -0
- package/AISB/image/aisb.b3.self_evolving_rl.svg +16 -0
- package/AISB/image/aisb.b4.lm_reasoning.svg +16 -0
- package/AISB/image/aisb.b5.math_proof.svg +16 -0
- package/AISB/image/aisb.b6.research_process.svg +16 -0
- package/AISB/image/aisb.b7.multimodal_fusion.svg +16 -0
- package/AISB/image/aisb.b8.lifesci_drug.svg +16 -0
- package/AISB/image/aisb.b9.material_science.svg +16 -0
- package/README.md +196 -32
- package/bin/ds.js +924 -66
- package/docs/en/00_QUICK_START.md +195 -18
- package/docs/en/01_SETTINGS_REFERENCE.md +468 -96
- package/docs/en/02_START_RESEARCH_GUIDE.md +26 -5
- package/docs/en/03_QQ_CONNECTOR_GUIDE.md +14 -3
- package/docs/en/04_LINGZHU_CONNECTOR_GUIDE.md +2 -0
- package/docs/en/05_TUI_GUIDE.md +171 -2
- package/docs/en/07_MEMORY_AND_MCP.md +38 -2
- package/docs/en/09_DOCTOR.md +78 -7
- package/docs/en/10_WEIXIN_CONNECTOR_GUIDE.md +38 -1
- package/docs/en/11_LICENSE_AND_RISK.md +4 -0
- package/docs/en/12_GUIDED_WORKFLOW_TOUR.md +15 -0
- package/docs/en/14_PROMPT_SKILLS_AND_MCP_GUIDE.md +9 -0
- package/docs/en/15_CODEX_PROVIDER_SETUP.md +624 -180
- package/docs/en/16_TELEGRAM_CONNECTOR_GUIDE.md +14 -0
- package/docs/en/17_WHATSAPP_CONNECTOR_GUIDE.md +14 -0
- package/docs/en/18_FEISHU_CONNECTOR_GUIDE.md +14 -0
- package/docs/en/21_LOCAL_MODEL_BACKENDS_GUIDE.md +386 -0
- package/docs/en/22_BENCHSTORE_YAML_REFERENCE.md +469 -0
- package/docs/en/23_BENCHSTORE_GITHUB_RELEASES_SPEC.md +316 -0
- package/docs/en/24_CLAUDE_CODE_PROVIDER_SETUP.md +469 -0
- package/docs/en/25_OPENCODE_PROVIDER_SETUP.md +653 -0
- package/docs/en/26_CITATION_AND_ATTRIBUTION.md +119 -0
- package/docs/en/27_KIMI_CODE_PROVIDER_SETUP.md +180 -0
- package/docs/en/28_DISCORD_CONNECTOR_GUIDE.md +61 -0
- package/docs/en/29_SLACK_CONNECTOR_GUIDE.md +60 -0
- package/docs/en/30_SETTINGS_CONTROL_CENTER_GUIDE.md +371 -0
- package/docs/en/{19_LOCAL_BROWSER_AUTH.md → 31_LOCAL_BROWSER_AUTH.md} +1 -1
- package/docs/en/32_WINDOWS_WSL2_DEPLOYMENT_GUIDE.md +273 -0
- package/docs/en/33_WORKSPACE_EXPLORER_QA.md +121 -0
- package/docs/en/91_DEVELOPMENT.md +266 -0
- package/docs/en/99_ACKNOWLEDGEMENTS.md +24 -19
- package/docs/en/README.md +48 -7
- package/docs/images/admin/admin-connectors-health-en.png +0 -0
- package/docs/images/admin/admin-controllers-en.png +0 -0
- package/docs/images/admin/admin-diagnostics-en.png +0 -0
- package/docs/images/admin/admin-errors-en.png +0 -0
- package/docs/images/admin/admin-issues-en.png +0 -0
- package/docs/images/admin/admin-logs-en.png +0 -0
- package/docs/images/admin/admin-quest-detail-en.png +0 -0
- package/docs/images/admin/admin-quests-en.png +0 -0
- package/docs/images/admin/admin-repairs-en.png +0 -0
- package/docs/images/admin/admin-runtime-en.png +0 -0
- package/docs/images/admin/admin-search-en.png +0 -0
- package/docs/images/admin/admin-stats-en.png +0 -0
- package/docs/images/admin/admin-summary-en.png +0 -0
- package/docs/images/connectors/connector-discord-en.png +0 -0
- package/docs/images/connectors/connector-feishu-en.png +0 -0
- package/docs/images/connectors/connector-lingzhu-en.png +0 -0
- package/docs/images/connectors/connector-qq-en.png +0 -0
- package/docs/images/connectors/connector-slack-en.png +0 -0
- package/docs/images/connectors/connector-telegram-en.png +0 -0
- package/docs/images/connectors/connector-weixin-en.png +0 -0
- package/docs/images/connectors/connector-whatsapp-en.png +0 -0
- package/docs/images/settings/settings-baselines-en.png +0 -0
- package/docs/images/settings/settings-config-en.png +0 -0
- package/docs/images/settings/settings-connectors-overview-en.png +0 -0
- package/docs/images/settings/settings-deepxiv-en.png +0 -0
- package/docs/images/settings/settings-mcp-servers-en.png +0 -0
- package/docs/images/settings/settings-plugins-en.png +0 -0
- package/docs/images/settings/settings-runners-en.png +0 -0
- package/docs/zh/00_QUICK_START.md +142 -18
- package/docs/zh/01_SETTINGS_REFERENCE.md +219 -98
- package/docs/zh/02_START_RESEARCH_GUIDE.md +26 -5
- package/docs/zh/05_TUI_GUIDE.md +171 -2
- package/docs/zh/07_MEMORY_AND_MCP.md +29 -2
- package/docs/zh/09_DOCTOR.md +54 -8
- package/docs/zh/10_WEIXIN_CONNECTOR_GUIDE.md +24 -1
- package/docs/zh/11_LICENSE_AND_RISK.md +4 -0
- package/docs/zh/12_GUIDED_WORKFLOW_TOUR.md +15 -0
- package/docs/zh/14_PROMPT_SKILLS_AND_MCP_GUIDE.md +9 -0
- package/docs/zh/15_CODEX_PROVIDER_SETUP.md +552 -181
- package/docs/zh/21_LOCAL_MODEL_BACKENDS_GUIDE.md +384 -0
- package/docs/zh/22_BENCHSTORE_YAML_REFERENCE.md +459 -0
- package/docs/zh/23_BENCHSTORE_GITHUB_RELEASES_SPEC.md +287 -0
- package/docs/zh/23_CLAUDE_RUNNER_GUIDE.md +103 -0
- package/docs/zh/24_CLAUDE_CODE_PROVIDER_SETUP.md +460 -0
- package/docs/zh/25_OPENCODE_PROVIDER_SETUP.md +660 -0
- package/docs/zh/26_CITATION_AND_ATTRIBUTION.md +102 -0
- package/docs/zh/27_KIMI_CODE_PROVIDER_SETUP.md +51 -0
- package/docs/zh/{19_LOCAL_BROWSER_AUTH.md → 31_LOCAL_BROWSER_AUTH.md} +1 -1
- package/docs/zh/32_WINDOWS_WSL2_DEPLOYMENT_GUIDE.md +264 -0
- package/docs/zh/33_WORKSPACE_EXPLORER_QA.md +127 -0
- package/docs/zh/99_ACKNOWLEDGEMENTS.md +23 -19
- package/docs/zh/README.md +33 -7
- package/install.sh +168 -20
- package/package.json +5 -1
- package/pyproject.toml +2 -1
- package/src/deepscientist/__init__.py +1 -1
- package/src/deepscientist/acp/envelope.py +13 -0
- package/src/deepscientist/admin/__init__.py +3 -0
- package/src/deepscientist/admin/charts.py +681 -0
- package/src/deepscientist/admin/logs.py +119 -0
- package/src/deepscientist/admin/repairs.py +217 -0
- package/src/deepscientist/admin/service.py +1310 -0
- package/src/deepscientist/admin/system_info.py +700 -0
- package/src/deepscientist/admin/tasks.py +465 -0
- package/src/deepscientist/admin/tool_metrics.py +600 -0
- package/src/deepscientist/artifact/guidance.py +8 -4
- package/src/deepscientist/artifact/schemas.py +115 -0
- package/src/deepscientist/artifact/service.py +4268 -260
- package/src/deepscientist/bash_exec/monitor.py +30 -3
- package/src/deepscientist/bash_exec/service.py +134 -1
- package/src/deepscientist/benchstore/__init__.py +4 -0
- package/src/deepscientist/benchstore/prompt_builder.py +224 -0
- package/src/deepscientist/benchstore/service.py +1716 -0
- package/src/deepscientist/bridges/connectors.py +8 -2
- package/src/deepscientist/channels/weixin_ilink.py +8 -1
- package/src/deepscientist/cli.py +92 -17
- package/src/deepscientist/codex_cli_compat.py +187 -74
- package/src/deepscientist/config/models.py +82 -11
- package/src/deepscientist/config/service.py +1077 -93
- package/src/deepscientist/connector/weixin_support.py +48 -17
- package/src/deepscientist/daemon/api/handlers.py +827 -235
- package/src/deepscientist/daemon/api/router.py +81 -1
- package/src/deepscientist/daemon/app.py +1512 -85
- package/src/deepscientist/diagnostics/__init__.py +6 -0
- package/src/deepscientist/diagnostics/runner_failures.py +277 -0
- package/src/deepscientist/doctor.py +407 -56
- package/src/deepscientist/evidence_packets.py +590 -0
- package/src/deepscientist/home.py +52 -4
- package/src/deepscientist/kimi_cli_compat.py +50 -0
- package/src/deepscientist/latex_runtime.py +2 -2
- package/src/deepscientist/mcp/context.py +2 -0
- package/src/deepscientist/mcp/schemas.py +114 -0
- package/src/deepscientist/mcp/server.py +1566 -126
- package/src/deepscientist/memory/service.py +203 -16
- package/src/deepscientist/process_control.py +8 -1
- package/src/deepscientist/prompts/builder.py +850 -88
- package/src/deepscientist/quest/__init__.py +2 -2
- package/src/deepscientist/quest/layout.py +12 -1
- package/src/deepscientist/quest/node_traces.py +10 -0
- package/src/deepscientist/quest/service.py +1852 -161
- package/src/deepscientist/quest/stage_views.py +1 -1
- package/src/deepscientist/runners/__init__.py +18 -0
- package/src/deepscientist/runners/base.py +89 -1
- package/src/deepscientist/runners/builtins.py +13 -1
- package/src/deepscientist/runners/claude.py +391 -0
- package/src/deepscientist/runners/codex.py +480 -35
- package/src/deepscientist/runners/codex_telemetry.py +127 -0
- package/src/deepscientist/runners/kimi.py +334 -0
- package/src/deepscientist/runners/metadata.py +68 -0
- package/src/deepscientist/runners/opencode.py +414 -0
- package/src/deepscientist/runners/runtime_overrides.py +100 -0
- package/src/deepscientist/runners/simple_cli.py +538 -0
- package/src/deepscientist/runtime_storage.py +303 -0
- package/src/deepscientist/shared.py +80 -16
- package/src/deepscientist/skills/installer.py +37 -0
- package/src/deepscientist/skills/registry.py +2 -0
- package/src/deepscientist/tinytex.py +2 -2
- package/src/deepscientist/tui.py +10 -3
- package/src/prompts/benchstore/system.md +77 -0
- package/src/prompts/connectors/qq.md +33 -2
- package/src/prompts/connectors/weixin.md +208 -23
- package/src/prompts/contracts/admin_ops.md +74 -0
- package/src/prompts/contracts/admin_ops_knowledge.md +138 -0
- package/src/prompts/contracts/shared_interaction.md +5 -10
- package/src/prompts/start_setup/system.md +422 -0
- package/src/prompts/system.md +411 -304
- package/src/prompts/system_copilot.md +89 -0
- package/src/skills/analysis-campaign/SKILL.md +239 -578
- package/src/skills/analysis-campaign/references/artifact-flow-examples.md +102 -0
- package/src/skills/analysis-campaign/references/boundary-cases.md +98 -0
- package/src/skills/analysis-campaign/references/campaign-checklist-template.md +39 -24
- package/src/skills/analysis-campaign/references/campaign-design.md +26 -10
- package/src/skills/analysis-campaign/references/campaign-plan-template.md +53 -54
- package/src/skills/analysis-campaign/references/operational-guidance.md +97 -0
- package/src/skills/analysis-campaign/references/writing-facing-slice-examples.md +10 -20
- package/src/skills/baseline/SKILL.md +183 -461
- package/src/skills/baseline/references/artifact-flow-examples.md +106 -0
- package/src/skills/baseline/references/artifact-payload-examples.md +1 -1
- package/src/skills/baseline/references/baseline-checklist-template.md +27 -35
- package/src/skills/baseline/references/baseline-plan-template.md +37 -76
- package/src/skills/baseline/references/boundary-cases.md +86 -0
- package/src/skills/baseline/references/codebase-audit-checklist.md +2 -6
- package/src/skills/baseline/references/comparability-contract.md +7 -12
- package/src/skills/baseline/references/operational-guidance.md +56 -0
- package/src/skills/baseline/references/route-selection.md +5 -25
- package/src/skills/decision/SKILL.md +113 -306
- package/src/skills/decision/references/checkpoint-memory-template.md +47 -0
- package/src/skills/decision/references/operational-guidance.md +94 -0
- package/src/skills/decision/references/research-route-criteria.md +7 -8
- package/src/skills/decision/references/strategic-decision-template.md +13 -26
- package/src/skills/experiment/SKILL.md +132 -670
- package/src/skills/experiment/references/execution-playbook.md +374 -0
- package/src/skills/experiment/references/main-experiment-checklist-template.md +26 -2
- package/src/skills/experiment/references/main-experiment-plan-template.md +28 -17
- package/src/skills/experiment/references/operational-guidance.md +108 -0
- package/src/skills/finalize/SKILL.md +62 -0
- package/src/skills/finalize/references/checkpoint-memory-template.md +49 -0
- package/src/skills/finalize/references/resume-packet-template.md +7 -0
- package/src/skills/idea/SKILL.md +228 -15
- package/src/skills/idea/references/controlled-brainstorming-playbook.md +78 -0
- package/src/skills/idea/references/current-board-packet-template.md +61 -0
- package/src/skills/idea/references/high-value-idea-sourcing.md +119 -0
- package/src/skills/idea/references/idea-generation-playbook.md +21 -0
- package/src/skills/idea/references/idea-thinking-flow.md +6 -0
- package/src/skills/idea/references/literature-survey-template.md +3 -0
- package/src/skills/idea/references/objective-contract-template.md +54 -0
- package/src/skills/idea/references/outline-seeding-example.md +56 -0
- package/src/skills/idea/references/pre-idea-draft-template.md +105 -0
- package/src/skills/idea/references/related-work-playbook.md +75 -2
- package/src/skills/idea/references/research-history-playbook.md +114 -0
- package/src/skills/idea/references/selection-gate.md +58 -6
- package/src/skills/intake-audit/SKILL.md +43 -2
- package/src/skills/intake-audit/references/state-audit-template.md +10 -0
- package/src/skills/nature-data/SKILL.md +128 -0
- package/src/skills/nature-data/UPSTREAM_LICENSE.txt +21 -0
- package/src/skills/nature-data/agents/openai.yaml +4 -0
- package/src/skills/nature-data/references/chinese-author-alignment.md +84 -0
- package/src/skills/nature-data/references/fair-metadata-checklist.md +105 -0
- package/src/skills/nature-data/references/policy-principles.md +103 -0
- package/src/skills/nature-data/references/repository-and-identifiers.md +96 -0
- package/src/skills/nature-data/references/source-basis.md +54 -0
- package/src/skills/nature-data/references/statement-patterns.md +153 -0
- package/src/skills/nature-figure/SKILL.md +197 -0
- package/src/skills/nature-figure/UPSTREAM_LICENSE.txt +21 -0
- package/src/skills/nature-figure/agents/openai.yaml +4 -0
- package/src/skills/nature-figure/evals/evals.json +37 -0
- package/src/skills/nature-figure/references/api.md +428 -0
- package/src/skills/nature-figure/references/backend-selection.md +100 -0
- package/src/skills/nature-figure/references/chart-types.md +281 -0
- package/src/skills/nature-figure/references/common-patterns.md +349 -0
- package/src/skills/nature-figure/references/design-theory.md +436 -0
- package/src/skills/nature-figure/references/figure-contract.md +93 -0
- package/src/skills/nature-figure/references/nature-2026-observations.md +112 -0
- package/src/skills/nature-figure/references/qa-contract.md +119 -0
- package/src/skills/nature-figure/references/r-template-index.md +66 -0
- package/src/skills/nature-figure/references/r-workflow.md +161 -0
- package/src/skills/nature-figure/references/tutorials.md +250 -0
- package/src/skills/nature-paper2ppt/SKILL.md +507 -0
- package/src/skills/nature-paper2ppt/UPSTREAM_LICENSE.txt +21 -0
- package/src/skills/nature-paper2ppt/agents/openai.yaml +4 -0
- package/src/skills/nature-polishing/SKILL.md +385 -0
- package/src/skills/nature-polishing/UPSTREAM_LICENSE.txt +21 -0
- package/src/skills/nature-polishing/agents/openai.yaml +4 -0
- package/src/skills/nature-polishing/references/phrasebank-playbook.md +162 -0
- package/src/skills/nature-polishing/references/section-moves.md +240 -0
- package/src/skills/nature-polishing/references/style-guardrails.md +94 -0
- package/src/skills/nature-polishing/references/writing-strategy.md +148 -0
- package/src/skills/optimize/SKILL.md +177 -1568
- package/src/skills/optimize/references/brief-shaping-playbook.md +95 -0
- package/src/skills/optimize/references/candidate-board-template.md +13 -0
- package/src/skills/optimize/references/candidate-ranking-template.md +51 -0
- package/src/skills/optimize/references/codegen-route-playbook.md +50 -0
- package/src/skills/optimize/references/debug-response-template.md +29 -0
- package/src/skills/optimize/references/frontier-review-template.md +32 -0
- package/src/skills/optimize/references/fusion-playbook.md +36 -0
- package/src/skills/optimize/references/method-brief-template.md +73 -0
- package/src/skills/optimize/references/operational-guidance.md +621 -0
- package/src/skills/optimize/references/optimization-memory-template.md +30 -0
- package/src/skills/optimize/references/optimize-checklist-template.md +18 -0
- package/src/skills/optimize/references/plateau-response-playbook.md +28 -0
- package/src/skills/optimize/references/prompt-patterns.md +49 -0
- package/src/skills/paper-outline/SKILL.md +227 -0
- package/src/skills/paper-outline/references/outline-patterns.md +87 -0
- package/src/skills/paper-plot/SKILL.md +79 -0
- package/src/skills/paper-plot/agents/openai.yaml +4 -0
- package/src/skills/paper-plot/references/bar_grouped_hatch.md +96 -0
- package/src/skills/paper-plot/references/bar_paired_delta.md +72 -0
- package/src/skills/paper-plot/references/line_confidence_band.md +75 -0
- package/src/skills/paper-plot/references/line_loss_with_inset.md +65 -0
- package/src/skills/paper-plot/references/line_training_curve.md +44 -0
- package/src/skills/paper-plot/references/radar_dual_series.md +59 -0
- package/src/skills/paper-plot/references/scatter_broken_axis.md +59 -0
- package/src/skills/paper-plot/references/scatter_tsne_cluster.md +72 -0
- package/src/skills/paper-plot/scripts/bar_memevolve.py +109 -0
- package/src/skills/paper-plot/scripts/bar_spice.py +166 -0
- package/src/skills/paper-plot/scripts/line_aime.py +94 -0
- package/src/skills/paper-plot/scripts/line_loss_inset.py +157 -0
- package/src/skills/paper-plot/scripts/line_selfdistill.py +168 -0
- package/src/skills/paper-plot/scripts/radar_dora.py +151 -0
- package/src/skills/paper-plot/scripts/scatter_break.py +169 -0
- package/src/skills/paper-plot/scripts/scatter_tsne.py +133 -0
- package/src/skills/rebuttal/SKILL.md +9 -0
- package/src/skills/references/tool-usage-by-stage.md +438 -0
- package/src/skills/review/SKILL.md +105 -7
- package/src/skills/science/PROVENANCE.md +44 -0
- package/src/skills/science/SKILL.md +137 -0
- package/src/skills/science/references/artifact-science-tool.md +110 -0
- package/src/skills/science/references/claim-type-discipline.md +56 -0
- package/src/skills/science/references/domain-index.md +422 -0
- package/src/skills/science/references/hpc-via-bash-exec.md +42 -0
- package/src/skills/science/references/package-check-playbook.md +64 -0
- package/src/skills/science/references/package-index.min.json +3616 -0
- package/src/skills/science/references/packages/abinit.md +80 -0
- package/src/skills/science/references/packages/acts.md +73 -0
- package/src/skills/science/references/packages/aiida-core.md +80 -0
- package/src/skills/science/references/packages/alamode.md +80 -0
- package/src/skills/science/references/packages/amuse.md +88 -0
- package/src/skills/science/references/packages/anndata.md +88 -0
- package/src/skills/science/references/packages/arbor.md +80 -0
- package/src/skills/science/references/packages/arc.md +73 -0
- package/src/skills/science/references/packages/astropy.md +88 -0
- package/src/skills/science/references/packages/astroquery.md +88 -0
- package/src/skills/science/references/packages/atomate2.md +80 -0
- package/src/skills/science/references/packages/atomsmltr.md +73 -0
- package/src/skills/science/references/packages/awkward.md +73 -0
- package/src/skills/science/references/packages/batman.md +88 -0
- package/src/skills/science/references/packages/biopython.md +88 -0
- package/src/skills/science/references/packages/bloqade.md +73 -0
- package/src/skills/science/references/packages/brian2.md +73 -0
- package/src/skills/science/references/packages/bullet3.md +73 -0
- package/src/skills/science/references/packages/calculix.md +80 -0
- package/src/skills/science/references/packages/cantera.md +73 -0
- package/src/skills/science/references/packages/cavity-md-ipi.md +80 -0
- package/src/skills/science/references/packages/ccdproc.md +88 -0
- package/src/skills/science/references/packages/celerite2.md +88 -0
- package/src/skills/science/references/packages/cellrank.md +73 -0
- package/src/skills/science/references/packages/cesm.md +80 -0
- package/src/skills/science/references/packages/chemicals.md +73 -0
- package/src/skills/science/references/packages/chempy.md +73 -0
- package/src/skills/science/references/packages/cirq.md +73 -0
- package/src/skills/science/references/packages/coffea.md +73 -0
- package/src/skills/science/references/packages/cp2k.md +88 -0
- package/src/skills/science/references/packages/custodian.md +80 -0
- package/src/skills/science/references/packages/dart.md +73 -0
- package/src/skills/science/references/packages/datamol.md +88 -0
- package/src/skills/science/references/packages/dd4hep.md +73 -0
- package/src/skills/science/references/packages/dealii.md +80 -0
- package/src/skills/science/references/packages/deepchem.md +88 -0
- package/src/skills/science/references/packages/delphes.md +73 -0
- package/src/skills/science/references/packages/devito.md +80 -0
- package/src/skills/science/references/packages/dftb.md +88 -0
- package/src/skills/science/references/packages/dftd4.md +88 -0
- package/src/skills/science/references/packages/dftk-jl.md +80 -0
- package/src/skills/science/references/packages/dolfinx.md +80 -0
- package/src/skills/science/references/packages/drake.md +73 -0
- package/src/skills/science/references/packages/dumux.md +73 -0
- package/src/skills/science/references/packages/elk.md +80 -0
- package/src/skills/science/references/packages/elmerfem.md +80 -0
- package/src/skills/science/references/packages/enzo-e.md +88 -0
- package/src/skills/science/references/packages/espresso.md +80 -0
- package/src/skills/science/references/packages/exoplanet.md +88 -0
- package/src/skills/science/references/packages/fairroot.md +73 -0
- package/src/skills/science/references/packages/fbpic.md +80 -0
- package/src/skills/science/references/packages/fdtdbath-meep.md +80 -0
- package/src/skills/science/references/packages/geant4.md +73 -0
- package/src/skills/science/references/packages/geosx.md +80 -0
- package/src/skills/science/references/packages/gprmax.md +80 -0
- package/src/skills/science/references/packages/gromacs.md +80 -0
- package/src/skills/science/references/packages/gwaslab.md +73 -0
- package/src/skills/science/references/packages/gz-sim.md +73 -0
- package/src/skills/science/references/packages/hail.md +88 -0
- package/src/skills/science/references/packages/hiphive.md +80 -0
- package/src/skills/science/references/packages/hoomd-blue.md +80 -0
- package/src/skills/science/references/packages/itensor.md +73 -0
- package/src/skills/science/references/packages/itensors-jl.md +73 -0
- package/src/skills/science/references/packages/jdftx.md +73 -0
- package/src/skills/science/references/packages/jobflow.md +80 -0
- package/src/skills/science/references/packages/kadanoffbaym-jl.md +73 -0
- package/src/skills/science/references/packages/kite.md +80 -0
- package/src/skills/science/references/packages/kratos.md +80 -0
- package/src/skills/science/references/packages/kwant.md +73 -0
- package/src/skills/science/references/packages/lammps.md +80 -0
- package/src/skills/science/references/packages/lightkurve.md +88 -0
- package/src/skills/science/references/packages/limix.md +73 -0
- package/src/skills/science/references/packages/maxwelllink.md +80 -0
- package/src/skills/science/references/packages/mcdc.md +73 -0
- package/src/skills/science/references/packages/meep.md +80 -0
- package/src/skills/science/references/packages/mfem.md +80 -0
- package/src/skills/science/references/packages/mitgcm.md +73 -0
- package/src/skills/science/references/packages/modflow6.md +73 -0
- package/src/skills/science/references/packages/molecool.md +73 -0
- package/src/skills/science/references/packages/mom6.md +73 -0
- package/src/skills/science/references/packages/moose.md +80 -0
- package/src/skills/science/references/packages/mpas-model.md +73 -0
- package/src/skills/science/references/packages/mujoco.md +73 -0
- package/src/skills/science/references/packages/mumax3.md +73 -0
- package/src/skills/science/references/packages/nekrs.md +80 -0
- package/src/skills/science/references/packages/nessi.md +73 -0
- package/src/skills/science/references/packages/nest-simulator.md +73 -0
- package/src/skills/science/references/packages/netket.md +73 -0
- package/src/skills/science/references/packages/neuron.md +73 -0
- package/src/skills/science/references/packages/nextflow.md +88 -0
- package/src/skills/science/references/packages/nwchem.md +88 -0
- package/src/skills/science/references/packages/openbabel.md +88 -0
- package/src/skills/science/references/packages/openems.md +80 -0
- package/src/skills/science/references/packages/openff-toolkit.md +88 -0
- package/src/skills/science/references/packages/openfoam-dev.md +80 -0
- package/src/skills/science/references/packages/openmc.md +73 -0
- package/src/skills/science/references/packages/openmm.md +80 -0
- package/src/skills/science/references/packages/openmoc.md +73 -0
- package/src/skills/science/references/packages/openmx.md +80 -0
- package/src/skills/science/references/packages/opensees.md +80 -0
- package/src/skills/science/references/packages/opensn.md +80 -0
- package/src/skills/science/references/packages/opm-simulators.md +73 -0
- package/src/skills/science/references/packages/oqupy.md +73 -0
- package/src/skills/science/references/packages/packmol.md +80 -0
- package/src/skills/science/references/packages/palabos.md +80 -0
- package/src/skills/science/references/packages/parflow.md +80 -0
- package/src/skills/science/references/packages/pennylane.md +88 -0
- package/src/skills/science/references/packages/perceval.md +73 -0
- package/src/skills/science/references/packages/phono3py.md +73 -0
- package/src/skills/science/references/packages/phonopy.md +73 -0
- package/src/skills/science/references/packages/photutils.md +88 -0
- package/src/skills/science/references/packages/picongpu.md +80 -0
- package/src/skills/science/references/packages/plink-ng.md +88 -0
- package/src/skills/science/references/packages/precice.md +73 -0
- package/src/skills/science/references/packages/psc.md +80 -0
- package/src/skills/science/references/packages/psi4.md +88 -0
- package/src/skills/science/references/packages/pybinding.md +73 -0
- package/src/skills/science/references/packages/pyfr.md +80 -0
- package/src/skills/science/references/packages/pyhf.md +73 -0
- package/src/skills/science/references/packages/pyiron_base.md +80 -0
- package/src/skills/science/references/packages/pylcp.md +73 -0
- package/src/skills/science/references/packages/pylith.md +80 -0
- package/src/skills/science/references/packages/pynbody.md +88 -0
- package/src/skills/science/references/packages/pysam.md +88 -0
- package/src/skills/science/references/packages/pyscf.md +88 -0
- package/src/skills/science/references/packages/q-e.md +73 -0
- package/src/skills/science/references/packages/qibo.md +73 -0
- package/src/skills/science/references/packages/qiskit.md +73 -0
- package/src/skills/science/references/packages/quantica-jl.md +73 -0
- package/src/skills/science/references/packages/quantumoptics-jl.md +73 -0
- package/src/skills/science/references/packages/quimb.md +73 -0
- package/src/skills/science/references/packages/qulacs.md +73 -0
- package/src/skills/science/references/packages/qutip.md +73 -0
- package/src/skills/science/references/packages/rdkit.md +88 -0
- package/src/skills/science/references/packages/rmg-py.md +73 -0
- package/src/skills/science/references/packages/root.md +73 -0
- package/src/skills/science/references/packages/scanpy.md +88 -0
- package/src/skills/science/references/packages/scikit-allel.md +88 -0
- package/src/skills/science/references/packages/scikit-bio.md +88 -0
- package/src/skills/science/references/packages/scqubits.md +73 -0
- package/src/skills/science/references/packages/scuff-em.md +80 -0
- package/src/skills/science/references/packages/scvi-tools.md +73 -0
- package/src/skills/science/references/packages/seissol.md +73 -0
- package/src/skills/science/references/packages/sfepy.md +80 -0
- package/src/skills/science/references/packages/sisl.md +73 -0
- package/src/skills/science/references/packages/smilei.md +80 -0
- package/src/skills/science/references/packages/snakemake.md +88 -0
- package/src/skills/science/references/packages/specfem3d-globe.md +80 -0
- package/src/skills/science/references/packages/specutils.md +88 -0
- package/src/skills/science/references/packages/spglib.md +80 -0
- package/src/skills/science/references/packages/squidpy.md +88 -0
- package/src/skills/science/references/packages/starry.md +88 -0
- package/src/skills/science/references/packages/strawberryfields.md +73 -0
- package/src/skills/science/references/packages/su2.md +80 -0
- package/src/skills/science/references/packages/sunny-jl.md +73 -0
- package/src/skills/science/references/packages/sw4.md +73 -0
- package/src/skills/science/references/packages/swift.md +88 -0
- package/src/skills/science/references/packages/tdnegf.md +73 -0
- package/src/skills/science/references/packages/tenpy.md +73 -0
- package/src/skills/science/references/packages/thermo.md +73 -0
- package/src/skills/science/references/packages/tkwant.md +73 -0
- package/src/skills/science/references/packages/tvb-root.md +73 -0
- package/src/skills/science/references/packages/uproot5.md +73 -0
- package/src/skills/science/references/packages/vampire.md +80 -0
- package/src/skills/science/references/packages/wannier_tools.md +73 -0
- package/src/skills/science/references/packages/warpx.md +80 -0
- package/src/skills/science/references/packages/wrf.md +73 -0
- package/src/skills/science/references/packages/xtb.md +88 -0
- package/src/skills/science/references/packages/yt.md +73 -0
- package/src/skills/science/references/science-task-brief-template.md +71 -0
- package/src/skills/scout/SKILL.md +83 -425
- package/src/skills/scout/references/literature-scout-template.md +5 -24
- package/src/skills/scout/references/operational-guidance.md +191 -0
- package/src/skills/scout/references/paper-triage-playbook.md +11 -35
- package/src/skills/write/SKILL.md +744 -1246
- package/src/skills/write/references/experiments_analysis_patterns.md +129 -0
- package/src/skills/write/references/oral_package_patterns.md +252 -0
- package/src/skills/write/references/oral_writing_principles.md +291 -0
- package/src/skills/write/references/section_rewrite_checklist.md +234 -0
- package/src/tui/dist/app/AppContainer.js +1314 -27
- package/src/tui/dist/components/Composer.js +26 -1
- package/src/tui/dist/components/ConfigScreen.js +2 -1
- package/src/tui/dist/components/InputPrompt.js +25 -9
- package/src/tui/dist/components/MainContent.js +18 -3
- package/src/tui/dist/components/QuestScreen.js +3 -2
- package/src/tui/dist/components/UtilityScreen.js +37 -0
- package/src/tui/dist/hooks/useSafeInput.js +10 -0
- package/src/tui/dist/index.js +13 -1
- package/src/tui/dist/layouts/DefaultAppLayout.js +11 -8
- package/src/tui/dist/lib/api.js +89 -1
- package/src/tui/package.json +1 -1
- package/src/ui/dist/assets/{AnalysisPlugin-DnSm0GZn.js → AnalysisPlugin-CA94NGmI.js} +1 -1
- package/src/ui/dist/assets/CliPlugin-DHBzphZU.js +79 -0
- package/src/ui/dist/assets/CodeEditorPlugin-BOFwD2rn.js +2 -0
- package/src/ui/dist/assets/{CodeViewerPlugin-itb0tltR.js → CodeViewerPlugin-CqDpgjik.js} +4 -4
- package/src/ui/dist/assets/{DocViewerPlugin-DqKkiCI6.js → DocViewerPlugin-UDBgt8-4.js} +3 -3
- package/src/ui/dist/assets/GitCommitViewerPlugin-BmHtZ0bZ.js +6 -0
- package/src/ui/dist/assets/{GitDiffViewerPlugin-DxL2ezFG.js → GitDiffViewerPlugin-CAxjNorQ.js} +2 -2
- package/src/ui/dist/assets/{GitSnapshotViewer-B_RQm1YZ.js → GitSnapshotViewer-CweA6VON.js} +2 -2
- package/src/ui/dist/assets/{ImageViewerPlugin-tHqlXY3n.js → ImageViewerPlugin-C8wHGvGN.js} +5 -5
- package/src/ui/dist/assets/LabPlugin-COyyLUol.js +32 -0
- package/src/ui/dist/assets/{LatexPlugin-B495DTXC.js → LatexPlugin-BQjAaA5J.js} +4 -4
- package/src/ui/dist/assets/{MarkdownViewerPlugin-DG28-61B.js → MarkdownViewerPlugin-Dy1NE2dI.js} +3 -3
- package/src/ui/dist/assets/{MarketplacePlugin-BiOGT-Kj.js → MarketplacePlugin-DMIZtEJ2.js} +2 -2
- package/src/ui/dist/assets/NotebookEditor-CFHMq_Qt.js +91 -0
- package/src/ui/dist/assets/{NotebookEditor-CVsj8h_T.js → NotebookEditor-WFyd8Ybt.js} +23 -23
- package/src/ui/dist/assets/{PdfLoader-CASDQmxJ.js → PdfLoader-CLE5u5TS.js} +3 -3
- package/src/ui/dist/assets/{PdfMarkdownPlugin-BFhwoKsY.js → PdfMarkdownPlugin-_iNK_H83.js} +1 -1
- package/src/ui/dist/assets/PdfViewerPlugin-DgWsbInT.js +22 -0
- package/src/ui/dist/assets/SearchPlugin-DrZmn5iw.js +11 -0
- package/src/ui/dist/assets/{TextViewerPlugin-CB4DYfWO.js → TextViewerPlugin-D1-T3aC7.js} +4 -4
- package/src/ui/dist/assets/branding/runner-claude.svg +107 -0
- package/src/ui/dist/assets/branding/runner-codex.svg +10 -0
- package/src/ui/dist/assets/branding/runner-kimi.svg +14 -0
- package/src/ui/dist/assets/branding/runner-opencode.svg +7 -0
- package/src/ui/dist/assets/cli-store-CoZ-x5Ip.js +1 -0
- package/src/ui/dist/assets/{code-DLC6G24T.js → code-DbsmSd3Y.js} +1 -1
- package/src/ui/dist/assets/file-diff-panel-DsvyRz47.js +1 -0
- package/src/ui/dist/assets/{wrap-text-CwMn-iqb.js → file-jump-queue-DeQBikaw.js} +3 -3
- package/src/ui/dist/assets/{file-socket-Cu4Qln7Y.js → file-socket-DA5XIx88.js} +1 -1
- package/src/ui/dist/assets/fonts/ds-fonts.css +50 -4
- package/src/ui/dist/assets/images/deepxiv/register-guide.png +0 -0
- package/src/ui/dist/assets/index-39vY9LmZ.js +1 -0
- package/src/ui/dist/assets/{index-wQ7RIIRd.js → index-BsO46tJA.js} +1 -1
- package/src/ui/dist/assets/index-CHzJ2xtB.js +3530 -0
- package/src/ui/dist/assets/index-DH-zxoZ3.css +33 -0
- package/src/ui/dist/assets/{plugin-notebook-HbW2K-1c.js → plugin-notebook-JRhysCqj.js} +2 -2
- package/src/ui/dist/assets/{project-sync-CsX08Qno.js → project-sync-DPmWKmKD.js} +1 -1
- package/src/ui/dist/assets/{zoom-out-R-GWEhzS.js → zoom-out-DAukFWen.js} +3 -3
- package/src/ui/dist/index.html +3 -3
- package/src/skills/analysis-campaign/references/artifact-orchestration.md +0 -58
- package/src/skills/baseline/references/memory-playbook.md +0 -40
- package/src/skills/baseline/references/publishable-baseline-package.md +0 -30
- package/src/skills/write/references/outline-evidence-contract-example.md +0 -107
- package/src/skills/write/references/paper-experiment-matrix-template.md +0 -131
- package/src/skills/write/references/paper-section-playbook.md +0 -64
- package/src/skills/write/references/reviewer-first-writing.md +0 -64
- package/src/skills/write/references/revision-checklist.md +0 -70
- package/src/skills/write/references/section-contracts.md +0 -82
- package/src/skills/write/references/sentence-level-proofing.md +0 -49
- package/src/ui/dist/assets/AiManusChatView-COFACy7V.js +0 -204
- package/src/ui/dist/assets/CliPlugin-CvwCmDQ5.js +0 -109
- package/src/ui/dist/assets/CodeEditorPlugin-cOqSa0xq.js +0 -2
- package/src/ui/dist/assets/GitCommitViewerPlugin-DVgNHBCS.js +0 -1
- package/src/ui/dist/assets/LabCopilotPanel-ClMbq5Yu.js +0 -14
- package/src/ui/dist/assets/LabPlugin-L_SuE8ow.js +0 -22
- package/src/ui/dist/assets/NotebookEditor-C-4Kt1p9.js +0 -81
- package/src/ui/dist/assets/PdfViewerPlugin-DcOzU9vd.js +0 -17
- package/src/ui/dist/assets/SearchPlugin-CHj7M58O.js +0 -16
- package/src/ui/dist/assets/VNCViewer-CjlbyCB3.js +0 -11
- package/src/ui/dist/assets/bot-CFkZY-JP.js +0 -6
- package/src/ui/dist/assets/chevron-up-Dq5ofbht.js +0 -6
- package/src/ui/dist/assets/file-content-Dv4LoZec.js +0 -1
- package/src/ui/dist/assets/file-diff-panel-Denq-lC3.js +0 -1
- package/src/ui/dist/assets/file-jump-queue-DA-SdG__.js +0 -1
- package/src/ui/dist/assets/git-commit-horizontal-BUh6G52n.js +0 -6
- package/src/ui/dist/assets/image-B9HUUddG.js +0 -6
- package/src/ui/dist/assets/index-B2B1sg-M.js +0 -1
- package/src/ui/dist/assets/index-Cgla8biy.css +0 -33
- package/src/ui/dist/assets/index-DRyx7vAc.js +0 -1
- package/src/ui/dist/assets/index-Gbl53BNp.js +0 -2496
- package/src/ui/dist/assets/pdf-effect-queue-ZtnHFCAi.js +0 -6
- package/src/ui/dist/assets/popover-DL6h35vr.js +0 -1
- package/src/ui/dist/assets/select-DvmXt1yY.js +0 -11
- package/src/ui/dist/assets/sigma-7jpXazui.js +0 -6
- package/src/ui/dist/assets/trash-xA7kFt8i.js +0 -11
- package/src/ui/dist/assets/useCliAccess-DsMwDjOp.js +0 -1
- package/src/ui/dist/assets/useFileDiffOverlay-FuhcnKiw.js +0 -1
|
@@ -2,19 +2,29 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
4
|
import os
|
|
5
|
+
import shlex
|
|
6
|
+
import shutil
|
|
5
7
|
import subprocess
|
|
6
8
|
import tempfile
|
|
7
9
|
from copy import deepcopy
|
|
8
10
|
from pathlib import Path
|
|
9
11
|
from urllib.error import URLError
|
|
12
|
+
from urllib.parse import urlencode
|
|
10
13
|
from urllib.request import Request
|
|
11
14
|
|
|
12
15
|
from ..codex_cli_compat import (
|
|
16
|
+
active_provider_metadata_from_home,
|
|
13
17
|
adapt_profile_only_provider_config,
|
|
18
|
+
chat_wire_compatible_codex_version,
|
|
19
|
+
codex_cli_version,
|
|
20
|
+
format_codex_cli_version,
|
|
14
21
|
materialize_codex_runtime_home,
|
|
22
|
+
missing_provider_env_key,
|
|
23
|
+
missing_provider_env_key_from_text,
|
|
15
24
|
normalize_codex_reasoning_effort,
|
|
16
|
-
|
|
25
|
+
provider_base_url_looks_local,
|
|
17
26
|
)
|
|
27
|
+
from ..kimi_cli_compat import materialize_kimi_runtime_home
|
|
18
28
|
from ..connector.connector_profiles import PROFILEABLE_CONNECTOR_NAMES, list_connector_profiles, normalize_connector_config
|
|
19
29
|
from ..connector_runtime import build_discovered_target, infer_connector_transport
|
|
20
30
|
from ..home import repo_root
|
|
@@ -43,8 +53,9 @@ from ..connector.qq_profiles import (
|
|
|
43
53
|
)
|
|
44
54
|
from ..connector.weixin_support import normalize_weixin_base_url, normalize_weixin_cdn_base_url
|
|
45
55
|
from ..network import urlopen_with_proxy as urlopen
|
|
56
|
+
from ..runners.metadata import get_runner_metadata, list_builtin_runner_names
|
|
46
57
|
from ..runners.runtime_overrides import apply_codex_runtime_overrides, apply_runners_runtime_overrides
|
|
47
|
-
from ..shared import read_json, read_text, read_yaml, resolve_runner_binary, run_command, sha256_text, utc_now, which, write_text, write_yaml
|
|
58
|
+
from ..shared import ensure_utf8_subprocess_env, read_json, read_text, read_yaml, resolve_runner_binary, run_command, sha256_text, utc_now, utf8_text_subprocess_kwargs, which, write_json, write_text, write_yaml
|
|
48
59
|
from .models import (
|
|
49
60
|
CONFIG_NAMES,
|
|
50
61
|
OPTIONAL_CONFIG_NAMES,
|
|
@@ -205,31 +216,83 @@ class ConfigManager:
|
|
|
205
216
|
return prepared
|
|
206
217
|
|
|
207
218
|
def _invalidate_codex_bootstrap_state_if_runner_changed(self, previous: dict, current: dict) -> None:
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
219
|
+
tracked_keys_by_runner = {
|
|
220
|
+
"codex": (
|
|
221
|
+
"binary",
|
|
222
|
+
"config_dir",
|
|
223
|
+
"profile",
|
|
224
|
+
"model",
|
|
225
|
+
"model_reasoning_effort",
|
|
226
|
+
"approval_policy",
|
|
227
|
+
"sandbox_mode",
|
|
228
|
+
"env",
|
|
229
|
+
"mcp_tool_timeout_sec",
|
|
230
|
+
),
|
|
231
|
+
"claude": (
|
|
232
|
+
"binary",
|
|
233
|
+
"config_dir",
|
|
234
|
+
"model",
|
|
235
|
+
"permission_mode",
|
|
236
|
+
"mcp_timeout_ms",
|
|
237
|
+
"mcp_tool_timeout_ms",
|
|
238
|
+
"env",
|
|
239
|
+
),
|
|
240
|
+
"kimi": (
|
|
241
|
+
"binary",
|
|
242
|
+
"config_dir",
|
|
243
|
+
"model",
|
|
244
|
+
"agent",
|
|
245
|
+
"thinking",
|
|
246
|
+
"yolo",
|
|
247
|
+
"mcp_tool_timeout_ms",
|
|
248
|
+
"env",
|
|
249
|
+
),
|
|
250
|
+
"opencode": (
|
|
251
|
+
"binary",
|
|
252
|
+
"config_dir",
|
|
253
|
+
"model",
|
|
254
|
+
"permission_mode",
|
|
255
|
+
"default_agent",
|
|
256
|
+
"variant",
|
|
257
|
+
"mcp_timeout_ms",
|
|
258
|
+
"env",
|
|
259
|
+
),
|
|
260
|
+
}
|
|
261
|
+
changed_runners: list[str] = []
|
|
262
|
+
for runner_name, tracked_keys in tracked_keys_by_runner.items():
|
|
263
|
+
previous_runner = previous.get(runner_name) if isinstance(previous.get(runner_name), dict) else {}
|
|
264
|
+
current_runner = current.get(runner_name) if isinstance(current.get(runner_name), dict) else {}
|
|
265
|
+
if all(previous_runner.get(key) == current_runner.get(key) for key in tracked_keys):
|
|
266
|
+
continue
|
|
267
|
+
changed_runners.append(runner_name)
|
|
268
|
+
if not changed_runners:
|
|
221
269
|
return
|
|
222
270
|
config = self.load_named_normalized("config")
|
|
223
271
|
bootstrap = config.get("bootstrap") if isinstance(config.get("bootstrap"), dict) else {}
|
|
224
|
-
bootstrap
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
"
|
|
232
|
-
|
|
272
|
+
runner_readiness = bootstrap.get("runner_readiness") if isinstance(bootstrap.get("runner_readiness"), dict) else {}
|
|
273
|
+
checked_at = utc_now()
|
|
274
|
+
for runner_name in changed_runners:
|
|
275
|
+
try:
|
|
276
|
+
runner_label = get_runner_metadata(runner_name).label
|
|
277
|
+
except KeyError:
|
|
278
|
+
runner_label = runner_name
|
|
279
|
+
summary = f"{runner_label} runner configuration changed. A new startup probe is required."
|
|
280
|
+
runner_readiness[runner_name] = {
|
|
281
|
+
"ready": False,
|
|
282
|
+
"last_checked_at": checked_at,
|
|
283
|
+
"last_result": {
|
|
284
|
+
"ok": False,
|
|
285
|
+
"summary": summary,
|
|
286
|
+
"warnings": [],
|
|
287
|
+
"errors": [],
|
|
288
|
+
"guidance": [],
|
|
289
|
+
},
|
|
290
|
+
}
|
|
291
|
+
bootstrap["runner_readiness"] = runner_readiness
|
|
292
|
+
codex_state = runner_readiness.get("codex") if isinstance(runner_readiness.get("codex"), dict) else {}
|
|
293
|
+
bootstrap["codex_ready"] = bool(codex_state.get("ready", False))
|
|
294
|
+
bootstrap["codex_last_checked_at"] = codex_state.get("last_checked_at")
|
|
295
|
+
bootstrap["codex_last_result"] = codex_state.get("last_result") if isinstance(codex_state.get("last_result"), dict) else {}
|
|
233
296
|
config["bootstrap"] = bootstrap
|
|
234
297
|
self.save_named_text("config", self.render_named_payload("config", config))
|
|
235
298
|
|
|
@@ -470,12 +533,12 @@ The **Test** button checks:
|
|
|
470
533
|
|
|
471
534
|
This is a safe local smoke test.
|
|
472
535
|
|
|
473
|
-
##
|
|
536
|
+
## Runner startup gate
|
|
474
537
|
|
|
475
|
-
-
|
|
476
|
-
-
|
|
477
|
-
-
|
|
478
|
-
-
|
|
538
|
+
- the launcher runs a real hello probe for the selected runner before first daemon start
|
|
539
|
+
- `codex`, `claude`, `kimi`, and `opencode` can each record readiness under `bootstrap.runner_readiness`
|
|
540
|
+
- if the selected runner fails, DeepScientist writes the failure summary back into config and blocks only that requested startup path
|
|
541
|
+
- you can start with the default runner first, then configure or switch Claude Code / Kimi Code / OpenCode from Settings
|
|
479
542
|
|
|
480
543
|
## Figure and chart style policy
|
|
481
544
|
|
|
@@ -491,15 +554,16 @@ This page edits `{home_text}/config/runners.yaml`.
|
|
|
491
554
|
## Recommended v1 choice
|
|
492
555
|
|
|
493
556
|
- keep `codex.enabled: true`
|
|
494
|
-
-
|
|
495
|
-
-
|
|
557
|
+
- enable whichever runners you actually plan to use (`codex`, `claude`, `kimi`, `opencode`)
|
|
558
|
+
- keep the others disabled if their local CLI or credentials are not ready yet
|
|
496
559
|
- set `codex.profile` only when your Codex CLI uses a named provider profile such as `m27`
|
|
497
560
|
- when you launch DeepScientist ad hoc with a provider profile, you can also use `ds --codex-profile <name>`
|
|
498
561
|
- when you want a one-off Codex binary override, you can also use `ds --codex /absolute/path/to/codex`
|
|
499
562
|
- keep `codex.model_reasoning_effort: xhigh` unless you explicitly want a lighter default
|
|
500
563
|
- keep `codex.retry_on_failure: true` so transient Codex failures can resume automatically
|
|
501
|
-
- keep retry timing near `10s / 6x / 1800s max` so Codex backs off exponentially and the
|
|
502
|
-
- DeepScientist hard-limits one turn to at most `
|
|
564
|
+
- keep retry timing near `10s / 6x / 1800s max` so Codex backs off exponentially and the final retries sit at the 30-minute cap
|
|
565
|
+
- DeepScientist hard-limits one turn to at most `7` total attempts, even if the config says more
|
|
566
|
+
- one-off diagnostics can target a runner without permanently enabling it: `ds doctor --runner claude`, `ds doctor --runner kimi`, or `ds doctor --runner opencode`
|
|
503
567
|
|
|
504
568
|
## Test behavior
|
|
505
569
|
|
|
@@ -507,7 +571,7 @@ The **Test** button checks:
|
|
|
507
571
|
|
|
508
572
|
- whether the configured runner binaries are on PATH
|
|
509
573
|
- whether disabled runners are intentionally skipped
|
|
510
|
-
- for
|
|
574
|
+
- for enabled runners, it also runs a real hello probe so login problems, profile misconfiguration, and first-run setup issues surface before quest execution
|
|
511
575
|
- it does not simulate the full failure/retry loop, so use quest runtime logs when debugging recovery behavior
|
|
512
576
|
"""
|
|
513
577
|
if name == "plugins":
|
|
@@ -601,21 +665,159 @@ Use **Test** when the file exposes runtime dependencies.
|
|
|
601
665
|
rendered = self.render_named_payload(name, payload)
|
|
602
666
|
return self.test_named_text(name, rendered, live=live, delivery_targets=delivery_targets)
|
|
603
667
|
|
|
604
|
-
def
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
668
|
+
def test_deepxiv_payload(self, payload: dict | None = None) -> dict:
|
|
669
|
+
normalized = self._normalize_named_payload("config", payload if isinstance(payload, dict) else self.load_named_normalized("config"))
|
|
670
|
+
literature = normalized.get("literature") if isinstance(normalized.get("literature"), dict) else {}
|
|
671
|
+
deepxiv = literature.get("deepxiv") if isinstance(literature.get("deepxiv"), dict) else {}
|
|
672
|
+
base_url = str(deepxiv.get("base_url") or "https://data.rag.ac.cn").strip() or "https://data.rag.ac.cn"
|
|
673
|
+
direct_token = str(deepxiv.get("token") or "").strip()
|
|
674
|
+
token_env_name = str(deepxiv.get("token_env") or "").strip()
|
|
675
|
+
env_token = str(os.environ.get(token_env_name) or "").strip() if token_env_name else ""
|
|
676
|
+
resolved_token = direct_token or env_token
|
|
677
|
+
query = "transformers"
|
|
678
|
+
result_size = max(1, int(deepxiv.get("default_result_size") or 10))
|
|
679
|
+
preview_characters = max(200, int(deepxiv.get("preview_characters") or 1200))
|
|
680
|
+
request_timeout_seconds = max(3, int(deepxiv.get("request_timeout_seconds") or 20))
|
|
681
|
+
details = {
|
|
682
|
+
"base_url": base_url,
|
|
683
|
+
"query": query,
|
|
684
|
+
"result_size": result_size,
|
|
685
|
+
"preview_characters": preview_characters,
|
|
686
|
+
"request_timeout_seconds": request_timeout_seconds,
|
|
687
|
+
"token_source": "direct_token" if direct_token else ("env" if env_token else "missing"),
|
|
688
|
+
"token_env": token_env_name or None,
|
|
689
|
+
}
|
|
690
|
+
if not resolved_token:
|
|
691
|
+
return {
|
|
692
|
+
"ok": False,
|
|
693
|
+
"summary": "DeepXiv test failed: token is missing.",
|
|
694
|
+
"warnings": [],
|
|
695
|
+
"errors": ["Provide a DeepXiv token before running the test."],
|
|
696
|
+
"details": details,
|
|
697
|
+
"results": [],
|
|
698
|
+
"preview": "",
|
|
699
|
+
}
|
|
700
|
+
url = f"{base_url.rstrip('/')}/arxiv/?{urlencode({'type': 'retrieve', 'query': query, 'size': str(result_size)})}"
|
|
701
|
+
request = Request(
|
|
702
|
+
url,
|
|
703
|
+
headers={
|
|
704
|
+
"Accept": "application/json",
|
|
705
|
+
"Authorization": f"Bearer {resolved_token}",
|
|
706
|
+
"User-Agent": "DeepScientist/DeepXivTest",
|
|
707
|
+
},
|
|
708
|
+
)
|
|
709
|
+
try:
|
|
710
|
+
with urlopen(request, timeout=request_timeout_seconds) as response: # noqa: S310
|
|
711
|
+
response_text = response.read().decode("utf-8", errors="replace")
|
|
712
|
+
except Exception as exc:
|
|
713
|
+
details["request_url"] = url
|
|
714
|
+
return {
|
|
715
|
+
"ok": False,
|
|
716
|
+
"summary": "DeepXiv test request failed.",
|
|
717
|
+
"warnings": [],
|
|
718
|
+
"errors": [str(exc)],
|
|
719
|
+
"details": details,
|
|
720
|
+
"results": [],
|
|
721
|
+
"preview": "",
|
|
722
|
+
}
|
|
723
|
+
try:
|
|
724
|
+
parsed = json.loads(response_text)
|
|
725
|
+
except json.JSONDecodeError:
|
|
726
|
+
preview = response_text[:preview_characters].rstrip()
|
|
727
|
+
if len(response_text) > preview_characters:
|
|
728
|
+
preview = f"{preview}\n...[truncated]"
|
|
729
|
+
details["request_url"] = url
|
|
730
|
+
return {
|
|
731
|
+
"ok": False,
|
|
732
|
+
"summary": "DeepXiv test returned invalid JSON.",
|
|
733
|
+
"warnings": [],
|
|
734
|
+
"errors": ["DeepXiv returned invalid JSON."],
|
|
735
|
+
"details": details,
|
|
736
|
+
"results": [],
|
|
737
|
+
"preview": preview,
|
|
738
|
+
}
|
|
739
|
+
results = parsed.get("results") if isinstance(parsed.get("results"), list) else []
|
|
740
|
+
if not results and isinstance(parsed.get("result"), list):
|
|
741
|
+
results = parsed.get("result") or []
|
|
742
|
+
total = parsed.get("total")
|
|
743
|
+
if total is None:
|
|
744
|
+
total = parsed.get("total_count")
|
|
745
|
+
preview_payload = {
|
|
746
|
+
"total": total,
|
|
747
|
+
"took": parsed.get("took"),
|
|
748
|
+
"results": results[: min(3, len(results))],
|
|
749
|
+
}
|
|
750
|
+
preview = json.dumps(preview_payload, ensure_ascii=False, indent=2)
|
|
751
|
+
if len(preview) > preview_characters:
|
|
752
|
+
preview = f"{preview[:preview_characters].rstrip()}\n...[truncated]"
|
|
753
|
+
details.update(
|
|
754
|
+
{
|
|
755
|
+
"request_url": url,
|
|
756
|
+
"total": total,
|
|
757
|
+
"result_count": len(results),
|
|
758
|
+
"first_title": str((results[0] or {}).get("title") or "").strip() if results else None,
|
|
759
|
+
}
|
|
760
|
+
)
|
|
761
|
+
ok = len(results) > 0
|
|
762
|
+
return {
|
|
763
|
+
"ok": ok,
|
|
764
|
+
"summary": "DeepXiv returned search results for `transformers`." if ok else "DeepXiv returned no search results for `transformers`.",
|
|
765
|
+
"warnings": [],
|
|
766
|
+
"errors": [] if ok else ["No results were returned for `transformers`."],
|
|
767
|
+
"details": details,
|
|
768
|
+
"results": results[:5],
|
|
769
|
+
"preview": preview,
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
def probe_runner_bootstrap(self, runner_name: str, *, persist: bool = False, payload: dict | None = None) -> dict:
|
|
773
|
+
normalized_runner = str(runner_name or "codex").strip().lower() or "codex"
|
|
774
|
+
runners_payload = payload if isinstance(payload, dict) else self.load_runners_config()
|
|
775
|
+
runner_payload = runners_payload.get(normalized_runner) if isinstance(runners_payload.get(normalized_runner), dict) else {}
|
|
776
|
+
if normalized_runner == "codex":
|
|
777
|
+
result = self._probe_codex_runner(runner_payload)
|
|
778
|
+
elif normalized_runner == "claude":
|
|
779
|
+
result = self._probe_claude_runner(runner_payload)
|
|
780
|
+
elif normalized_runner == "kimi":
|
|
781
|
+
result = self._probe_kimi_runner(runner_payload)
|
|
782
|
+
elif normalized_runner == "opencode":
|
|
783
|
+
result = self._probe_opencode_runner(runner_payload)
|
|
784
|
+
else:
|
|
785
|
+
raise KeyError(f"Unknown runner `{normalized_runner}`.")
|
|
608
786
|
if persist:
|
|
609
|
-
self.
|
|
787
|
+
self._persist_runner_bootstrap_result(normalized_runner, result)
|
|
610
788
|
return result
|
|
611
789
|
|
|
612
|
-
def
|
|
790
|
+
def runner_bootstrap_state(self, runner_name: str) -> dict:
|
|
791
|
+
normalized_runner = str(runner_name or "codex").strip().lower() or "codex"
|
|
613
792
|
config = self.load_named_normalized("config")
|
|
614
793
|
bootstrap = config.get("bootstrap") if isinstance(config.get("bootstrap"), dict) else {}
|
|
794
|
+
runner_readiness = bootstrap.get("runner_readiness") if isinstance(bootstrap.get("runner_readiness"), dict) else {}
|
|
795
|
+
runner_state = runner_readiness.get(normalized_runner) if isinstance(runner_readiness.get(normalized_runner), dict) else {}
|
|
796
|
+
if normalized_runner == "codex" and not runner_state:
|
|
797
|
+
runner_state = {
|
|
798
|
+
"ready": bool(bootstrap.get("codex_ready", False)),
|
|
799
|
+
"last_checked_at": bootstrap.get("codex_last_checked_at"),
|
|
800
|
+
"last_result": bootstrap.get("codex_last_result") if isinstance(bootstrap.get("codex_last_result"), dict) else {},
|
|
801
|
+
}
|
|
615
802
|
return {
|
|
616
|
-
"
|
|
617
|
-
"
|
|
618
|
-
"
|
|
803
|
+
"runner": normalized_runner,
|
|
804
|
+
"ready": bool(runner_state.get("ready", False)),
|
|
805
|
+
"last_checked_at": runner_state.get("last_checked_at"),
|
|
806
|
+
"last_result": runner_state.get("last_result") if isinstance(runner_state.get("last_result"), dict) else {},
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
def runner_readiness_map(self) -> dict[str, dict[str, Any]]:
|
|
810
|
+
return {name: self.runner_bootstrap_state(name) for name in list_builtin_runner_names()}
|
|
811
|
+
|
|
812
|
+
def probe_codex_bootstrap(self, *, persist: bool = False, payload: dict | None = None) -> dict:
|
|
813
|
+
return self.probe_runner_bootstrap("codex", persist=persist, payload=payload)
|
|
814
|
+
|
|
815
|
+
def codex_bootstrap_state(self) -> dict:
|
|
816
|
+
state = self.runner_bootstrap_state("codex")
|
|
817
|
+
return {
|
|
818
|
+
"codex_ready": bool(state.get("ready")),
|
|
819
|
+
"codex_last_checked_at": state.get("last_checked_at"),
|
|
820
|
+
"codex_last_result": state.get("last_result") if isinstance(state.get("last_result"), dict) else {},
|
|
619
821
|
}
|
|
620
822
|
|
|
621
823
|
def git_readiness(self) -> dict:
|
|
@@ -695,7 +897,8 @@ Use **Test** when the file exposes runtime dependencies.
|
|
|
695
897
|
|
|
696
898
|
def _test_runners_payload(self, payload: dict, *, live: bool) -> dict:
|
|
697
899
|
items = []
|
|
698
|
-
|
|
900
|
+
normalized_payload = apply_runners_runtime_overrides(self._normalize_named_payload("runners", payload))
|
|
901
|
+
for name, config in normalized_payload.items():
|
|
699
902
|
if not isinstance(config, dict):
|
|
700
903
|
continue
|
|
701
904
|
enabled = bool(config.get("enabled", False))
|
|
@@ -718,8 +921,8 @@ Use **Test** when the file exposes runtime dependencies.
|
|
|
718
921
|
"live_probe_executed": False,
|
|
719
922
|
},
|
|
720
923
|
}
|
|
721
|
-
if enabled and
|
|
722
|
-
probe = self.
|
|
924
|
+
if enabled and exists and live:
|
|
925
|
+
probe = self.probe_runner_bootstrap(name, persist=False, payload=normalized_payload)
|
|
723
926
|
item["ok"] = bool(probe.get("ok"))
|
|
724
927
|
item["warnings"] = [*warnings, *list(probe.get("warnings") or [])]
|
|
725
928
|
item["errors"] = list(probe.get("errors") or [])
|
|
@@ -1215,7 +1418,7 @@ Use **Test** when the file exposes runtime dependencies.
|
|
|
1215
1418
|
def _codex_runner_env(config: dict) -> dict[str, str]:
|
|
1216
1419
|
raw_env = config.get("env")
|
|
1217
1420
|
if not isinstance(raw_env, dict):
|
|
1218
|
-
return {}
|
|
1421
|
+
return ensure_utf8_subprocess_env({})
|
|
1219
1422
|
resolved: dict[str, str] = {}
|
|
1220
1423
|
for key, value in raw_env.items():
|
|
1221
1424
|
env_key = str(key or "").strip()
|
|
@@ -1225,7 +1428,7 @@ Use **Test** when the file exposes runtime dependencies.
|
|
|
1225
1428
|
if env_value == "":
|
|
1226
1429
|
continue
|
|
1227
1430
|
resolved[env_key] = env_value
|
|
1228
|
-
return resolved
|
|
1431
|
+
return ensure_utf8_subprocess_env(resolved)
|
|
1229
1432
|
|
|
1230
1433
|
def _prepare_codex_probe_home(
|
|
1231
1434
|
self,
|
|
@@ -1267,34 +1470,233 @@ Use **Test** when the file exposes runtime dependencies.
|
|
|
1267
1470
|
]
|
|
1268
1471
|
)
|
|
1269
1472
|
else:
|
|
1270
|
-
guidance.append("Run `codex
|
|
1473
|
+
guidance.append("Run `codex login` (or just `codex`) once and finish authentication before starting DeepScientist.")
|
|
1271
1474
|
guidance.append(
|
|
1272
1475
|
"If you use a custom Codex path, either set `runners.codex.binary` or launch with `ds --codex /absolute/path/to/codex`."
|
|
1273
1476
|
)
|
|
1274
1477
|
return guidance
|
|
1275
1478
|
|
|
1276
|
-
|
|
1479
|
+
@staticmethod
|
|
1480
|
+
def _provider_profile_probe_hints(metadata: dict[str, object]) -> list[str]:
|
|
1481
|
+
base_url = str(metadata.get("base_url") or "").strip().lower()
|
|
1482
|
+
model = str(metadata.get("model") or "").strip().lower()
|
|
1483
|
+
provider = str(metadata.get("provider") or "").strip().lower()
|
|
1484
|
+
if "dashscope.aliyuncs.com" not in base_url and "bailian" not in provider and "qwen" not in model:
|
|
1485
|
+
return []
|
|
1486
|
+
if "coding.dashscope.aliyuncs.com" not in base_url:
|
|
1487
|
+
return [
|
|
1488
|
+
"Alibaba Bailian's generic DashScope / Qwen platform API is not supported by the Codex-backed DeepScientist path.",
|
|
1489
|
+
"If you want to use Qwen here, switch the profile to the Bailian Coding Plan endpoint: `https://coding.dashscope.aliyuncs.com/v1`.",
|
|
1490
|
+
]
|
|
1491
|
+
return [
|
|
1492
|
+
"For Qwen on Alibaba Bailian, only the Coding Plan endpoint is supported here; do not switch back to the generic Bailian / DashScope Qwen API.",
|
|
1493
|
+
]
|
|
1494
|
+
|
|
1495
|
+
@staticmethod
|
|
1496
|
+
def _local_provider_probe_hints(metadata: dict[str, object]) -> list[str]:
|
|
1497
|
+
base_url = str(metadata.get("base_url") or "").strip()
|
|
1498
|
+
wire_api = str(metadata.get("wire_api") or "").strip().lower()
|
|
1499
|
+
requires_openai_auth = metadata.get("requires_openai_auth")
|
|
1500
|
+
if not base_url:
|
|
1501
|
+
return []
|
|
1502
|
+
is_local_provider = provider_base_url_looks_local(base_url)
|
|
1503
|
+
if requires_openai_auth is not False and not is_local_provider:
|
|
1504
|
+
return []
|
|
1505
|
+
hints = [
|
|
1506
|
+
f"Verify the local provider directly: `curl {base_url}/models`.",
|
|
1507
|
+
f"Then verify the Responses API explicitly: `curl {base_url}/responses ...`.",
|
|
1508
|
+
"Latest Codex CLI requires `wire_api = \"responses\"`; chat-only provider configs are no longer accepted.",
|
|
1509
|
+
"If `/v1/chat/completions` works but `/v1/responses` fails, that backend is not currently compatible with the latest Codex runner.",
|
|
1510
|
+
"If the backend is chat-only and you still want to test it through Codex, try `@openai/codex@0.57.0` with top-level `model_provider` / `model` plus `wire_api = \"chat\"`.",
|
|
1511
|
+
"For local model backends, vLLM is the safest path. Ollama only works when its `/v1/responses` endpoint works; chat-only SGLang deployments will fail with the latest Codex.",
|
|
1512
|
+
]
|
|
1513
|
+
if requires_openai_auth is not False:
|
|
1514
|
+
hints.insert(
|
|
1515
|
+
0,
|
|
1516
|
+
"For local or self-hosted providers, add `requires_openai_auth = false` so DeepScientist can remove conflicting `OPENAI_*` auth variables.",
|
|
1517
|
+
)
|
|
1518
|
+
if not wire_api:
|
|
1519
|
+
hints.insert(0, "Your current provider config does not declare `wire_api`; set `wire_api = \"responses\"` first.")
|
|
1520
|
+
elif wire_api != "responses":
|
|
1521
|
+
hints.insert(0, f"Your current provider config uses `wire_api = \"{wire_api}\"`; switch it to `wire_api = \"responses\"` first.")
|
|
1522
|
+
return hints
|
|
1523
|
+
|
|
1524
|
+
@staticmethod
|
|
1525
|
+
def _codex_direct_hello_probe_command(*, profile: str = "") -> str:
|
|
1526
|
+
profile_args = f" --profile {shlex.quote(profile)}" if profile else ""
|
|
1527
|
+
return (
|
|
1528
|
+
"printf 'Reply with exactly HELLO.' | "
|
|
1529
|
+
f"codex --search{profile_args} exec --json --cd /tmp --skip-git-repo-check -"
|
|
1530
|
+
)
|
|
1531
|
+
|
|
1532
|
+
@staticmethod
|
|
1533
|
+
def _missing_provider_env_guidance(
|
|
1534
|
+
*,
|
|
1535
|
+
profile: str,
|
|
1536
|
+
env_key: str,
|
|
1537
|
+
metadata: dict[str, object],
|
|
1538
|
+
) -> list[str]:
|
|
1539
|
+
guidance = [
|
|
1540
|
+
f"Set `runners.codex.env.{env_key}` in `~/DeepScientist/config/runners.yaml`, or export `{env_key}` before launching `ds`.",
|
|
1541
|
+
]
|
|
1542
|
+
if provider_base_url_looks_local(str(metadata.get("base_url") or "").strip()):
|
|
1543
|
+
guidance.append(
|
|
1544
|
+
f"If `{env_key}` is only a placeholder for a local OpenAI-compatible backend, any non-empty value such as `1234` is usually enough."
|
|
1545
|
+
)
|
|
1546
|
+
if metadata.get("requires_openai_auth") is not False:
|
|
1547
|
+
guidance.append(
|
|
1548
|
+
"Also add `requires_openai_auth = false` to that local provider profile so DeepScientist can remove conflicting `OPENAI_*` auth variables."
|
|
1549
|
+
)
|
|
1550
|
+
guidance.append(
|
|
1551
|
+
"Before retrying DeepScientist, run a real request such as "
|
|
1552
|
+
f"`{ConfigManager._codex_direct_hello_probe_command(profile=profile)}` and verify it returns `HELLO`."
|
|
1553
|
+
)
|
|
1554
|
+
return guidance
|
|
1555
|
+
|
|
1556
|
+
@staticmethod
|
|
1557
|
+
def _chat_wire_probe_version_block(
|
|
1558
|
+
metadata: dict[str, object],
|
|
1559
|
+
*,
|
|
1560
|
+
resolved_binary: str,
|
|
1561
|
+
) -> tuple[tuple[int, int, int] | None, dict[str, object] | None]:
|
|
1562
|
+
wire_api = str(metadata.get("wire_api") or "").strip().lower()
|
|
1563
|
+
if wire_api != "chat":
|
|
1564
|
+
return None, None
|
|
1565
|
+
detected_version = codex_cli_version(str(resolved_binary or ""))
|
|
1566
|
+
required_version = chat_wire_compatible_codex_version()
|
|
1567
|
+
if detected_version == required_version:
|
|
1568
|
+
return detected_version, None
|
|
1569
|
+
required_text = format_codex_cli_version(required_version)
|
|
1570
|
+
detected_text = format_codex_cli_version(detected_version)
|
|
1571
|
+
errors = [
|
|
1572
|
+
"This provider uses `wire_api = \"chat\"`, but DeepScientist only probes chat-mode providers with `codex-cli 0.57.0`.",
|
|
1573
|
+
]
|
|
1574
|
+
if detected_text:
|
|
1575
|
+
errors.append(f"Detected Codex CLI version: `{detected_text}`.")
|
|
1576
|
+
else:
|
|
1577
|
+
errors.append("DeepScientist could not determine the active Codex CLI version from the configured binary.")
|
|
1578
|
+
guidance = [
|
|
1579
|
+
"Install `npm install -g @openai/codex@0.57.0`, or point DeepScientist at a dedicated `0.57.0` binary with `ds --codex /absolute/path/to/codex`.",
|
|
1580
|
+
"If you want to stay on a newer Codex CLI, switch the provider/backend to `wire_api = \"responses\"` instead.",
|
|
1581
|
+
"For chat-mode fallback configs, keep the compatible top-level `model_provider` / `model` entries in `~/.codex/config.toml`.",
|
|
1582
|
+
]
|
|
1583
|
+
return (
|
|
1584
|
+
detected_version,
|
|
1585
|
+
{
|
|
1586
|
+
"summary": f"Codex startup probe blocked by chat-mode provider compatibility. Required Codex CLI: `{required_text}`.",
|
|
1587
|
+
"errors": errors,
|
|
1588
|
+
"guidance": guidance,
|
|
1589
|
+
},
|
|
1590
|
+
)
|
|
1591
|
+
|
|
1592
|
+
@staticmethod
|
|
1593
|
+
def _codex_probe_text_looks_auth_related(stdout_text: str, stderr_text: str) -> bool:
|
|
1594
|
+
haystack = f"{stdout_text}\n{stderr_text}".lower()
|
|
1595
|
+
markers = (
|
|
1596
|
+
"please login",
|
|
1597
|
+
"not logged in",
|
|
1598
|
+
"login required",
|
|
1599
|
+
"authentication required",
|
|
1600
|
+
"auth required",
|
|
1601
|
+
"oauth",
|
|
1602
|
+
"unauthenticated",
|
|
1603
|
+
"missing credentials",
|
|
1604
|
+
"no credentials",
|
|
1605
|
+
)
|
|
1606
|
+
return any(marker in haystack for marker in markers)
|
|
1607
|
+
|
|
1608
|
+
@staticmethod
|
|
1609
|
+
def _codex_probe_text_looks_network_related(stdout_text: str, stderr_text: str) -> bool:
|
|
1610
|
+
haystack = f"{stdout_text}\n{stderr_text}".lower()
|
|
1611
|
+
markers = (
|
|
1612
|
+
"connection refused",
|
|
1613
|
+
"connection reset",
|
|
1614
|
+
"connection timed out",
|
|
1615
|
+
"network is unreachable",
|
|
1616
|
+
"name or service not known",
|
|
1617
|
+
"temporary failure in name resolution",
|
|
1618
|
+
"dns",
|
|
1619
|
+
"proxy",
|
|
1620
|
+
"tls",
|
|
1621
|
+
"certificate",
|
|
1622
|
+
"ssl",
|
|
1623
|
+
"timeout",
|
|
1624
|
+
"timed out",
|
|
1625
|
+
"econnreset",
|
|
1626
|
+
"econnrefused",
|
|
1627
|
+
"enotfound",
|
|
1628
|
+
)
|
|
1629
|
+
return any(marker in haystack for marker in markers)
|
|
1630
|
+
|
|
1631
|
+
def _codex_probe_failure_guidance(
|
|
1632
|
+
self,
|
|
1633
|
+
config: dict,
|
|
1634
|
+
*,
|
|
1635
|
+
stdout_text: str = "",
|
|
1636
|
+
stderr_text: str = "",
|
|
1637
|
+
) -> tuple[list[str], list[str]]:
|
|
1277
1638
|
profile = self._codex_profile_name(config)
|
|
1639
|
+
config_dir = str(config.get("config_dir") or "~/.codex").strip()
|
|
1640
|
+
metadata = active_provider_metadata_from_home(config_dir, profile=profile or None) if config_dir else {}
|
|
1278
1641
|
if profile:
|
|
1642
|
+
provider_hints = self._provider_profile_probe_hints(metadata)
|
|
1643
|
+
local_hints = self._local_provider_probe_hints(metadata)
|
|
1279
1644
|
return (
|
|
1280
1645
|
[
|
|
1281
1646
|
f"Codex profile `{profile}` did not complete the startup hello probe successfully.",
|
|
1282
1647
|
],
|
|
1283
1648
|
[
|
|
1284
|
-
f"Run `
|
|
1649
|
+
f"Run `{self._codex_direct_hello_probe_command(profile=profile)}` in a terminal and confirm that a real `HELLO` request succeeds.",
|
|
1285
1650
|
"If the profile uses a custom provider, make sure its API key, Base URL, and model configuration are available to Codex.",
|
|
1286
1651
|
"If the provider expects the model from the Codex profile itself, set `model: inherit` in `~/DeepScientist/config/runners.yaml`.",
|
|
1652
|
+
*provider_hints,
|
|
1653
|
+
*local_hints,
|
|
1654
|
+
"Then run `ds doctor` and start DeepScientist again.",
|
|
1655
|
+
],
|
|
1656
|
+
)
|
|
1657
|
+
if self._codex_probe_text_looks_auth_related(stdout_text, stderr_text):
|
|
1658
|
+
return (
|
|
1659
|
+
[
|
|
1660
|
+
"Codex reported an authentication or first-run setup problem during the startup hello probe.",
|
|
1661
|
+
"Run `codex login` (or just `codex`) once and complete login before starting DeepScientist.",
|
|
1662
|
+
],
|
|
1663
|
+
[
|
|
1664
|
+
"Run `codex login` (or just `codex`) in a terminal and complete login or first-run setup.",
|
|
1665
|
+
"Then run `printf 'Reply with exactly HELLO.' | codex --search exec --json --cd /tmp --skip-git-repo-check -` and confirm the real request succeeds.",
|
|
1666
|
+
"If login succeeds but the direct probe still fails, check the configured model, provider profile, proxy, and Codex account access.",
|
|
1667
|
+
"Then run `ds doctor` and start DeepScientist again.",
|
|
1668
|
+
],
|
|
1669
|
+
)
|
|
1670
|
+
if self._codex_model_unavailable(stdout_text, stderr_text):
|
|
1671
|
+
return (
|
|
1672
|
+
[
|
|
1673
|
+
"Codex authentication may be working, but the configured startup probe model was not accepted.",
|
|
1674
|
+
],
|
|
1675
|
+
[
|
|
1676
|
+
"Run `printf 'Reply with exactly HELLO.' | codex --search exec --json --cd /tmp --skip-git-repo-check -` in the same shell and confirm the current Codex default model works.",
|
|
1677
|
+
"Set `runners.codex.model: inherit` in `~/DeepScientist/config/runners.yaml`, or set it to a model that your Codex account can actually use.",
|
|
1678
|
+
"Then run `ds doctor` and start DeepScientist again.",
|
|
1679
|
+
],
|
|
1680
|
+
)
|
|
1681
|
+
if self._codex_probe_text_looks_network_related(stdout_text, stderr_text):
|
|
1682
|
+
return (
|
|
1683
|
+
[
|
|
1684
|
+
"Codex CLI was found, but the real startup hello request appears to have failed at the network, proxy, TLS, or provider layer.",
|
|
1685
|
+
],
|
|
1686
|
+
[
|
|
1687
|
+
"Run `printf 'Reply with exactly HELLO.' | codex --search exec --json --cd /tmp --skip-git-repo-check -` from the same shell and verify the request succeeds.",
|
|
1688
|
+
"If this host needs a proxy, export `HTTP_PROXY`, `HTTPS_PROXY`, and `NO_PROXY` before launching `ds`; for managed or supervised runs, also put required environment variables under `runners.codex.env`.",
|
|
1287
1689
|
"Then run `ds doctor` and start DeepScientist again.",
|
|
1288
1690
|
],
|
|
1289
1691
|
)
|
|
1290
1692
|
return (
|
|
1291
1693
|
[
|
|
1292
|
-
"
|
|
1694
|
+
"Codex CLI was found, but its real startup hello request did not complete successfully.",
|
|
1293
1695
|
],
|
|
1294
1696
|
[
|
|
1295
|
-
"Run `codex --
|
|
1296
|
-
"If `
|
|
1297
|
-
"If the configured model is not available to your Codex account,
|
|
1697
|
+
"Run `printf 'Reply with exactly HELLO.' | codex --search exec --json --cd /tmp --skip-git-repo-check -` in the same shell and inspect the Codex stderr/stdout.",
|
|
1698
|
+
"If that direct command succeeds but `ds doctor` fails, compare `which codex`, `CODEX_HOME`, proxy variables, and `~/DeepScientist/config/runners.yaml`.",
|
|
1699
|
+
"If the configured model is not available to your Codex account, set `runners.codex.model: inherit` or another accessible model.",
|
|
1298
1700
|
"Then run `ds doctor` and start DeepScientist again.",
|
|
1299
1701
|
],
|
|
1300
1702
|
)
|
|
@@ -1417,8 +1819,8 @@ Use **Test** when the file exposes runtime dependencies.
|
|
|
1417
1819
|
approval_policy = str(config.get("approval_policy") or "on-request").strip()
|
|
1418
1820
|
sandbox_mode = str(config.get("sandbox_mode") or "workspace-write").strip()
|
|
1419
1821
|
|
|
1420
|
-
env = os.environ.copy()
|
|
1421
|
-
env.update(self._codex_runner_env(config))
|
|
1822
|
+
env = ensure_utf8_subprocess_env(os.environ.copy())
|
|
1823
|
+
env.update(self._claude_auth_runner_env(self._codex_runner_env(config)))
|
|
1422
1824
|
config_dir = str(config.get("config_dir") or "~/.codex").strip()
|
|
1423
1825
|
probe_home_handle: tempfile.TemporaryDirectory[str] | None = None
|
|
1424
1826
|
compatibility_warnings: list[str] = []
|
|
@@ -1430,10 +1832,20 @@ Use **Test** when the file exposes runtime dependencies.
|
|
|
1430
1832
|
env["CODEX_HOME"] = prepared_home
|
|
1431
1833
|
if profile_config_warning:
|
|
1432
1834
|
compatibility_warnings.append(profile_config_warning)
|
|
1433
|
-
metadata =
|
|
1835
|
+
metadata = active_provider_metadata_from_home(env.get("CODEX_HOME") or config_dir, profile=profile or None)
|
|
1434
1836
|
if metadata.get("requires_openai_auth") is False:
|
|
1435
1837
|
env.pop("OPENAI_API_KEY", None)
|
|
1436
1838
|
env.pop("OPENAI_BASE_URL", None)
|
|
1839
|
+
configured_provider_env_key = missing_provider_env_key(metadata, env)
|
|
1840
|
+
details["provider_env_key"] = str(metadata.get("env_key") or "").strip() or None
|
|
1841
|
+
details["provider_env_missing"] = bool(configured_provider_env_key)
|
|
1842
|
+
details["provider_wire_api"] = str(metadata.get("wire_api") or "").strip() or None
|
|
1843
|
+
detected_codex_version, chat_wire_block = self._chat_wire_probe_version_block(
|
|
1844
|
+
metadata,
|
|
1845
|
+
resolved_binary=resolved_binary,
|
|
1846
|
+
)
|
|
1847
|
+
if detected_codex_version is not None:
|
|
1848
|
+
details["codex_cli_version"] = format_codex_cli_version(detected_codex_version) or None
|
|
1437
1849
|
prompt = "Reply with exactly HELLO."
|
|
1438
1850
|
if reasoning_effort_warning:
|
|
1439
1851
|
compatibility_warnings.append(reasoning_effort_warning)
|
|
@@ -1442,6 +1854,15 @@ Use **Test** when the file exposes runtime dependencies.
|
|
|
1442
1854
|
f"Codex profile `{profile}` is provider-backed. DeepScientist is probing it with `model: inherit`."
|
|
1443
1855
|
)
|
|
1444
1856
|
base_warnings: list[str] = list(compatibility_warnings)
|
|
1857
|
+
if chat_wire_block is not None:
|
|
1858
|
+
return {
|
|
1859
|
+
"ok": False,
|
|
1860
|
+
"summary": str(chat_wire_block["summary"]),
|
|
1861
|
+
"warnings": base_warnings,
|
|
1862
|
+
"errors": list(chat_wire_block["errors"]),
|
|
1863
|
+
"details": details,
|
|
1864
|
+
"guidance": list(chat_wire_block["guidance"]),
|
|
1865
|
+
}
|
|
1445
1866
|
|
|
1446
1867
|
def run_probe_once(model_for_command: str) -> tuple[list[str], subprocess.CompletedProcess[str] | None, subprocess.TimeoutExpired | None]:
|
|
1447
1868
|
command = self._build_codex_probe_command(
|
|
@@ -1458,10 +1879,10 @@ Use **Test** when the file exposes runtime dependencies.
|
|
|
1458
1879
|
input=prompt,
|
|
1459
1880
|
cwd=str(repo_root()),
|
|
1460
1881
|
env=env,
|
|
1461
|
-
text=True,
|
|
1462
1882
|
capture_output=True,
|
|
1463
1883
|
timeout=90,
|
|
1464
1884
|
check=False,
|
|
1885
|
+
**utf8_text_subprocess_kwargs(),
|
|
1465
1886
|
)
|
|
1466
1887
|
except subprocess.TimeoutExpired as exc:
|
|
1467
1888
|
return command, None, exc
|
|
@@ -1469,25 +1890,32 @@ Use **Test** when the file exposes runtime dependencies.
|
|
|
1469
1890
|
|
|
1470
1891
|
command, result, timeout_error = run_probe_once(effective_model)
|
|
1471
1892
|
if timeout_error is not None:
|
|
1893
|
+
stdout_text = str(timeout_error.stdout or "")
|
|
1894
|
+
stderr_text = str(timeout_error.stderr or "")
|
|
1472
1895
|
details.update(
|
|
1473
1896
|
{
|
|
1474
1897
|
"exit_code": None,
|
|
1475
|
-
"stdout_excerpt": self._compact_probe_text(
|
|
1476
|
-
"stderr_excerpt": self._compact_probe_text(
|
|
1898
|
+
"stdout_excerpt": self._compact_probe_text(stdout_text),
|
|
1899
|
+
"stderr_excerpt": self._compact_probe_text(stderr_text),
|
|
1477
1900
|
"probe_command": command,
|
|
1478
1901
|
}
|
|
1479
1902
|
)
|
|
1903
|
+
failure_errors, failure_guidance = self._codex_probe_failure_guidance(
|
|
1904
|
+
config,
|
|
1905
|
+
stdout_text=stdout_text,
|
|
1906
|
+
stderr_text=stderr_text,
|
|
1907
|
+
)
|
|
1480
1908
|
return {
|
|
1481
1909
|
"ok": False,
|
|
1482
1910
|
"summary": "Codex startup probe timed out.",
|
|
1483
1911
|
"warnings": base_warnings,
|
|
1484
1912
|
"errors": [
|
|
1485
1913
|
"Codex did not answer the startup hello probe within 90 seconds.",
|
|
1486
|
-
*
|
|
1914
|
+
*failure_errors,
|
|
1487
1915
|
],
|
|
1488
1916
|
"details": details,
|
|
1489
1917
|
"guidance": [
|
|
1490
|
-
*
|
|
1918
|
+
*failure_guidance,
|
|
1491
1919
|
"If `codex` is missing on PATH, install it explicitly with `npm install -g @openai/codex`.",
|
|
1492
1920
|
"Confirm the configured model is available to your Codex setup. DeepScientist currently probes Codex with the configured runner model first.",
|
|
1493
1921
|
],
|
|
@@ -1567,8 +1995,31 @@ Use **Test** when the file exposes runtime dependencies.
|
|
|
1567
1995
|
warnings.append("Codex returned stderr during the startup probe.")
|
|
1568
1996
|
if details.get("model_fallback_attempted") and not details.get("model_fallback_used"):
|
|
1569
1997
|
warnings.append("DeepScientist also tried the current Codex default model, but that fallback probe did not succeed.")
|
|
1570
|
-
errors.extend(
|
|
1571
|
-
|
|
1998
|
+
errors.extend(
|
|
1999
|
+
self._codex_probe_failure_guidance(
|
|
2000
|
+
config,
|
|
2001
|
+
stdout_text=stdout_text,
|
|
2002
|
+
stderr_text=stderr_text,
|
|
2003
|
+
)[0]
|
|
2004
|
+
)
|
|
2005
|
+
missing_env_key = missing_provider_env_key_from_text(stdout_text, stderr_text) or configured_provider_env_key
|
|
2006
|
+
failure_guidance = self._codex_probe_failure_guidance(
|
|
2007
|
+
config,
|
|
2008
|
+
stdout_text=stdout_text,
|
|
2009
|
+
stderr_text=stderr_text,
|
|
2010
|
+
)[1]
|
|
2011
|
+
if not ok and missing_env_key and profile:
|
|
2012
|
+
errors.append(
|
|
2013
|
+
f"Codex profile `{profile}` requires environment variable `{missing_env_key}`, but DeepScientist did not receive it."
|
|
2014
|
+
)
|
|
2015
|
+
failure_guidance = [
|
|
2016
|
+
*self._missing_provider_env_guidance(
|
|
2017
|
+
profile=profile,
|
|
2018
|
+
env_key=missing_env_key,
|
|
2019
|
+
metadata=metadata,
|
|
2020
|
+
),
|
|
2021
|
+
*failure_guidance,
|
|
2022
|
+
]
|
|
1572
2023
|
return {
|
|
1573
2024
|
"ok": ok,
|
|
1574
2025
|
"summary": "Codex startup probe completed." if ok else "Codex startup probe failed.",
|
|
@@ -1578,38 +2029,402 @@ Use **Test** when the file exposes runtime dependencies.
|
|
|
1578
2029
|
"guidance": [] if ok else failure_guidance,
|
|
1579
2030
|
}
|
|
1580
2031
|
|
|
1581
|
-
def
|
|
2032
|
+
def _persist_runner_bootstrap_result(self, runner_name: str, result: dict) -> None:
|
|
2033
|
+
normalized_runner = str(runner_name or "codex").strip().lower() or "codex"
|
|
1582
2034
|
config = self.load_named_normalized("config")
|
|
1583
2035
|
bootstrap = config.get("bootstrap") if isinstance(config.get("bootstrap"), dict) else {}
|
|
1584
2036
|
details = result.get("details") if isinstance(result.get("details"), dict) else {}
|
|
1585
|
-
bootstrap
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
"
|
|
1589
|
-
"
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
2037
|
+
runner_readiness = bootstrap.get("runner_readiness") if isinstance(bootstrap.get("runner_readiness"), dict) else {}
|
|
2038
|
+
runner_readiness[normalized_runner] = {
|
|
2039
|
+
"ready": bool(result.get("ok")),
|
|
2040
|
+
"last_checked_at": details.get("checked_at") or utc_now(),
|
|
2041
|
+
"last_result": {
|
|
2042
|
+
"ok": bool(result.get("ok")),
|
|
2043
|
+
"summary": result.get("summary"),
|
|
2044
|
+
"warnings": list(result.get("warnings") or []),
|
|
2045
|
+
"errors": list(result.get("errors") or []),
|
|
2046
|
+
"guidance": list(result.get("guidance") or []),
|
|
2047
|
+
"binary": details.get("binary"),
|
|
2048
|
+
"resolved_binary": details.get("resolved_binary"),
|
|
2049
|
+
"model": details.get("model"),
|
|
2050
|
+
"requested_model": details.get("requested_model"),
|
|
2051
|
+
"effective_model": details.get("effective_model"),
|
|
2052
|
+
"exit_code": details.get("exit_code"),
|
|
2053
|
+
"stdout_excerpt": details.get("stdout_excerpt"),
|
|
2054
|
+
"stderr_excerpt": details.get("stderr_excerpt"),
|
|
2055
|
+
"profile": details.get("profile"),
|
|
2056
|
+
"permission_mode": details.get("permission_mode"),
|
|
2057
|
+
"variant": details.get("variant"),
|
|
2058
|
+
},
|
|
1607
2059
|
}
|
|
2060
|
+
bootstrap["runner_readiness"] = runner_readiness
|
|
2061
|
+
if normalized_runner == "codex":
|
|
2062
|
+
codex_state = runner_readiness["codex"]
|
|
2063
|
+
bootstrap["codex_ready"] = bool(codex_state.get("ready"))
|
|
2064
|
+
bootstrap["codex_last_checked_at"] = codex_state.get("last_checked_at")
|
|
2065
|
+
bootstrap["codex_last_result"] = codex_state.get("last_result")
|
|
1608
2066
|
config["bootstrap"] = bootstrap
|
|
1609
2067
|
self.save_named_payload("config", config)
|
|
1610
|
-
if bool(result.get("ok")) and bool(details.get("model_fallback_used")):
|
|
2068
|
+
if normalized_runner == "codex" and bool(result.get("ok")) and bool(details.get("model_fallback_used")):
|
|
1611
2069
|
self._persist_codex_model_inherit(details.get("requested_model"))
|
|
1612
2070
|
|
|
2071
|
+
def _persist_codex_bootstrap_result(self, result: dict) -> None:
|
|
2072
|
+
self._persist_runner_bootstrap_result("codex", result)
|
|
2073
|
+
|
|
2074
|
+
@staticmethod
|
|
2075
|
+
def _copy_runner_file_if_exists(source: Path, target: Path) -> None:
|
|
2076
|
+
if not source.exists() or not source.is_file():
|
|
2077
|
+
return
|
|
2078
|
+
target.parent.mkdir(parents=True, exist_ok=True)
|
|
2079
|
+
shutil.copy2(source, target)
|
|
2080
|
+
|
|
2081
|
+
@staticmethod
|
|
2082
|
+
def _claude_auth_runner_env(env: dict[str, str]) -> dict[str, str]:
|
|
2083
|
+
resolved = dict(env)
|
|
2084
|
+
auth_token = str(resolved.get("ANTHROPIC_AUTH_TOKEN") or "").strip()
|
|
2085
|
+
api_key = str(resolved.get("ANTHROPIC_API_KEY") or "").strip()
|
|
2086
|
+
if auth_token and not api_key:
|
|
2087
|
+
resolved["ANTHROPIC_API_KEY"] = auth_token
|
|
2088
|
+
return resolved
|
|
2089
|
+
|
|
2090
|
+
def _runner_missing_binary_guidance(self, runner_name: str, config: dict) -> list[str]:
|
|
2091
|
+
normalized_runner = str(runner_name or "").strip().lower()
|
|
2092
|
+
binary = str(config.get("binary") or normalized_runner).strip() or normalized_runner
|
|
2093
|
+
if normalized_runner == "codex":
|
|
2094
|
+
return self._codex_missing_binary_guidance(config)
|
|
2095
|
+
if normalized_runner == "claude":
|
|
2096
|
+
return [
|
|
2097
|
+
f"Install Claude Code and make sure `{binary} --version` works in the current shell.",
|
|
2098
|
+
"If Claude Code is already installed elsewhere, set `runners.claude.binary` to the absolute path.",
|
|
2099
|
+
]
|
|
2100
|
+
if normalized_runner == "opencode":
|
|
2101
|
+
return [
|
|
2102
|
+
f"Install OpenCode and make sure `{binary} --version` works in the current shell.",
|
|
2103
|
+
"If OpenCode is already installed elsewhere, set `runners.opencode.binary` to the absolute path.",
|
|
2104
|
+
]
|
|
2105
|
+
if normalized_runner == "kimi":
|
|
2106
|
+
return [
|
|
2107
|
+
f"Install Kimi Code and make sure `{binary} --version` works in the current shell.",
|
|
2108
|
+
"Run `kimi login` (or just `kimi`) once to complete the first-run login flow.",
|
|
2109
|
+
"If Kimi Code uses a custom home, point `runners.kimi.config_dir` at the correct `~/.kimi`-style directory that contains `config.toml` and `mcp.json`.",
|
|
2110
|
+
]
|
|
2111
|
+
return [f"Install runner `{normalized_runner}` and ensure `{binary}` is on PATH."]
|
|
2112
|
+
|
|
2113
|
+
def _probe_claude_runner(self, config: dict) -> dict:
|
|
2114
|
+
checked_at = utc_now()
|
|
2115
|
+
binary = str(config.get("binary") or "claude").strip() or "claude"
|
|
2116
|
+
resolved_binary = resolve_runner_binary(binary, runner_name="claude")
|
|
2117
|
+
requested_model = str(config.get("model") or "inherit").strip() or "inherit"
|
|
2118
|
+
permission_mode = str(config.get("permission_mode") or "bypassPermissions").strip() or "bypassPermissions"
|
|
2119
|
+
details: dict[str, object] = {
|
|
2120
|
+
"binary": binary,
|
|
2121
|
+
"resolved_binary": resolved_binary,
|
|
2122
|
+
"config_dir": str(config.get("config_dir") or "~/.claude"),
|
|
2123
|
+
"model": requested_model,
|
|
2124
|
+
"requested_model": requested_model,
|
|
2125
|
+
"effective_model": requested_model,
|
|
2126
|
+
"permission_mode": permission_mode,
|
|
2127
|
+
"checked_at": checked_at,
|
|
2128
|
+
}
|
|
2129
|
+
if not resolved_binary:
|
|
2130
|
+
return {
|
|
2131
|
+
"ok": False,
|
|
2132
|
+
"summary": "Claude Code startup probe failed before execution.",
|
|
2133
|
+
"warnings": [],
|
|
2134
|
+
"errors": [f"Claude Code binary `{binary}` is not available."],
|
|
2135
|
+
"details": details,
|
|
2136
|
+
"guidance": self._runner_missing_binary_guidance("claude", config),
|
|
2137
|
+
}
|
|
2138
|
+
env = ensure_utf8_subprocess_env(os.environ.copy())
|
|
2139
|
+
env.update(self._claude_auth_runner_env(self._codex_runner_env(config)))
|
|
2140
|
+
temp_home_handle = tempfile.TemporaryDirectory()
|
|
2141
|
+
try:
|
|
2142
|
+
temp_home = Path(temp_home_handle.name)
|
|
2143
|
+
source_home = Path(str(config.get("config_dir") or Path.home() / ".claude")).expanduser()
|
|
2144
|
+
for filename in (".credentials.json", "settings.json", "settings.local.json"):
|
|
2145
|
+
self._copy_runner_file_if_exists(source_home / filename, temp_home / filename)
|
|
2146
|
+
env["CLAUDE_CONFIG_DIR"] = str(temp_home)
|
|
2147
|
+
command = [
|
|
2148
|
+
resolved_binary,
|
|
2149
|
+
"-p",
|
|
2150
|
+
"--input-format",
|
|
2151
|
+
"text",
|
|
2152
|
+
"--output-format",
|
|
2153
|
+
"json",
|
|
2154
|
+
"--add-dir",
|
|
2155
|
+
str(repo_root()),
|
|
2156
|
+
"--no-session-persistence",
|
|
2157
|
+
"--permission-mode",
|
|
2158
|
+
permission_mode,
|
|
2159
|
+
]
|
|
2160
|
+
if requested_model.lower() not in {"", "inherit", "default", "claude-default"}:
|
|
2161
|
+
command.extend(["--model", requested_model])
|
|
2162
|
+
command.extend(["--tools", ""])
|
|
2163
|
+
result = subprocess.run(
|
|
2164
|
+
command,
|
|
2165
|
+
input="Reply with exactly HELLO.",
|
|
2166
|
+
cwd=str(repo_root()),
|
|
2167
|
+
env=env,
|
|
2168
|
+
capture_output=True,
|
|
2169
|
+
timeout=90,
|
|
2170
|
+
check=False,
|
|
2171
|
+
**utf8_text_subprocess_kwargs(),
|
|
2172
|
+
)
|
|
2173
|
+
except subprocess.TimeoutExpired as exc:
|
|
2174
|
+
details.update({
|
|
2175
|
+
"exit_code": None,
|
|
2176
|
+
"stdout_excerpt": self._compact_probe_text(exc.stdout or ""),
|
|
2177
|
+
"stderr_excerpt": self._compact_probe_text(exc.stderr or ""),
|
|
2178
|
+
})
|
|
2179
|
+
return {
|
|
2180
|
+
"ok": False,
|
|
2181
|
+
"summary": "Claude Code startup probe timed out.",
|
|
2182
|
+
"warnings": [],
|
|
2183
|
+
"errors": ["Claude Code did not answer the startup probe within 90 seconds."],
|
|
2184
|
+
"details": details,
|
|
2185
|
+
"guidance": [
|
|
2186
|
+
"Run a small headless Claude Code request manually and confirm it can answer before starting DeepScientist.",
|
|
2187
|
+
],
|
|
2188
|
+
}
|
|
2189
|
+
finally:
|
|
2190
|
+
temp_home_handle.cleanup()
|
|
2191
|
+
stdout_text = (result.stdout or "").strip()
|
|
2192
|
+
stderr_text = (result.stderr or "").strip()
|
|
2193
|
+
ok = result.returncode == 0 and "HELLO" in f"{stdout_text}\n{stderr_text}".upper()
|
|
2194
|
+
details.update({
|
|
2195
|
+
"exit_code": result.returncode,
|
|
2196
|
+
"stdout_excerpt": self._compact_probe_text(stdout_text),
|
|
2197
|
+
"stderr_excerpt": self._compact_probe_text(stderr_text),
|
|
2198
|
+
"probe_command": command,
|
|
2199
|
+
})
|
|
2200
|
+
return {
|
|
2201
|
+
"ok": ok,
|
|
2202
|
+
"summary": "Claude Code startup probe completed." if ok else "Claude Code startup probe failed.",
|
|
2203
|
+
"warnings": ["Claude Code returned stderr during the startup probe."] if stderr_text else [],
|
|
2204
|
+
"errors": [] if ok else ["Claude Code did not complete the startup hello probe successfully."],
|
|
2205
|
+
"details": details,
|
|
2206
|
+
"guidance": [] if ok else [
|
|
2207
|
+
"Run `claude -p \"Reply with exactly HELLO.\" --output-format json --tools \"\"` manually and confirm it returns `HELLO`.",
|
|
2208
|
+
"If Claude Code uses a custom account or credential path, point `runners.claude.config_dir` at the correct home.",
|
|
2209
|
+
],
|
|
2210
|
+
}
|
|
2211
|
+
|
|
2212
|
+
def _probe_opencode_runner(self, config: dict) -> dict:
|
|
2213
|
+
checked_at = utc_now()
|
|
2214
|
+
binary = str(config.get("binary") or "opencode").strip() or "opencode"
|
|
2215
|
+
resolved_binary = resolve_runner_binary(binary, runner_name="opencode")
|
|
2216
|
+
requested_model = str(config.get("model") or "inherit").strip() or "inherit"
|
|
2217
|
+
variant = str(config.get("variant") or "").strip() or None
|
|
2218
|
+
permission_mode = str(config.get("permission_mode") or "allow").strip().lower() or "allow"
|
|
2219
|
+
details: dict[str, object] = {
|
|
2220
|
+
"binary": binary,
|
|
2221
|
+
"resolved_binary": resolved_binary,
|
|
2222
|
+
"config_dir": str(config.get("config_dir") or "~/.config/opencode"),
|
|
2223
|
+
"model": requested_model,
|
|
2224
|
+
"requested_model": requested_model,
|
|
2225
|
+
"effective_model": requested_model,
|
|
2226
|
+
"variant": variant,
|
|
2227
|
+
"permission_mode": permission_mode,
|
|
2228
|
+
"checked_at": checked_at,
|
|
2229
|
+
}
|
|
2230
|
+
if not resolved_binary:
|
|
2231
|
+
return {
|
|
2232
|
+
"ok": False,
|
|
2233
|
+
"summary": "OpenCode startup probe failed before execution.",
|
|
2234
|
+
"warnings": [],
|
|
2235
|
+
"errors": [f"OpenCode binary `{binary}` is not available."],
|
|
2236
|
+
"details": details,
|
|
2237
|
+
"guidance": self._runner_missing_binary_guidance("opencode", config),
|
|
2238
|
+
}
|
|
2239
|
+
env = ensure_utf8_subprocess_env(os.environ.copy())
|
|
2240
|
+
env.update(self._codex_runner_env(config))
|
|
2241
|
+
temp_home_handle = tempfile.TemporaryDirectory()
|
|
2242
|
+
try:
|
|
2243
|
+
temp_home = Path(temp_home_handle.name)
|
|
2244
|
+
config_root = temp_home / ".config" / "opencode"
|
|
2245
|
+
config_root.mkdir(parents=True, exist_ok=True)
|
|
2246
|
+
source_root = Path(str(config.get("config_dir") or Path.home() / ".config" / "opencode")).expanduser()
|
|
2247
|
+
self._copy_runner_file_if_exists(source_root / "opencode.json", config_root / "opencode.json")
|
|
2248
|
+
env["HOME"] = str(temp_home)
|
|
2249
|
+
env["XDG_CONFIG_HOME"] = str(temp_home / ".config")
|
|
2250
|
+
command = [
|
|
2251
|
+
resolved_binary,
|
|
2252
|
+
"run",
|
|
2253
|
+
"--format",
|
|
2254
|
+
"json",
|
|
2255
|
+
"--pure",
|
|
2256
|
+
"--dir",
|
|
2257
|
+
str(repo_root()),
|
|
2258
|
+
]
|
|
2259
|
+
if requested_model.lower() not in {"", "inherit", "default", "opencode-default"}:
|
|
2260
|
+
command.extend(["--model", requested_model])
|
|
2261
|
+
if variant:
|
|
2262
|
+
command.extend(["--variant", variant])
|
|
2263
|
+
command.append("Reply with exactly HELLO")
|
|
2264
|
+
result = subprocess.run(
|
|
2265
|
+
command,
|
|
2266
|
+
cwd=str(repo_root()),
|
|
2267
|
+
env=env,
|
|
2268
|
+
capture_output=True,
|
|
2269
|
+
timeout=90,
|
|
2270
|
+
check=False,
|
|
2271
|
+
**utf8_text_subprocess_kwargs(),
|
|
2272
|
+
)
|
|
2273
|
+
except subprocess.TimeoutExpired as exc:
|
|
2274
|
+
details.update({
|
|
2275
|
+
"exit_code": None,
|
|
2276
|
+
"stdout_excerpt": self._compact_probe_text(exc.stdout or ""),
|
|
2277
|
+
"stderr_excerpt": self._compact_probe_text(exc.stderr or ""),
|
|
2278
|
+
})
|
|
2279
|
+
return {
|
|
2280
|
+
"ok": False,
|
|
2281
|
+
"summary": "OpenCode startup probe timed out.",
|
|
2282
|
+
"warnings": [],
|
|
2283
|
+
"errors": ["OpenCode did not answer the startup probe within 90 seconds."],
|
|
2284
|
+
"details": details,
|
|
2285
|
+
"guidance": [
|
|
2286
|
+
"Run a small `opencode run --format json` request manually and confirm it can answer before starting DeepScientist.",
|
|
2287
|
+
],
|
|
2288
|
+
}
|
|
2289
|
+
finally:
|
|
2290
|
+
temp_home_handle.cleanup()
|
|
2291
|
+
stdout_text = (result.stdout or "").strip()
|
|
2292
|
+
stderr_text = (result.stderr or "").strip()
|
|
2293
|
+
ok = result.returncode == 0 and "HELLO" in f"{stdout_text}\n{stderr_text}".upper()
|
|
2294
|
+
details.update({
|
|
2295
|
+
"exit_code": result.returncode,
|
|
2296
|
+
"stdout_excerpt": self._compact_probe_text(stdout_text),
|
|
2297
|
+
"stderr_excerpt": self._compact_probe_text(stderr_text),
|
|
2298
|
+
"probe_command": command,
|
|
2299
|
+
})
|
|
2300
|
+
return {
|
|
2301
|
+
"ok": ok,
|
|
2302
|
+
"summary": "OpenCode startup probe completed." if ok else "OpenCode startup probe failed.",
|
|
2303
|
+
"warnings": ["OpenCode returned stderr during the startup probe."] if stderr_text else [],
|
|
2304
|
+
"errors": [] if ok else ["OpenCode did not complete the startup hello probe successfully."],
|
|
2305
|
+
"details": details,
|
|
2306
|
+
"guidance": [] if ok else [
|
|
2307
|
+
"Run `opencode run --format json \"Reply with exactly HELLO\"` manually and confirm it succeeds.",
|
|
2308
|
+
"If OpenCode uses a custom config root, point `runners.opencode.config_dir` at the correct directory.",
|
|
2309
|
+
],
|
|
2310
|
+
}
|
|
2311
|
+
|
|
2312
|
+
def _probe_kimi_runner(self, config: dict) -> dict:
|
|
2313
|
+
checked_at = utc_now()
|
|
2314
|
+
binary = str(config.get("binary") or "kimi").strip() or "kimi"
|
|
2315
|
+
resolved_binary = resolve_runner_binary(binary, runner_name="kimi")
|
|
2316
|
+
requested_model = str(config.get("model") or "inherit").strip() or "inherit"
|
|
2317
|
+
agent_name = str(config.get("agent") or "").strip() or None
|
|
2318
|
+
yolo_enabled = bool(config.get("yolo", True))
|
|
2319
|
+
thinking_enabled = bool(config.get("thinking", False))
|
|
2320
|
+
details: dict[str, object] = {
|
|
2321
|
+
"binary": binary,
|
|
2322
|
+
"resolved_binary": resolved_binary,
|
|
2323
|
+
"config_dir": str(config.get("config_dir") or "~/.kimi"),
|
|
2324
|
+
"model": requested_model,
|
|
2325
|
+
"requested_model": requested_model,
|
|
2326
|
+
"effective_model": requested_model,
|
|
2327
|
+
"agent": agent_name,
|
|
2328
|
+
"thinking": thinking_enabled,
|
|
2329
|
+
"yolo": yolo_enabled,
|
|
2330
|
+
"checked_at": checked_at,
|
|
2331
|
+
}
|
|
2332
|
+
if not resolved_binary:
|
|
2333
|
+
return {
|
|
2334
|
+
"ok": False,
|
|
2335
|
+
"summary": "Kimi Code startup probe failed before execution.",
|
|
2336
|
+
"warnings": [],
|
|
2337
|
+
"errors": [f"Kimi Code binary `{binary}` is not available."],
|
|
2338
|
+
"details": details,
|
|
2339
|
+
"guidance": self._runner_missing_binary_guidance("kimi", config),
|
|
2340
|
+
}
|
|
2341
|
+
env = ensure_utf8_subprocess_env(os.environ.copy())
|
|
2342
|
+
env.update(self._codex_runner_env(config))
|
|
2343
|
+
temp_home_handle = tempfile.TemporaryDirectory()
|
|
2344
|
+
try:
|
|
2345
|
+
temp_home = Path(temp_home_handle.name)
|
|
2346
|
+
kimi_home = materialize_kimi_runtime_home(
|
|
2347
|
+
source_home=Path(str(config.get("config_dir") or Path.home() / ".kimi")).expanduser(),
|
|
2348
|
+
target_home=temp_home,
|
|
2349
|
+
)
|
|
2350
|
+
mcp_config_path = kimi_home / "mcp.json"
|
|
2351
|
+
write_json(mcp_config_path, {"mcpServers": {}})
|
|
2352
|
+
env["HOME"] = str(temp_home)
|
|
2353
|
+
env["USERPROFILE"] = str(temp_home)
|
|
2354
|
+
command = [
|
|
2355
|
+
resolved_binary,
|
|
2356
|
+
"--print",
|
|
2357
|
+
"--input-format",
|
|
2358
|
+
"text",
|
|
2359
|
+
"--output-format",
|
|
2360
|
+
"stream-json",
|
|
2361
|
+
"--work-dir",
|
|
2362
|
+
str(repo_root()),
|
|
2363
|
+
"--mcp-config-file",
|
|
2364
|
+
str(mcp_config_path),
|
|
2365
|
+
]
|
|
2366
|
+
if yolo_enabled:
|
|
2367
|
+
command.append("--yolo")
|
|
2368
|
+
if requested_model.lower() not in {"", "inherit", "default", "kimi-default"}:
|
|
2369
|
+
command.extend(["--model", requested_model])
|
|
2370
|
+
if agent_name:
|
|
2371
|
+
command.extend(["--agent", agent_name])
|
|
2372
|
+
if thinking_enabled:
|
|
2373
|
+
command.append("--thinking")
|
|
2374
|
+
result = subprocess.run(
|
|
2375
|
+
command,
|
|
2376
|
+
input="Reply with exactly HELLO.",
|
|
2377
|
+
cwd=str(repo_root()),
|
|
2378
|
+
env=env,
|
|
2379
|
+
capture_output=True,
|
|
2380
|
+
timeout=90,
|
|
2381
|
+
check=False,
|
|
2382
|
+
**utf8_text_subprocess_kwargs(),
|
|
2383
|
+
)
|
|
2384
|
+
except subprocess.TimeoutExpired as exc:
|
|
2385
|
+
details.update(
|
|
2386
|
+
{
|
|
2387
|
+
"exit_code": None,
|
|
2388
|
+
"stdout_excerpt": self._compact_probe_text(exc.stdout or ""),
|
|
2389
|
+
"stderr_excerpt": self._compact_probe_text(exc.stderr or ""),
|
|
2390
|
+
}
|
|
2391
|
+
)
|
|
2392
|
+
return {
|
|
2393
|
+
"ok": False,
|
|
2394
|
+
"summary": "Kimi Code startup probe timed out.",
|
|
2395
|
+
"warnings": [],
|
|
2396
|
+
"errors": ["Kimi Code did not answer the startup probe within 90 seconds."],
|
|
2397
|
+
"details": details,
|
|
2398
|
+
"guidance": [
|
|
2399
|
+
"Run a small `kimi --print --output-format stream-json` request manually and confirm it can answer before starting DeepScientist.",
|
|
2400
|
+
],
|
|
2401
|
+
}
|
|
2402
|
+
finally:
|
|
2403
|
+
temp_home_handle.cleanup()
|
|
2404
|
+
stdout_text = (result.stdout or "").strip()
|
|
2405
|
+
stderr_text = (result.stderr or "").strip()
|
|
2406
|
+
ok = result.returncode == 0 and "HELLO" in f"{stdout_text}\n{stderr_text}".upper()
|
|
2407
|
+
details.update(
|
|
2408
|
+
{
|
|
2409
|
+
"exit_code": result.returncode,
|
|
2410
|
+
"stdout_excerpt": self._compact_probe_text(stdout_text),
|
|
2411
|
+
"stderr_excerpt": self._compact_probe_text(stderr_text),
|
|
2412
|
+
"probe_command": command,
|
|
2413
|
+
}
|
|
2414
|
+
)
|
|
2415
|
+
return {
|
|
2416
|
+
"ok": ok,
|
|
2417
|
+
"summary": "Kimi Code startup probe completed." if ok else "Kimi Code startup probe failed.",
|
|
2418
|
+
"warnings": ["Kimi Code returned stderr during the startup probe."] if stderr_text else [],
|
|
2419
|
+
"errors": [] if ok else ["Kimi Code did not complete the startup hello probe successfully."],
|
|
2420
|
+
"details": details,
|
|
2421
|
+
"guidance": [] if ok else [
|
|
2422
|
+
"Run `kimi --print --input-format text --output-format stream-json --yolo` manually and confirm it returns `HELLO`.",
|
|
2423
|
+
"Run `kimi login` first if this machine has not completed the Kimi Code login flow yet.",
|
|
2424
|
+
"If Kimi Code uses a custom home, point `runners.kimi.config_dir` at the correct `~/.kimi`-style directory.",
|
|
2425
|
+
],
|
|
2426
|
+
}
|
|
2427
|
+
|
|
1613
2428
|
@staticmethod
|
|
1614
2429
|
def _compact_probe_text(value: str, *, limit: int = 1200) -> str:
|
|
1615
2430
|
text = str(value or "").strip()
|
|
@@ -1864,11 +2679,31 @@ Use **Test** when the file exposes runtime dependencies.
|
|
|
1864
2679
|
defaults = default_payload(name, self.home)
|
|
1865
2680
|
if name == "runners":
|
|
1866
2681
|
normalized = self._deep_merge(defaults, prepared)
|
|
2682
|
+
runtime_enabled_runners = self._runtime_enabled_runner_names()
|
|
1867
2683
|
codex = normalized.get("codex")
|
|
1868
|
-
if isinstance(codex, dict)
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
2684
|
+
if isinstance(codex, dict):
|
|
2685
|
+
if self._looks_like_legacy_codex_retry_profile(codex):
|
|
2686
|
+
codex["retry_initial_backoff_sec"] = 10.0
|
|
2687
|
+
codex["retry_backoff_multiplier"] = 6.0
|
|
2688
|
+
codex["retry_max_backoff_sec"] = 1800.0
|
|
2689
|
+
if self._looks_like_preupgrade_codex_retry_attempt_profile(codex):
|
|
2690
|
+
codex["retry_max_attempts"] = 7
|
|
2691
|
+
claude = normalized.get("claude")
|
|
2692
|
+
if isinstance(claude, dict):
|
|
2693
|
+
legacy_approval_policy = str(claude.get("approval_policy") or "").strip().lower()
|
|
2694
|
+
if legacy_approval_policy and not str(claude.get("permission_mode") or "").strip():
|
|
2695
|
+
if legacy_approval_policy == "never":
|
|
2696
|
+
claude["permission_mode"] = "bypassPermissions"
|
|
2697
|
+
elif legacy_approval_policy in {"on-request", "default"}:
|
|
2698
|
+
claude["permission_mode"] = "default"
|
|
2699
|
+
if "approval_policy" in claude:
|
|
2700
|
+
claude.pop("approval_policy", None)
|
|
2701
|
+
if "sandbox_mode" in claude:
|
|
2702
|
+
claude.pop("sandbox_mode", None)
|
|
2703
|
+
for runner_name in runtime_enabled_runners:
|
|
2704
|
+
runner_config = normalized.get(runner_name)
|
|
2705
|
+
if isinstance(runner_config, dict):
|
|
2706
|
+
runner_config["enabled"] = True
|
|
1872
2707
|
return normalized
|
|
1873
2708
|
if name == "connectors":
|
|
1874
2709
|
normalized = deepcopy(defaults)
|
|
@@ -1913,9 +2748,44 @@ Use **Test** when the file exposes runtime dependencies.
|
|
|
1913
2748
|
return normalized
|
|
1914
2749
|
return self._deep_merge(defaults, prepared)
|
|
1915
2750
|
|
|
2751
|
+
@staticmethod
|
|
2752
|
+
def _normalize_runtime_runner_name(value: object) -> str:
|
|
2753
|
+
normalized = str(value or "").strip().lower().replace("_", "-")
|
|
2754
|
+
if normalized in {"claude-code", "claudecode"}:
|
|
2755
|
+
return "claude"
|
|
2756
|
+
if normalized in {"kimi-code", "kimicode"}:
|
|
2757
|
+
return "kimi"
|
|
2758
|
+
if normalized in {"open-code", "open code", "opencode-ai", "opencodeai"}:
|
|
2759
|
+
return "opencode"
|
|
2760
|
+
return normalized.replace("-", "")
|
|
2761
|
+
|
|
2762
|
+
@classmethod
|
|
2763
|
+
def _runtime_enabled_runner_names(cls) -> set[str]:
|
|
2764
|
+
names: set[str] = set()
|
|
2765
|
+
raw_values = [
|
|
2766
|
+
os.environ.get("DEEPSCIENTIST_DEFAULT_RUNNER"),
|
|
2767
|
+
os.environ.get("DS_DEFAULT_RUNNER"),
|
|
2768
|
+
os.environ.get("DEEPSCIENTIST_ENABLE_RUNNER"),
|
|
2769
|
+
os.environ.get("DS_ENABLE_RUNNER"),
|
|
2770
|
+
os.environ.get("DEEPSCIENTIST_ENABLE_RUNNERS"),
|
|
2771
|
+
os.environ.get("DS_ENABLE_RUNNERS"),
|
|
2772
|
+
]
|
|
2773
|
+
for raw_value in raw_values:
|
|
2774
|
+
for item in str(raw_value or "").replace(";", ",").split(","):
|
|
2775
|
+
normalized = cls._normalize_runtime_runner_name(item)
|
|
2776
|
+
if normalized:
|
|
2777
|
+
names.add(normalized)
|
|
2778
|
+
return names
|
|
2779
|
+
|
|
1916
2780
|
def _normalize_config_payload(self, payload: dict) -> dict:
|
|
1917
2781
|
defaults = default_payload("config", self.home)
|
|
1918
2782
|
normalized = self._deep_merge(defaults, payload)
|
|
2783
|
+
default_runner_override = str(
|
|
2784
|
+
os.environ.get("DEEPSCIENTIST_DEFAULT_RUNNER") or os.environ.get("DS_DEFAULT_RUNNER") or ""
|
|
2785
|
+
).strip().lower()
|
|
2786
|
+
default_runner_override = self._normalize_runtime_runner_name(default_runner_override)
|
|
2787
|
+
if default_runner_override:
|
|
2788
|
+
normalized["default_runner"] = default_runner_override
|
|
1919
2789
|
bootstrap = normalized.get("bootstrap") if isinstance(normalized.get("bootstrap"), dict) else {}
|
|
1920
2790
|
raw_bootstrap = payload.get("bootstrap") if isinstance(payload.get("bootstrap"), dict) else {}
|
|
1921
2791
|
connectors = normalized.get("connectors") if isinstance(normalized.get("connectors"), dict) else {}
|
|
@@ -1942,6 +2812,25 @@ Use **Test** when the file exposes runtime dependencies.
|
|
|
1942
2812
|
bootstrap["locale_initialized_from_browser"] = locale_initialized_from_browser
|
|
1943
2813
|
bootstrap["locale_initialized_at"] = bootstrap.get("locale_initialized_at")
|
|
1944
2814
|
bootstrap["locale_initialized_browser_locale"] = bootstrap.get("locale_initialized_browser_locale")
|
|
2815
|
+
runner_readiness = bootstrap.get("runner_readiness") if isinstance(bootstrap.get("runner_readiness"), dict) else {}
|
|
2816
|
+
normalized_runner_readiness: dict[str, dict[str, Any]] = {}
|
|
2817
|
+
for runner_name in list_builtin_runner_names():
|
|
2818
|
+
state = runner_readiness.get(runner_name) if isinstance(runner_readiness.get(runner_name), dict) else {}
|
|
2819
|
+
if runner_name == "codex" and not state:
|
|
2820
|
+
state = {
|
|
2821
|
+
"ready": bool(bootstrap.get("codex_ready", False)),
|
|
2822
|
+
"last_checked_at": bootstrap.get("codex_last_checked_at"),
|
|
2823
|
+
"last_result": bootstrap.get("codex_last_result") if isinstance(bootstrap.get("codex_last_result"), dict) else {},
|
|
2824
|
+
}
|
|
2825
|
+
normalized_runner_readiness[runner_name] = {
|
|
2826
|
+
"ready": bool(state.get("ready", False)),
|
|
2827
|
+
"last_checked_at": state.get("last_checked_at"),
|
|
2828
|
+
"last_result": state.get("last_result") if isinstance(state.get("last_result"), dict) else {},
|
|
2829
|
+
}
|
|
2830
|
+
bootstrap["runner_readiness"] = normalized_runner_readiness
|
|
2831
|
+
bootstrap["codex_ready"] = bool(normalized_runner_readiness.get("codex", {}).get("ready", False))
|
|
2832
|
+
bootstrap["codex_last_checked_at"] = normalized_runner_readiness.get("codex", {}).get("last_checked_at")
|
|
2833
|
+
bootstrap["codex_last_result"] = normalized_runner_readiness.get("codex", {}).get("last_result") if isinstance(normalized_runner_readiness.get("codex", {}).get("last_result"), dict) else {}
|
|
1945
2834
|
normalized["bootstrap"] = bootstrap
|
|
1946
2835
|
raw_system_enabled = raw_connectors.get("system_enabled") if isinstance(raw_connectors.get("system_enabled"), dict) else {}
|
|
1947
2836
|
default_system_enabled = (
|
|
@@ -1962,6 +2851,85 @@ Use **Test** when the file exposes runtime dependencies.
|
|
|
1962
2851
|
for name in SYSTEM_CONNECTOR_NAMES
|
|
1963
2852
|
}
|
|
1964
2853
|
normalized["connectors"] = connectors
|
|
2854
|
+
hardware = normalized.get("hardware") if isinstance(normalized.get("hardware"), dict) else {}
|
|
2855
|
+
raw_hardware = payload.get("hardware") if isinstance(payload.get("hardware"), dict) else {}
|
|
2856
|
+
gpu_selection_mode = str(raw_hardware.get("gpu_selection_mode") or hardware.get("gpu_selection_mode") or "all").strip().lower()
|
|
2857
|
+
if gpu_selection_mode not in {"all", "selected"}:
|
|
2858
|
+
gpu_selection_mode = "all"
|
|
2859
|
+
raw_selected_gpu_ids = raw_hardware.get("selected_gpu_ids", hardware.get("selected_gpu_ids", []))
|
|
2860
|
+
selected_gpu_ids: list[str] = []
|
|
2861
|
+
if isinstance(raw_selected_gpu_ids, list):
|
|
2862
|
+
for item in raw_selected_gpu_ids:
|
|
2863
|
+
normalized_id = str(item or "").strip()
|
|
2864
|
+
if normalized_id and normalized_id not in selected_gpu_ids:
|
|
2865
|
+
selected_gpu_ids.append(normalized_id)
|
|
2866
|
+
elif isinstance(raw_selected_gpu_ids, str):
|
|
2867
|
+
for item in raw_selected_gpu_ids.split(","):
|
|
2868
|
+
normalized_id = item.strip()
|
|
2869
|
+
if normalized_id and normalized_id not in selected_gpu_ids:
|
|
2870
|
+
selected_gpu_ids.append(normalized_id)
|
|
2871
|
+
hardware["gpu_selection_mode"] = gpu_selection_mode
|
|
2872
|
+
hardware["selected_gpu_ids"] = selected_gpu_ids
|
|
2873
|
+
hardware["include_system_hardware_in_prompt"] = self._coerce_bool(
|
|
2874
|
+
raw_hardware.get(
|
|
2875
|
+
"include_system_hardware_in_prompt",
|
|
2876
|
+
hardware.get("include_system_hardware_in_prompt", True),
|
|
2877
|
+
),
|
|
2878
|
+
default=True,
|
|
2879
|
+
)
|
|
2880
|
+
normalized["hardware"] = hardware
|
|
2881
|
+
memory = normalized.get("memory") if isinstance(normalized.get("memory"), dict) else {}
|
|
2882
|
+
raw_memory = payload.get("memory") if isinstance(payload.get("memory"), dict) else {}
|
|
2883
|
+
read_visibility_mode = str(
|
|
2884
|
+
raw_memory.get("read_visibility_mode", memory.get("read_visibility_mode", "independent")) or "independent"
|
|
2885
|
+
).strip().lower()
|
|
2886
|
+
if read_visibility_mode not in {"independent", "shared_across_quests"}:
|
|
2887
|
+
read_visibility_mode = "independent"
|
|
2888
|
+
memory["read_visibility_mode"] = read_visibility_mode
|
|
2889
|
+
normalized["memory"] = memory
|
|
2890
|
+
literature = normalized.get("literature") if isinstance(normalized.get("literature"), dict) else {}
|
|
2891
|
+
raw_literature = payload.get("literature") if isinstance(payload.get("literature"), dict) else {}
|
|
2892
|
+
default_literature = defaults.get("literature") if isinstance(defaults.get("literature"), dict) else {}
|
|
2893
|
+
deepxiv_defaults = default_literature.get("deepxiv") if isinstance(default_literature.get("deepxiv"), dict) else {}
|
|
2894
|
+
deepxiv = literature.get("deepxiv") if isinstance(literature.get("deepxiv"), dict) else {}
|
|
2895
|
+
raw_deepxiv = raw_literature.get("deepxiv") if isinstance(raw_literature.get("deepxiv"), dict) else {}
|
|
2896
|
+
deepxiv["enabled"] = self._coerce_bool(
|
|
2897
|
+
raw_deepxiv.get("enabled", deepxiv.get("enabled", deepxiv_defaults.get("enabled", False))),
|
|
2898
|
+
default=bool(deepxiv_defaults.get("enabled", False)),
|
|
2899
|
+
)
|
|
2900
|
+
deepxiv["base_url"] = str(
|
|
2901
|
+
raw_deepxiv.get("base_url", deepxiv.get("base_url", deepxiv_defaults.get("base_url", "https://data.rag.ac.cn"))) or ""
|
|
2902
|
+
).strip() or str(deepxiv_defaults.get("base_url") or "https://data.rag.ac.cn")
|
|
2903
|
+
deepxiv["token"] = str(raw_deepxiv.get("token", deepxiv.get("token", "")) or "").strip() or None
|
|
2904
|
+
deepxiv["token_env"] = str(
|
|
2905
|
+
raw_deepxiv.get("token_env", deepxiv.get("token_env", deepxiv_defaults.get("token_env", "DEEPXIV_TOKEN"))) or ""
|
|
2906
|
+
).strip() or None
|
|
2907
|
+
try:
|
|
2908
|
+
raw_result_size = raw_deepxiv.get(
|
|
2909
|
+
"default_result_size",
|
|
2910
|
+
deepxiv.get("default_result_size", deepxiv_defaults.get("default_result_size", 10)),
|
|
2911
|
+
)
|
|
2912
|
+
deepxiv["default_result_size"] = max(1, int(raw_result_size))
|
|
2913
|
+
except (TypeError, ValueError):
|
|
2914
|
+
deepxiv["default_result_size"] = int(deepxiv_defaults.get("default_result_size", 10) or 10)
|
|
2915
|
+
try:
|
|
2916
|
+
raw_preview_characters = raw_deepxiv.get(
|
|
2917
|
+
"preview_characters",
|
|
2918
|
+
deepxiv.get("preview_characters", deepxiv_defaults.get("preview_characters", 1200)),
|
|
2919
|
+
)
|
|
2920
|
+
deepxiv["preview_characters"] = max(200, int(raw_preview_characters))
|
|
2921
|
+
except (TypeError, ValueError):
|
|
2922
|
+
deepxiv["preview_characters"] = int(deepxiv_defaults.get("preview_characters", 1200) or 1200)
|
|
2923
|
+
try:
|
|
2924
|
+
raw_timeout = raw_deepxiv.get(
|
|
2925
|
+
"request_timeout_seconds",
|
|
2926
|
+
deepxiv.get("request_timeout_seconds", deepxiv_defaults.get("request_timeout_seconds", 20)),
|
|
2927
|
+
)
|
|
2928
|
+
deepxiv["request_timeout_seconds"] = max(3, int(raw_timeout))
|
|
2929
|
+
except (TypeError, ValueError):
|
|
2930
|
+
deepxiv["request_timeout_seconds"] = int(deepxiv_defaults.get("request_timeout_seconds", 20) or 20)
|
|
2931
|
+
literature["deepxiv"] = deepxiv
|
|
2932
|
+
normalized["literature"] = literature
|
|
1965
2933
|
return normalized
|
|
1966
2934
|
|
|
1967
2935
|
@staticmethod
|
|
@@ -1974,6 +2942,22 @@ Use **Test** when the file exposes runtime dependencies.
|
|
|
1974
2942
|
return False
|
|
1975
2943
|
return abs(initial - 1.0) < 1e-9 and abs(multiplier - 2.0) < 1e-9 and abs(max_backoff - 8.0) < 1e-9
|
|
1976
2944
|
|
|
2945
|
+
@staticmethod
|
|
2946
|
+
def _looks_like_preupgrade_codex_retry_attempt_profile(payload: dict) -> bool:
|
|
2947
|
+
try:
|
|
2948
|
+
max_attempts = int(payload.get("retry_max_attempts"))
|
|
2949
|
+
initial = float(payload.get("retry_initial_backoff_sec"))
|
|
2950
|
+
multiplier = float(payload.get("retry_backoff_multiplier"))
|
|
2951
|
+
max_backoff = float(payload.get("retry_max_backoff_sec"))
|
|
2952
|
+
except (TypeError, ValueError):
|
|
2953
|
+
return False
|
|
2954
|
+
return (
|
|
2955
|
+
max_attempts == 5
|
|
2956
|
+
and abs(initial - 10.0) < 1e-9
|
|
2957
|
+
and abs(multiplier - 6.0) < 1e-9
|
|
2958
|
+
and abs(max_backoff - 1800.0) < 1e-9
|
|
2959
|
+
)
|
|
2960
|
+
|
|
1977
2961
|
@staticmethod
|
|
1978
2962
|
def _coerce_bool(value: object, *, default: bool = False) -> bool:
|
|
1979
2963
|
if value is None:
|