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.
- qwen_sci-0.2.2.dist-info/METADATA +492 -0
- qwen_sci-0.2.2.dist-info/RECORD +549 -0
- qwen_sci-0.2.2.dist-info/WHEEL +4 -0
- qwen_sci-0.2.2.dist-info/entry_points.txt +6 -0
- qwen_sci-0.2.2.dist-info/licenses/LICENSE +21 -0
- src/1.txt +1 -0
- src/__init__.py +1 -0
- src/__main__.py +5 -0
- src/agents/__init__.py +1 -0
- src/agents/experiment_design_agent/__init__.py +268 -0
- src/agents/experiment_design_agent/artifacts.py +747 -0
- src/agents/experiment_design_agent/cache.py +319 -0
- src/agents/experiment_design_agent/completeness.py +130 -0
- src/agents/experiment_design_agent/contracts.py +771 -0
- src/agents/experiment_design_agent/counterexample_analyzer.py +187 -0
- src/agents/experiment_design_agent/design_evidence_paper_screener.py +470 -0
- src/agents/experiment_design_agent/discipline_catalog.py +178 -0
- src/agents/experiment_design_agent/evidence_cards.py +338 -0
- src/agents/experiment_design_agent/evidence_planner.py +452 -0
- src/agents/experiment_design_agent/formal_reasoning_planner.py +884 -0
- src/agents/experiment_design_agent/fulltext_acquisition.py +863 -0
- src/agents/experiment_design_agent/idea_adapter.py +100 -0
- src/agents/experiment_design_agent/idea_intake.py +87 -0
- src/agents/experiment_design_agent/llm_json.py +328 -0
- src/agents/experiment_design_agent/orchestrator.py +1220 -0
- src/agents/experiment_design_agent/reasoning_context.py +183 -0
- src/agents/experiment_design_agent/reasoning_validation.py +546 -0
- src/agents/experiment_design_agent/run.py +481 -0
- src/agents/experiment_design_agent/run_logging.py +292 -0
- src/agents/experiment_design_agent/scope_gate.py +198 -0
- src/agents/experiment_design_agent/study_type_composer.py +1360 -0
- src/agents/experiment_design_agent/survey_evidence.py +1381 -0
- src/agents/experiment_design_agent/template_router.py +195 -0
- src/agents/experiment_design_agent/variable_claim_extractor.py +93 -0
- src/agents/idea_agent/__init__.py +1 -0
- src/agents/idea_agent/agent/__init__.py +6 -0
- src/agents/idea_agent/agent/artifacts.py +308 -0
- src/agents/idea_agent/agent/base.py +122 -0
- src/agents/idea_agent/agent/ligagent.py +488 -0
- src/agents/idea_agent/agent/mcts.py +2060 -0
- src/agents/idea_agent/agent/prompts/__init__.py +48 -0
- src/agents/idea_agent/agent/prompts/advanced_analysis.py +235 -0
- src/agents/idea_agent/agent/prompts/algorithm_alignment.py +55 -0
- src/agents/idea_agent/agent/prompts/algorithm_structuring.py +48 -0
- src/agents/idea_agent/agent/prompts/component_extraction.py +62 -0
- src/agents/idea_agent/agent/prompts/component_novelty_evaluation.py +54 -0
- src/agents/idea_agent/agent/prompts/experiment_findings_extraction.py +39 -0
- src/agents/idea_agent/agent/prompts/idea_fusion.py +295 -0
- src/agents/idea_agent/agent/prompts/idea_introduction.py +30 -0
- src/agents/idea_agent/agent/prompts/idea_result_alignment.py +39 -0
- src/agents/idea_agent/agent/prompts/input_interpreter.py +52 -0
- src/agents/idea_agent/agent/prompts/keynote_ops.py +78 -0
- src/agents/idea_agent/agent/prompts/mcts_evaluation.py +235 -0
- src/agents/idea_agent/agent/prompts/mcts_generation.py +140 -0
- src/agents/idea_agent/agent/prompts/mechanism_commit_query.py +99 -0
- src/agents/idea_agent/agent/prompts/memory_selection.py +0 -0
- src/agents/idea_agent/agent/prompts/prompt_modes.py +16 -0
- src/agents/idea_agent/agent/prompts/rag_query.py +34 -0
- src/agents/idea_agent/agent/prompts/re_analysis_replan.py +48 -0
- src/agents/idea_agent/agent/prompts/reference_grounding.py +34 -0
- src/agents/idea_agent/agent/prompts/root_domain_classification.py +32 -0
- src/agents/idea_agent/agent/prompts/scientific_debate.py +88 -0
- src/agents/idea_agent/agent/prompts/scientific_materialization.py +45 -0
- src/agents/idea_agent/agent/prompts/skill_instantiation.py +193 -0
- src/agents/idea_agent/agent/prompts/theory_transfer_query.py +93 -0
- src/agents/idea_agent/agent/prompts/topic_background.py +15 -0
- src/agents/idea_agent/agent/skills/DEFAULT_SKILL_TEMPLATES.json +263 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/alternative-path-contrast/SKILL.md +40 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/alternative-path-contrast/references/contrast_patterns.md +22 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/feedback-closed-loop/SKILL.md +40 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/feedback-closed-loop/references/mechanism_cards.md +24 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/hierarchical-decomposition/SKILL.md +39 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/hierarchical-decomposition/references/hierarchy_patterns.md +22 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/mechanism-commit-innovation/SKILL.md +39 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/mechanism-commit-innovation/references/mechanism_commit_patterns.md +24 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/multi-scale-coordinator/SKILL.md +39 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/multi-scale-coordinator/references/coordination_patterns.md +22 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/speculative-execution-with-repair/SKILL.md +41 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/speculative-execution-with-repair/references/speculation_patterns.md +22 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/surgical-modularity/SKILL.md +39 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/surgical-modularity/references/modularity_patterns.md +22 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/theory-transfer-injection/SKILL.md +40 -0
- src/agents/idea_agent/agent/skills/edit_operator_skills/theory-transfer-injection/references/transfer_patterns.md +24 -0
- src/agents/idea_agent/example/idea_result.json +900 -0
- src/agents/idea_agent/run.py +276 -0
- src/agents/idea_agent/tests/test_advanced_analysis_contract.py +90 -0
- src/agents/idea_agent/tests/test_gap_hypothesis_bridge.py +166 -0
- src/agents/idea_agent/tests/test_idea_debate.py +480 -0
- src/agents/idea_agent/tests/test_idea_result_v5.py +99 -0
- src/agents/idea_agent/tests/test_idea_synthesis.py +92 -0
- src/agents/idea_agent/tests/test_mature_idea_sources.py +27 -0
- src/agents/idea_agent/tests/test_multimodal_idea_integration.py +386 -0
- src/agents/idea_agent/tests/test_profile_materialization_and_scoring.py +219 -0
- src/agents/idea_agent/tests/test_profile_native_skill_rendering.py +122 -0
- src/agents/idea_agent/tests/test_result_persistence.py +183 -0
- src/agents/idea_agent/tests/test_scientific_intervention_profiles.py +241 -0
- src/agents/idea_agent/tests/test_scientific_rubric_and_prompts.py +559 -0
- src/agents/idea_agent/tests/test_strict_json_object_responses.py +48 -0
- src/agents/idea_agent/utils/core/__init__.py +1 -0
- src/agents/idea_agent/utils/core/ablation_inputs.py +60 -0
- src/agents/idea_agent/utils/core/chat_errors.py +95 -0
- src/agents/idea_agent/utils/core/chat_router.py +130 -0
- src/agents/idea_agent/utils/core/chat_transport.py +188 -0
- src/agents/idea_agent/utils/core/config_loader.py +166 -0
- src/agents/idea_agent/utils/core/json_utils.py +28 -0
- src/agents/idea_agent/utils/core/logger.py +287 -0
- src/agents/idea_agent/utils/core/progress.py +58 -0
- src/agents/idea_agent/utils/core/response_parsing.py +57 -0
- src/agents/idea_agent/utils/core/run_inputs.py +198 -0
- src/agents/idea_agent/utils/mcts/__init__.py +1 -0
- src/agents/idea_agent/utils/mcts/component_novelty.py +342 -0
- src/agents/idea_agent/utils/mcts/defect_registry.py +302 -0
- src/agents/idea_agent/utils/mcts/idea_routes.py +61 -0
- src/agents/idea_agent/utils/mcts/idea_taste_presets.py +312 -0
- src/agents/idea_agent/utils/mcts/mcts_helpers.py +738 -0
- src/agents/idea_agent/utils/mcts/mcts_runtime.py +3000 -0
- src/agents/idea_agent/utils/mcts/scientific_intervention_ontology.py +1561 -0
- src/agents/idea_agent/utils/mcts/scientific_rubric.py +211 -0
- src/agents/idea_agent/utils/mcts/skill_parsing.py +92 -0
- src/agents/idea_agent/utils/papers/__init__.py +1 -0
- src/agents/idea_agent/utils/papers/paper_graph_vector_store.py +499 -0
- src/agents/idea_agent/utils/papers/paper_repository.py +372 -0
- src/agents/idea_agent/utils/prompting/__init__.py +1 -0
- src/agents/idea_agent/utils/prompting/prompt_views.py +637 -0
- src/agents/idea_agent/utils/workflow/__init__.py +1 -0
- src/agents/idea_agent/utils/workflow/advanced_analysis_contract.py +244 -0
- src/agents/idea_agent/utils/workflow/gap_hypothesis_bridge.py +461 -0
- src/agents/idea_agent/utils/workflow/idea_contract.py +426 -0
- src/agents/idea_agent/utils/workflow/idea_debate.py +1238 -0
- src/agents/idea_agent/utils/workflow/idea_diversity.py +163 -0
- src/agents/idea_agent/utils/workflow/idea_fusion.py +889 -0
- src/agents/idea_agent/utils/workflow/idea_helpers.py +478 -0
- src/agents/idea_agent/utils/workflow/idea_portfolio.py +422 -0
- src/agents/idea_agent/utils/workflow/idea_synthesis.py +482 -0
- src/agents/idea_agent/utils/workflow/ligagent_flow.py +581 -0
- src/agents/idea_agent/utils/workflow/ligagent_handlers.py +1836 -0
- src/agents/idea_agent/utils/workflow/ligagent_helpers.py +1331 -0
- src/agents/idea_agent/utils/workflow/ligagent_utils.py +322 -0
- src/agents/idea_agent/utils/workflow/mature_idea_sources.py +648 -0
- src/agents/idea_agent/utils/workflow/multimodal_data_anchoring.py +578 -0
- src/agents/idea_agent/utils/workflow/result_persistence.py +774 -0
- src/agents/idea_agent/utils/workflow/stage_contract.py +76 -0
- src/agents/idea_agent/utils/workflow/workflow_runtime.py +288 -0
- src/agents/research_plan_author/__init__.py +50 -0
- src/agents/research_plan_author/artifacts.py +270 -0
- src/agents/research_plan_author/authoring_blueprint.py +1246 -0
- src/agents/research_plan_author/bibtex_renderer.py +252 -0
- src/agents/research_plan_author/contract_repair.py +131 -0
- src/agents/research_plan_author/contracts.py +745 -0
- src/agents/research_plan_author/cross_section_editor.py +232 -0
- src/agents/research_plan_author/document_quality.py +987 -0
- src/agents/research_plan_author/idea_evolution.py +223 -0
- src/agents/research_plan_author/input_loader.py +76 -0
- src/agents/research_plan_author/latex_compiler.py +260 -0
- src/agents/research_plan_author/latex_safety.py +159 -0
- src/agents/research_plan_author/llm_json.py +74 -0
- src/agents/research_plan_author/markdown_renderer.py +275 -0
- src/agents/research_plan_author/pdf_validator.py +149 -0
- src/agents/research_plan_author/render.py +166 -0
- src/agents/research_plan_author/render_artifacts.py +187 -0
- src/agents/research_plan_author/run.py +765 -0
- src/agents/research_plan_author/run_logging.py +209 -0
- src/agents/research_plan_author/section_cache.py +184 -0
- src/agents/research_plan_author/section_composer.py +1764 -0
- src/agents/research_plan_author/section_router.py +209 -0
- src/agents/research_plan_author/semantic_validator.py +254 -0
- src/agents/research_plan_author/source_bundle.py +46 -0
- src/agents/research_plan_author/source_registry.py +208 -0
- src/agents/research_plan_author/survey_source_loader.py +137 -0
- src/agents/research_plan_author/template_adapter.py +173 -0
- src/agents/research_plan_author/template_profile.py +204 -0
- src/agents/research_plan_author/tex_renderer.py +496 -0
- src/agents/research_plan_author/theory_presentation.py +134 -0
- src/agents/research_plan_author/theory_spine.py +703 -0
- src/agents/survey_agent/Dockerfile +54 -0
- src/agents/survey_agent/README.md +350 -0
- src/agents/survey_agent/config/deep_survey.yaml +217 -0
- src/agents/survey_agent/config/deep_survey_batch.yaml +176 -0
- src/agents/survey_agent/config/deep_survey_fast.yaml +183 -0
- src/agents/survey_agent/config/evaluate_baseline.yaml +197 -0
- src/agents/survey_agent/config/outcomeRAG.yaml +159 -0
- src/agents/survey_agent/env_report.md +348 -0
- src/agents/survey_agent/modules/__init__.py +0 -0
- src/agents/survey_agent/modules/code_collector.py +2194 -0
- src/agents/survey_agent/modules/code_report_generator.py +1282 -0
- src/agents/survey_agent/modules/data_manager.py +1713 -0
- src/agents/survey_agent/modules/database.py +167 -0
- src/agents/survey_agent/modules/fulltext_download_cache.py +462 -0
- src/agents/survey_agent/modules/fulltext_http.py +134 -0
- src/agents/survey_agent/modules/fulltext_resolution.py +749 -0
- src/agents/survey_agent/modules/judge.py +434 -0
- src/agents/survey_agent/modules/outcome_RAG.py +236 -0
- src/agents/survey_agent/modules/paper_graph_retriever.py +1075 -0
- src/agents/survey_agent/modules/pe.py +1729 -0
- src/agents/survey_agent/modules/pseudo_creator.py +782 -0
- src/agents/survey_agent/modules/pseudo_reviser.py +537 -0
- src/agents/survey_agent/modules/refine_agent.py +1952 -0
- src/agents/survey_agent/modules/survey_generator.py +5691 -0
- src/agents/survey_agent/modules/survey_visualizer.py +1817 -0
- src/agents/survey_agent/modules/visual_prompts.py +327 -0
- src/agents/survey_agent/modules/work_analyzer.py +2750 -0
- src/agents/survey_agent/modules/work_collector.py +5649 -0
- src/agents/survey_agent/scripts/baseline_evaluation.py +411 -0
- src/agents/survey_agent/scripts/run_deep_survey.py +224 -0
- src/agents/survey_agent/scripts/run_deep_survey_adapter.py +407 -0
- src/agents/survey_agent/scripts/run_deep_survey_adapter_with_input.py +409 -0
- src/agents/survey_agent/scripts/run_deep_survey_batch.py +228 -0
- src/agents/survey_agent/scripts/run_deep_survey_batch_arg.py +243 -0
- src/agents/survey_agent/scripts/run_deep_survey_batch_settings.py +218 -0
- src/agents/survey_agent/scripts/run_keynotes_gen.py +128 -0
- src/agents/survey_agent/scripts/run_work_clusters.py +140 -0
- src/agents/survey_agent/utils/__init__.py +0 -0
- src/agents/survey_agent/utils/ablation_utils.py +317 -0
- src/agents/survey_agent/utils/api_call.py +2518 -0
- src/agents/survey_agent/utils/chat_utils.py +82 -0
- src/agents/survey_agent/utils/config_utils.py +70 -0
- src/agents/survey_agent/utils/convert_to_md.py +29 -0
- src/agents/survey_agent/utils/err_info.py +24 -0
- src/agents/survey_agent/utils/file_utils.py +176 -0
- src/agents/survey_agent/utils/gpu_utils.py +145 -0
- src/agents/survey_agent/utils/graph_visualizer.py +279 -0
- src/agents/survey_agent/utils/html_utils.py +181 -0
- src/agents/survey_agent/utils/latex_generator_intra_cluster.py +529 -0
- src/agents/survey_agent/utils/latex_generator_relation_table.py +193 -0
- src/agents/survey_agent/utils/mineru_section_packer.py +334 -0
- src/agents/survey_agent/utils/mineru_utils.py +396 -0
- src/agents/survey_agent/utils/paper.py +144 -0
- src/agents/survey_agent/utils/read_yaml.py +15 -0
- src/agents/survey_agent/utils/repo_utils.py +167 -0
- src/agents/survey_agent/utils/rich_logger.py +77 -0
- src/agents/survey_agent/utils/step2v2.py +874 -0
- src/agents/survey_agent/utils/step2v2_extractor.py +856 -0
- src/agents/survey_agent/utils/topic_survey_storage.py +309 -0
- src/agents/survey_agent/utils/utils.py +118 -0
- src/agents/survey_agent/utils/work.py +2 -0
- src/cli.py +1611 -0
- src/config/__init__.py +213 -0
- src/config/default.yaml +1122 -0
- src/harness/LICENSE +21 -0
- src/harness/VENDORED.md +14 -0
- src/harness/src/__init__.py +0 -0
- src/harness/src/openharness/__init__.py +0 -0
- src/harness/src/openharness/__main__.py +6 -0
- src/harness/src/openharness/api/__init__.py +21 -0
- src/harness/src/openharness/api/client.py +281 -0
- src/harness/src/openharness/api/codex_client.py +407 -0
- src/harness/src/openharness/api/copilot_auth.py +240 -0
- src/harness/src/openharness/api/copilot_client.py +134 -0
- src/harness/src/openharness/api/errors.py +19 -0
- src/harness/src/openharness/api/openai_client.py +577 -0
- src/harness/src/openharness/api/provider.py +186 -0
- src/harness/src/openharness/api/registry.py +437 -0
- src/harness/src/openharness/api/usage.py +17 -0
- src/harness/src/openharness/auth/__init__.py +29 -0
- src/harness/src/openharness/auth/external.py +610 -0
- src/harness/src/openharness/auth/flows.py +189 -0
- src/harness/src/openharness/auth/manager.py +482 -0
- src/harness/src/openharness/auth/storage.py +269 -0
- src/harness/src/openharness/autopilot/__init__.py +23 -0
- src/harness/src/openharness/autopilot/service.py +2239 -0
- src/harness/src/openharness/autopilot/types.py +91 -0
- src/harness/src/openharness/bridge/__init__.py +20 -0
- src/harness/src/openharness/bridge/manager.py +106 -0
- src/harness/src/openharness/bridge/session_runner.py +46 -0
- src/harness/src/openharness/bridge/types.py +37 -0
- src/harness/src/openharness/bridge/work_secret.py +41 -0
- src/harness/src/openharness/channels/UPSTREAM +6 -0
- src/harness/src/openharness/channels/__init__.py +22 -0
- src/harness/src/openharness/channels/adapter.py +131 -0
- src/harness/src/openharness/channels/bus/__init__.py +6 -0
- src/harness/src/openharness/channels/bus/events.py +38 -0
- src/harness/src/openharness/channels/bus/queue.py +44 -0
- src/harness/src/openharness/channels/impl/__init__.py +6 -0
- src/harness/src/openharness/channels/impl/base.py +141 -0
- src/harness/src/openharness/channels/impl/dingtalk.py +445 -0
- src/harness/src/openharness/channels/impl/discord.py +311 -0
- src/harness/src/openharness/channels/impl/email.py +410 -0
- src/harness/src/openharness/channels/impl/feishu.py +1342 -0
- src/harness/src/openharness/channels/impl/manager.py +257 -0
- src/harness/src/openharness/channels/impl/matrix.py +700 -0
- src/harness/src/openharness/channels/impl/mochat.py +897 -0
- src/harness/src/openharness/channels/impl/qq.py +141 -0
- src/harness/src/openharness/channels/impl/slack.py +284 -0
- src/harness/src/openharness/channels/impl/telegram.py +525 -0
- src/harness/src/openharness/channels/impl/whatsapp.py +159 -0
- src/harness/src/openharness/cli.py +2551 -0
- src/harness/src/openharness/commands/__init__.py +21 -0
- src/harness/src/openharness/commands/registry.py +2783 -0
- src/harness/src/openharness/config/__init__.py +34 -0
- src/harness/src/openharness/config/paths.py +160 -0
- src/harness/src/openharness/config/schema.py +119 -0
- src/harness/src/openharness/config/settings.py +1104 -0
- src/harness/src/openharness/coordinator/__init__.py +12 -0
- src/harness/src/openharness/coordinator/agent_definitions.py +975 -0
- src/harness/src/openharness/coordinator/coordinator_mode.py +520 -0
- src/harness/src/openharness/engine/__init__.py +80 -0
- src/harness/src/openharness/engine/cost_tracker.py +24 -0
- src/harness/src/openharness/engine/messages.py +222 -0
- src/harness/src/openharness/engine/query.py +1188 -0
- src/harness/src/openharness/engine/query_engine.py +313 -0
- src/harness/src/openharness/engine/stream_events.py +90 -0
- src/harness/src/openharness/hooks/__init__.py +50 -0
- src/harness/src/openharness/hooks/events.py +20 -0
- src/harness/src/openharness/hooks/executor.py +242 -0
- src/harness/src/openharness/hooks/hot_reload.py +31 -0
- src/harness/src/openharness/hooks/loader.py +68 -0
- src/harness/src/openharness/hooks/schemas.py +66 -0
- src/harness/src/openharness/hooks/types.py +38 -0
- src/harness/src/openharness/keybindings/__init__.py +14 -0
- src/harness/src/openharness/keybindings/default_bindings.py +11 -0
- src/harness/src/openharness/keybindings/loader.py +22 -0
- src/harness/src/openharness/keybindings/parser.py +18 -0
- src/harness/src/openharness/keybindings/resolver.py +13 -0
- src/harness/src/openharness/mcp/__init__.py +79 -0
- src/harness/src/openharness/mcp/client.py +298 -0
- src/harness/src/openharness/mcp/config.py +16 -0
- src/harness/src/openharness/mcp/types.py +76 -0
- src/harness/src/openharness/memory/__init__.py +25 -0
- src/harness/src/openharness/memory/agent.py +91 -0
- src/harness/src/openharness/memory/manager.py +183 -0
- src/harness/src/openharness/memory/memdir.py +52 -0
- src/harness/src/openharness/memory/migrate.py +137 -0
- src/harness/src/openharness/memory/paths.py +22 -0
- src/harness/src/openharness/memory/relevance.py +145 -0
- src/harness/src/openharness/memory/scan.py +116 -0
- src/harness/src/openharness/memory/schema.py +443 -0
- src/harness/src/openharness/memory/search.py +71 -0
- src/harness/src/openharness/memory/team.py +90 -0
- src/harness/src/openharness/memory/types.py +33 -0
- src/harness/src/openharness/memory/usage.py +153 -0
- src/harness/src/openharness/output_styles/__init__.py +5 -0
- src/harness/src/openharness/output_styles/loader.py +42 -0
- src/harness/src/openharness/permissions/__init__.py +26 -0
- src/harness/src/openharness/permissions/checker.py +200 -0
- src/harness/src/openharness/permissions/modes.py +13 -0
- src/harness/src/openharness/personalization/__init__.py +6 -0
- src/harness/src/openharness/personalization/extractor.py +138 -0
- src/harness/src/openharness/personalization/rules.py +64 -0
- src/harness/src/openharness/personalization/session_hook.py +65 -0
- src/harness/src/openharness/platforms.py +86 -0
- src/harness/src/openharness/plugins/__init__.py +53 -0
- src/harness/src/openharness/plugins/bundled/__init__.py +0 -0
- src/harness/src/openharness/plugins/installer.py +39 -0
- src/harness/src/openharness/plugins/loader.py +730 -0
- src/harness/src/openharness/plugins/schemas.py +24 -0
- src/harness/src/openharness/plugins/types.py +59 -0
- src/harness/src/openharness/prompts/__init__.py +14 -0
- src/harness/src/openharness/prompts/claudemd.py +48 -0
- src/harness/src/openharness/prompts/context.py +187 -0
- src/harness/src/openharness/prompts/environment.py +135 -0
- src/harness/src/openharness/prompts/system_prompt.py +109 -0
- src/harness/src/openharness/sandbox/Dockerfile +6 -0
- src/harness/src/openharness/sandbox/__init__.py +33 -0
- src/harness/src/openharness/sandbox/adapter.py +148 -0
- src/harness/src/openharness/sandbox/docker_backend.py +232 -0
- src/harness/src/openharness/sandbox/docker_image.py +103 -0
- src/harness/src/openharness/sandbox/path_validator.py +37 -0
- src/harness/src/openharness/sandbox/session.py +63 -0
- src/harness/src/openharness/services/__init__.py +30 -0
- src/harness/src/openharness/services/autodream/__init__.py +34 -0
- src/harness/src/openharness/services/autodream/backup.py +104 -0
- src/harness/src/openharness/services/autodream/lock.py +138 -0
- src/harness/src/openharness/services/autodream/prompt.py +128 -0
- src/harness/src/openharness/services/autodream/service.py +313 -0
- src/harness/src/openharness/services/compact/__init__.py +1725 -0
- src/harness/src/openharness/services/cron.py +137 -0
- src/harness/src/openharness/services/cron_scheduler.py +595 -0
- src/harness/src/openharness/services/lsp/__init__.py +216 -0
- src/harness/src/openharness/services/memory_extract/__init__.py +261 -0
- src/harness/src/openharness/services/oauth/__init__.py +0 -0
- src/harness/src/openharness/services/session_backend.py +97 -0
- src/harness/src/openharness/services/session_memory/__init__.py +139 -0
- src/harness/src/openharness/services/session_storage.py +230 -0
- src/harness/src/openharness/services/token_estimation.py +15 -0
- src/harness/src/openharness/services/tool_outputs.py +55 -0
- src/harness/src/openharness/skills/__init__.py +44 -0
- src/harness/src/openharness/skills/_frontmatter.py +97 -0
- src/harness/src/openharness/skills/bundled/__init__.py +75 -0
- src/harness/src/openharness/skills/bundled/content/commit.md +25 -0
- src/harness/src/openharness/skills/bundled/content/debug.md +25 -0
- src/harness/src/openharness/skills/bundled/content/diagnose.md +35 -0
- src/harness/src/openharness/skills/bundled/content/plan.md +39 -0
- src/harness/src/openharness/skills/bundled/content/review.md +33 -0
- src/harness/src/openharness/skills/bundled/content/simplify.md +26 -0
- src/harness/src/openharness/skills/bundled/content/skill-creator.md +175 -0
- src/harness/src/openharness/skills/bundled/content/test.md +38 -0
- src/harness/src/openharness/skills/loader.py +229 -0
- src/harness/src/openharness/skills/registry.py +29 -0
- src/harness/src/openharness/skills/types.py +24 -0
- src/harness/src/openharness/state/__init__.py +6 -0
- src/harness/src/openharness/state/app_state.py +30 -0
- src/harness/src/openharness/state/store.py +40 -0
- src/harness/src/openharness/swarm/__init__.py +70 -0
- src/harness/src/openharness/swarm/in_process.py +693 -0
- src/harness/src/openharness/swarm/lockfile.py +24 -0
- src/harness/src/openharness/swarm/mailbox.py +522 -0
- src/harness/src/openharness/swarm/permission_sync.py +1168 -0
- src/harness/src/openharness/swarm/registry.py +410 -0
- src/harness/src/openharness/swarm/spawn_utils.py +229 -0
- src/harness/src/openharness/swarm/subprocess_backend.py +171 -0
- src/harness/src/openharness/swarm/team_lifecycle.py +910 -0
- src/harness/src/openharness/swarm/types.py +398 -0
- src/harness/src/openharness/swarm/worktree.py +315 -0
- src/harness/src/openharness/tasks/__init__.py +18 -0
- src/harness/src/openharness/tasks/local_agent_task.py +28 -0
- src/harness/src/openharness/tasks/local_shell_task.py +17 -0
- src/harness/src/openharness/tasks/manager.py +475 -0
- src/harness/src/openharness/tasks/stop_task.py +11 -0
- src/harness/src/openharness/tasks/types.py +32 -0
- src/harness/src/openharness/themes/__init__.py +21 -0
- src/harness/src/openharness/themes/builtin.py +89 -0
- src/harness/src/openharness/themes/loader.py +55 -0
- src/harness/src/openharness/themes/schema.py +54 -0
- src/harness/src/openharness/tools/__init__.py +107 -0
- src/harness/src/openharness/tools/agent_tool.py +141 -0
- src/harness/src/openharness/tools/ask_user_question_tool.py +46 -0
- src/harness/src/openharness/tools/base.py +80 -0
- src/harness/src/openharness/tools/bash_tool.py +259 -0
- src/harness/src/openharness/tools/brief_tool.py +33 -0
- src/harness/src/openharness/tools/config_tool.py +54 -0
- src/harness/src/openharness/tools/cron_create_tool.py +105 -0
- src/harness/src/openharness/tools/cron_delete_tool.py +32 -0
- src/harness/src/openharness/tools/cron_list_tool.py +69 -0
- src/harness/src/openharness/tools/cron_toggle_tool.py +37 -0
- src/harness/src/openharness/tools/enter_plan_mode_tool.py +28 -0
- src/harness/src/openharness/tools/enter_worktree_tool.py +80 -0
- src/harness/src/openharness/tools/exit_plan_mode_tool.py +28 -0
- src/harness/src/openharness/tools/exit_worktree_tool.py +42 -0
- src/harness/src/openharness/tools/file_edit_tool.py +95 -0
- src/harness/src/openharness/tools/file_read_tool.py +72 -0
- src/harness/src/openharness/tools/file_write_tool.py +87 -0
- src/harness/src/openharness/tools/glob_tool.py +175 -0
- src/harness/src/openharness/tools/grep_tool.py +374 -0
- src/harness/src/openharness/tools/image_generation_tool.py +447 -0
- src/harness/src/openharness/tools/image_to_text_tool.py +237 -0
- src/harness/src/openharness/tools/list_mcp_resources_tool.py +36 -0
- src/harness/src/openharness/tools/lsp_tool.py +154 -0
- src/harness/src/openharness/tools/mcp_auth_tool.py +71 -0
- src/harness/src/openharness/tools/mcp_tool.py +72 -0
- src/harness/src/openharness/tools/notebook_edit_tool.py +97 -0
- src/harness/src/openharness/tools/read_mcp_resource_tool.py +38 -0
- src/harness/src/openharness/tools/remote_trigger_tool.py +74 -0
- src/harness/src/openharness/tools/send_message_tool.py +58 -0
- src/harness/src/openharness/tools/skill_tool.py +43 -0
- src/harness/src/openharness/tools/sleep_tool.py +32 -0
- src/harness/src/openharness/tools/task_create_tool.py +56 -0
- src/harness/src/openharness/tools/task_get_tool.py +33 -0
- src/harness/src/openharness/tools/task_list_tool.py +35 -0
- src/harness/src/openharness/tools/task_output_tool.py +35 -0
- src/harness/src/openharness/tools/task_stop_tool.py +30 -0
- src/harness/src/openharness/tools/task_update_tool.py +50 -0
- src/harness/src/openharness/tools/team_create_tool.py +31 -0
- src/harness/src/openharness/tools/team_delete_tool.py +30 -0
- src/harness/src/openharness/tools/todo_write_tool.py +46 -0
- src/harness/src/openharness/tools/tool_search_tool.py +38 -0
- src/harness/src/openharness/tools/web_fetch_tool.py +117 -0
- src/harness/src/openharness/tools/web_search_tool.py +119 -0
- src/harness/src/openharness/ui/__init__.py +5 -0
- src/harness/src/openharness/ui/app.py +320 -0
- src/harness/src/openharness/ui/backend_host.py +941 -0
- src/harness/src/openharness/ui/coordinator_drain.py +198 -0
- src/harness/src/openharness/ui/input.py +32 -0
- src/harness/src/openharness/ui/output.py +265 -0
- src/harness/src/openharness/ui/permission_dialog.py +14 -0
- src/harness/src/openharness/ui/protocol.py +247 -0
- src/harness/src/openharness/ui/react_launcher.py +179 -0
- src/harness/src/openharness/ui/runtime.py +799 -0
- src/harness/src/openharness/ui/textual_app.py +495 -0
- src/harness/src/openharness/utils/__init__.py +0 -0
- src/harness/src/openharness/utils/file_lock.py +86 -0
- src/harness/src/openharness/utils/fs.py +98 -0
- src/harness/src/openharness/utils/helpers.py +77 -0
- src/harness/src/openharness/utils/network_guard.py +340 -0
- src/harness/src/openharness/utils/shell.py +147 -0
- src/harness/src/openharness/vim/__init__.py +5 -0
- src/harness/src/openharness/vim/transitions.py +8 -0
- src/harness/src/openharness/voice/__init__.py +7 -0
- src/harness/src/openharness/voice/keyterms.py +10 -0
- src/harness/src/openharness/voice/stream_stt.py +8 -0
- src/harness/src/openharness/voice/voice_mode.py +44 -0
- src/llm/__init__.py +29 -0
- src/llm/image_generation.py +402 -0
- src/llm/provider_registry.py +419 -0
- src/llm/runtime_env.py +64 -0
- src/llm/structured_output.py +131 -0
- src/llm/vision.py +198 -0
- src/memory/__init__.py +2 -0
- src/memory/api/__init__.py +1 -0
- src/memory/api/base_memory_system_api.py +98 -0
- src/memory/api/base_symbolic_memory_system_api.py +190 -0
- src/memory/api/base_vector_memory_system_api.py +116 -0
- src/memory/api/faiss_memory_system_api.py +228 -0
- src/memory/api/slot_process_api.py +827 -0
- src/memory/api/symbolic_memory_system_api.py +572 -0
- src/memory/memory_system/__init__.py +48 -0
- src/memory/memory_system/component_taxonomy.py +430 -0
- src/memory/memory_system/llm.py +437 -0
- src/memory/memory_system/models.py +168 -0
- src/memory/memory_system/user_prompt.py +418 -0
- src/memory/memory_system/utils.py +282 -0
- src/memory/memory_system/vectorstore.py +311 -0
- src/memory/memory_system/working_slot.py +99 -0
- src/pipeline/__init__.py +129 -0
- src/pipeline/contracts.py +531 -0
- src/pipeline/discipline_taxonomy.py +916 -0
- src/pipeline/evidence_coverage_ledger.py +1150 -0
- src/pipeline/evidence_refinement.py +620 -0
- src/pipeline/experiment_to_symbolic.py +137 -0
- src/pipeline/multimodal_evidence/__init__.py +28 -0
- src/pipeline/multimodal_evidence/capabilities.py +107 -0
- src/pipeline/multimodal_evidence/claims.py +135 -0
- src/pipeline/multimodal_evidence/contract.py +291 -0
- src/pipeline/multimodal_evidence/data_sh_compiler.py +505 -0
- src/pipeline/multimodal_evidence/handoff_binding.py +135 -0
- src/pipeline/multimodal_evidence/manifest.py +254 -0
- src/pipeline/multimodal_evidence/native_analysis.py +479 -0
- src/pipeline/multimodal_evidence/perception.py +277 -0
- src/pipeline/multimodal_evidence/query_binding.py +65 -0
- src/pipeline/multimodal_evidence/rendering.py +120 -0
- src/pipeline/multimodal_evidence/safety.py +42 -0
- src/pipeline/multimodal_evidence/sampling.py +69 -0
- src/pipeline/multimodal_evidence/service.py +148 -0
- src/pipeline/multimodal_evidence/survey_integration.py +460 -0
- src/pipeline/paper_identity.py +52 -0
- src/pipeline/research_design_inventory.py +338 -0
- src/pipeline/research_domain_resolution.py +669 -0
- src/pipeline/research_identity.py +548 -0
- src/pipeline/research_question_contract.py +646 -0
- src/pipeline/retrieval_lanes.py +889 -0
- src/pipeline/run_loop.py +862 -0
- src/pipeline/science_events.py +30 -0
- src/pipeline/science_manifests.py +602 -0
- src/pipeline/science_run.py +918 -0
- src/pipeline/science_stages.py +709 -0
- src/pipeline/science_workflow.py +807 -0
- src/pipeline/sh_cluster_projection.py +306 -0
- src/pipeline/sh_graph_provenance.py +648 -0
- src/pipeline/subhypothesis_decomposition.py +392 -0
- src/pipeline/subhypothesis_evidence.py +856 -0
- src/pipeline/survey_evidence_plan.py +858 -0
- src/pipeline/survey_gap_adjudication.py +647 -0
- src/pipeline/survey_gap_candidates.py +840 -0
- src/pipeline/survey_gap_ledger.py +683 -0
- src/pipeline/survey_gap_triage.py +401 -0
- src/pipeline/survey_handoff_persistence.py +481 -0
- src/pipeline/survey_handoff_projection.py +457 -0
- src/pipeline/survey_idea_handoff.py +1112 -0
- src/pipeline/survey_idea_loader.py +289 -0
- 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)
|