qwen-sci 0.2.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (549) hide show
  1. qwen_sci-0.2.2.dist-info/METADATA +492 -0
  2. qwen_sci-0.2.2.dist-info/RECORD +549 -0
  3. qwen_sci-0.2.2.dist-info/WHEEL +4 -0
  4. qwen_sci-0.2.2.dist-info/entry_points.txt +6 -0
  5. qwen_sci-0.2.2.dist-info/licenses/LICENSE +21 -0
  6. src/1.txt +1 -0
  7. src/__init__.py +1 -0
  8. src/__main__.py +5 -0
  9. src/agents/__init__.py +1 -0
  10. src/agents/experiment_design_agent/__init__.py +268 -0
  11. src/agents/experiment_design_agent/artifacts.py +747 -0
  12. src/agents/experiment_design_agent/cache.py +319 -0
  13. src/agents/experiment_design_agent/completeness.py +130 -0
  14. src/agents/experiment_design_agent/contracts.py +771 -0
  15. src/agents/experiment_design_agent/counterexample_analyzer.py +187 -0
  16. src/agents/experiment_design_agent/design_evidence_paper_screener.py +470 -0
  17. src/agents/experiment_design_agent/discipline_catalog.py +178 -0
  18. src/agents/experiment_design_agent/evidence_cards.py +338 -0
  19. src/agents/experiment_design_agent/evidence_planner.py +452 -0
  20. src/agents/experiment_design_agent/formal_reasoning_planner.py +884 -0
  21. src/agents/experiment_design_agent/fulltext_acquisition.py +863 -0
  22. src/agents/experiment_design_agent/idea_adapter.py +100 -0
  23. src/agents/experiment_design_agent/idea_intake.py +87 -0
  24. src/agents/experiment_design_agent/llm_json.py +328 -0
  25. src/agents/experiment_design_agent/orchestrator.py +1220 -0
  26. src/agents/experiment_design_agent/reasoning_context.py +183 -0
  27. src/agents/experiment_design_agent/reasoning_validation.py +546 -0
  28. src/agents/experiment_design_agent/run.py +481 -0
  29. src/agents/experiment_design_agent/run_logging.py +292 -0
  30. src/agents/experiment_design_agent/scope_gate.py +198 -0
  31. src/agents/experiment_design_agent/study_type_composer.py +1360 -0
  32. src/agents/experiment_design_agent/survey_evidence.py +1381 -0
  33. src/agents/experiment_design_agent/template_router.py +195 -0
  34. src/agents/experiment_design_agent/variable_claim_extractor.py +93 -0
  35. src/agents/idea_agent/__init__.py +1 -0
  36. src/agents/idea_agent/agent/__init__.py +6 -0
  37. src/agents/idea_agent/agent/artifacts.py +308 -0
  38. src/agents/idea_agent/agent/base.py +122 -0
  39. src/agents/idea_agent/agent/ligagent.py +488 -0
  40. src/agents/idea_agent/agent/mcts.py +2060 -0
  41. src/agents/idea_agent/agent/prompts/__init__.py +48 -0
  42. src/agents/idea_agent/agent/prompts/advanced_analysis.py +235 -0
  43. src/agents/idea_agent/agent/prompts/algorithm_alignment.py +55 -0
  44. src/agents/idea_agent/agent/prompts/algorithm_structuring.py +48 -0
  45. src/agents/idea_agent/agent/prompts/component_extraction.py +62 -0
  46. src/agents/idea_agent/agent/prompts/component_novelty_evaluation.py +54 -0
  47. src/agents/idea_agent/agent/prompts/experiment_findings_extraction.py +39 -0
  48. src/agents/idea_agent/agent/prompts/idea_fusion.py +295 -0
  49. src/agents/idea_agent/agent/prompts/idea_introduction.py +30 -0
  50. src/agents/idea_agent/agent/prompts/idea_result_alignment.py +39 -0
  51. src/agents/idea_agent/agent/prompts/input_interpreter.py +52 -0
  52. src/agents/idea_agent/agent/prompts/keynote_ops.py +78 -0
  53. src/agents/idea_agent/agent/prompts/mcts_evaluation.py +235 -0
  54. src/agents/idea_agent/agent/prompts/mcts_generation.py +140 -0
  55. src/agents/idea_agent/agent/prompts/mechanism_commit_query.py +99 -0
  56. src/agents/idea_agent/agent/prompts/memory_selection.py +0 -0
  57. src/agents/idea_agent/agent/prompts/prompt_modes.py +16 -0
  58. src/agents/idea_agent/agent/prompts/rag_query.py +34 -0
  59. src/agents/idea_agent/agent/prompts/re_analysis_replan.py +48 -0
  60. src/agents/idea_agent/agent/prompts/reference_grounding.py +34 -0
  61. src/agents/idea_agent/agent/prompts/root_domain_classification.py +32 -0
  62. src/agents/idea_agent/agent/prompts/scientific_debate.py +88 -0
  63. src/agents/idea_agent/agent/prompts/scientific_materialization.py +45 -0
  64. src/agents/idea_agent/agent/prompts/skill_instantiation.py +193 -0
  65. src/agents/idea_agent/agent/prompts/theory_transfer_query.py +93 -0
  66. src/agents/idea_agent/agent/prompts/topic_background.py +15 -0
  67. src/agents/idea_agent/agent/skills/DEFAULT_SKILL_TEMPLATES.json +263 -0
  68. src/agents/idea_agent/agent/skills/edit_operator_skills/alternative-path-contrast/SKILL.md +40 -0
  69. src/agents/idea_agent/agent/skills/edit_operator_skills/alternative-path-contrast/references/contrast_patterns.md +22 -0
  70. src/agents/idea_agent/agent/skills/edit_operator_skills/feedback-closed-loop/SKILL.md +40 -0
  71. src/agents/idea_agent/agent/skills/edit_operator_skills/feedback-closed-loop/references/mechanism_cards.md +24 -0
  72. src/agents/idea_agent/agent/skills/edit_operator_skills/hierarchical-decomposition/SKILL.md +39 -0
  73. src/agents/idea_agent/agent/skills/edit_operator_skills/hierarchical-decomposition/references/hierarchy_patterns.md +22 -0
  74. src/agents/idea_agent/agent/skills/edit_operator_skills/mechanism-commit-innovation/SKILL.md +39 -0
  75. src/agents/idea_agent/agent/skills/edit_operator_skills/mechanism-commit-innovation/references/mechanism_commit_patterns.md +24 -0
  76. src/agents/idea_agent/agent/skills/edit_operator_skills/multi-scale-coordinator/SKILL.md +39 -0
  77. src/agents/idea_agent/agent/skills/edit_operator_skills/multi-scale-coordinator/references/coordination_patterns.md +22 -0
  78. src/agents/idea_agent/agent/skills/edit_operator_skills/speculative-execution-with-repair/SKILL.md +41 -0
  79. src/agents/idea_agent/agent/skills/edit_operator_skills/speculative-execution-with-repair/references/speculation_patterns.md +22 -0
  80. src/agents/idea_agent/agent/skills/edit_operator_skills/surgical-modularity/SKILL.md +39 -0
  81. src/agents/idea_agent/agent/skills/edit_operator_skills/surgical-modularity/references/modularity_patterns.md +22 -0
  82. src/agents/idea_agent/agent/skills/edit_operator_skills/theory-transfer-injection/SKILL.md +40 -0
  83. src/agents/idea_agent/agent/skills/edit_operator_skills/theory-transfer-injection/references/transfer_patterns.md +24 -0
  84. src/agents/idea_agent/example/idea_result.json +900 -0
  85. src/agents/idea_agent/run.py +276 -0
  86. src/agents/idea_agent/tests/test_advanced_analysis_contract.py +90 -0
  87. src/agents/idea_agent/tests/test_gap_hypothesis_bridge.py +166 -0
  88. src/agents/idea_agent/tests/test_idea_debate.py +480 -0
  89. src/agents/idea_agent/tests/test_idea_result_v5.py +99 -0
  90. src/agents/idea_agent/tests/test_idea_synthesis.py +92 -0
  91. src/agents/idea_agent/tests/test_mature_idea_sources.py +27 -0
  92. src/agents/idea_agent/tests/test_multimodal_idea_integration.py +386 -0
  93. src/agents/idea_agent/tests/test_profile_materialization_and_scoring.py +219 -0
  94. src/agents/idea_agent/tests/test_profile_native_skill_rendering.py +122 -0
  95. src/agents/idea_agent/tests/test_result_persistence.py +183 -0
  96. src/agents/idea_agent/tests/test_scientific_intervention_profiles.py +241 -0
  97. src/agents/idea_agent/tests/test_scientific_rubric_and_prompts.py +559 -0
  98. src/agents/idea_agent/tests/test_strict_json_object_responses.py +48 -0
  99. src/agents/idea_agent/utils/core/__init__.py +1 -0
  100. src/agents/idea_agent/utils/core/ablation_inputs.py +60 -0
  101. src/agents/idea_agent/utils/core/chat_errors.py +95 -0
  102. src/agents/idea_agent/utils/core/chat_router.py +130 -0
  103. src/agents/idea_agent/utils/core/chat_transport.py +188 -0
  104. src/agents/idea_agent/utils/core/config_loader.py +166 -0
  105. src/agents/idea_agent/utils/core/json_utils.py +28 -0
  106. src/agents/idea_agent/utils/core/logger.py +287 -0
  107. src/agents/idea_agent/utils/core/progress.py +58 -0
  108. src/agents/idea_agent/utils/core/response_parsing.py +57 -0
  109. src/agents/idea_agent/utils/core/run_inputs.py +198 -0
  110. src/agents/idea_agent/utils/mcts/__init__.py +1 -0
  111. src/agents/idea_agent/utils/mcts/component_novelty.py +342 -0
  112. src/agents/idea_agent/utils/mcts/defect_registry.py +302 -0
  113. src/agents/idea_agent/utils/mcts/idea_routes.py +61 -0
  114. src/agents/idea_agent/utils/mcts/idea_taste_presets.py +312 -0
  115. src/agents/idea_agent/utils/mcts/mcts_helpers.py +738 -0
  116. src/agents/idea_agent/utils/mcts/mcts_runtime.py +3000 -0
  117. src/agents/idea_agent/utils/mcts/scientific_intervention_ontology.py +1561 -0
  118. src/agents/idea_agent/utils/mcts/scientific_rubric.py +211 -0
  119. src/agents/idea_agent/utils/mcts/skill_parsing.py +92 -0
  120. src/agents/idea_agent/utils/papers/__init__.py +1 -0
  121. src/agents/idea_agent/utils/papers/paper_graph_vector_store.py +499 -0
  122. src/agents/idea_agent/utils/papers/paper_repository.py +372 -0
  123. src/agents/idea_agent/utils/prompting/__init__.py +1 -0
  124. src/agents/idea_agent/utils/prompting/prompt_views.py +637 -0
  125. src/agents/idea_agent/utils/workflow/__init__.py +1 -0
  126. src/agents/idea_agent/utils/workflow/advanced_analysis_contract.py +244 -0
  127. src/agents/idea_agent/utils/workflow/gap_hypothesis_bridge.py +461 -0
  128. src/agents/idea_agent/utils/workflow/idea_contract.py +426 -0
  129. src/agents/idea_agent/utils/workflow/idea_debate.py +1238 -0
  130. src/agents/idea_agent/utils/workflow/idea_diversity.py +163 -0
  131. src/agents/idea_agent/utils/workflow/idea_fusion.py +889 -0
  132. src/agents/idea_agent/utils/workflow/idea_helpers.py +478 -0
  133. src/agents/idea_agent/utils/workflow/idea_portfolio.py +422 -0
  134. src/agents/idea_agent/utils/workflow/idea_synthesis.py +482 -0
  135. src/agents/idea_agent/utils/workflow/ligagent_flow.py +581 -0
  136. src/agents/idea_agent/utils/workflow/ligagent_handlers.py +1836 -0
  137. src/agents/idea_agent/utils/workflow/ligagent_helpers.py +1331 -0
  138. src/agents/idea_agent/utils/workflow/ligagent_utils.py +322 -0
  139. src/agents/idea_agent/utils/workflow/mature_idea_sources.py +648 -0
  140. src/agents/idea_agent/utils/workflow/multimodal_data_anchoring.py +578 -0
  141. src/agents/idea_agent/utils/workflow/result_persistence.py +774 -0
  142. src/agents/idea_agent/utils/workflow/stage_contract.py +76 -0
  143. src/agents/idea_agent/utils/workflow/workflow_runtime.py +288 -0
  144. src/agents/research_plan_author/__init__.py +50 -0
  145. src/agents/research_plan_author/artifacts.py +270 -0
  146. src/agents/research_plan_author/authoring_blueprint.py +1246 -0
  147. src/agents/research_plan_author/bibtex_renderer.py +252 -0
  148. src/agents/research_plan_author/contract_repair.py +131 -0
  149. src/agents/research_plan_author/contracts.py +745 -0
  150. src/agents/research_plan_author/cross_section_editor.py +232 -0
  151. src/agents/research_plan_author/document_quality.py +987 -0
  152. src/agents/research_plan_author/idea_evolution.py +223 -0
  153. src/agents/research_plan_author/input_loader.py +76 -0
  154. src/agents/research_plan_author/latex_compiler.py +260 -0
  155. src/agents/research_plan_author/latex_safety.py +159 -0
  156. src/agents/research_plan_author/llm_json.py +74 -0
  157. src/agents/research_plan_author/markdown_renderer.py +275 -0
  158. src/agents/research_plan_author/pdf_validator.py +149 -0
  159. src/agents/research_plan_author/render.py +166 -0
  160. src/agents/research_plan_author/render_artifacts.py +187 -0
  161. src/agents/research_plan_author/run.py +765 -0
  162. src/agents/research_plan_author/run_logging.py +209 -0
  163. src/agents/research_plan_author/section_cache.py +184 -0
  164. src/agents/research_plan_author/section_composer.py +1764 -0
  165. src/agents/research_plan_author/section_router.py +209 -0
  166. src/agents/research_plan_author/semantic_validator.py +254 -0
  167. src/agents/research_plan_author/source_bundle.py +46 -0
  168. src/agents/research_plan_author/source_registry.py +208 -0
  169. src/agents/research_plan_author/survey_source_loader.py +137 -0
  170. src/agents/research_plan_author/template_adapter.py +173 -0
  171. src/agents/research_plan_author/template_profile.py +204 -0
  172. src/agents/research_plan_author/tex_renderer.py +496 -0
  173. src/agents/research_plan_author/theory_presentation.py +134 -0
  174. src/agents/research_plan_author/theory_spine.py +703 -0
  175. src/agents/survey_agent/Dockerfile +54 -0
  176. src/agents/survey_agent/README.md +350 -0
  177. src/agents/survey_agent/config/deep_survey.yaml +217 -0
  178. src/agents/survey_agent/config/deep_survey_batch.yaml +176 -0
  179. src/agents/survey_agent/config/deep_survey_fast.yaml +183 -0
  180. src/agents/survey_agent/config/evaluate_baseline.yaml +197 -0
  181. src/agents/survey_agent/config/outcomeRAG.yaml +159 -0
  182. src/agents/survey_agent/env_report.md +348 -0
  183. src/agents/survey_agent/modules/__init__.py +0 -0
  184. src/agents/survey_agent/modules/code_collector.py +2194 -0
  185. src/agents/survey_agent/modules/code_report_generator.py +1282 -0
  186. src/agents/survey_agent/modules/data_manager.py +1713 -0
  187. src/agents/survey_agent/modules/database.py +167 -0
  188. src/agents/survey_agent/modules/fulltext_download_cache.py +462 -0
  189. src/agents/survey_agent/modules/fulltext_http.py +134 -0
  190. src/agents/survey_agent/modules/fulltext_resolution.py +749 -0
  191. src/agents/survey_agent/modules/judge.py +434 -0
  192. src/agents/survey_agent/modules/outcome_RAG.py +236 -0
  193. src/agents/survey_agent/modules/paper_graph_retriever.py +1075 -0
  194. src/agents/survey_agent/modules/pe.py +1729 -0
  195. src/agents/survey_agent/modules/pseudo_creator.py +782 -0
  196. src/agents/survey_agent/modules/pseudo_reviser.py +537 -0
  197. src/agents/survey_agent/modules/refine_agent.py +1952 -0
  198. src/agents/survey_agent/modules/survey_generator.py +5691 -0
  199. src/agents/survey_agent/modules/survey_visualizer.py +1817 -0
  200. src/agents/survey_agent/modules/visual_prompts.py +327 -0
  201. src/agents/survey_agent/modules/work_analyzer.py +2750 -0
  202. src/agents/survey_agent/modules/work_collector.py +5649 -0
  203. src/agents/survey_agent/scripts/baseline_evaluation.py +411 -0
  204. src/agents/survey_agent/scripts/run_deep_survey.py +224 -0
  205. src/agents/survey_agent/scripts/run_deep_survey_adapter.py +407 -0
  206. src/agents/survey_agent/scripts/run_deep_survey_adapter_with_input.py +409 -0
  207. src/agents/survey_agent/scripts/run_deep_survey_batch.py +228 -0
  208. src/agents/survey_agent/scripts/run_deep_survey_batch_arg.py +243 -0
  209. src/agents/survey_agent/scripts/run_deep_survey_batch_settings.py +218 -0
  210. src/agents/survey_agent/scripts/run_keynotes_gen.py +128 -0
  211. src/agents/survey_agent/scripts/run_work_clusters.py +140 -0
  212. src/agents/survey_agent/utils/__init__.py +0 -0
  213. src/agents/survey_agent/utils/ablation_utils.py +317 -0
  214. src/agents/survey_agent/utils/api_call.py +2518 -0
  215. src/agents/survey_agent/utils/chat_utils.py +82 -0
  216. src/agents/survey_agent/utils/config_utils.py +70 -0
  217. src/agents/survey_agent/utils/convert_to_md.py +29 -0
  218. src/agents/survey_agent/utils/err_info.py +24 -0
  219. src/agents/survey_agent/utils/file_utils.py +176 -0
  220. src/agents/survey_agent/utils/gpu_utils.py +145 -0
  221. src/agents/survey_agent/utils/graph_visualizer.py +279 -0
  222. src/agents/survey_agent/utils/html_utils.py +181 -0
  223. src/agents/survey_agent/utils/latex_generator_intra_cluster.py +529 -0
  224. src/agents/survey_agent/utils/latex_generator_relation_table.py +193 -0
  225. src/agents/survey_agent/utils/mineru_section_packer.py +334 -0
  226. src/agents/survey_agent/utils/mineru_utils.py +396 -0
  227. src/agents/survey_agent/utils/paper.py +144 -0
  228. src/agents/survey_agent/utils/read_yaml.py +15 -0
  229. src/agents/survey_agent/utils/repo_utils.py +167 -0
  230. src/agents/survey_agent/utils/rich_logger.py +77 -0
  231. src/agents/survey_agent/utils/step2v2.py +874 -0
  232. src/agents/survey_agent/utils/step2v2_extractor.py +856 -0
  233. src/agents/survey_agent/utils/topic_survey_storage.py +309 -0
  234. src/agents/survey_agent/utils/utils.py +118 -0
  235. src/agents/survey_agent/utils/work.py +2 -0
  236. src/cli.py +1611 -0
  237. src/config/__init__.py +213 -0
  238. src/config/default.yaml +1122 -0
  239. src/harness/LICENSE +21 -0
  240. src/harness/VENDORED.md +14 -0
  241. src/harness/src/__init__.py +0 -0
  242. src/harness/src/openharness/__init__.py +0 -0
  243. src/harness/src/openharness/__main__.py +6 -0
  244. src/harness/src/openharness/api/__init__.py +21 -0
  245. src/harness/src/openharness/api/client.py +281 -0
  246. src/harness/src/openharness/api/codex_client.py +407 -0
  247. src/harness/src/openharness/api/copilot_auth.py +240 -0
  248. src/harness/src/openharness/api/copilot_client.py +134 -0
  249. src/harness/src/openharness/api/errors.py +19 -0
  250. src/harness/src/openharness/api/openai_client.py +577 -0
  251. src/harness/src/openharness/api/provider.py +186 -0
  252. src/harness/src/openharness/api/registry.py +437 -0
  253. src/harness/src/openharness/api/usage.py +17 -0
  254. src/harness/src/openharness/auth/__init__.py +29 -0
  255. src/harness/src/openharness/auth/external.py +610 -0
  256. src/harness/src/openharness/auth/flows.py +189 -0
  257. src/harness/src/openharness/auth/manager.py +482 -0
  258. src/harness/src/openharness/auth/storage.py +269 -0
  259. src/harness/src/openharness/autopilot/__init__.py +23 -0
  260. src/harness/src/openharness/autopilot/service.py +2239 -0
  261. src/harness/src/openharness/autopilot/types.py +91 -0
  262. src/harness/src/openharness/bridge/__init__.py +20 -0
  263. src/harness/src/openharness/bridge/manager.py +106 -0
  264. src/harness/src/openharness/bridge/session_runner.py +46 -0
  265. src/harness/src/openharness/bridge/types.py +37 -0
  266. src/harness/src/openharness/bridge/work_secret.py +41 -0
  267. src/harness/src/openharness/channels/UPSTREAM +6 -0
  268. src/harness/src/openharness/channels/__init__.py +22 -0
  269. src/harness/src/openharness/channels/adapter.py +131 -0
  270. src/harness/src/openharness/channels/bus/__init__.py +6 -0
  271. src/harness/src/openharness/channels/bus/events.py +38 -0
  272. src/harness/src/openharness/channels/bus/queue.py +44 -0
  273. src/harness/src/openharness/channels/impl/__init__.py +6 -0
  274. src/harness/src/openharness/channels/impl/base.py +141 -0
  275. src/harness/src/openharness/channels/impl/dingtalk.py +445 -0
  276. src/harness/src/openharness/channels/impl/discord.py +311 -0
  277. src/harness/src/openharness/channels/impl/email.py +410 -0
  278. src/harness/src/openharness/channels/impl/feishu.py +1342 -0
  279. src/harness/src/openharness/channels/impl/manager.py +257 -0
  280. src/harness/src/openharness/channels/impl/matrix.py +700 -0
  281. src/harness/src/openharness/channels/impl/mochat.py +897 -0
  282. src/harness/src/openharness/channels/impl/qq.py +141 -0
  283. src/harness/src/openharness/channels/impl/slack.py +284 -0
  284. src/harness/src/openharness/channels/impl/telegram.py +525 -0
  285. src/harness/src/openharness/channels/impl/whatsapp.py +159 -0
  286. src/harness/src/openharness/cli.py +2551 -0
  287. src/harness/src/openharness/commands/__init__.py +21 -0
  288. src/harness/src/openharness/commands/registry.py +2783 -0
  289. src/harness/src/openharness/config/__init__.py +34 -0
  290. src/harness/src/openharness/config/paths.py +160 -0
  291. src/harness/src/openharness/config/schema.py +119 -0
  292. src/harness/src/openharness/config/settings.py +1104 -0
  293. src/harness/src/openharness/coordinator/__init__.py +12 -0
  294. src/harness/src/openharness/coordinator/agent_definitions.py +975 -0
  295. src/harness/src/openharness/coordinator/coordinator_mode.py +520 -0
  296. src/harness/src/openharness/engine/__init__.py +80 -0
  297. src/harness/src/openharness/engine/cost_tracker.py +24 -0
  298. src/harness/src/openharness/engine/messages.py +222 -0
  299. src/harness/src/openharness/engine/query.py +1188 -0
  300. src/harness/src/openharness/engine/query_engine.py +313 -0
  301. src/harness/src/openharness/engine/stream_events.py +90 -0
  302. src/harness/src/openharness/hooks/__init__.py +50 -0
  303. src/harness/src/openharness/hooks/events.py +20 -0
  304. src/harness/src/openharness/hooks/executor.py +242 -0
  305. src/harness/src/openharness/hooks/hot_reload.py +31 -0
  306. src/harness/src/openharness/hooks/loader.py +68 -0
  307. src/harness/src/openharness/hooks/schemas.py +66 -0
  308. src/harness/src/openharness/hooks/types.py +38 -0
  309. src/harness/src/openharness/keybindings/__init__.py +14 -0
  310. src/harness/src/openharness/keybindings/default_bindings.py +11 -0
  311. src/harness/src/openharness/keybindings/loader.py +22 -0
  312. src/harness/src/openharness/keybindings/parser.py +18 -0
  313. src/harness/src/openharness/keybindings/resolver.py +13 -0
  314. src/harness/src/openharness/mcp/__init__.py +79 -0
  315. src/harness/src/openharness/mcp/client.py +298 -0
  316. src/harness/src/openharness/mcp/config.py +16 -0
  317. src/harness/src/openharness/mcp/types.py +76 -0
  318. src/harness/src/openharness/memory/__init__.py +25 -0
  319. src/harness/src/openharness/memory/agent.py +91 -0
  320. src/harness/src/openharness/memory/manager.py +183 -0
  321. src/harness/src/openharness/memory/memdir.py +52 -0
  322. src/harness/src/openharness/memory/migrate.py +137 -0
  323. src/harness/src/openharness/memory/paths.py +22 -0
  324. src/harness/src/openharness/memory/relevance.py +145 -0
  325. src/harness/src/openharness/memory/scan.py +116 -0
  326. src/harness/src/openharness/memory/schema.py +443 -0
  327. src/harness/src/openharness/memory/search.py +71 -0
  328. src/harness/src/openharness/memory/team.py +90 -0
  329. src/harness/src/openharness/memory/types.py +33 -0
  330. src/harness/src/openharness/memory/usage.py +153 -0
  331. src/harness/src/openharness/output_styles/__init__.py +5 -0
  332. src/harness/src/openharness/output_styles/loader.py +42 -0
  333. src/harness/src/openharness/permissions/__init__.py +26 -0
  334. src/harness/src/openharness/permissions/checker.py +200 -0
  335. src/harness/src/openharness/permissions/modes.py +13 -0
  336. src/harness/src/openharness/personalization/__init__.py +6 -0
  337. src/harness/src/openharness/personalization/extractor.py +138 -0
  338. src/harness/src/openharness/personalization/rules.py +64 -0
  339. src/harness/src/openharness/personalization/session_hook.py +65 -0
  340. src/harness/src/openharness/platforms.py +86 -0
  341. src/harness/src/openharness/plugins/__init__.py +53 -0
  342. src/harness/src/openharness/plugins/bundled/__init__.py +0 -0
  343. src/harness/src/openharness/plugins/installer.py +39 -0
  344. src/harness/src/openharness/plugins/loader.py +730 -0
  345. src/harness/src/openharness/plugins/schemas.py +24 -0
  346. src/harness/src/openharness/plugins/types.py +59 -0
  347. src/harness/src/openharness/prompts/__init__.py +14 -0
  348. src/harness/src/openharness/prompts/claudemd.py +48 -0
  349. src/harness/src/openharness/prompts/context.py +187 -0
  350. src/harness/src/openharness/prompts/environment.py +135 -0
  351. src/harness/src/openharness/prompts/system_prompt.py +109 -0
  352. src/harness/src/openharness/sandbox/Dockerfile +6 -0
  353. src/harness/src/openharness/sandbox/__init__.py +33 -0
  354. src/harness/src/openharness/sandbox/adapter.py +148 -0
  355. src/harness/src/openharness/sandbox/docker_backend.py +232 -0
  356. src/harness/src/openharness/sandbox/docker_image.py +103 -0
  357. src/harness/src/openharness/sandbox/path_validator.py +37 -0
  358. src/harness/src/openharness/sandbox/session.py +63 -0
  359. src/harness/src/openharness/services/__init__.py +30 -0
  360. src/harness/src/openharness/services/autodream/__init__.py +34 -0
  361. src/harness/src/openharness/services/autodream/backup.py +104 -0
  362. src/harness/src/openharness/services/autodream/lock.py +138 -0
  363. src/harness/src/openharness/services/autodream/prompt.py +128 -0
  364. src/harness/src/openharness/services/autodream/service.py +313 -0
  365. src/harness/src/openharness/services/compact/__init__.py +1725 -0
  366. src/harness/src/openharness/services/cron.py +137 -0
  367. src/harness/src/openharness/services/cron_scheduler.py +595 -0
  368. src/harness/src/openharness/services/lsp/__init__.py +216 -0
  369. src/harness/src/openharness/services/memory_extract/__init__.py +261 -0
  370. src/harness/src/openharness/services/oauth/__init__.py +0 -0
  371. src/harness/src/openharness/services/session_backend.py +97 -0
  372. src/harness/src/openharness/services/session_memory/__init__.py +139 -0
  373. src/harness/src/openharness/services/session_storage.py +230 -0
  374. src/harness/src/openharness/services/token_estimation.py +15 -0
  375. src/harness/src/openharness/services/tool_outputs.py +55 -0
  376. src/harness/src/openharness/skills/__init__.py +44 -0
  377. src/harness/src/openharness/skills/_frontmatter.py +97 -0
  378. src/harness/src/openharness/skills/bundled/__init__.py +75 -0
  379. src/harness/src/openharness/skills/bundled/content/commit.md +25 -0
  380. src/harness/src/openharness/skills/bundled/content/debug.md +25 -0
  381. src/harness/src/openharness/skills/bundled/content/diagnose.md +35 -0
  382. src/harness/src/openharness/skills/bundled/content/plan.md +39 -0
  383. src/harness/src/openharness/skills/bundled/content/review.md +33 -0
  384. src/harness/src/openharness/skills/bundled/content/simplify.md +26 -0
  385. src/harness/src/openharness/skills/bundled/content/skill-creator.md +175 -0
  386. src/harness/src/openharness/skills/bundled/content/test.md +38 -0
  387. src/harness/src/openharness/skills/loader.py +229 -0
  388. src/harness/src/openharness/skills/registry.py +29 -0
  389. src/harness/src/openharness/skills/types.py +24 -0
  390. src/harness/src/openharness/state/__init__.py +6 -0
  391. src/harness/src/openharness/state/app_state.py +30 -0
  392. src/harness/src/openharness/state/store.py +40 -0
  393. src/harness/src/openharness/swarm/__init__.py +70 -0
  394. src/harness/src/openharness/swarm/in_process.py +693 -0
  395. src/harness/src/openharness/swarm/lockfile.py +24 -0
  396. src/harness/src/openharness/swarm/mailbox.py +522 -0
  397. src/harness/src/openharness/swarm/permission_sync.py +1168 -0
  398. src/harness/src/openharness/swarm/registry.py +410 -0
  399. src/harness/src/openharness/swarm/spawn_utils.py +229 -0
  400. src/harness/src/openharness/swarm/subprocess_backend.py +171 -0
  401. src/harness/src/openharness/swarm/team_lifecycle.py +910 -0
  402. src/harness/src/openharness/swarm/types.py +398 -0
  403. src/harness/src/openharness/swarm/worktree.py +315 -0
  404. src/harness/src/openharness/tasks/__init__.py +18 -0
  405. src/harness/src/openharness/tasks/local_agent_task.py +28 -0
  406. src/harness/src/openharness/tasks/local_shell_task.py +17 -0
  407. src/harness/src/openharness/tasks/manager.py +475 -0
  408. src/harness/src/openharness/tasks/stop_task.py +11 -0
  409. src/harness/src/openharness/tasks/types.py +32 -0
  410. src/harness/src/openharness/themes/__init__.py +21 -0
  411. src/harness/src/openharness/themes/builtin.py +89 -0
  412. src/harness/src/openharness/themes/loader.py +55 -0
  413. src/harness/src/openharness/themes/schema.py +54 -0
  414. src/harness/src/openharness/tools/__init__.py +107 -0
  415. src/harness/src/openharness/tools/agent_tool.py +141 -0
  416. src/harness/src/openharness/tools/ask_user_question_tool.py +46 -0
  417. src/harness/src/openharness/tools/base.py +80 -0
  418. src/harness/src/openharness/tools/bash_tool.py +259 -0
  419. src/harness/src/openharness/tools/brief_tool.py +33 -0
  420. src/harness/src/openharness/tools/config_tool.py +54 -0
  421. src/harness/src/openharness/tools/cron_create_tool.py +105 -0
  422. src/harness/src/openharness/tools/cron_delete_tool.py +32 -0
  423. src/harness/src/openharness/tools/cron_list_tool.py +69 -0
  424. src/harness/src/openharness/tools/cron_toggle_tool.py +37 -0
  425. src/harness/src/openharness/tools/enter_plan_mode_tool.py +28 -0
  426. src/harness/src/openharness/tools/enter_worktree_tool.py +80 -0
  427. src/harness/src/openharness/tools/exit_plan_mode_tool.py +28 -0
  428. src/harness/src/openharness/tools/exit_worktree_tool.py +42 -0
  429. src/harness/src/openharness/tools/file_edit_tool.py +95 -0
  430. src/harness/src/openharness/tools/file_read_tool.py +72 -0
  431. src/harness/src/openharness/tools/file_write_tool.py +87 -0
  432. src/harness/src/openharness/tools/glob_tool.py +175 -0
  433. src/harness/src/openharness/tools/grep_tool.py +374 -0
  434. src/harness/src/openharness/tools/image_generation_tool.py +447 -0
  435. src/harness/src/openharness/tools/image_to_text_tool.py +237 -0
  436. src/harness/src/openharness/tools/list_mcp_resources_tool.py +36 -0
  437. src/harness/src/openharness/tools/lsp_tool.py +154 -0
  438. src/harness/src/openharness/tools/mcp_auth_tool.py +71 -0
  439. src/harness/src/openharness/tools/mcp_tool.py +72 -0
  440. src/harness/src/openharness/tools/notebook_edit_tool.py +97 -0
  441. src/harness/src/openharness/tools/read_mcp_resource_tool.py +38 -0
  442. src/harness/src/openharness/tools/remote_trigger_tool.py +74 -0
  443. src/harness/src/openharness/tools/send_message_tool.py +58 -0
  444. src/harness/src/openharness/tools/skill_tool.py +43 -0
  445. src/harness/src/openharness/tools/sleep_tool.py +32 -0
  446. src/harness/src/openharness/tools/task_create_tool.py +56 -0
  447. src/harness/src/openharness/tools/task_get_tool.py +33 -0
  448. src/harness/src/openharness/tools/task_list_tool.py +35 -0
  449. src/harness/src/openharness/tools/task_output_tool.py +35 -0
  450. src/harness/src/openharness/tools/task_stop_tool.py +30 -0
  451. src/harness/src/openharness/tools/task_update_tool.py +50 -0
  452. src/harness/src/openharness/tools/team_create_tool.py +31 -0
  453. src/harness/src/openharness/tools/team_delete_tool.py +30 -0
  454. src/harness/src/openharness/tools/todo_write_tool.py +46 -0
  455. src/harness/src/openharness/tools/tool_search_tool.py +38 -0
  456. src/harness/src/openharness/tools/web_fetch_tool.py +117 -0
  457. src/harness/src/openharness/tools/web_search_tool.py +119 -0
  458. src/harness/src/openharness/ui/__init__.py +5 -0
  459. src/harness/src/openharness/ui/app.py +320 -0
  460. src/harness/src/openharness/ui/backend_host.py +941 -0
  461. src/harness/src/openharness/ui/coordinator_drain.py +198 -0
  462. src/harness/src/openharness/ui/input.py +32 -0
  463. src/harness/src/openharness/ui/output.py +265 -0
  464. src/harness/src/openharness/ui/permission_dialog.py +14 -0
  465. src/harness/src/openharness/ui/protocol.py +247 -0
  466. src/harness/src/openharness/ui/react_launcher.py +179 -0
  467. src/harness/src/openharness/ui/runtime.py +799 -0
  468. src/harness/src/openharness/ui/textual_app.py +495 -0
  469. src/harness/src/openharness/utils/__init__.py +0 -0
  470. src/harness/src/openharness/utils/file_lock.py +86 -0
  471. src/harness/src/openharness/utils/fs.py +98 -0
  472. src/harness/src/openharness/utils/helpers.py +77 -0
  473. src/harness/src/openharness/utils/network_guard.py +340 -0
  474. src/harness/src/openharness/utils/shell.py +147 -0
  475. src/harness/src/openharness/vim/__init__.py +5 -0
  476. src/harness/src/openharness/vim/transitions.py +8 -0
  477. src/harness/src/openharness/voice/__init__.py +7 -0
  478. src/harness/src/openharness/voice/keyterms.py +10 -0
  479. src/harness/src/openharness/voice/stream_stt.py +8 -0
  480. src/harness/src/openharness/voice/voice_mode.py +44 -0
  481. src/llm/__init__.py +29 -0
  482. src/llm/image_generation.py +402 -0
  483. src/llm/provider_registry.py +419 -0
  484. src/llm/runtime_env.py +64 -0
  485. src/llm/structured_output.py +131 -0
  486. src/llm/vision.py +198 -0
  487. src/memory/__init__.py +2 -0
  488. src/memory/api/__init__.py +1 -0
  489. src/memory/api/base_memory_system_api.py +98 -0
  490. src/memory/api/base_symbolic_memory_system_api.py +190 -0
  491. src/memory/api/base_vector_memory_system_api.py +116 -0
  492. src/memory/api/faiss_memory_system_api.py +228 -0
  493. src/memory/api/slot_process_api.py +827 -0
  494. src/memory/api/symbolic_memory_system_api.py +572 -0
  495. src/memory/memory_system/__init__.py +48 -0
  496. src/memory/memory_system/component_taxonomy.py +430 -0
  497. src/memory/memory_system/llm.py +437 -0
  498. src/memory/memory_system/models.py +168 -0
  499. src/memory/memory_system/user_prompt.py +418 -0
  500. src/memory/memory_system/utils.py +282 -0
  501. src/memory/memory_system/vectorstore.py +311 -0
  502. src/memory/memory_system/working_slot.py +99 -0
  503. src/pipeline/__init__.py +129 -0
  504. src/pipeline/contracts.py +531 -0
  505. src/pipeline/discipline_taxonomy.py +916 -0
  506. src/pipeline/evidence_coverage_ledger.py +1150 -0
  507. src/pipeline/evidence_refinement.py +620 -0
  508. src/pipeline/experiment_to_symbolic.py +137 -0
  509. src/pipeline/multimodal_evidence/__init__.py +28 -0
  510. src/pipeline/multimodal_evidence/capabilities.py +107 -0
  511. src/pipeline/multimodal_evidence/claims.py +135 -0
  512. src/pipeline/multimodal_evidence/contract.py +291 -0
  513. src/pipeline/multimodal_evidence/data_sh_compiler.py +505 -0
  514. src/pipeline/multimodal_evidence/handoff_binding.py +135 -0
  515. src/pipeline/multimodal_evidence/manifest.py +254 -0
  516. src/pipeline/multimodal_evidence/native_analysis.py +479 -0
  517. src/pipeline/multimodal_evidence/perception.py +277 -0
  518. src/pipeline/multimodal_evidence/query_binding.py +65 -0
  519. src/pipeline/multimodal_evidence/rendering.py +120 -0
  520. src/pipeline/multimodal_evidence/safety.py +42 -0
  521. src/pipeline/multimodal_evidence/sampling.py +69 -0
  522. src/pipeline/multimodal_evidence/service.py +148 -0
  523. src/pipeline/multimodal_evidence/survey_integration.py +460 -0
  524. src/pipeline/paper_identity.py +52 -0
  525. src/pipeline/research_design_inventory.py +338 -0
  526. src/pipeline/research_domain_resolution.py +669 -0
  527. src/pipeline/research_identity.py +548 -0
  528. src/pipeline/research_question_contract.py +646 -0
  529. src/pipeline/retrieval_lanes.py +889 -0
  530. src/pipeline/run_loop.py +862 -0
  531. src/pipeline/science_events.py +30 -0
  532. src/pipeline/science_manifests.py +602 -0
  533. src/pipeline/science_run.py +918 -0
  534. src/pipeline/science_stages.py +709 -0
  535. src/pipeline/science_workflow.py +807 -0
  536. src/pipeline/sh_cluster_projection.py +306 -0
  537. src/pipeline/sh_graph_provenance.py +648 -0
  538. src/pipeline/subhypothesis_decomposition.py +392 -0
  539. src/pipeline/subhypothesis_evidence.py +856 -0
  540. src/pipeline/survey_evidence_plan.py +858 -0
  541. src/pipeline/survey_gap_adjudication.py +647 -0
  542. src/pipeline/survey_gap_candidates.py +840 -0
  543. src/pipeline/survey_gap_ledger.py +683 -0
  544. src/pipeline/survey_gap_triage.py +401 -0
  545. src/pipeline/survey_handoff_persistence.py +481 -0
  546. src/pipeline/survey_handoff_projection.py +457 -0
  547. src/pipeline/survey_idea_handoff.py +1112 -0
  548. src/pipeline/survey_idea_loader.py +289 -0
  549. src/research_run_ids.py +11 -0
@@ -0,0 +1,537 @@
1
+ import json
2
+ import os
3
+ from typing import List, Optional, Dict
4
+ from dataclasses import dataclass, field
5
+ from utils.rich_logger import get_logger
6
+ from utils.api_call import ChatAgent
7
+ from utils.utils import extract_json
8
+
9
+
10
+ # Agent prompt for deciding operations
11
+ AGENT_OPERATE_PROMPT = """
12
+ You are an intelligent agent that refines project pseudocode by interacting with a code repository.
13
+
14
+ [Repository Information]
15
+ - Name: {repo_name}
16
+ - Title: {paper_title}
17
+ - Abstract: {paper_abstract}
18
+ - Structure:
19
+ {repo_structure}
20
+
21
+ [Core Files (for reference)]
22
+ {core_files_info}
23
+
24
+ [Main Files (for reference)]
25
+ {main_files_info}
26
+
27
+ [Current Project Pseudocode]
28
+ {current_pseudocode}
29
+
30
+ [Memory - Operation History]
31
+ {memory}
32
+
33
+ [Suggestion - Review Feedback]
34
+ {suggestions}
35
+
36
+ [Context - Retrieved Content]
37
+ {context}
38
+
39
+ [Revise Requirement]
40
+ - The recommended operation sequence is: review, get_pseudocode/get_source_code, revise, so that you can provide abundant information to reviser.
41
+ - The core operation is revise since the target is refine the pseudocode.
42
+ - You MUST call "revise" operation at least once every 3 rounds to improve the pseudocode.
43
+
44
+ ---
45
+
46
+ Your task is to plan a sequence of operations to refine the pseudocode.
47
+
48
+ Available operations:
49
+ 1. "get_pseudocode": Query pseudocode of a specific file by providing its path
50
+ 2. "get_source_code": Query source code of a specific file in main file list or core file list by providing its path
51
+ 3. "revise": Modify the current pseudocode based on the context (retrieved content) and suggestion - IMPORTANT: you must call this at least once every 3 rounds!
52
+ 4. "review": Call the review skill to provide suggestions on what to do next
53
+ 5. "finish": Complete the refinement process when the pseudocode is satisfactory
54
+
55
+ Output format (JSON):
56
+ {{
57
+ "plan": [
58
+ {{"operation": "...", "file_path": "...", "reason": "..."}},
59
+ ...
60
+ ]
61
+ }}
62
+
63
+ - Each item in "plan" is one operation to execute in order
64
+ - For "get_pseudocode" or "get_source_code", include "file_path"
65
+ - For "revise" or "finish", no file_path needed
66
+ - Include at least 1 operation, up to 3 operations per plan
67
+ - "review" operation does not require file_path
68
+ - You must call "revise" when getting enough information with other skills
69
+
70
+ Generate JSON directly without any other things.
71
+ """
72
+
73
+ REVIEW_PROMPT = """
74
+ You are a code review expert. Review the current project pseudocode and provide specific suggestions.
75
+
76
+ [Paper Info]
77
+ Title: {paper_title}
78
+ Abstract: {paper_abstract}
79
+
80
+ [Repository Structure]
81
+ {repo_structure}
82
+
83
+ [Core Files (high score)]
84
+ {core_files_info}
85
+
86
+ [Main Files]
87
+ {main_files_info}
88
+
89
+ [Current Project Pseudocode]
90
+ {final_pseudocode}
91
+
92
+ ---
93
+ Requirements:
94
+ 1. The pseudocode should be well formatted and well structured with clear logic.
95
+ 2. The pseudocode should contain all the core implementation specifically.
96
+ 3. The pseudocode should be concise. No more than 7 sections and no more than 400 lines.
97
+ 4. The pseudocode should be concise on or skip less important parts.
98
+
99
+ Please provide suggestions and scores (0-10) for the pseudocode.
100
+ - suggestions: List of concrete improvement suggestions
101
+ - conciseness_score: How concise the pseudocode is (higher = more concise, less redundant)
102
+ - logic_score: How clear and logical the pseudocode structure is (higher = better)
103
+ - specificity_score: How specific the pseudocode is about key implementation details (core model components, critical loss functions, key algorithms) - NOT about including trivial imports or boilerplate
104
+
105
+ Scoring Standards (0-10):
106
+ 1. conciseness_score:
107
+ - 9-10: Very concise, minimal redundancy, focuses on essential logic only
108
+ - 7-8: Mostly concise, minor redundancies
109
+ - 5-6: Some redundant sections or verbose descriptions
110
+ - 3-4: Noticeable redundancies, verbose in places
111
+ - 1-2: Highly repetitive, lots of unnecessary details
112
+
113
+ 2. logic_score:
114
+ - 9-10: Clear control flow, logical section organization, easy to follow
115
+ - 7-8: Good structure, minor issues with flow
116
+ - 5-6: Some logical issues, sections somewhat disconnected
117
+ - 3-4: Confusing flow, poor section organization
118
+ - 1-2: Very hard to understand the logic
119
+
120
+ 3. specificity_score: Focus on KEY content specificity, NOT adding irrelevant details like imports or file paths
121
+ - 9-10: Captures key details: core model components, critical loss functions, key algorithms, important data flow - without trivial imports
122
+ - 7-8: Good detail on main components, minor missing key details
123
+ - 5-6: Too generic, missing important specifics (e.g., just says "train model" without explaining how)
124
+ - 3-4: Lacks important details about core algorithms/components
125
+ - 1-2: Very vague, no meaningful implementation details
126
+
127
+ Output format (JSON):
128
+ {{
129
+ "suggestions": ["suggestion1", "suggestion2", ...],
130
+ "conciseness_score": 7,
131
+ "logic_score": 8,
132
+ "specificity_score": 8
133
+ }}
134
+
135
+ Generate JSON directly without any other things.
136
+ """
137
+
138
+ MODIFY_PROMPT = """
139
+ TASK:
140
+
141
+ Build a well-structed pseudocode and analysis for the source code of a paper.
142
+ Given the following information, refine the project pseudocode:
143
+ [Paper Info]
144
+ {paper_title}:
145
+ {paper_abstract}
146
+
147
+ [Repository Info]
148
+ {repo_structure}
149
+
150
+ [Current Pseudocode]
151
+ {final_pseudocode}
152
+
153
+ [Retrieved Context]
154
+ {context}
155
+
156
+ [Reviewer suggestion]
157
+ {suggestions}
158
+
159
+ [Reason for modification]
160
+ {reason}
161
+
162
+ Please provide the refined pseudocode that incorporates the relevant details from the context.
163
+
164
+ REQUIRMENTS:
165
+ - Merge necessary content in context rather than simply adding the context.
166
+ - Be cautious about adding new section in the pseudocode.
167
+ - Keep the pseudocode at a reasonable length. If it gets too long, prioritize the most important additions or delete less important part.
168
+ - Output the refined pseudocode and analysis directly
169
+ """
170
+
171
+
172
+ @dataclass
173
+ class AgentContext:
174
+ """Structured input for the central agent."""
175
+ repo_name: str
176
+ paper_title: str
177
+ paper_abstract: str
178
+ repo_structure: Dict
179
+ core_files: List[Dict] = field(default_factory=list)
180
+ main_files: List[Dict] = field(default_factory=list)
181
+ current_pseudocode: str = ""
182
+ memory: List[Dict] = field(default_factory=list)
183
+ suggestions: List[str] = field(default_factory=list)
184
+ context: str = ""
185
+ error_log: List[str] = field(default_factory=list)
186
+ review_scores: Dict = field(default_factory=dict) # {"conciseness": 0-10, "logic": 0-10, "specificity": 0-10}
187
+
188
+
189
+ class PseudoReviser:
190
+ """
191
+ Agent-based pseudocode refiner that uses a central agent to decide operations.
192
+ """
193
+
194
+ def __init__(self, config, chat_agent: ChatAgent, repo_cache_path: str):
195
+ self.chat_agent = chat_agent
196
+ self.logger = get_logger("PseudoReviser")
197
+ self.repo_cache_path = repo_cache_path
198
+ self.default_max_steps = 20 # Maximum number of agent steps
199
+ self.config = config
200
+
201
+ def _get_pseudocode_from_repo_structure(self, repo_structure: dict, rel_path: str) -> Optional[str]:
202
+ """Get pseudocode from repo_structure by file path."""
203
+ try:
204
+ parts = rel_path.split(os.sep)
205
+ node = repo_structure
206
+ for p in parts[:-1]:
207
+ if p not in node:
208
+ return None
209
+ node = node[p]
210
+ filename = parts[-1]
211
+ if filename in node and isinstance(node[filename], dict):
212
+ return node[filename].get("pseudocode")
213
+ except Exception as e:
214
+ self.logger.debug(f"Error getting pseudocode for {rel_path}: {e}")
215
+ return None
216
+
217
+ def _get_source_code(self, repo_name: str, rel_path: str) -> Optional[str]:
218
+ """Read source code from the repository."""
219
+ try:
220
+ repo_path = os.path.join(self.repo_cache_path, repo_name)
221
+ file_abs = os.path.join(repo_path, rel_path)
222
+ if os.path.exists(file_abs):
223
+ with open(file_abs, "r", encoding="utf-8", errors="ignore") as f:
224
+ # Limit to first 500 lines to avoid too much content
225
+ lines = f.readlines()[:500]
226
+ return "".join(lines)
227
+ except Exception as e:
228
+ self.logger.error(f"Error reading source code for {rel_path}: {e}")
229
+ return None
230
+
231
+ def _format_memory(self, memory: List[Dict]) -> str:
232
+ """Format memory (operation history) as string."""
233
+ if not memory:
234
+ return "No operations performed yet."
235
+
236
+ lines = []
237
+ for i, op in enumerate(memory):
238
+ lines.append(f"{i+1}. {op['operation']}: {op.get('reason', '')}")
239
+ if op['operation'] == 'modify_pseudocode':
240
+ lines.append(f" Modified pseudocode")
241
+ return "\n".join(lines)
242
+
243
+ def _format_core_main_files(self, mainfest: dict) -> tuple:
244
+ """Format core and main files info for the prompt."""
245
+ # Core files
246
+ core_files = mainfest.get("core_files", [])
247
+ core_lines = []
248
+ for f in core_files[:10]: # Top 10
249
+ path = f.get("path", "")
250
+ scores = f.get("scores", [])
251
+ max_score = max(scores) if scores else 0
252
+ reason = f.get("reason", "")[:100]
253
+ core_lines.append(f"- {path} (score: {max_score}, reason: {reason})")
254
+ core_files_info = "\n".join(core_lines) if core_lines else "No core files"
255
+
256
+ # Main files
257
+ main_files = mainfest.get("main_files", [])
258
+ main_lines = []
259
+ for f in main_files[:5]: # Top 5
260
+ path = f.get("path", "")
261
+ reason = f.get("reason", "")[:100]
262
+ main_lines.append(f"- {path}: {reason}")
263
+ main_files_info = "\n".join(main_lines) if main_lines else "No main files"
264
+
265
+ return core_files_info, main_files_info
266
+
267
+ def _validate_review_response(self, response: str, info_dict: dict) -> None:
268
+ """Validate review response format."""
269
+ result = extract_json(response)
270
+ if not isinstance(result, dict):
271
+ raise ValueError(f"Review response is not a dict: {type(result)}")
272
+ if "suggestions" not in result:
273
+ raise ValueError("Missing 'suggestions' field")
274
+ if "conciseness_score" not in result:
275
+ raise ValueError("Missing 'conciseness_score' field")
276
+ if "logic_score" not in result:
277
+ raise ValueError("Missing 'logic_score' field")
278
+ if "specificity_score" not in result:
279
+ raise ValueError("Missing 'specificity_score' field")
280
+ # Validate score range
281
+ conciseness = result.get("conciseness_score", 0)
282
+ logic = result.get("logic_score", 0)
283
+ specificity = result.get("specificity_score", 0)
284
+ if not (0 <= conciseness <= 10):
285
+ raise ValueError(f"conciseness_score out of range: {conciseness}")
286
+ if not (0 <= logic <= 10):
287
+ raise ValueError(f"logic_score out of range: {logic}")
288
+ if not (0 <= specificity <= 10):
289
+ raise ValueError(f"specificity_score out of range: {specificity}")
290
+ return True, response
291
+
292
+ def _call_review(self, agent_ctx: AgentContext) -> Dict:
293
+ """Call review skill to get suggestions and scores."""
294
+ core_files_info, main_files_info = self._format_core_main_files({
295
+ "core_files": agent_ctx.core_files,
296
+ "main_files": agent_ctx.main_files
297
+ })
298
+
299
+ prompt = REVIEW_PROMPT.format(
300
+ paper_title=agent_ctx.paper_title,
301
+ paper_abstract=agent_ctx.paper_abstract,
302
+ repo_structure=self._format_repo_structure(agent_ctx.repo_structure),
303
+ core_files_info=core_files_info,
304
+ main_files_info=main_files_info,
305
+ final_pseudocode=agent_ctx.current_pseudocode
306
+ )
307
+
308
+ response = self.chat_agent.remote_chat_with_retry(
309
+ prompt,
310
+ validate_fn=self._validate_review_response,
311
+ max_retry=3,
312
+ temperature=0
313
+ )
314
+
315
+ result = extract_json(response)
316
+ # result should be dict with suggestions and scores
317
+ if isinstance(result, dict):
318
+ suggestions = result.get("suggestions", [])
319
+ scores = {
320
+ "conciseness": result.get("conciseness_score", 0),
321
+ "logic": result.get("logic_score", 0),
322
+ "specificity": result.get("specificity_score", 0)
323
+ }
324
+ return {"suggestions": suggestions, "scores": scores}
325
+ else:
326
+ self.logger.warning(f"Review response is not a dict: {result}")
327
+ return {"suggestions": [str(result)] if result else [], "scores": {"conciseness": 0, "logic": 0, "specificity": 0}}
328
+
329
+
330
+ def _execute_operation(self, op: dict, agent_ctx: AgentContext) -> None:
331
+ """Execute a single operation."""
332
+ operation = op.get("operation", "")
333
+ file_path = op.get("file_path", "")
334
+ reason = op.get("reason", "")
335
+
336
+ if operation == "get_pseudocode":
337
+ if file_path:
338
+ pseudocode = self._get_pseudocode_from_repo_structure(agent_ctx.repo_structure, file_path)
339
+ agent_ctx.context += f"=== Pseudocode of {file_path} ===\n{pseudocode if pseudocode else 'Not available'}\n"
340
+ self.logger.info(f"Retrieved pseudocode for: {file_path}, reason: {reason}")
341
+ else:
342
+ self.logger.error("get_pseudocode: file_path not provided, skipped")
343
+ agent_ctx.error_log.append(f"file path do not have pseudocode: {file_path}")
344
+
345
+ elif operation == "get_source_code":
346
+ if file_path:
347
+ source_code = self._get_source_code(agent_ctx.repo_name, file_path)
348
+ agent_ctx.context += f"=== Source code of {file_path} ===\n{source_code if source_code else 'Not available'}\n"
349
+ self.logger.info(f"Retrieved source code for: {file_path}, reason: {reason}")
350
+ else:
351
+ self.logger.error("get_source_code: file_path not provided, skipped")
352
+ agent_ctx.error_log.append(f"Unknown filepath in retrieve: {file_path}")
353
+
354
+ elif operation == "revise":
355
+ modify_prompt = MODIFY_PROMPT.format(
356
+ paper_title=agent_ctx.paper_title,
357
+ paper_abstract=agent_ctx.paper_abstract,
358
+ repo_structure=self._format_repo_structure(agent_ctx.repo_structure),
359
+ final_pseudocode=agent_ctx.current_pseudocode,
360
+ context=agent_ctx.context,
361
+ suggestions="\n".join(agent_ctx.suggestions) if agent_ctx.suggestions else "No suggestion yet.",
362
+ reason=reason,
363
+ )
364
+ result = self.chat_agent.remote_chat_with_retry(modify_prompt, temperature=0)
365
+ agent_ctx.current_pseudocode = result
366
+ agent_ctx.context = "" # Clear context after modification
367
+ agent_ctx.suggestions = [] # Clear suggestion after modification
368
+ self.logger.info(f"Revised pseudocode, reason: {reason}")
369
+
370
+ elif operation == "finish":
371
+ self.logger.info(f"Operation: finish, reason: {reason}")
372
+
373
+ elif operation == "review":
374
+ review_result = self._call_review(agent_ctx)
375
+ agent_ctx.suggestions.extend(review_result.get("suggestions", []))
376
+ agent_ctx.review_scores = review_result.get("scores", {"conciseness": 0, "logic": 0, "specificity": 0})
377
+ # Record scores in memory
378
+ if agent_ctx.memory:
379
+ agent_ctx.memory[-1]["review_scores"] = agent_ctx.review_scores
380
+ self.logger.info(f"Review scores: conciseness={agent_ctx.review_scores['conciseness']}, logic={agent_ctx.review_scores['logic']}, specificity={agent_ctx.review_scores['specificity']}")
381
+ self.logger.info(f"reason: {reason}")
382
+
383
+ else:
384
+ self.logger.error(f"Unknown operation: {operation}, skipped")
385
+ agent_ctx.error_log.append(f"Unknown operation: {operation}, skipped")
386
+
387
+ def refine_pseudocode_with_agent(
388
+ self,
389
+ mainfest: dict,
390
+ current_pseudocode: str,
391
+ max_steps: int = None,
392
+ hard_code_revise: bool = False,
393
+ max_rounds_without_revise: int = 3,
394
+ last_round_revise: bool = True,
395
+ ) -> str:
396
+ """
397
+ Refine pseudocode using agent-based approach with plan-based execution.
398
+
399
+ Args:
400
+ mainfest: the mainfest dict containing repo_info and core_files info
401
+ current_pseudocode: the initial project pseudocode
402
+ max_steps: maximum number of agent steps
403
+ hard_code_revise: if True, force call revise after max_rounds_without_revise rounds without revise
404
+ max_rounds_without_revise: maximum rounds without revise before forcing (default: 3)
405
+
406
+ Returns:
407
+ Final refined pseudocode
408
+ """
409
+ repo_info = mainfest["repo_info"]
410
+
411
+ # Build AgentContext
412
+ core_files_info, main_files_info = self._format_core_main_files(mainfest)
413
+
414
+ agent_ctx = AgentContext(
415
+ repo_name=repo_info["repo_name"],
416
+ paper_title=repo_info["paper_title"],
417
+ paper_abstract=repo_info["paper_abstract"],
418
+ repo_structure=repo_info["repo_structure"],
419
+ core_files=mainfest.get("core_files", []),
420
+ main_files=mainfest.get("main_files", []),
421
+ current_pseudocode=current_pseudocode,
422
+ memory=[],
423
+ suggestions=[],
424
+ context="",
425
+ error_log=[],
426
+ review_scores={"conciseness": 0, "logic": 0, "specificity": 0}
427
+ )
428
+
429
+ max_steps = max_steps or self.default_max_steps
430
+
431
+ # Track rounds since last revise for hard_code_revise feature
432
+ rounds_since_last_revise = 0
433
+
434
+ self.logger.info(f"Starting agent-based pseudocode refinement (max {max_steps} steps, hard_code_revise={hard_code_revise})")
435
+
436
+ for step in range(max_steps):
437
+ self.logger.info(f"Agent step {step + 1}/{max_steps}")
438
+
439
+ # Format the prompt with plan-based format
440
+ prompt = AGENT_OPERATE_PROMPT.format(
441
+ repo_name=agent_ctx.repo_name,
442
+ paper_title=agent_ctx.paper_title,
443
+ paper_abstract=agent_ctx.paper_abstract,
444
+ repo_structure=self._format_repo_structure(agent_ctx.repo_structure),
445
+ core_files_info=core_files_info,
446
+ main_files_info=main_files_info,
447
+ current_pseudocode=agent_ctx.current_pseudocode,
448
+ memory=self._format_memory(agent_ctx.memory),
449
+ suggestions="\n".join(agent_ctx.suggestions) if agent_ctx.suggestions else "No suggestion yet.",
450
+ context=agent_ctx.context if agent_ctx.context else "No context yet."
451
+ )
452
+
453
+ # self.logger.info(f"[PLANNER PROMPT] {prompt}")
454
+ # Get agent's plan
455
+ response = self.chat_agent.remote_chat(prompt, temperature=0)
456
+
457
+ # self.logger.info(f"[PLANNER RESPONSE] {response}")
458
+
459
+ # Parse the response - now expects "plan" array
460
+ try:
461
+ decision = extract_json(response)
462
+ plan = decision.get("plan", [])
463
+ if not isinstance(plan, list):
464
+ plan = [decision] # Fallback: treat as single operation
465
+ except Exception as e:
466
+ self.logger.error(f"Failed to parse agent response: {response[:200]}..., skipped this round")
467
+ agent_ctx.error_log.append(f"error in parsing planning json: {e}")
468
+ continue
469
+
470
+ # Execute each operation in the plan
471
+ for op in plan:
472
+ op_type = op.get("operation", "")
473
+ # Record to memory
474
+ agent_ctx.memory.append({"operation": op_type, "reason": op.get("reason", "")})
475
+
476
+ # Check for finish
477
+ if op_type == "finish":
478
+ self.logger.info("Agent decided to finish")
479
+ break
480
+
481
+ # Execute operation
482
+ self._execute_operation(op, agent_ctx)
483
+
484
+ # Track revise operations
485
+ if op_type == "revise":
486
+ rounds_since_last_revise = 0
487
+ else:
488
+ rounds_since_last_revise += 1
489
+
490
+ # Check if we need to force revise
491
+ if hard_code_revise and rounds_since_last_revise >= max_rounds_without_revise:
492
+ self.logger.info(f"Force calling revise after {rounds_since_last_revise} rounds without revise")
493
+ # Force execute revise operation
494
+ force_revise_op = {"operation": "revise", "reason": "Forced revise after max rounds without revise"}
495
+ agent_ctx.memory.append({"operation": "revise", "reason": "Forced revise (hard_code)"})
496
+ self._execute_operation(force_revise_op, agent_ctx)
497
+ rounds_since_last_revise = 0
498
+ continue
499
+
500
+ if step + 1 == max_steps:
501
+ if(last_round_revise and rounds_since_last_revise > 0):
502
+ self.logger.info("last round does not include revise, force calling revise")
503
+ force_revise_op = {"operation": "revise", "reason": "Forced revise in last round"}
504
+ agent_ctx.memory.append({"operation": "revise", "reason": "Forced revise (last round)"})
505
+ self._execute_operation(force_revise_op, agent_ctx)
506
+ rounds_since_last_revise = 0
507
+
508
+ # Check if finished
509
+ if any(m.get("operation") == "finish" for m in agent_ctx.memory[-len(plan):] if plan):
510
+ self.logger.info(f"planning agent decide to finish at step {step}")
511
+ break
512
+
513
+ self.logger.info(f"Agent-based refinement completed after {step + 1} steps")
514
+ return agent_ctx.current_pseudocode
515
+
516
+ def _format_repo_structure(self, structure: dict) -> str:
517
+ """Format repo structure as string (similar to format_repo_structure in CodeAnalyzer)."""
518
+ lines = []
519
+
520
+ def _build_tree_string(node: dict, prefix: str = ""):
521
+ keys = sorted(node.keys())
522
+ total_items = len(keys)
523
+
524
+ for i, key in enumerate(keys):
525
+ value = node[key]
526
+ is_last = (i == total_items - 1)
527
+ connector = "└── " if is_last else "├── "
528
+ lines.append(f"{prefix}{connector}{key}")
529
+
530
+ if isinstance(value, dict) and value.get("_is_file"):
531
+ pass
532
+ else:
533
+ extension = " " if is_last else "│ "
534
+ _build_tree_string(value, prefix + extension)
535
+
536
+ _build_tree_string(structure)
537
+ return "\n".join(lines)