@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.
Files changed (323) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +270 -0
  3. package/package.json +71 -0
  4. package/python/LICENSE +21 -0
  5. package/python/config/README.md +15 -0
  6. package/python/config/bash_only.yaml +222 -0
  7. package/python/config/benchmarks/250212_sweagent_heavy_sbl.yaml +188 -0
  8. package/python/config/benchmarks/250225_anthropic_filemap_simple_review.yaml +75 -0
  9. package/python/config/benchmarks/250522_anthropic_filemap_simple_review.yaml +92 -0
  10. package/python/config/benchmarks/250526_anthropic_filemap_simple_review_sbl.yaml +93 -0
  11. package/python/config/benchmarks/anthropic_filemap_multilingual.yaml +66 -0
  12. package/python/config/coding_challenge.yaml +104 -0
  13. package/python/config/default.yaml +69 -0
  14. package/python/config/default_backticks.yaml +69 -0
  15. package/python/config/default_mm_no_images.yaml +82 -0
  16. package/python/config/default_mm_with_images.yaml +83 -0
  17. package/python/config/demo/default.yaml +80 -0
  18. package/python/config/demo/no_instructions.yaml +69 -0
  19. package/python/config/demo/only_bash.yaml +60 -0
  20. package/python/config/exotic/default_shell.yaml +52 -0
  21. package/python/config/exotic/windowed_replace.yaml +125 -0
  22. package/python/config/exotic/windowed_replace_late_repro.yaml +127 -0
  23. package/python/config/human/human.yaml +24 -0
  24. package/python/config/human/human_demo.yaml +52 -0
  25. package/python/config/sweagent_0_7/07.yaml +101 -0
  26. package/python/config/sweagent_0_7/07_fcalling.yaml +100 -0
  27. package/python/config/sweagent_0_7/07_from_url.yaml +114 -0
  28. package/python/config/sweagent_0_7/07_thought_action.yaml +102 -0
  29. package/python/config/sweagent_0_7/07_thought_action_xml.yaml +96 -0
  30. package/python/mlc_config.json +44 -0
  31. package/python/pyproject.toml +262 -0
  32. package/python/sweagent/__init__.py +114 -0
  33. package/python/sweagent/__main__.py +4 -0
  34. package/python/sweagent/agent/__init__.py +0 -0
  35. package/python/sweagent/agent/action_sampler.py +317 -0
  36. package/python/sweagent/agent/agents.py +1294 -0
  37. package/python/sweagent/agent/extra/shell_agent.py +106 -0
  38. package/python/sweagent/agent/history_processors.py +399 -0
  39. package/python/sweagent/agent/hooks/__init__.py +0 -0
  40. package/python/sweagent/agent/hooks/abstract.py +139 -0
  41. package/python/sweagent/agent/hooks/status.py +34 -0
  42. package/python/sweagent/agent/models.py +896 -0
  43. package/python/sweagent/agent/problem_statement.py +312 -0
  44. package/python/sweagent/agent/reviewer.py +664 -0
  45. package/python/sweagent/environment/__init__.py +0 -0
  46. package/python/sweagent/environment/hooks/__init__.py +0 -0
  47. package/python/sweagent/environment/hooks/abstract.py +60 -0
  48. package/python/sweagent/environment/hooks/status.py +28 -0
  49. package/python/sweagent/environment/repo.py +219 -0
  50. package/python/sweagent/environment/swe_env.py +276 -0
  51. package/python/sweagent/exceptions.py +54 -0
  52. package/python/sweagent/inspector/README.md +6 -0
  53. package/python/sweagent/inspector/__init__.py +0 -0
  54. package/python/sweagent/inspector/favicon.ico +0 -0
  55. package/python/sweagent/inspector/fileViewer.js +354 -0
  56. package/python/sweagent/inspector/icons/computer.png +0 -0
  57. package/python/sweagent/inspector/icons/edit_icon.svg +11 -0
  58. package/python/sweagent/inspector/icons/swe-agent-logo-50.png +0 -0
  59. package/python/sweagent/inspector/icons/swellama_blue.png +0 -0
  60. package/python/sweagent/inspector/icons/swellama_brown.png +0 -0
  61. package/python/sweagent/inspector/icons/swellama_grey.png +0 -0
  62. package/python/sweagent/inspector/icons/swellama_tan.png +0 -0
  63. package/python/sweagent/inspector/index.html +25 -0
  64. package/python/sweagent/inspector/server.py +354 -0
  65. package/python/sweagent/inspector/static.py +169 -0
  66. package/python/sweagent/inspector/style.css +454 -0
  67. package/python/sweagent/run/__init__.py +0 -0
  68. package/python/sweagent/run/_progress.py +158 -0
  69. package/python/sweagent/run/batch_instances.py +419 -0
  70. package/python/sweagent/run/common.py +387 -0
  71. package/python/sweagent/run/compare_runs.py +123 -0
  72. package/python/sweagent/run/extract_pred.py +19 -0
  73. package/python/sweagent/run/hooks/__init__.py +0 -0
  74. package/python/sweagent/run/hooks/abstract.py +67 -0
  75. package/python/sweagent/run/hooks/apply_patch.py +106 -0
  76. package/python/sweagent/run/hooks/open_pr.py +244 -0
  77. package/python/sweagent/run/hooks/swe_bench_evaluate.py +113 -0
  78. package/python/sweagent/run/inspector_cli.py +493 -0
  79. package/python/sweagent/run/merge_predictions.py +64 -0
  80. package/python/sweagent/run/quick_stats.py +96 -0
  81. package/python/sweagent/run/remove_unfinished.py +63 -0
  82. package/python/sweagent/run/rich_test.py +91 -0
  83. package/python/sweagent/run/run.py +147 -0
  84. package/python/sweagent/run/run_batch.py +442 -0
  85. package/python/sweagent/run/run_replay.py +219 -0
  86. package/python/sweagent/run/run_shell.py +155 -0
  87. package/python/sweagent/run/run_single.py +225 -0
  88. package/python/sweagent/run/run_traj_to_demo.py +85 -0
  89. package/python/sweagent/tools/__init__.py +0 -0
  90. package/python/sweagent/tools/bundle.py +57 -0
  91. package/python/sweagent/tools/commands.py +220 -0
  92. package/python/sweagent/tools/parsing.py +619 -0
  93. package/python/sweagent/tools/tools.py +430 -0
  94. package/python/sweagent/tools/utils.py +108 -0
  95. package/python/sweagent/types.py +102 -0
  96. package/python/sweagent/utils/__init__.py +0 -0
  97. package/python/sweagent/utils/config.py +80 -0
  98. package/python/sweagent/utils/files.py +27 -0
  99. package/python/sweagent/utils/github.py +118 -0
  100. package/python/sweagent/utils/jinja_warnings.py +14 -0
  101. package/python/sweagent/utils/log.py +175 -0
  102. package/python/sweagent/utils/patch_formatter.py +152 -0
  103. package/python/sweagent/utils/serialization.py +45 -0
  104. package/python/tests/__init__.py +0 -0
  105. package/python/tests/conftest.py +191 -0
  106. package/python/tests/test_agent.py +258 -0
  107. package/python/tests/test_batch_instance.py +43 -0
  108. package/python/tests/test_commands/_interactive_dummy.py +35 -0
  109. package/python/tests/test_commands/interactive_dummy_wrapper.sh +29 -0
  110. package/python/tests/test_data/config_files/dummy_interactive.yaml +62 -0
  111. package/python/tests/test_data/data_sources/ctf/crypto/Katy/Dockerfile +20 -0
  112. package/python/tests/test_data/data_sources/ctf/crypto/Katy/README.md +13 -0
  113. package/python/tests/test_data/data_sources/ctf/crypto/Katy/challenge.json +12 -0
  114. package/python/tests/test_data/data_sources/ctf/crypto/Katy/customrandom.c +50 -0
  115. package/python/tests/test_data/data_sources/ctf/crypto/Katy/docker-compose.yml +14 -0
  116. package/python/tests/test_data/data_sources/ctf/crypto/Katy/release +0 -0
  117. package/python/tests/test_data/data_sources/ctf/crypto/Katy/server +0 -0
  118. package/python/tests/test_data/data_sources/ctf/crypto/Katy/solver.py +12 -0
  119. package/python/tests/test_data/data_sources/ctf/forensics/flash/README.md +16 -0
  120. package/python/tests/test_data/data_sources/ctf/forensics/flash/challenge.json +9 -0
  121. package/python/tests/test_data/data_sources/ctf/forensics/flash/flash_c8429a430278283c0e571baebca3d139.zip +0 -0
  122. package/python/tests/test_data/data_sources/ctf/misc/networking_1/README.md +15 -0
  123. package/python/tests/test_data/data_sources/ctf/misc/networking_1/challenge.json +10 -0
  124. package/python/tests/test_data/data_sources/ctf/misc/networking_1/networking.pcap +0 -0
  125. package/python/tests/test_data/data_sources/ctf/pwn/warmup/Dockerfile +28 -0
  126. package/python/tests/test_data/data_sources/ctf/pwn/warmup/README.md +14 -0
  127. package/python/tests/test_data/data_sources/ctf/pwn/warmup/challenge.json +14 -0
  128. package/python/tests/test_data/data_sources/ctf/pwn/warmup/docker-compose.yml +14 -0
  129. package/python/tests/test_data/data_sources/ctf/pwn/warmup/flag.txt +1 -0
  130. package/python/tests/test_data/data_sources/ctf/pwn/warmup/warmup +0 -0
  131. package/python/tests/test_data/data_sources/ctf/pwn/warmup/warmup.c +26 -0
  132. package/python/tests/test_data/data_sources/ctf/pwn/warmup/warmup.py +9 -0
  133. package/python/tests/test_data/data_sources/ctf/rev/rock/README.md +14 -0
  134. package/python/tests/test_data/data_sources/ctf/rev/rock/challenge.json +8 -0
  135. package/python/tests/test_data/data_sources/ctf/rev/rock/rock +0 -0
  136. package/python/tests/test_data/data_sources/ctf/rev/rock/rock.cpp +167 -0
  137. package/python/tests/test_data/data_sources/ctf/rev/rock/solution.cpp +24 -0
  138. package/python/tests/test_data/data_sources/ctf/rev/rock/test_solver/solution.py +6 -0
  139. package/python/tests/test_data/data_sources/ctf/rev/rock/test_solver/test.sh +10 -0
  140. package/python/tests/test_data/data_sources/ctf/web/i_got_id_demo/000-default.conf +18 -0
  141. package/python/tests/test_data/data_sources/ctf/web/i_got_id_demo/Dockerfile +20 -0
  142. package/python/tests/test_data/data_sources/ctf/web/i_got_id_demo/cgi/file.pl +38 -0
  143. package/python/tests/test_data/data_sources/ctf/web/i_got_id_demo/cgi/forms.pl +40 -0
  144. package/python/tests/test_data/data_sources/ctf/web/i_got_id_demo/cgi/hello.pl +11 -0
  145. package/python/tests/test_data/data_sources/ctf/web/i_got_id_demo/challenge.json +12 -0
  146. package/python/tests/test_data/data_sources/ctf/web/i_got_id_demo/docker-compose.yml +14 -0
  147. package/python/tests/test_data/data_sources/ctf/web/i_got_id_demo/flag +1 -0
  148. package/python/tests/test_data/data_sources/ctf/web/i_got_id_demo/index.html +11 -0
  149. package/python/tests/test_data/data_sources/ctf/web/i_got_id_demo/solution.txt +1 -0
  150. package/python/tests/test_data/data_sources/debug_20240322.json +1 -0
  151. package/python/tests/test_data/data_sources/expert_instances.yaml +16 -0
  152. package/python/tests/test_data/data_sources/human_eval.json +1 -0
  153. package/python/tests/test_data/data_sources/simple_instances.yaml +3 -0
  154. package/python/tests/test_data/data_sources/simple_instances_long.yaml +30 -0
  155. package/python/tests/test_data/data_sources/swe-bench-dev-easy.json +1 -0
  156. package/python/tests/test_data/data_sources/swe-bench-dev-easy_first_only.json +1 -0
  157. package/python/tests/test_data/data_sources/swe-bench-lite-test.json +1 -0
  158. 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
  159. 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
  160. 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
  161. 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
  162. 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
  163. 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
  164. 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
  165. 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
  166. package/python/tests/test_env.py +66 -0
  167. package/python/tests/test_env_utils.py +129 -0
  168. package/python/tests/test_history_processors.py +40 -0
  169. package/python/tests/test_models.py +23 -0
  170. package/python/tests/test_openai_live.py +164 -0
  171. package/python/tests/test_packaging.py +7 -0
  172. package/python/tests/test_parsing.py +131 -0
  173. package/python/tests/test_problem_statement_multimodal.py +111 -0
  174. package/python/tests/test_quick_stats.py +42 -0
  175. package/python/tests/test_run.py +37 -0
  176. package/python/tests/test_run_batch.py +110 -0
  177. package/python/tests/test_run_hooks.py +114 -0
  178. package/python/tests/test_run_replay.py +33 -0
  179. package/python/tests/test_run_single.py +125 -0
  180. package/python/tests/test_tools_command_parsing.py +193 -0
  181. package/python/tests/test_utils.py +15 -0
  182. package/python/tests/tools/__init__.py +0 -0
  183. package/python/tests/tools/conftest.py +12 -0
  184. package/python/tests/tools/test_default_utils.py +153 -0
  185. package/python/tests/tools/test_edit_replace.py +0 -0
  186. package/python/tests/tools/test_split_string.py +82 -0
  187. package/python/tests/utils.py +29 -0
  188. package/python/tools/diff_state/bin/_state_diff_state +52 -0
  189. package/python/tools/diff_state/config.yaml +2 -0
  190. package/python/tools/edit_anthropic/bin/_state_anthropic +21 -0
  191. package/python/tools/edit_anthropic/bin/str_replace_editor +710 -0
  192. package/python/tools/edit_anthropic/config.yaml +56 -0
  193. package/python/tools/edit_anthropic/install.sh +3 -0
  194. package/python/tools/filemap/bin/filemap +45 -0
  195. package/python/tools/filemap/config.yaml +9 -0
  196. package/python/tools/filemap/install.sh +2 -0
  197. package/python/tools/forfeit/bin/exit_forfeit +5 -0
  198. package/python/tools/forfeit/config.yaml +5 -0
  199. package/python/tools/image_tools/bin/view_image +36 -0
  200. package/python/tools/image_tools/config.yaml +9 -0
  201. package/python/tools/multilingual_setup/bin/do_nothing +2 -0
  202. package/python/tools/multilingual_setup/config.yaml +1 -0
  203. package/python/tools/multilingual_setup/install.sh +45 -0
  204. package/python/tools/registry/bin/_read_env +10 -0
  205. package/python/tools/registry/bin/_write_env +10 -0
  206. package/python/tools/registry/config.yaml +1 -0
  207. package/python/tools/registry/install.sh +6 -0
  208. package/python/tools/registry/lib/__init__.py +0 -0
  209. package/python/tools/registry/lib/registry.py +56 -0
  210. package/python/tools/review_on_submit_m/README.md +6 -0
  211. package/python/tools/review_on_submit_m/bin/submit +54 -0
  212. package/python/tools/review_on_submit_m/config.yaml +6 -0
  213. package/python/tools/review_on_submit_m/install.sh +0 -0
  214. package/python/tools/search/bin/find_file +31 -0
  215. package/python/tools/search/bin/search_dir +39 -0
  216. package/python/tools/search/bin/search_file +55 -0
  217. package/python/tools/search/config.yaml +37 -0
  218. package/python/tools/search/install.sh +3 -0
  219. package/python/tools/submit/bin/submit +17 -0
  220. package/python/tools/submit/config.yaml +5 -0
  221. package/python/tools/web_browser/bin/click_mouse +41 -0
  222. package/python/tools/web_browser/bin/close_site +28 -0
  223. package/python/tools/web_browser/bin/double_click_mouse +37 -0
  224. package/python/tools/web_browser/bin/drag_mouse +46 -0
  225. package/python/tools/web_browser/bin/execute_script_on_page +39 -0
  226. package/python/tools/web_browser/bin/get_console_output +48 -0
  227. package/python/tools/web_browser/bin/move_mouse +35 -0
  228. package/python/tools/web_browser/bin/navigate_back +33 -0
  229. package/python/tools/web_browser/bin/navigate_forward +33 -0
  230. package/python/tools/web_browser/bin/open_site +36 -0
  231. package/python/tools/web_browser/bin/press_keys_on_page +51 -0
  232. package/python/tools/web_browser/bin/reload_page +33 -0
  233. package/python/tools/web_browser/bin/run_web_browser_server +394 -0
  234. package/python/tools/web_browser/bin/screenshot_site +38 -0
  235. package/python/tools/web_browser/bin/scroll_on_page +40 -0
  236. package/python/tools/web_browser/bin/set_browser_window_size +40 -0
  237. package/python/tools/web_browser/bin/type_text +34 -0
  238. package/python/tools/web_browser/bin/wait_time +39 -0
  239. package/python/tools/web_browser/config.yaml +155 -0
  240. package/python/tools/web_browser/install.sh +22 -0
  241. package/python/tools/web_browser/lib/browser_manager.py +404 -0
  242. package/python/tools/web_browser/lib/web_browser_config.py +33 -0
  243. package/python/tools/web_browser/lib/web_browser_utils.py +126 -0
  244. package/python/tools/web_browser/test_console.html +1 -0
  245. package/python/tools/windowed/bin/_state +25 -0
  246. package/python/tools/windowed/bin/create +29 -0
  247. package/python/tools/windowed/bin/goto +37 -0
  248. package/python/tools/windowed/bin/open +49 -0
  249. package/python/tools/windowed/bin/scroll_down +12 -0
  250. package/python/tools/windowed/bin/scroll_up +13 -0
  251. package/python/tools/windowed/config.yaml +38 -0
  252. package/python/tools/windowed/install.sh +15 -0
  253. package/python/tools/windowed/lib/__init__.py +0 -0
  254. package/python/tools/windowed/lib/flake8_utils.py +147 -0
  255. package/python/tools/windowed/lib/windowed_file.py +312 -0
  256. package/python/tools/windowed_edit_linting/bin/edit +128 -0
  257. package/python/tools/windowed_edit_linting/config.yaml +31 -0
  258. package/python/tools/windowed_edit_linting/install.sh +5 -0
  259. package/python/tools/windowed_edit_replace/bin/edit +172 -0
  260. package/python/tools/windowed_edit_replace/bin/insert +77 -0
  261. package/python/tools/windowed_edit_replace/config.yaml +60 -0
  262. package/python/tools/windowed_edit_replace/install.sh +5 -0
  263. package/python/tools/windowed_edit_rewrite/bin/edit +78 -0
  264. package/python/tools/windowed_edit_rewrite/config.yaml +11 -0
  265. package/python/tools/windowed_edit_rewrite/install.sh +5 -0
  266. package/python/trajectories/demonstrations/ctf/crypto/BabyEncryption.traj +318 -0
  267. package/python/trajectories/demonstrations/ctf/crypto/BabyTimeCapsule.traj +197 -0
  268. package/python/trajectories/demonstrations/ctf/crypto/eps.traj +289 -0
  269. package/python/trajectories/demonstrations/ctf/crypto/katy.traj +368 -0
  270. package/python/trajectories/demonstrations/ctf/forensics/flash.traj +102 -0
  271. package/python/trajectories/demonstrations/ctf/misc/networking_1.traj +102 -0
  272. package/python/trajectories/demonstrations/ctf/pwn/warmup.traj +159 -0
  273. package/python/trajectories/demonstrations/ctf/rev/rock.traj +251 -0
  274. package/python/trajectories/demonstrations/ctf/web/i_got_id_demo.traj +422 -0
  275. package/python/trajectories/demonstrations/function_calling_simple.traj +151 -0
  276. 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
  277. 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
  278. 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
  279. 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
  280. package/python/trajectories/demonstrations/replay__marshmallow-code__marshmallow-1867__function_calling__install-1/marshmallow-code__marshmallow-1867.traj +594 -0
  281. package/python/trajectories/demonstrations/replay__marshmallow-code__marshmallow-1867__function_calling_replace__install-1/marshmallow-code__marshmallow-1867.traj +592 -0
  282. package/python/trajectories/demonstrations/replay__marshmallow-code__marshmallow-1867__function_calling_replace_from_source/marshmallow-code__marshmallow-1867.traj +3316 -0
  283. 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
  284. 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
  285. package/python/trajectories/demonstrations/str_replace_anthropic_demo.yaml +432 -0
  286. package/rust/Cargo.toml +100 -0
  287. package/rust/README.md +49 -0
  288. package/rust/src/agent/action_sampler.rs +130 -0
  289. package/rust/src/agent/agents.rs +1029 -0
  290. package/rust/src/agent/history_processors.rs +277 -0
  291. package/rust/src/agent/hooks/mod.rs +208 -0
  292. package/rust/src/agent/mod.rs +24 -0
  293. package/rust/src/agent/models.rs +837 -0
  294. package/rust/src/agent/problem_statement.rs +355 -0
  295. package/rust/src/agent/reviewer.rs +505 -0
  296. package/rust/src/bin/sweagent.rs +784 -0
  297. package/rust/src/environment/deployment.rs +631 -0
  298. package/rust/src/environment/hooks/mod.rs +114 -0
  299. package/rust/src/environment/mod.rs +16 -0
  300. package/rust/src/environment/repo.rs +265 -0
  301. package/rust/src/environment/runtime.rs +237 -0
  302. package/rust/src/environment/swe_env.rs +248 -0
  303. package/rust/src/exceptions.rs +228 -0
  304. package/rust/src/lib.rs +68 -0
  305. package/rust/src/monitoring.rs +482 -0
  306. package/rust/src/run/hooks/mod.rs +134 -0
  307. package/rust/src/run/mod.rs +12 -0
  308. package/rust/src/run/run_batch.rs +563 -0
  309. package/rust/src/run/run_single.rs +196 -0
  310. package/rust/src/tools/bundle.rs +224 -0
  311. package/rust/src/tools/commands.rs +173 -0
  312. package/rust/src/tools/mod.rs +295 -0
  313. package/rust/src/tools/parsing.rs +354 -0
  314. package/rust/src/tools/registry.rs +143 -0
  315. package/rust/src/types.rs +554 -0
  316. package/rust/src/utils/config.rs +105 -0
  317. package/rust/src/utils/files.rs +137 -0
  318. package/rust/src/utils/github.rs +171 -0
  319. package/rust/src/utils/log.rs +65 -0
  320. package/rust/src/utils/mod.rs +17 -0
  321. package/rust/src/utils/serialization.rs +181 -0
  322. package/rust/src/utils/template.rs +173 -0
  323. package/typescript/README.md +335 -0
@@ -0,0 +1,126 @@
1
+ from __future__ import annotations
2
+
3
+ import base64
4
+ import functools
5
+ import sys
6
+ from enum import Enum
7
+ from pathlib import Path
8
+
9
+ import requests
10
+ from flask import jsonify, request
11
+
12
+
13
+ class ScreenshotMode(Enum):
14
+ SAVE = "save" # saves screenshot to png file
15
+ PRINT = "print" # prints base64 encoded screenshot to stdout
16
+
17
+
18
+ def normalize_url(url: str) -> str:
19
+ # if starts with http:// or https://, return as is
20
+ # if starts with file://, return as is
21
+ # elif local file path exists, return as file://
22
+ # else: return as https://
23
+ if any(url.startswith(prefix) for prefix in ["http://", "https://", "file://"]):
24
+ return url
25
+ elif Path(url).exists():
26
+ return f"file://{Path(url).resolve()}"
27
+ else:
28
+ return "https://" + url
29
+
30
+
31
+ def validate_request(*required_keys):
32
+ """Decorator to validate that all required keys are present in request JSON."""
33
+
34
+ def decorator(func):
35
+ @functools.wraps(func)
36
+ def wrapper(*args, **kwargs):
37
+ if not request.is_json:
38
+ return jsonify({"status": "error", "message": "Request must be JSON"})
39
+
40
+ request_data = request.get_json()
41
+ if not request_data:
42
+ return jsonify({"status": "error", "message": "Request body cannot be empty"})
43
+
44
+ missing_keys = [key for key in required_keys if key not in request_data]
45
+ if missing_keys:
46
+ return jsonify({"status": "error", "message": f"Missing required fields: {', '.join(missing_keys)}"})
47
+
48
+ return func(*args, **kwargs)
49
+
50
+ return wrapper
51
+
52
+ return decorator
53
+
54
+
55
+ def catch_error(func):
56
+ """Decorator to catch exceptions and return them as JSON."""
57
+
58
+ @functools.wraps(func)
59
+ def wrapper(*args, **kwargs):
60
+ try:
61
+ return func(*args, **kwargs)
62
+ except Exception as e:
63
+ return jsonify({"status": "error", "message": str(e)})
64
+
65
+ return wrapper
66
+
67
+
68
+ def _print_error(message, error_type="ERROR"):
69
+ """Print error message in a normalized format."""
70
+ print(f"{error_type}: {message}", file=sys.stderr)
71
+
72
+
73
+ def _format_metadata_info(response):
74
+ """Format metadata information from API response for display."""
75
+ if "metadata" not in response or not response["metadata"]:
76
+ return ""
77
+ return "\n".join(f"{key}: {value}" for key, value in response["metadata"].items())
78
+
79
+
80
+ def send_request(port, endpoint, method="GET", data=None):
81
+ url = f"http://localhost:{port}/{endpoint}"
82
+ if method == "GET":
83
+ response = requests.get(url)
84
+ else:
85
+ response = requests.post(url, json=data)
86
+ if response.status_code != 200:
87
+ _print_error(f"Internal error communicating with backend: {response.text}", "INTERNAL ERROR")
88
+ return None
89
+ data = response.json()
90
+ if data["status"] == "error":
91
+ metadata_info = _format_metadata_info(data)
92
+ error_message = data["message"]
93
+ _print_error(f"ACTION ERROR:\n{error_message}")
94
+ if metadata_info:
95
+ print(f"\nMETADATA:\n{metadata_info}", file=sys.stderr)
96
+ return None
97
+ return data
98
+
99
+
100
+ def _print_response_with_metadata(response):
101
+ """Print response message with formatted metadata information."""
102
+ message = response.get("message", "")
103
+ metadata_info = _format_metadata_info(response)
104
+ print(f"ACTION RESPONSE:\n{message}")
105
+
106
+ if metadata_info:
107
+ print(f"\nMETADATA:\n{metadata_info}")
108
+
109
+
110
+ def _handle_screenshot(screenshot_data, mode):
111
+ """Handle screenshot data according to the specified mode"""
112
+ if mode == ScreenshotMode.SAVE:
113
+ path = Path("latest_screenshot.png")
114
+ path.write_bytes(base64.b64decode(screenshot_data))
115
+ print(f"![Screenshot]({path})")
116
+ elif mode == ScreenshotMode.PRINT:
117
+ print(f"![Screenshot](data:image/png;base64,{screenshot_data})")
118
+ else:
119
+ message = f"Invalid screenshot mode: {mode}"
120
+ raise ValueError(message)
121
+
122
+
123
+ def _autosave_screenshot_from_response(response, mode):
124
+ """Handle screenshot from response data according to the specified mode"""
125
+ if "screenshot" in response:
126
+ _handle_screenshot(response["screenshot"], mode)
@@ -0,0 +1 @@
1
+ <script>console.log("Hello from console!"); console.error("Test error"); console.warn("Test warning");</script><h1>Test Page</h1>
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env python3
2
+
3
+ import json
4
+ import os
5
+ from pathlib import Path
6
+
7
+ from registry import registry # type: ignore
8
+
9
+
10
+ def main():
11
+ state_path = Path("/root/state.json")
12
+
13
+ if state_path.exists():
14
+ state = json.loads(state_path.read_text())
15
+ else:
16
+ state = {}
17
+
18
+ current_file = registry.get("CURRENT_FILE")
19
+ open_file = "n/a" if not current_file else str(Path(current_file).resolve())
20
+ state["open_file"] = open_file
21
+ state["working_dir"] = os.getcwd()
22
+ state_path.write_text(json.dumps(state))
23
+
24
+ if __name__ == "__main__":
25
+ main()
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env python3
2
+ import sys
3
+ from pathlib import Path
4
+
5
+ from windowed_file import WindowedFile # type: ignore
6
+
7
+
8
+ def main():
9
+ if len(sys.argv) < 2:
10
+ print("Usage: create <filename>")
11
+ sys.exit(1)
12
+
13
+ path = Path(sys.argv[1])
14
+ if not path.parent.is_dir():
15
+ path.parent.mkdir(parents=True, exist_ok=True)
16
+
17
+ if path.exists():
18
+ print(f"Warning: File '{path}' already exists.")
19
+ sys.exit(1)
20
+
21
+ path.touch()
22
+
23
+ wfile = WindowedFile(path=path)
24
+ wfile.first_line = 0
25
+ wfile.print_window()
26
+
27
+
28
+ if __name__ == "__main__":
29
+ main()
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env python3
2
+ import sys
3
+ from typing import List
4
+
5
+ from windowed_file import WindowedFile # type: ignore
6
+
7
+
8
+ def main(args: List[str]) -> int:
9
+ if len(args) > 1:
10
+ print("goto allows only one line number at a time.")
11
+ return 1
12
+
13
+ if not args:
14
+ print("Usage: goto <line>")
15
+ return 1
16
+
17
+ try:
18
+ line_number = int(args[0])
19
+ except ValueError:
20
+ print("Usage: goto <line>")
21
+ print("Error: <line> must be a number")
22
+ return 1
23
+
24
+ wf = WindowedFile()
25
+
26
+ if line_number > wf.n_lines:
27
+ print(f"Error: <line> must be less than or equal to {wf.n_lines}")
28
+ return 1
29
+
30
+ # Convert from 1-based line numbers (user input) to 0-based (internal representation)
31
+ wf.goto(line_number - 1, mode="top")
32
+ wf.print_window()
33
+ return 0
34
+
35
+
36
+ if __name__ == "__main__":
37
+ sys.exit(main(sys.argv[1:]))
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env python3
2
+ import sys
3
+ from typing import Optional
4
+
5
+ from windowed_file import FileNotOpened, WindowedFile # type: ignore
6
+
7
+
8
+ def main(path: Optional[str] = None, line_number: Optional[str] = None) -> None:
9
+ if path is None:
10
+ try:
11
+ WindowedFile(exit_on_exception=False).print_window()
12
+ # If this passes, then there was already a file open and we just show it again
13
+ sys.exit(0)
14
+ except FileNotOpened:
15
+ print('Usage: open "<file>"')
16
+ sys.exit(1)
17
+
18
+ assert path is not None
19
+
20
+ wf = WindowedFile(path=path)
21
+
22
+ if line_number is not None:
23
+ try:
24
+ line_num = int(line_number)
25
+ except ValueError:
26
+ print('Usage: open "<file>" [<line_number>]')
27
+ print("Error: <line_number> must be a number")
28
+ sys.exit(1)
29
+ if line_num > wf.n_lines:
30
+ print(f"Warning: <line_number> ({line_num}) is greater than the number of lines in the file ({wf.n_lines})")
31
+ print(f"Warning: Setting <line_number> to {wf.n_lines}")
32
+ line_num = wf.n_lines
33
+ elif line_num < 1:
34
+ print(f"Warning: <line_number> ({line_num}) is less than 1")
35
+ print("Warning: Setting <line_number> to 1")
36
+ line_num = 1
37
+ else:
38
+ # Default to middle of window if no line number provided
39
+ line_num = wf.first_line
40
+
41
+ wf.goto(line_num - 1, mode="top")
42
+ wf.print_window()
43
+
44
+
45
+ if __name__ == "__main__":
46
+ args = sys.argv[1:]
47
+ file_path = args[0] if args else None
48
+ line_number = args[1] if len(args) > 1 else None
49
+ main(file_path, line_number)
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env python3
2
+
3
+ from windowed_file import WindowedFile # type: ignore
4
+
5
+
6
+ def main():
7
+ wf = WindowedFile()
8
+ wf.scroll(wf.window)
9
+ wf.print_window()
10
+
11
+ if __name__ == "__main__":
12
+ main()
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env python3
2
+
3
+ from windowed_file import WindowedFile # type: ignore
4
+
5
+
6
+ def main():
7
+ wf = WindowedFile()
8
+ wf.scroll(-wf.window)
9
+ wf.print_window()
10
+
11
+
12
+ if __name__ == "__main__":
13
+ main()
@@ -0,0 +1,38 @@
1
+ tools:
2
+ goto:
3
+ signature: "goto <line_number>"
4
+ docstring: "moves the window to show <line_number>"
5
+ arguments:
6
+ - name: line_number
7
+ type: integer
8
+ description: "the line number to move the window to"
9
+ required: true
10
+ open:
11
+ signature: 'open "<path>" [<line_number>]'
12
+ docstring: "opens the file at the given path in the editor. If line_number is provided, the window will be move to include that line"
13
+ arguments:
14
+ - name: path
15
+ type: string
16
+ description: "the path to the file to open"
17
+ required: true
18
+ - name: line_number
19
+ type: integer
20
+ description: "the line number to move the window to (if not provided, the window will start at the top of the file)"
21
+ required: false
22
+ create:
23
+ signature: "create <filename>"
24
+ docstring: "creates and opens a new file with the given name"
25
+ arguments:
26
+ - name: filename
27
+ type: string
28
+ description: "the name of the file to create"
29
+ required: true
30
+ scroll_up:
31
+ signature: "scroll_up"
32
+ docstring: "moves the window up {WINDOW} lines"
33
+ arguments: []
34
+ scroll_down:
35
+ signature: "scroll_down"
36
+ docstring: "moves the window down {WINDOW} lines"
37
+ arguments: []
38
+ state_command: "_state"
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # script_dir=$(dirname "$(readlink -f "$0")")
4
+ bundle_dir=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
5
+
6
+ export PYTHONPATH="$bundle_dir/lib":$PYTHONPATH
7
+
8
+ # Write default environment variables into the environment storage
9
+ _write_env "WINDOW" "${WINDOW:-100}"
10
+ _write_env "OVERLAP" "${OVERLAP:-2}"
11
+ _write_env "FIRST_LINE" "${FIRST_LINE:-0}"
12
+ _write_env "CURRENT_FILE" "${CURRENT_FILE:-}"
13
+
14
+ # install jq
15
+ # apt-get update && apt-get install -y jq
File without changes
@@ -0,0 +1,147 @@
1
+ #!/usr/bin/env python3
2
+
3
+ """This helper command is used to parse and print flake8 output."""
4
+
5
+ import subprocess
6
+ from pathlib import Path
7
+
8
+ try:
9
+ from sweagent import TOOLS_DIR
10
+ except ImportError:
11
+ pass
12
+ else:
13
+ import sys
14
+
15
+ default_lib = TOOLS_DIR / "windowed" / "lib"
16
+ assert default_lib.is_dir()
17
+ sys.path.append(str(default_lib))
18
+ sys.path.append(str(TOOLS_DIR / "registry" / "lib"))
19
+
20
+ from registry import registry
21
+
22
+
23
+ class Flake8Error:
24
+ """A class to represent a single flake8 error"""
25
+
26
+ def __init__(self, filename: str, line_number: int, col_number: int, problem: str):
27
+ self.filename = filename
28
+ self.line_number = line_number
29
+ self.col_number = col_number
30
+ self.problem = problem
31
+
32
+ @classmethod
33
+ def from_line(cls, line: str):
34
+ try:
35
+ prefix, _sep, problem = line.partition(": ")
36
+ filename, line_number, col_number = prefix.split(":")
37
+ except (ValueError, IndexError) as e:
38
+ msg = f"Invalid flake8 error line: {line}"
39
+ raise ValueError(msg) from e
40
+ return cls(filename, int(line_number), int(col_number), problem)
41
+
42
+ def __eq__(self, other):
43
+ if not isinstance(other, Flake8Error):
44
+ return NotImplemented
45
+ return (
46
+ self.filename == other.filename
47
+ and self.line_number == other.line_number
48
+ and self.col_number == other.col_number
49
+ and self.problem == other.problem
50
+ )
51
+
52
+ def __repr__(self):
53
+ return f"Flake8Error(filename={self.filename}, line_number={self.line_number}, col_number={self.col_number}, problem={self.problem})"
54
+
55
+
56
+ def _update_previous_errors(
57
+ previous_errors: list[Flake8Error],
58
+ replacement_window: tuple[int, int],
59
+ replacement_n_lines: int,
60
+ ) -> list[Flake8Error]:
61
+ """Update the line numbers of the previous errors to what they would be after the edit window.
62
+ This is a helper function for `_filter_previous_errors`.
63
+
64
+ All previous errors that are inside of the edit window should not be ignored,
65
+ so they are removed from the previous errors list.
66
+
67
+ Args:
68
+ previous_errors: list of errors with old line numbers
69
+ replacement_window: the window of the edit/lines that will be replaced
70
+ replacement_n_lines: the number of lines that will be used to replace the text
71
+
72
+ Returns:
73
+ list of errors with updated line numbers
74
+ """
75
+ updated = []
76
+ lines_added = replacement_n_lines - (replacement_window[1] - replacement_window[0] + 1)
77
+ for error in previous_errors:
78
+ if error.line_number < replacement_window[0]:
79
+ # no need to adjust the line number
80
+ updated.append(error)
81
+ continue
82
+ if replacement_window[0] <= error.line_number <= replacement_window[1]:
83
+ # The error is within the edit window, so let's not ignore it
84
+ # either way (we wouldn't know how to adjust the line number anyway)
85
+ continue
86
+ # We're out of the edit window, so we need to adjust the line number
87
+ updated.append(Flake8Error(error.filename, error.line_number + lines_added, error.col_number, error.problem))
88
+ return updated
89
+
90
+
91
+ def format_flake8_output(
92
+ input_string: str,
93
+ show_line_numbers: bool = False,
94
+ *,
95
+ previous_errors_string: str = "",
96
+ replacement_window: tuple[int, int] | None = None,
97
+ replacement_n_lines: int | None = None,
98
+ ) -> str:
99
+ """Filter flake8 output for previous errors and print it for a given file.
100
+
101
+ Args:
102
+ input_string: The flake8 output as a string
103
+ show_line_numbers: Whether to show line numbers in the output
104
+ previous_errors_string: The previous errors as a string
105
+ replacement_window: The window of the edit (lines that will be replaced)
106
+ replacement_n_lines: The number of lines used to replace the text
107
+
108
+ Returns:
109
+ The filtered flake8 output as a string
110
+ """
111
+ errors = [Flake8Error.from_line(line.strip()) for line in input_string.split("\n") if line.strip()]
112
+ # print(f"New errors before filtering: {errors=}")
113
+ lines = []
114
+ if previous_errors_string:
115
+ assert replacement_window is not None
116
+ assert replacement_n_lines is not None
117
+ previous_errors = [
118
+ Flake8Error.from_line(line.strip()) for line in previous_errors_string.split("\n") if line.strip()
119
+ ]
120
+ # print(f"Previous errors before updating: {previous_errors=}")
121
+ previous_errors = _update_previous_errors(previous_errors, replacement_window, replacement_n_lines)
122
+ # print(f"Previous errors after updating: {previous_errors=}")
123
+ errors = [error for error in errors if error not in previous_errors]
124
+ # Sometimes new errors appear above the replacement window that were 'shadowed' by the previous errors
125
+ # they still clearly aren't caused by the edit.
126
+ errors = [error for error in errors if error.line_number >= replacement_window[0]]
127
+ # print(f"New errors after filtering: {errors=}")
128
+ for error in errors:
129
+ if not show_line_numbers:
130
+ lines.append(f"- {error.problem}")
131
+ else:
132
+ lines.append(f"- line {error.line_number} col {error.col_number}: {error.problem}")
133
+ return "\n".join(lines)
134
+
135
+
136
+ def flake8(file_path: str) -> str:
137
+ """Run flake8 on a given file and return the output as a string"""
138
+ if Path(file_path).suffix != ".py":
139
+ return ""
140
+ cmd = registry.get("LINT_COMMAND", "flake8 --isolated --select=F821,F822,F831,E111,E112,E113,E999,E902 {file_path}")
141
+ out = subprocess.run(
142
+ cmd.format(file_path=file_path),
143
+ shell=True,
144
+ capture_output=True,
145
+ text=True,
146
+ )
147
+ return out.stdout