@elizaos/sweagent-root 2.0.0-alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +270 -0
- package/package.json +71 -0
- package/python/LICENSE +21 -0
- package/python/config/README.md +15 -0
- package/python/config/bash_only.yaml +222 -0
- package/python/config/benchmarks/250212_sweagent_heavy_sbl.yaml +188 -0
- package/python/config/benchmarks/250225_anthropic_filemap_simple_review.yaml +75 -0
- package/python/config/benchmarks/250522_anthropic_filemap_simple_review.yaml +92 -0
- package/python/config/benchmarks/250526_anthropic_filemap_simple_review_sbl.yaml +93 -0
- package/python/config/benchmarks/anthropic_filemap_multilingual.yaml +66 -0
- package/python/config/coding_challenge.yaml +104 -0
- package/python/config/default.yaml +69 -0
- package/python/config/default_backticks.yaml +69 -0
- package/python/config/default_mm_no_images.yaml +82 -0
- package/python/config/default_mm_with_images.yaml +83 -0
- package/python/config/demo/default.yaml +80 -0
- package/python/config/demo/no_instructions.yaml +69 -0
- package/python/config/demo/only_bash.yaml +60 -0
- package/python/config/exotic/default_shell.yaml +52 -0
- package/python/config/exotic/windowed_replace.yaml +125 -0
- package/python/config/exotic/windowed_replace_late_repro.yaml +127 -0
- package/python/config/human/human.yaml +24 -0
- package/python/config/human/human_demo.yaml +52 -0
- package/python/config/sweagent_0_7/07.yaml +101 -0
- package/python/config/sweagent_0_7/07_fcalling.yaml +100 -0
- package/python/config/sweagent_0_7/07_from_url.yaml +114 -0
- package/python/config/sweagent_0_7/07_thought_action.yaml +102 -0
- package/python/config/sweagent_0_7/07_thought_action_xml.yaml +96 -0
- package/python/mlc_config.json +44 -0
- package/python/pyproject.toml +262 -0
- package/python/sweagent/__init__.py +114 -0
- package/python/sweagent/__main__.py +4 -0
- package/python/sweagent/agent/__init__.py +0 -0
- package/python/sweagent/agent/action_sampler.py +317 -0
- package/python/sweagent/agent/agents.py +1294 -0
- package/python/sweagent/agent/extra/shell_agent.py +106 -0
- package/python/sweagent/agent/history_processors.py +399 -0
- package/python/sweagent/agent/hooks/__init__.py +0 -0
- package/python/sweagent/agent/hooks/abstract.py +139 -0
- package/python/sweagent/agent/hooks/status.py +34 -0
- package/python/sweagent/agent/models.py +896 -0
- package/python/sweagent/agent/problem_statement.py +312 -0
- package/python/sweagent/agent/reviewer.py +664 -0
- package/python/sweagent/environment/__init__.py +0 -0
- package/python/sweagent/environment/hooks/__init__.py +0 -0
- package/python/sweagent/environment/hooks/abstract.py +60 -0
- package/python/sweagent/environment/hooks/status.py +28 -0
- package/python/sweagent/environment/repo.py +219 -0
- package/python/sweagent/environment/swe_env.py +276 -0
- package/python/sweagent/exceptions.py +54 -0
- package/python/sweagent/inspector/README.md +6 -0
- package/python/sweagent/inspector/__init__.py +0 -0
- package/python/sweagent/inspector/favicon.ico +0 -0
- package/python/sweagent/inspector/fileViewer.js +354 -0
- package/python/sweagent/inspector/icons/computer.png +0 -0
- package/python/sweagent/inspector/icons/edit_icon.svg +11 -0
- package/python/sweagent/inspector/icons/swe-agent-logo-50.png +0 -0
- package/python/sweagent/inspector/icons/swellama_blue.png +0 -0
- package/python/sweagent/inspector/icons/swellama_brown.png +0 -0
- package/python/sweagent/inspector/icons/swellama_grey.png +0 -0
- package/python/sweagent/inspector/icons/swellama_tan.png +0 -0
- package/python/sweagent/inspector/index.html +25 -0
- package/python/sweagent/inspector/server.py +354 -0
- package/python/sweagent/inspector/static.py +169 -0
- package/python/sweagent/inspector/style.css +454 -0
- package/python/sweagent/run/__init__.py +0 -0
- package/python/sweagent/run/_progress.py +158 -0
- package/python/sweagent/run/batch_instances.py +419 -0
- package/python/sweagent/run/common.py +387 -0
- package/python/sweagent/run/compare_runs.py +123 -0
- package/python/sweagent/run/extract_pred.py +19 -0
- package/python/sweagent/run/hooks/__init__.py +0 -0
- package/python/sweagent/run/hooks/abstract.py +67 -0
- package/python/sweagent/run/hooks/apply_patch.py +106 -0
- package/python/sweagent/run/hooks/open_pr.py +244 -0
- package/python/sweagent/run/hooks/swe_bench_evaluate.py +113 -0
- package/python/sweagent/run/inspector_cli.py +493 -0
- package/python/sweagent/run/merge_predictions.py +64 -0
- package/python/sweagent/run/quick_stats.py +96 -0
- package/python/sweagent/run/remove_unfinished.py +63 -0
- package/python/sweagent/run/rich_test.py +91 -0
- package/python/sweagent/run/run.py +147 -0
- package/python/sweagent/run/run_batch.py +442 -0
- package/python/sweagent/run/run_replay.py +219 -0
- package/python/sweagent/run/run_shell.py +155 -0
- package/python/sweagent/run/run_single.py +225 -0
- package/python/sweagent/run/run_traj_to_demo.py +85 -0
- package/python/sweagent/tools/__init__.py +0 -0
- package/python/sweagent/tools/bundle.py +57 -0
- package/python/sweagent/tools/commands.py +220 -0
- package/python/sweagent/tools/parsing.py +619 -0
- package/python/sweagent/tools/tools.py +430 -0
- package/python/sweagent/tools/utils.py +108 -0
- package/python/sweagent/types.py +102 -0
- package/python/sweagent/utils/__init__.py +0 -0
- package/python/sweagent/utils/config.py +80 -0
- package/python/sweagent/utils/files.py +27 -0
- package/python/sweagent/utils/github.py +118 -0
- package/python/sweagent/utils/jinja_warnings.py +14 -0
- package/python/sweagent/utils/log.py +175 -0
- package/python/sweagent/utils/patch_formatter.py +152 -0
- package/python/sweagent/utils/serialization.py +45 -0
- package/python/tests/__init__.py +0 -0
- package/python/tests/conftest.py +191 -0
- package/python/tests/test_agent.py +258 -0
- package/python/tests/test_batch_instance.py +43 -0
- package/python/tests/test_commands/_interactive_dummy.py +35 -0
- package/python/tests/test_commands/interactive_dummy_wrapper.sh +29 -0
- package/python/tests/test_data/config_files/dummy_interactive.yaml +62 -0
- package/python/tests/test_data/data_sources/ctf/crypto/Katy/Dockerfile +20 -0
- package/python/tests/test_data/data_sources/ctf/crypto/Katy/README.md +13 -0
- package/python/tests/test_data/data_sources/ctf/crypto/Katy/challenge.json +12 -0
- package/python/tests/test_data/data_sources/ctf/crypto/Katy/customrandom.c +50 -0
- package/python/tests/test_data/data_sources/ctf/crypto/Katy/docker-compose.yml +14 -0
- package/python/tests/test_data/data_sources/ctf/crypto/Katy/release +0 -0
- package/python/tests/test_data/data_sources/ctf/crypto/Katy/server +0 -0
- package/python/tests/test_data/data_sources/ctf/crypto/Katy/solver.py +12 -0
- package/python/tests/test_data/data_sources/ctf/forensics/flash/README.md +16 -0
- package/python/tests/test_data/data_sources/ctf/forensics/flash/challenge.json +9 -0
- package/python/tests/test_data/data_sources/ctf/forensics/flash/flash_c8429a430278283c0e571baebca3d139.zip +0 -0
- package/python/tests/test_data/data_sources/ctf/misc/networking_1/README.md +15 -0
- package/python/tests/test_data/data_sources/ctf/misc/networking_1/challenge.json +10 -0
- package/python/tests/test_data/data_sources/ctf/misc/networking_1/networking.pcap +0 -0
- package/python/tests/test_data/data_sources/ctf/pwn/warmup/Dockerfile +28 -0
- package/python/tests/test_data/data_sources/ctf/pwn/warmup/README.md +14 -0
- package/python/tests/test_data/data_sources/ctf/pwn/warmup/challenge.json +14 -0
- package/python/tests/test_data/data_sources/ctf/pwn/warmup/docker-compose.yml +14 -0
- package/python/tests/test_data/data_sources/ctf/pwn/warmup/flag.txt +1 -0
- package/python/tests/test_data/data_sources/ctf/pwn/warmup/warmup +0 -0
- package/python/tests/test_data/data_sources/ctf/pwn/warmup/warmup.c +26 -0
- package/python/tests/test_data/data_sources/ctf/pwn/warmup/warmup.py +9 -0
- package/python/tests/test_data/data_sources/ctf/rev/rock/README.md +14 -0
- package/python/tests/test_data/data_sources/ctf/rev/rock/challenge.json +8 -0
- package/python/tests/test_data/data_sources/ctf/rev/rock/rock +0 -0
- package/python/tests/test_data/data_sources/ctf/rev/rock/rock.cpp +167 -0
- package/python/tests/test_data/data_sources/ctf/rev/rock/solution.cpp +24 -0
- package/python/tests/test_data/data_sources/ctf/rev/rock/test_solver/solution.py +6 -0
- package/python/tests/test_data/data_sources/ctf/rev/rock/test_solver/test.sh +10 -0
- package/python/tests/test_data/data_sources/ctf/web/i_got_id_demo/000-default.conf +18 -0
- package/python/tests/test_data/data_sources/ctf/web/i_got_id_demo/Dockerfile +20 -0
- package/python/tests/test_data/data_sources/ctf/web/i_got_id_demo/cgi/file.pl +38 -0
- package/python/tests/test_data/data_sources/ctf/web/i_got_id_demo/cgi/forms.pl +40 -0
- package/python/tests/test_data/data_sources/ctf/web/i_got_id_demo/cgi/hello.pl +11 -0
- package/python/tests/test_data/data_sources/ctf/web/i_got_id_demo/challenge.json +12 -0
- package/python/tests/test_data/data_sources/ctf/web/i_got_id_demo/docker-compose.yml +14 -0
- package/python/tests/test_data/data_sources/ctf/web/i_got_id_demo/flag +1 -0
- package/python/tests/test_data/data_sources/ctf/web/i_got_id_demo/index.html +11 -0
- package/python/tests/test_data/data_sources/ctf/web/i_got_id_demo/solution.txt +1 -0
- package/python/tests/test_data/data_sources/debug_20240322.json +1 -0
- package/python/tests/test_data/data_sources/expert_instances.yaml +16 -0
- package/python/tests/test_data/data_sources/human_eval.json +1 -0
- package/python/tests/test_data/data_sources/simple_instances.yaml +3 -0
- package/python/tests/test_data/data_sources/simple_instances_long.yaml +30 -0
- package/python/tests/test_data/data_sources/swe-bench-dev-easy.json +1 -0
- package/python/tests/test_data/data_sources/swe-bench-dev-easy_first_only.json +1 -0
- package/python/tests/test_data/data_sources/swe-bench-lite-test.json +1 -0
- package/python/tests/test_data/trajectories/gpt4__swe-agent-test-repo__default_from_url__t-0.00__p-0.95__c-3.00__install-1/6e44b9__sweagenttestrepo-1c2844.traj +342 -0
- package/python/tests/test_data/trajectories/gpt4__swe-agent-test-repo__default_from_url__t-0.00__p-0.95__c-3.00__install-1/solution_missing_colon.py +15 -0
- package/python/tests/test_data/trajectories/gpt4__swe-agent__test-repo__default_from_url__t-0.00__p-0.95__c-3.00__install-1/args.yaml +518 -0
- package/python/tests/test_data/trajectories/gpt4__swe-agent__test-repo__default_from_url__t-0.00__p-0.95__c-3.00__install-1/swe-agent__test-repo-i1.traj +124 -0
- package/python/tests/test_data/trajectories/gpt4__swe-bench-dev-easy_first_only__default__t-0.00__p-0.95__c-3.00__install-1/all_preds.jsonl +1 -0
- package/python/tests/test_data/trajectories/gpt4__swe-bench-dev-easy_first_only__default__t-0.00__p-0.95__c-3.00__install-1/args.yaml +520 -0
- package/python/tests/test_data/trajectories/gpt4__swe-bench-dev-easy_first_only__default__t-0.00__p-0.95__c-3.00__install-1/patches/pydicom__pydicom-1458.patch +18 -0
- package/python/tests/test_data/trajectories/gpt4__swe-bench-dev-easy_first_only__default__t-0.00__p-0.95__c-3.00__install-1/pydicom__pydicom-1458.traj +257 -0
- package/python/tests/test_env.py +66 -0
- package/python/tests/test_env_utils.py +129 -0
- package/python/tests/test_history_processors.py +40 -0
- package/python/tests/test_models.py +23 -0
- package/python/tests/test_openai_live.py +164 -0
- package/python/tests/test_packaging.py +7 -0
- package/python/tests/test_parsing.py +131 -0
- package/python/tests/test_problem_statement_multimodal.py +111 -0
- package/python/tests/test_quick_stats.py +42 -0
- package/python/tests/test_run.py +37 -0
- package/python/tests/test_run_batch.py +110 -0
- package/python/tests/test_run_hooks.py +114 -0
- package/python/tests/test_run_replay.py +33 -0
- package/python/tests/test_run_single.py +125 -0
- package/python/tests/test_tools_command_parsing.py +193 -0
- package/python/tests/test_utils.py +15 -0
- package/python/tests/tools/__init__.py +0 -0
- package/python/tests/tools/conftest.py +12 -0
- package/python/tests/tools/test_default_utils.py +153 -0
- package/python/tests/tools/test_edit_replace.py +0 -0
- package/python/tests/tools/test_split_string.py +82 -0
- package/python/tests/utils.py +29 -0
- package/python/tools/diff_state/bin/_state_diff_state +52 -0
- package/python/tools/diff_state/config.yaml +2 -0
- package/python/tools/edit_anthropic/bin/_state_anthropic +21 -0
- package/python/tools/edit_anthropic/bin/str_replace_editor +710 -0
- package/python/tools/edit_anthropic/config.yaml +56 -0
- package/python/tools/edit_anthropic/install.sh +3 -0
- package/python/tools/filemap/bin/filemap +45 -0
- package/python/tools/filemap/config.yaml +9 -0
- package/python/tools/filemap/install.sh +2 -0
- package/python/tools/forfeit/bin/exit_forfeit +5 -0
- package/python/tools/forfeit/config.yaml +5 -0
- package/python/tools/image_tools/bin/view_image +36 -0
- package/python/tools/image_tools/config.yaml +9 -0
- package/python/tools/multilingual_setup/bin/do_nothing +2 -0
- package/python/tools/multilingual_setup/config.yaml +1 -0
- package/python/tools/multilingual_setup/install.sh +45 -0
- package/python/tools/registry/bin/_read_env +10 -0
- package/python/tools/registry/bin/_write_env +10 -0
- package/python/tools/registry/config.yaml +1 -0
- package/python/tools/registry/install.sh +6 -0
- package/python/tools/registry/lib/__init__.py +0 -0
- package/python/tools/registry/lib/registry.py +56 -0
- package/python/tools/review_on_submit_m/README.md +6 -0
- package/python/tools/review_on_submit_m/bin/submit +54 -0
- package/python/tools/review_on_submit_m/config.yaml +6 -0
- package/python/tools/review_on_submit_m/install.sh +0 -0
- package/python/tools/search/bin/find_file +31 -0
- package/python/tools/search/bin/search_dir +39 -0
- package/python/tools/search/bin/search_file +55 -0
- package/python/tools/search/config.yaml +37 -0
- package/python/tools/search/install.sh +3 -0
- package/python/tools/submit/bin/submit +17 -0
- package/python/tools/submit/config.yaml +5 -0
- package/python/tools/web_browser/bin/click_mouse +41 -0
- package/python/tools/web_browser/bin/close_site +28 -0
- package/python/tools/web_browser/bin/double_click_mouse +37 -0
- package/python/tools/web_browser/bin/drag_mouse +46 -0
- package/python/tools/web_browser/bin/execute_script_on_page +39 -0
- package/python/tools/web_browser/bin/get_console_output +48 -0
- package/python/tools/web_browser/bin/move_mouse +35 -0
- package/python/tools/web_browser/bin/navigate_back +33 -0
- package/python/tools/web_browser/bin/navigate_forward +33 -0
- package/python/tools/web_browser/bin/open_site +36 -0
- package/python/tools/web_browser/bin/press_keys_on_page +51 -0
- package/python/tools/web_browser/bin/reload_page +33 -0
- package/python/tools/web_browser/bin/run_web_browser_server +394 -0
- package/python/tools/web_browser/bin/screenshot_site +38 -0
- package/python/tools/web_browser/bin/scroll_on_page +40 -0
- package/python/tools/web_browser/bin/set_browser_window_size +40 -0
- package/python/tools/web_browser/bin/type_text +34 -0
- package/python/tools/web_browser/bin/wait_time +39 -0
- package/python/tools/web_browser/config.yaml +155 -0
- package/python/tools/web_browser/install.sh +22 -0
- package/python/tools/web_browser/lib/browser_manager.py +404 -0
- package/python/tools/web_browser/lib/web_browser_config.py +33 -0
- package/python/tools/web_browser/lib/web_browser_utils.py +126 -0
- package/python/tools/web_browser/test_console.html +1 -0
- package/python/tools/windowed/bin/_state +25 -0
- package/python/tools/windowed/bin/create +29 -0
- package/python/tools/windowed/bin/goto +37 -0
- package/python/tools/windowed/bin/open +49 -0
- package/python/tools/windowed/bin/scroll_down +12 -0
- package/python/tools/windowed/bin/scroll_up +13 -0
- package/python/tools/windowed/config.yaml +38 -0
- package/python/tools/windowed/install.sh +15 -0
- package/python/tools/windowed/lib/__init__.py +0 -0
- package/python/tools/windowed/lib/flake8_utils.py +147 -0
- package/python/tools/windowed/lib/windowed_file.py +312 -0
- package/python/tools/windowed_edit_linting/bin/edit +128 -0
- package/python/tools/windowed_edit_linting/config.yaml +31 -0
- package/python/tools/windowed_edit_linting/install.sh +5 -0
- package/python/tools/windowed_edit_replace/bin/edit +172 -0
- package/python/tools/windowed_edit_replace/bin/insert +77 -0
- package/python/tools/windowed_edit_replace/config.yaml +60 -0
- package/python/tools/windowed_edit_replace/install.sh +5 -0
- package/python/tools/windowed_edit_rewrite/bin/edit +78 -0
- package/python/tools/windowed_edit_rewrite/config.yaml +11 -0
- package/python/tools/windowed_edit_rewrite/install.sh +5 -0
- package/python/trajectories/demonstrations/ctf/crypto/BabyEncryption.traj +318 -0
- package/python/trajectories/demonstrations/ctf/crypto/BabyTimeCapsule.traj +197 -0
- package/python/trajectories/demonstrations/ctf/crypto/eps.traj +289 -0
- package/python/trajectories/demonstrations/ctf/crypto/katy.traj +368 -0
- package/python/trajectories/demonstrations/ctf/forensics/flash.traj +102 -0
- package/python/trajectories/demonstrations/ctf/misc/networking_1.traj +102 -0
- package/python/trajectories/demonstrations/ctf/pwn/warmup.traj +159 -0
- package/python/trajectories/demonstrations/ctf/rev/rock.traj +251 -0
- package/python/trajectories/demonstrations/ctf/web/i_got_id_demo.traj +422 -0
- package/python/trajectories/demonstrations/function_calling_simple.traj +151 -0
- package/python/trajectories/demonstrations/human_thought__swe-bench-HumanEvalFix-python__lcb__t-0.00__p-0.95__c-4.00__install-0/humanevalfix-python-0.traj +129 -0
- package/python/trajectories/demonstrations/replay__marshmallow-code__marshmallow-1867__default__t-0.20__p-0.95__c-2.00__install-1___install_from_source/marshmallow-code__marshmallow-1867.traj +318 -0
- package/python/trajectories/demonstrations/replay__marshmallow-code__marshmallow-1867__default_sys-env_cursors_window100__t-0.20__p-0.95__c-2.00__install-1/marshmallow-code__marshmallow-1867.traj +251 -0
- package/python/trajectories/demonstrations/replay__marshmallow-code__marshmallow-1867__default_sys-env_window100__t-0.20__p-0.95__c-2.00__install-1/marshmallow-code__marshmallow-1867.traj +399 -0
- package/python/trajectories/demonstrations/replay__marshmallow-code__marshmallow-1867__function_calling__install-1/marshmallow-code__marshmallow-1867.traj +594 -0
- package/python/trajectories/demonstrations/replay__marshmallow-code__marshmallow-1867__function_calling_replace__install-1/marshmallow-code__marshmallow-1867.traj +592 -0
- package/python/trajectories/demonstrations/replay__marshmallow-code__marshmallow-1867__function_calling_replace_from_source/marshmallow-code__marshmallow-1867.traj +3316 -0
- package/python/trajectories/demonstrations/replay__marshmallow-code__marshmallow-1867__xml_sys-env_cursors_window100__t-0.20__p-0.95__c-2.00__install-1/marshmallow-code__marshmallow-1867.traj +251 -0
- package/python/trajectories/demonstrations/replay__marshmallow-code__marshmallow-1867__xml_sys-env_window100__t-0.20__p-0.95__c-2.00__install-1/marshmallow-code__marshmallow-1867.traj +399 -0
- package/python/trajectories/demonstrations/str_replace_anthropic_demo.yaml +432 -0
- package/rust/Cargo.toml +100 -0
- package/rust/README.md +49 -0
- package/rust/src/agent/action_sampler.rs +130 -0
- package/rust/src/agent/agents.rs +1029 -0
- package/rust/src/agent/history_processors.rs +277 -0
- package/rust/src/agent/hooks/mod.rs +208 -0
- package/rust/src/agent/mod.rs +24 -0
- package/rust/src/agent/models.rs +837 -0
- package/rust/src/agent/problem_statement.rs +355 -0
- package/rust/src/agent/reviewer.rs +505 -0
- package/rust/src/bin/sweagent.rs +784 -0
- package/rust/src/environment/deployment.rs +631 -0
- package/rust/src/environment/hooks/mod.rs +114 -0
- package/rust/src/environment/mod.rs +16 -0
- package/rust/src/environment/repo.rs +265 -0
- package/rust/src/environment/runtime.rs +237 -0
- package/rust/src/environment/swe_env.rs +248 -0
- package/rust/src/exceptions.rs +228 -0
- package/rust/src/lib.rs +68 -0
- package/rust/src/monitoring.rs +482 -0
- package/rust/src/run/hooks/mod.rs +134 -0
- package/rust/src/run/mod.rs +12 -0
- package/rust/src/run/run_batch.rs +563 -0
- package/rust/src/run/run_single.rs +196 -0
- package/rust/src/tools/bundle.rs +224 -0
- package/rust/src/tools/commands.rs +173 -0
- package/rust/src/tools/mod.rs +295 -0
- package/rust/src/tools/parsing.rs +354 -0
- package/rust/src/tools/registry.rs +143 -0
- package/rust/src/types.rs +554 -0
- package/rust/src/utils/config.rs +105 -0
- package/rust/src/utils/files.rs +137 -0
- package/rust/src/utils/github.rs +171 -0
- package/rust/src/utils/log.rs +65 -0
- package/rust/src/utils/mod.rs +17 -0
- package/rust/src/utils/serialization.rs +181 -0
- package/rust/src/utils/template.rs +173 -0
- package/typescript/README.md +335 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"""[cyan][bold]Run SWE-agent in semi-interactive mode.[/bold][/cyan]
|
|
2
|
+
|
|
3
|
+
[cyan][bold]sweagen-sh is EXPERIMENTAL[/bold][/cyan]
|
|
4
|
+
|
|
5
|
+
[cyan][bold]=== BASIC OPTIONS ===[/bold][/cyan]
|
|
6
|
+
|
|
7
|
+
-h --help Show help text and exit
|
|
8
|
+
--help_option Print specific help text and exit
|
|
9
|
+
--config CONFIG Load additional config files. Use this option multiple times to load
|
|
10
|
+
multiple files, e.g., --config config1.yaml --config config2.yaml
|
|
11
|
+
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import argparse
|
|
15
|
+
import logging
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
|
|
18
|
+
import yaml
|
|
19
|
+
from rich.prompt import Prompt
|
|
20
|
+
from swerex.deployment.config import DockerDeploymentConfig
|
|
21
|
+
|
|
22
|
+
from sweagent import CONFIG_DIR
|
|
23
|
+
from sweagent.agent.agents import AbstractAgent, ShellAgentConfig
|
|
24
|
+
from sweagent.agent.extra.shell_agent import ShellAgent
|
|
25
|
+
from sweagent.agent.problem_statement import (
|
|
26
|
+
GithubIssue,
|
|
27
|
+
ProblemStatement,
|
|
28
|
+
ProblemStatementConfig,
|
|
29
|
+
TextProblemStatement,
|
|
30
|
+
)
|
|
31
|
+
from sweagent.environment.repo import PreExistingRepoConfig
|
|
32
|
+
from sweagent.environment.swe_env import EnvironmentConfig, SWEEnv
|
|
33
|
+
from sweagent.run.common import save_predictions
|
|
34
|
+
from sweagent.run.hooks.abstract import CombinedRunHooks, RunHook
|
|
35
|
+
from sweagent.utils.config import load_environment_variables
|
|
36
|
+
from sweagent.utils.github import _is_github_issue_url
|
|
37
|
+
from sweagent.utils.log import add_file_handler, get_logger, set_stream_handler_levels
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class RunShell:
|
|
41
|
+
def __init__(
|
|
42
|
+
self,
|
|
43
|
+
env: SWEEnv,
|
|
44
|
+
agent: AbstractAgent,
|
|
45
|
+
problem_statement: ProblemStatement | ProblemStatementConfig,
|
|
46
|
+
*,
|
|
47
|
+
output_dir: Path = Path("."),
|
|
48
|
+
hooks: list[RunHook] | None = None,
|
|
49
|
+
):
|
|
50
|
+
"""Note: When initializing this class, make sure to add the hooks that are required by your actions.
|
|
51
|
+
See `from_config` for an example.
|
|
52
|
+
"""
|
|
53
|
+
self.logger = get_logger("swea-run", emoji="🏃")
|
|
54
|
+
instance_id = problem_statement.id
|
|
55
|
+
_log_filename_template = f"{instance_id}.{{level}}.log"
|
|
56
|
+
for level in ["trace", "debug", "info"]:
|
|
57
|
+
add_file_handler(
|
|
58
|
+
output_dir / instance_id / _log_filename_template.format(level=level),
|
|
59
|
+
level=level,
|
|
60
|
+
id_=f"{instance_id}-{level}",
|
|
61
|
+
)
|
|
62
|
+
self.env = env
|
|
63
|
+
self.agent = agent
|
|
64
|
+
self.output_dir = output_dir
|
|
65
|
+
self._hooks = []
|
|
66
|
+
self._chooks = CombinedRunHooks()
|
|
67
|
+
self.problem_statement = problem_statement
|
|
68
|
+
for hook in hooks or []:
|
|
69
|
+
self.add_hook(hook)
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def hooks(self) -> list[RunHook]:
|
|
73
|
+
return self._chooks.hooks
|
|
74
|
+
|
|
75
|
+
def add_hook(self, hook: RunHook) -> None:
|
|
76
|
+
hook.on_init(run=self)
|
|
77
|
+
self._chooks.add_hook(hook)
|
|
78
|
+
|
|
79
|
+
def run(self):
|
|
80
|
+
self._chooks.on_start()
|
|
81
|
+
self.logger.info("Starting environment")
|
|
82
|
+
self.env.start()
|
|
83
|
+
self.logger.info("Running agent")
|
|
84
|
+
self._chooks.on_instance_start(index=0, env=self.env, problem_statement=self.problem_statement)
|
|
85
|
+
output_dir = self.output_dir / self.problem_statement.id
|
|
86
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
|
87
|
+
result = self.agent.run(
|
|
88
|
+
problem_statement=self.problem_statement,
|
|
89
|
+
env=self.env,
|
|
90
|
+
output_dir=output_dir,
|
|
91
|
+
)
|
|
92
|
+
self._chooks.on_instance_completed(result=result)
|
|
93
|
+
self.logger.info("Done")
|
|
94
|
+
self._chooks.on_end()
|
|
95
|
+
save_predictions(self.output_dir, self.problem_statement.id, result)
|
|
96
|
+
self.env.close()
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def get_cli():
|
|
100
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
101
|
+
parser.add_argument("-r", "--repo", type=Path, help="Path to the repository.", default=None)
|
|
102
|
+
# parser.add_argument(dest="--model", type=str, help="Model to use.", default="claude-sonnet-4-20250514")
|
|
103
|
+
parser.add_argument(
|
|
104
|
+
"--config",
|
|
105
|
+
type=Path,
|
|
106
|
+
help="Path to the agent config file.",
|
|
107
|
+
default=CONFIG_DIR / "exotic" / "default_shell.yaml",
|
|
108
|
+
)
|
|
109
|
+
parser.add_argument(
|
|
110
|
+
"-p",
|
|
111
|
+
type=str,
|
|
112
|
+
help="Problem statement.",
|
|
113
|
+
default="",
|
|
114
|
+
)
|
|
115
|
+
return parser
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def run_from_cli(args: list[str] | None = None):
|
|
119
|
+
set_stream_handler_levels(logging.INFO)
|
|
120
|
+
cli_args = get_cli().parse_args(args)
|
|
121
|
+
try:
|
|
122
|
+
load_environment_variables(Path(".env"))
|
|
123
|
+
except FileNotFoundError:
|
|
124
|
+
print("Env file .env not found, please set API key as env variables.")
|
|
125
|
+
env_config = EnvironmentConfig(
|
|
126
|
+
repo=PreExistingRepoConfig(repo_name="repo", reset=False),
|
|
127
|
+
deployment=DockerDeploymentConfig(
|
|
128
|
+
image="python:3.11",
|
|
129
|
+
docker_args=[
|
|
130
|
+
"-v",
|
|
131
|
+
f"{cli_args.repo}:/repo",
|
|
132
|
+
],
|
|
133
|
+
python_standalone_dir="/root",
|
|
134
|
+
),
|
|
135
|
+
)
|
|
136
|
+
agent_config = ShellAgentConfig.model_validate(yaml.safe_load(cli_args.config.read_text())["agent"])
|
|
137
|
+
agent = ShellAgent.from_config(agent_config)
|
|
138
|
+
env = SWEEnv.from_config(env_config)
|
|
139
|
+
if cli_args.repo is None:
|
|
140
|
+
cli_args.repo = Path(Prompt.ask("[cyan]Repository path[/cyan]", default="", show_default=False))
|
|
141
|
+
problem_input = cli_args.p
|
|
142
|
+
if not problem_input:
|
|
143
|
+
problem_input = Prompt.ask("[cyan]Problem statement or GitHub issue URL[/cyan]", default="", show_default=False)
|
|
144
|
+
if _is_github_issue_url(problem_input):
|
|
145
|
+
problem_statement = GithubIssue(github_url=problem_input)
|
|
146
|
+
else:
|
|
147
|
+
problem_statement = TextProblemStatement(
|
|
148
|
+
text=problem_input,
|
|
149
|
+
)
|
|
150
|
+
run_shell = RunShell(env, agent, problem_statement=problem_statement, output_dir=Path.home() / "sweagent_shell")
|
|
151
|
+
run_shell.run()
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
if __name__ == "__main__":
|
|
155
|
+
run_from_cli()
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
"""[cyan][bold]Run SWE-agent on a single instance taken from github or similar.[/bold][/cyan]
|
|
2
|
+
|
|
3
|
+
[cyan][bold]=== BASIC OPTIONS ===[/bold][/cyan]
|
|
4
|
+
|
|
5
|
+
-h --help Show help text and exit
|
|
6
|
+
--help_option Print specific help text and exit
|
|
7
|
+
--config CONFIG Load additional config files. Use this option multiple times to load
|
|
8
|
+
multiple files, e.g., --config config1.yaml --config config2.yaml
|
|
9
|
+
|
|
10
|
+
[cyan][bold]=== EXAMPLES ===[/bold][/cyan]
|
|
11
|
+
|
|
12
|
+
Basic usage: Run over a [bold][cyan]github issue[/bold][/cyan][green]:
|
|
13
|
+
|
|
14
|
+
sweagent run --config config/default.yaml --agent.model.name "gpt-4o" \\
|
|
15
|
+
--env.repo.github_url=https://github.com/SWE-agent/test-repo/ \\
|
|
16
|
+
--problem_statement.github_url=https://github.com/SWE-agent/test-repo/issues/1
|
|
17
|
+
[/green]
|
|
18
|
+
|
|
19
|
+
By default this will start a docker container and run the agent in there.
|
|
20
|
+
You can set the image with [green]--env.docker.image[/green].
|
|
21
|
+
|
|
22
|
+
Here's an example that uses [bold][cyan]modal[/bold][/cyan] instead of docker and also a [bold][cyan]local repository[/bold][/cyan]:
|
|
23
|
+
|
|
24
|
+
[green]sweagent run --config config/default.yaml --agent.model.name "gpt-4o" \\
|
|
25
|
+
--env.deployment.type=modal --env.repo.path /path/to/repo \\
|
|
26
|
+
--problem_statement.path=path/to/problem_statement.md
|
|
27
|
+
[/green]
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
import getpass
|
|
31
|
+
import sys
|
|
32
|
+
from pathlib import Path
|
|
33
|
+
from typing import Self
|
|
34
|
+
|
|
35
|
+
import yaml
|
|
36
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
37
|
+
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
38
|
+
|
|
39
|
+
from sweagent.agent.agents import AbstractAgent, AgentConfig, get_agent_from_config
|
|
40
|
+
from sweagent.agent.problem_statement import (
|
|
41
|
+
EmptyProblemStatement,
|
|
42
|
+
ProblemStatement,
|
|
43
|
+
ProblemStatementConfig,
|
|
44
|
+
)
|
|
45
|
+
from sweagent.environment.swe_env import EnvironmentConfig, SWEEnv
|
|
46
|
+
from sweagent.run.common import AutoCorrectSuggestion as ACS
|
|
47
|
+
from sweagent.run.common import BasicCLI, ConfigHelper, save_predictions
|
|
48
|
+
from sweagent.run.hooks.abstract import CombinedRunHooks, RunHook
|
|
49
|
+
from sweagent.run.hooks.apply_patch import SaveApplyPatchHook
|
|
50
|
+
from sweagent.run.hooks.open_pr import OpenPRConfig, OpenPRHook
|
|
51
|
+
from sweagent.utils.config import load_environment_variables
|
|
52
|
+
from sweagent.utils.log import add_file_handler, get_logger
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class RunSingleActionConfig(BaseModel):
|
|
56
|
+
"""Run real-life actions (opening PRs, etc.) if we can solve the issue."""
|
|
57
|
+
|
|
58
|
+
# Open a PR with the patch if we can solve the issue
|
|
59
|
+
open_pr: bool = False
|
|
60
|
+
pr_config: OpenPRConfig = Field(default_factory=OpenPRConfig)
|
|
61
|
+
# When working with local repository: Apply patch
|
|
62
|
+
apply_patch_locally: bool = False
|
|
63
|
+
|
|
64
|
+
# pydantic config
|
|
65
|
+
model_config = ConfigDict(extra="forbid")
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _get_default_output_dir(output_dir: Path, problem_statement: ProblemStatement, agent: AgentConfig) -> Path:
|
|
69
|
+
if output_dir == Path("DEFAULT"):
|
|
70
|
+
user_id = getpass.getuser()
|
|
71
|
+
problem_id = problem_statement.id
|
|
72
|
+
try:
|
|
73
|
+
model_id = agent.model.id # type: ignore[attr-defined]
|
|
74
|
+
except AttributeError:
|
|
75
|
+
model_id = "unknown_model"
|
|
76
|
+
config_file = getattr(agent, "_config_files", ["no_config"])[0]
|
|
77
|
+
if isinstance(config_file, Path):
|
|
78
|
+
config_file = config_file.stem
|
|
79
|
+
return Path.cwd() / "trajectories" / user_id / f"{config_file}__{model_id}___{problem_id}"
|
|
80
|
+
return output_dir
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class RunSingleConfig(BaseSettings, cli_implicit_flags=False):
|
|
84
|
+
env: EnvironmentConfig = Field(default_factory=EnvironmentConfig, description="Environment options.")
|
|
85
|
+
agent: AgentConfig = Field(description="Agent options.")
|
|
86
|
+
problem_statement: ProblemStatementConfig = Field(
|
|
87
|
+
default_factory=EmptyProblemStatement, description="Problem statement options."
|
|
88
|
+
)
|
|
89
|
+
output_dir: Path = Field(default=Path("DEFAULT"), description="Output directory.")
|
|
90
|
+
|
|
91
|
+
actions: RunSingleActionConfig = Field(default_factory=RunSingleActionConfig)
|
|
92
|
+
|
|
93
|
+
env_var_path: Path | None = None
|
|
94
|
+
"""Path to a .env file to load environment variables from."""
|
|
95
|
+
|
|
96
|
+
# pydantic config
|
|
97
|
+
model_config = SettingsConfigDict(extra="forbid", env_prefix="SWE_AGENT_")
|
|
98
|
+
|
|
99
|
+
def set_default_output_dir(self) -> None:
|
|
100
|
+
# Needs to be called explicitly, because self._config_files will be setup
|
|
101
|
+
# post-init.
|
|
102
|
+
self.output_dir = _get_default_output_dir(self.output_dir, self.problem_statement, self.agent)
|
|
103
|
+
|
|
104
|
+
@classmethod
|
|
105
|
+
def _get_auto_correct(cls) -> list[ACS]:
|
|
106
|
+
return [
|
|
107
|
+
ACS("model", "agent.model.name"),
|
|
108
|
+
ACS("agent.model", "agent.model.name"),
|
|
109
|
+
ACS("model.name", "agent.model.name"),
|
|
110
|
+
ACS("per_instance_cost_limit", "agent.model.per_instance_cost_limit"),
|
|
111
|
+
ACS("model.per_instance_cost_limit", "agent.model.per_instance_cost_limit"),
|
|
112
|
+
ACS("config_file", "config"),
|
|
113
|
+
ACS(
|
|
114
|
+
"data_path",
|
|
115
|
+
help="--data_path is no longer support for SWE-A 1.0. Please check the tutorial and use one of the --problem_statement options, e.g., --problem_statement.github_url or --problem_statement.path",
|
|
116
|
+
),
|
|
117
|
+
ACS(
|
|
118
|
+
"repo_path",
|
|
119
|
+
help="--repo_path is no longer support for SWE-A 1.0. Please check the tutorial and use one of the --env.repo options, e.g., --env.repo.github_url or --env.repo.path",
|
|
120
|
+
),
|
|
121
|
+
ACS("repo.path", "env.repo.path"),
|
|
122
|
+
]
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class RunSingle:
|
|
126
|
+
def __init__(
|
|
127
|
+
self,
|
|
128
|
+
env: SWEEnv,
|
|
129
|
+
agent: AbstractAgent,
|
|
130
|
+
problem_statement: ProblemStatement | ProblemStatementConfig,
|
|
131
|
+
*,
|
|
132
|
+
output_dir: Path = Path("."),
|
|
133
|
+
hooks: list[RunHook] | None = None,
|
|
134
|
+
actions: RunSingleActionConfig | None = None,
|
|
135
|
+
):
|
|
136
|
+
"""Note: When initializing this class, make sure to add the hooks that are required by your actions.
|
|
137
|
+
See `from_config` for an example.
|
|
138
|
+
"""
|
|
139
|
+
self.logger = get_logger("swea-run", emoji="🏃")
|
|
140
|
+
instance_id = problem_statement.id
|
|
141
|
+
_log_filename_template = f"{instance_id}.{{level}}.log"
|
|
142
|
+
for level in ["trace", "debug", "info"]:
|
|
143
|
+
add_file_handler(
|
|
144
|
+
output_dir / instance_id / _log_filename_template.format(level=level),
|
|
145
|
+
level=level,
|
|
146
|
+
id_=f"{instance_id}-{level}",
|
|
147
|
+
)
|
|
148
|
+
self.env = env
|
|
149
|
+
self.agent = agent
|
|
150
|
+
self.output_dir = output_dir
|
|
151
|
+
self._hooks = []
|
|
152
|
+
if actions is not None:
|
|
153
|
+
actions = RunSingleActionConfig()
|
|
154
|
+
self.actions = actions
|
|
155
|
+
self._chooks = CombinedRunHooks()
|
|
156
|
+
self.problem_statement = problem_statement
|
|
157
|
+
for hook in hooks or []:
|
|
158
|
+
self.add_hook(hook)
|
|
159
|
+
|
|
160
|
+
@property
|
|
161
|
+
def hooks(self) -> list[RunHook]:
|
|
162
|
+
return self._chooks.hooks
|
|
163
|
+
|
|
164
|
+
@classmethod
|
|
165
|
+
def from_config(cls, config: RunSingleConfig) -> Self:
|
|
166
|
+
load_environment_variables(config.env_var_path)
|
|
167
|
+
config.set_default_output_dir()
|
|
168
|
+
config.output_dir.mkdir(parents=True, exist_ok=True)
|
|
169
|
+
agent = get_agent_from_config(config.agent)
|
|
170
|
+
agent.replay_config = config # type: ignore[attr-defined]
|
|
171
|
+
self = cls(
|
|
172
|
+
env=SWEEnv.from_config(config.env),
|
|
173
|
+
agent=agent,
|
|
174
|
+
problem_statement=config.problem_statement,
|
|
175
|
+
output_dir=config.output_dir,
|
|
176
|
+
actions=config.actions,
|
|
177
|
+
)
|
|
178
|
+
self.add_hook(SaveApplyPatchHook(apply_patch_locally=config.actions.apply_patch_locally))
|
|
179
|
+
if config.actions.open_pr:
|
|
180
|
+
self.logger.debug("Adding OpenPRHook")
|
|
181
|
+
self.add_hook(OpenPRHook(config.actions.pr_config))
|
|
182
|
+
return self
|
|
183
|
+
|
|
184
|
+
def add_hook(self, hook: RunHook) -> None:
|
|
185
|
+
hook.on_init(run=self)
|
|
186
|
+
self._chooks.add_hook(hook)
|
|
187
|
+
|
|
188
|
+
def run(self):
|
|
189
|
+
self._chooks.on_start()
|
|
190
|
+
self.logger.info("Starting environment")
|
|
191
|
+
self.env.start()
|
|
192
|
+
self.logger.info("Running agent")
|
|
193
|
+
self._chooks.on_instance_start(index=0, env=self.env, problem_statement=self.problem_statement)
|
|
194
|
+
output_dir = self.output_dir / self.problem_statement.id
|
|
195
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
|
196
|
+
if self.agent.replay_config is not None: # type: ignore[attr-defined]
|
|
197
|
+
(output_dir / "config.yaml").write_text(yaml.dump(self.agent.replay_config.model_dump_json(), indent=2)) # type: ignore[attr-defined]
|
|
198
|
+
result = self.agent.run(
|
|
199
|
+
problem_statement=self.problem_statement,
|
|
200
|
+
env=self.env,
|
|
201
|
+
output_dir=output_dir,
|
|
202
|
+
)
|
|
203
|
+
self._chooks.on_instance_completed(result=result)
|
|
204
|
+
self.logger.info("Done")
|
|
205
|
+
self._chooks.on_end()
|
|
206
|
+
save_predictions(self.output_dir, self.problem_statement.id, result)
|
|
207
|
+
self.env.close()
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def run_from_config(config: RunSingleConfig):
|
|
211
|
+
RunSingle.from_config(config).run()
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def run_from_cli(args: list[str] | None = None):
|
|
215
|
+
if args is None:
|
|
216
|
+
args = sys.argv[1:]
|
|
217
|
+
assert __doc__ is not None
|
|
218
|
+
help_text = ( # type: ignore
|
|
219
|
+
__doc__ + "\n[cyan][bold]=== ALL THE OPTIONS ===[/bold][/cyan]\n\n" + ConfigHelper().get_help(RunSingleConfig)
|
|
220
|
+
)
|
|
221
|
+
run_from_config(BasicCLI(RunSingleConfig, help_text=help_text).get_config(args)) # type: ignore
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
if __name__ == "__main__":
|
|
225
|
+
run_from_cli()
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""Convert a trajectory file to a yaml file for editing of demos.
|
|
2
|
+
You can then load the yaml file with `run_replay.py` to replay the actions in an environment to get
|
|
3
|
+
environment output.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import json
|
|
9
|
+
from argparse import ArgumentParser
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
from sweagent.utils.log import get_logger
|
|
13
|
+
from sweagent.utils.serialization import _yaml_serialization_with_linebreaks
|
|
14
|
+
|
|
15
|
+
logger = get_logger("traj2demo")
|
|
16
|
+
|
|
17
|
+
DEMO_COMMENT = """# This is a demo file generated from trajectory file:
|
|
18
|
+
# {traj_path}
|
|
19
|
+
# You can use this demo file to replay the actions in the trajectory with run_replay.py.
|
|
20
|
+
# You can edit the content of the actions in this file to modify the replay behavior.
|
|
21
|
+
# NOTICE:
|
|
22
|
+
# Only the actions of the assistant will be replayed.
|
|
23
|
+
# You do not need to modify the observation's contents or any other fields.
|
|
24
|
+
# You can add or remove actions to modify the replay behavior."""
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def save_demo(data: str | dict | list, file: Path, traj_path: Path) -> None:
|
|
28
|
+
"""Save demo data as a yaml file. Takes care of multi-line strings and adds a header."""
|
|
29
|
+
content = _yaml_serialization_with_linebreaks(data)
|
|
30
|
+
header = DEMO_COMMENT.format(traj_path=str(traj_path))
|
|
31
|
+
with open(file, "w") as f:
|
|
32
|
+
f.write(f"{header}\n{content}")
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def convert_traj_to_action_demo(traj_path: Path, output_file: Path, include_user: bool = False) -> None:
|
|
36
|
+
with open(traj_path) as file:
|
|
37
|
+
traj = json.load(file)
|
|
38
|
+
replay_config = traj["replay_config"]
|
|
39
|
+
if isinstance(traj["replay_config"], str):
|
|
40
|
+
replay_config = json.loads(traj["replay_config"])
|
|
41
|
+
history = traj["history"]
|
|
42
|
+
|
|
43
|
+
copy_fields = {"content", "role", "tool_calls", "agent", "message_type", "tool_call_ids"}
|
|
44
|
+
|
|
45
|
+
admissible_roles = {"assistant", "user", "tool"} if include_user else {"assistant"}
|
|
46
|
+
filtered_history = [
|
|
47
|
+
{k: v for k, v in step.items() if k in copy_fields}
|
|
48
|
+
for step in history
|
|
49
|
+
if step["role"] in admissible_roles
|
|
50
|
+
and step.get("agent", "main") in {"main", "primary"}
|
|
51
|
+
and not step.get("is_demo")
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
output_data = {"history": filtered_history, "replay_config": replay_config}
|
|
55
|
+
save_demo(output_data, output_file, traj_path)
|
|
56
|
+
logger.info(f"Saved demo to {output_file}")
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def main(traj_path: Path, output_dir: Path, suffix: str = "", overwrite: bool = False, include_user: bool = False):
|
|
60
|
+
output_file = output_dir / (traj_path.parent.name + suffix) / (traj_path.stem.removesuffix(".traj") + ".demo.yaml")
|
|
61
|
+
if output_file.exists() and not overwrite:
|
|
62
|
+
msg = f"Output file already exists: {output_file}. Use --overwrite to overwrite."
|
|
63
|
+
raise FileExistsError(msg)
|
|
64
|
+
output_file.parent.mkdir(parents=True, exist_ok=True)
|
|
65
|
+
convert_traj_to_action_demo(traj_path, output_file, include_user)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def run_from_cli(args: list[str] | None = None):
|
|
69
|
+
"""Convert a trajectory file to a demo file."""
|
|
70
|
+
parser = ArgumentParser(description=__doc__)
|
|
71
|
+
parser.add_argument("traj_path", type=Path, help="Path to trajectory file")
|
|
72
|
+
parser.add_argument("--output_dir", type=Path, help="Output directory for action demos", default=Path("./demos"))
|
|
73
|
+
parser.add_argument("--suffix", type=str, help="Suffix for the output file", default="")
|
|
74
|
+
parser.add_argument("--overwrite", help="Overwrite existing files", action="store_true")
|
|
75
|
+
parser.add_argument(
|
|
76
|
+
"--include_user",
|
|
77
|
+
help="Include user responses (computer)",
|
|
78
|
+
action="store_true",
|
|
79
|
+
)
|
|
80
|
+
parsed_args = parser.parse_args(args)
|
|
81
|
+
main(**vars(parsed_args))
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
if __name__ == "__main__":
|
|
85
|
+
run_from_cli()
|
|
File without changes
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
import yaml
|
|
6
|
+
from pydantic import BaseModel, Field, PrivateAttr, model_validator
|
|
7
|
+
|
|
8
|
+
from sweagent.tools.commands import Command
|
|
9
|
+
from sweagent.utils.config import _convert_path_to_abspath
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class BundleConfig(BaseModel):
|
|
13
|
+
tools: dict[str, dict]
|
|
14
|
+
state_command: str | None = None
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Bundle(BaseModel):
|
|
18
|
+
path: Path
|
|
19
|
+
hidden_tools: list[str] = Field(default_factory=list)
|
|
20
|
+
_config: BundleConfig = PrivateAttr(default=None)
|
|
21
|
+
|
|
22
|
+
@model_validator(mode="after")
|
|
23
|
+
def validate_tools(self):
|
|
24
|
+
self.path = _convert_path_to_abspath(self.path)
|
|
25
|
+
if not self.path.exists():
|
|
26
|
+
msg = f"Bundle path '{self.path}' does not exist."
|
|
27
|
+
raise ValueError(msg)
|
|
28
|
+
|
|
29
|
+
config_path = self.path / "config.yaml"
|
|
30
|
+
if not config_path.exists():
|
|
31
|
+
msg = f"Bundle config file '{config_path}' does not exist."
|
|
32
|
+
raise ValueError(msg)
|
|
33
|
+
|
|
34
|
+
config_data = yaml.safe_load(config_path.read_text())
|
|
35
|
+
self._config = BundleConfig(**config_data)
|
|
36
|
+
|
|
37
|
+
invalid_hidden_tools = set(self.hidden_tools) - set(self._config.tools.keys())
|
|
38
|
+
if invalid_hidden_tools:
|
|
39
|
+
msg = f"Hidden tools {invalid_hidden_tools} do not exist in available tools"
|
|
40
|
+
raise ValueError(msg)
|
|
41
|
+
return self
|
|
42
|
+
|
|
43
|
+
@property
|
|
44
|
+
def state_command(self) -> str | None:
|
|
45
|
+
return self.config.state_command
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def config(self) -> BundleConfig:
|
|
49
|
+
return self._config
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def commands(self) -> list[Command]:
|
|
53
|
+
return [
|
|
54
|
+
Command(name=tool, **tool_config.model_dump() if isinstance(tool_config, Command) else tool_config)
|
|
55
|
+
for tool, tool_config in self.config.tools.items()
|
|
56
|
+
if tool not in self.hidden_tools
|
|
57
|
+
]
|