@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,155 @@
1
+ tools:
2
+ open_site:
3
+ signature: "open_site <url>"
4
+ docstring: "Open the specified website URL or local file path"
5
+ arguments:
6
+ - name: url
7
+ type: string
8
+ description: "The URL to open (can be a web URL or file path)"
9
+ required: true
10
+
11
+ close_site:
12
+ signature: "close_site"
13
+ docstring: "Close the currently open browser window"
14
+ arguments: []
15
+
16
+ screenshot_site:
17
+ signature: "screenshot_site"
18
+ docstring: "Take a screenshot of the current page"
19
+ arguments: []
20
+
21
+ click_mouse:
22
+ signature: "click_mouse <x> <y> [<button>]"
23
+ docstring: "Click at the specified coordinates (shown as a red crosshair) on the current page"
24
+ arguments:
25
+ - name: x
26
+ type: integer
27
+ description: "X coordinate"
28
+ required: true
29
+ - name: y
30
+ type: integer
31
+ description: "Y coordinate"
32
+ required: true
33
+ - name: button
34
+ type: string
35
+ description: "Mouse button to click (left or right, default: left)"
36
+ required: false
37
+ enum: ["left", "right"]
38
+
39
+ double_click_mouse:
40
+ signature: "double_click_mouse <x> <y>"
41
+ docstring: "Double-click at the specified coordinates (shown as a red crosshair) on the current page"
42
+ arguments:
43
+ - name: x
44
+ type: integer
45
+ description: "X coordinate"
46
+ required: true
47
+ - name: y
48
+ type: integer
49
+ description: "Y coordinate"
50
+ required: true
51
+
52
+ move_mouse:
53
+ signature: "move_mouse <x> <y>"
54
+ docstring: "Move mouse to the specified coordinates (shown as a red crosshair) on the current page"
55
+ arguments:
56
+ - name: x
57
+ type: integer
58
+ description: "X coordinate"
59
+ required: true
60
+ - name: y
61
+ type: integer
62
+ description: "Y coordinate"
63
+ required: true
64
+
65
+ drag_mouse:
66
+ signature: "drag_mouse <path>"
67
+ docstring: "Drag mouse along a path (JSON format: [[x1,y1],[x2,y2],...]) on the current page"
68
+ arguments:
69
+ - name: path
70
+ type: string
71
+ description: "JSON array of coordinate pairs for the drag path (e.g., '[[0,0],[100,100]]')"
72
+ required: true
73
+
74
+ type_text:
75
+ signature: "type_text <text>"
76
+ docstring: "Type the given text at the current focused element on the current page"
77
+ arguments:
78
+ - name: text
79
+ type: string
80
+ description: "Text to type"
81
+ required: true
82
+
83
+ scroll_on_page:
84
+ signature: "scroll_on_page <scroll_x> <scroll_y>"
85
+ docstring: "Scroll by the specified number of pixels on the current page"
86
+ arguments:
87
+ - name: scroll_x
88
+ type: integer
89
+ description: "Horizontal scroll amount in pixels"
90
+ required: true
91
+ - name: scroll_y
92
+ type: integer
93
+ description: "Vertical scroll amount in pixels"
94
+ required: true
95
+
96
+ execute_script_on_page:
97
+ signature: "execute_script_on_page <script>"
98
+ docstring: "Execute a custom JavaScript code snippet on the current page"
99
+ arguments:
100
+ - name: script
101
+ type: string
102
+ description: "JavaScript code to execute"
103
+ required: true
104
+
105
+ navigate_back:
106
+ signature: "navigate_back"
107
+ docstring: "Navigate back in the browser history"
108
+ arguments: []
109
+
110
+ navigate_forward:
111
+ signature: "navigate_forward"
112
+ docstring: "Navigate forward in the browser history"
113
+ arguments: []
114
+
115
+ reload_page:
116
+ signature: "reload_page"
117
+ docstring: "Reload the current webpage"
118
+ arguments: []
119
+
120
+ wait_time:
121
+ signature: "wait_time <ms>"
122
+ docstring: "Wait for the specified number of milliseconds"
123
+ arguments:
124
+ - name: ms
125
+ type: integer
126
+ description: "Time to wait in milliseconds"
127
+ required: true
128
+
129
+ press_keys_on_page:
130
+ signature: "press_keys_on_page <keys>"
131
+ docstring: "Press the specified keys (JSON format: [\"key1\", \"key2\"]) on the current page"
132
+ arguments:
133
+ - name: keys
134
+ type: string
135
+ description: "JSON array of keys to press (e.g., '[\"ctrl\", \"c\"]')"
136
+ required: true
137
+
138
+ set_browser_window_size:
139
+ signature: "set_browser_window_size <width> <height>"
140
+ docstring: "Set the browser window size to the specified dimensions"
141
+ arguments:
142
+ - name: width
143
+ type: integer
144
+ description: "Window width in pixels"
145
+ required: true
146
+ - name: height
147
+ type: integer
148
+ description: "Window height in pixels"
149
+ required: true
150
+
151
+
152
+ get_console_output:
153
+ signature: "get_console_output"
154
+ docstring: "Get console output messages from the browser (logs, errors, warnings, etc.)"
155
+ arguments: []
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env bash
2
+
3
+ /root/python3.11/bin/python3 -m pip install flask requests playwright
4
+ /root/python3.11/bin/python3 -m playwright install-deps chromium
5
+
6
+ if [ -f /usr/bin/google-chrome ]; then
7
+ export WEB_BROWSER_CHROMIUM_EXECUTABLE_PATH=/usr/bin/google-chrome
8
+ elif [ -f /usr/bin/chromium ]; then
9
+ export WEB_BROWSER_CHROMIUM_EXECUTABLE_PATH=/usr/bin/chromium
10
+ elif [ -f /usr/bin/google-chrome-stable ]; then
11
+ export WEB_BROWSER_CHROMIUM_EXECUTABLE_PATH=/usr/bin/google-chrome-stable
12
+ else
13
+ /root/python3.11/bin/python3 -m playwright install chromium
14
+ fi
15
+
16
+ export WEB_BROWSER_SCREENSHOT_MODE=print
17
+
18
+ export WEB_BROWSER_PORT=19321
19
+
20
+ mkdir -p /root/.web_browser_logs
21
+
22
+ run_web_browser_server &> /root/.web_browser_logs/web-browser-server.log &
@@ -0,0 +1,404 @@
1
+ from __future__ import annotations
2
+
3
+ import base64
4
+ import contextlib
5
+ import threading
6
+ import time
7
+ from pathlib import Path
8
+ from typing import Any
9
+
10
+ from playwright.sync_api import Browser, Page, Playwright, sync_playwright
11
+ from web_browser_config import ServerConfig
12
+
13
+ config = ServerConfig()
14
+
15
+ SUPPORTED_BROWSERS = {"chromium", "firefox"}
16
+
17
+ CROSSHAIR_JS = """
18
+ ([x, y, id]) => {
19
+ const size = 20;
20
+ const thickness = 3;
21
+ const hId = id + '_h';
22
+ const vId = id + '_v';
23
+
24
+ const createLine = (elementId, styles) => {
25
+ let line = document.getElementById(elementId);
26
+ if (!line) {
27
+ line = document.createElement('div');
28
+ line.id = elementId;
29
+ Object.assign(line.style, {
30
+ position: 'fixed',
31
+ pointerEvents: 'none',
32
+ zIndex: '2147483647',
33
+ backgroundColor: 'red',
34
+ boxSizing: 'border-box',
35
+ margin: '0',
36
+ padding: '0',
37
+ border: 'none',
38
+ outline: 'none',
39
+ transform: 'translateZ(0)',
40
+ ...styles
41
+ });
42
+ document.body.appendChild(line);
43
+ }
44
+ return line;
45
+ };
46
+
47
+ const hLine = createLine(hId, {
48
+ width: `${size}px`,
49
+ height: `${thickness}px`,
50
+ left: `${Math.round(x - size / 2)}px`,
51
+ top: `${Math.round(y - thickness / 2)}px`
52
+ });
53
+
54
+ const vLine = createLine(vId, {
55
+ width: `${thickness}px`,
56
+ height: `${size}px`,
57
+ left: `${Math.round(x - thickness / 2)}px`,
58
+ top: `${Math.round(y - size / 2)}px`
59
+ });
60
+ }
61
+ """
62
+
63
+
64
+ REMOVE_CROSSHAIR_JS = """
65
+ (id) => {
66
+ const hEl = document.getElementById(id + '_h');
67
+ const vEl = document.getElementById(id + '_v');
68
+ if (hEl) hEl.remove();
69
+ if (vEl) vEl.remove();
70
+ }
71
+ """
72
+
73
+
74
+ KEY_MAP = {
75
+ # Function keys
76
+ "f1": "F1",
77
+ "f2": "F2",
78
+ "f3": "F3",
79
+ "f4": "F4",
80
+ "f5": "F5",
81
+ "f6": "F6",
82
+ "f7": "F7",
83
+ "f8": "F8",
84
+ "f9": "F9",
85
+ "f10": "F10",
86
+ "f11": "F11",
87
+ "f12": "F12",
88
+ # Number keys (top row)
89
+ "0": "Digit0",
90
+ "1": "Digit1",
91
+ "2": "Digit2",
92
+ "3": "Digit3",
93
+ "4": "Digit4",
94
+ "5": "Digit5",
95
+ "6": "Digit6",
96
+ "7": "Digit7",
97
+ "8": "Digit8",
98
+ "9": "Digit9",
99
+ # Letter keys
100
+ "a": "KeyA",
101
+ "b": "KeyB",
102
+ "c": "KeyC",
103
+ "d": "KeyD",
104
+ "e": "KeyE",
105
+ "f": "KeyF",
106
+ "g": "KeyG",
107
+ "h": "KeyH",
108
+ "i": "KeyI",
109
+ "j": "KeyJ",
110
+ "k": "KeyK",
111
+ "l": "KeyL",
112
+ "m": "KeyM",
113
+ "n": "KeyN",
114
+ "o": "KeyO",
115
+ "p": "KeyP",
116
+ "q": "KeyQ",
117
+ "r": "KeyR",
118
+ "s": "KeyS",
119
+ "t": "KeyT",
120
+ "u": "KeyU",
121
+ "v": "KeyV",
122
+ "w": "KeyW",
123
+ "x": "KeyX",
124
+ "y": "KeyY",
125
+ "z": "KeyZ",
126
+ # Arrow keys
127
+ "up": "ArrowUp",
128
+ "down": "ArrowDown",
129
+ "left": "ArrowLeft",
130
+ "right": "ArrowRight",
131
+ "arrow_up": "ArrowUp",
132
+ "arrow_down": "ArrowDown",
133
+ "arrow_left": "ArrowLeft",
134
+ "arrow_right": "ArrowRight",
135
+ # Navigation keys
136
+ "home": "Home",
137
+ "end": "End",
138
+ "page_up": "PageUp",
139
+ "page_down": "PageDown",
140
+ "pageup": "PageUp",
141
+ "pagedown": "PageDown",
142
+ # Editing keys
143
+ "backspace": "Backspace",
144
+ "delete": "Delete",
145
+ "insert": "Insert",
146
+ "enter": "Enter",
147
+ "return": "Enter",
148
+ "tab": "Tab",
149
+ "escape": "Escape",
150
+ "esc": "Escape",
151
+ # Modifier keys
152
+ "shift": "Shift",
153
+ "ctrl": "Control",
154
+ "control": "Control",
155
+ "alt": "Alt",
156
+ "meta": "Meta",
157
+ "shift_left": "ShiftLeft",
158
+ "ctrl_or_meta": "ControlOrMeta",
159
+ "control_or_meta": "ControlOrMeta",
160
+ # Punctuation and symbols
161
+ "space": " ",
162
+ "spacebar": " ",
163
+ "backquote": "Backquote",
164
+ "`": "Backquote",
165
+ "backtick": "Backquote",
166
+ "minus": "Minus",
167
+ "-": "Minus",
168
+ "dash": "Minus",
169
+ "equal": "Equal",
170
+ "=": "Equal",
171
+ "equals": "Equal",
172
+ "backslash": "Backslash",
173
+ "\\": "Backslash",
174
+ "bracket_left": "BracketLeft",
175
+ "[": "BracketLeft",
176
+ "bracket_right": "BracketRight",
177
+ "]": "BracketRight",
178
+ "semicolon": "Semicolon",
179
+ ";": "Semicolon",
180
+ "quote": "Quote",
181
+ "'": "Quote",
182
+ "apostrophe": "Quote",
183
+ "comma": "Comma",
184
+ ",": "Comma",
185
+ "period": "Period",
186
+ ".": "Period",
187
+ "dot": "Period",
188
+ "slash": "Slash",
189
+ "/": "Slash",
190
+ # Numpad keys
191
+ "numpad_0": "Numpad0",
192
+ "numpad_1": "Numpad1",
193
+ "numpad_2": "Numpad2",
194
+ "numpad_3": "Numpad3",
195
+ "numpad_4": "Numpad4",
196
+ "numpad_5": "Numpad5",
197
+ "numpad_6": "Numpad6",
198
+ "numpad_7": "Numpad7",
199
+ "numpad_8": "Numpad8",
200
+ "numpad_9": "Numpad9",
201
+ "numpad_add": "NumpadAdd",
202
+ "numpad_subtract": "NumpadSubtract",
203
+ "numpad_multiply": "NumpadMultiply",
204
+ "numpad_divide": "NumpadDivide",
205
+ "numpad_decimal": "NumpadDecimal",
206
+ "numpad_enter": "NumpadEnter",
207
+ # Lock keys
208
+ "caps_lock": "CapsLock",
209
+ "capslock": "CapsLock",
210
+ "num_lock": "NumLock",
211
+ "numlock": "NumLock",
212
+ "scroll_lock": "ScrollLock",
213
+ "scrolllock": "ScrollLock",
214
+ # Common combinations (case-insensitive aliases)
215
+ "ENTER": "Enter",
216
+ "ESCAPE": "Escape",
217
+ "BACKSPACE": "Backspace",
218
+ "DELETE": "Delete",
219
+ "TAB": "Tab",
220
+ "SPACE": " ",
221
+ "UP": "ArrowUp",
222
+ "DOWN": "ArrowDown",
223
+ "LEFT": "ArrowLeft",
224
+ "RIGHT": "ArrowRight",
225
+ "HOME": "Home",
226
+ "END": "End",
227
+ }
228
+
229
+
230
+ class BrowserManager:
231
+ """Manages Playwright browser instance with proper resource cleanup."""
232
+
233
+ def __init__(self):
234
+ self.headless = config.headless
235
+ self.browser_type = self._validate_browser_type(config.browser_type)
236
+ self.page: Page | None = None
237
+ self.screenshot_index = 0
238
+ self.mouse_x = 0
239
+ self.mouse_y = 0
240
+ self._lock = threading.RLock()
241
+ self.window_width = config.window_width
242
+ self.window_height = config.window_height
243
+ self.screenshot_delay = config.screenshot_delay
244
+ self.reconnect_timeout = config.reconnect_timeout
245
+ self.crosshair_id = config.crosshair_id
246
+ self.console_messages: list[dict[str, Any]] = []
247
+ self._init_browser()
248
+
249
+ def _validate_browser_type(self, browser_type: str) -> str:
250
+ """Validate and return the browser type."""
251
+ browser_type = browser_type.lower()
252
+ if browser_type not in SUPPORTED_BROWSERS:
253
+ msg = (
254
+ f"Unsupported browser type: {browser_type}. Supported browsers: {', '.join(sorted(SUPPORTED_BROWSERS))}"
255
+ )
256
+ raise ValueError(msg)
257
+ return browser_type
258
+
259
+ def _init_browser(self):
260
+ self.playwright: Playwright = sync_playwright().start()
261
+ browser_launcher = getattr(self.playwright, self.browser_type)
262
+ executable_path = None
263
+ if self.browser_type == "chromium" and config.chromium_executable_path:
264
+ executable_path = config.chromium_executable_path
265
+ elif self.browser_type == "firefox" and config.firefox_executable_path:
266
+ executable_path = config.firefox_executable_path
267
+ launch_options = {"headless": self.headless}
268
+ if executable_path and Path(executable_path).exists():
269
+ launch_options["executable_path"] = executable_path
270
+ elif executable_path:
271
+ print(f"Warning: Executable path '{executable_path}' does not exist, using default browser")
272
+ self.browser: Browser = browser_launcher.launch(**launch_options)
273
+
274
+ @property
275
+ def browser_name(self) -> str:
276
+ """Get the name of the browser."""
277
+ return self.browser.browser_type.name
278
+
279
+ @contextlib.contextmanager
280
+ def _browser_lock(self):
281
+ """Context manager for thread-safe browser operations."""
282
+ with self._lock:
283
+ yield self._ensure_browser()
284
+
285
+ def _ensure_browser(self) -> Page:
286
+ """Launch Chromium lazily and move cursor to (0,0) once."""
287
+ if self.page is not None:
288
+ return self.page
289
+ ctx = self.browser.new_context(viewport={"width": self.window_width, "height": self.window_height})
290
+ self.page = ctx.new_page()
291
+ self._setup_console_listener(self.page)
292
+ self.page.mouse.move(0, 0)
293
+ self.mouse_x = self.mouse_y = 0
294
+ return self.page
295
+
296
+ def is_website_open(self) -> bool:
297
+ """Check if a website is currently open."""
298
+ return self.page is not None and self.page.url not in (None, "about:blank", "")
299
+
300
+ def cleanup(self):
301
+ """Clean up browser resources safely."""
302
+ with self._lock:
303
+ for resource, name in [(self.page, "page"), (self.browser, "browser"), (self.playwright, "playwright")]:
304
+ if resource is not None:
305
+ try:
306
+ if name == "playwright":
307
+ resource.stop()
308
+ else:
309
+ resource.close()
310
+ except Exception:
311
+ pass # Ignore cleanup errors
312
+
313
+ self.browser = self.page = self.playwright = None
314
+
315
+ def _inject_crosshair(self, page: Page, x: int, y: int) -> bool:
316
+ """Inject crosshair at given coordinates. Returns True if successful."""
317
+ try:
318
+ page.evaluate(CROSSHAIR_JS, [x, y, self.crosshair_id])
319
+ return True
320
+ except Exception:
321
+ return False
322
+
323
+ def _remove_crosshair(self, page: Page) -> None:
324
+ """Remove crosshair elements from the page."""
325
+ try:
326
+ page.evaluate(REMOVE_CROSSHAIR_JS, self.crosshair_id)
327
+ except Exception:
328
+ pass
329
+
330
+ def take_screenshot(self) -> dict[str, Any]:
331
+ """Capture screenshot with crosshair."""
332
+ with self._browser_lock() as page:
333
+ # this retry logic is a hack to ensure the page is loaded
334
+ # (at least enough to inject the crosshair)
335
+ timeout = time.time() + self.reconnect_timeout
336
+ while time.time() < timeout:
337
+ if self._inject_crosshair(page, self.mouse_x, self.mouse_y):
338
+ break
339
+ time.sleep(max(0.3, self.screenshot_delay))
340
+ time.sleep(self.screenshot_delay)
341
+ screenshot_data = page.screenshot(type="png")
342
+ self._remove_crosshair(page)
343
+ self.screenshot_index += 1
344
+ return {
345
+ "screenshot": base64.b64encode(screenshot_data).decode(),
346
+ "screenshot_index": self.screenshot_index,
347
+ }
348
+
349
+ def validate_coordinates(self, x: int, y: int) -> tuple[bool, bool]:
350
+ x_is_valid = 0 <= x <= self.window_width
351
+ y_is_valid = 0 <= y <= self.window_height
352
+ return (x_is_valid, y_is_valid)
353
+
354
+ def constrain_mouse_position(self, page: Page) -> bool:
355
+ """Constrain mouse position to window bounds and move if needed."""
356
+ if self.window_width <= 0 or self.window_height <= 0:
357
+ return False
358
+ if self.mouse_x >= self.window_width or self.mouse_y >= self.window_height:
359
+ self.mouse_x = min(self.mouse_x, self.window_width - 1)
360
+ self.mouse_y = min(self.mouse_y, self.window_height - 1)
361
+ self.mouse_x = max(0, self.mouse_x)
362
+ self.mouse_y = max(0, self.mouse_y)
363
+ page.mouse.move(self.mouse_x, self.mouse_y)
364
+ return True
365
+ return False
366
+
367
+ def get_key(self, key: str) -> str:
368
+ """Get the key from the key map."""
369
+ if key.lower() in KEY_MAP:
370
+ return KEY_MAP[key.lower()]
371
+ msg = f"Key {key} not found. Supported keys: {', '.join(KEY_MAP.keys())}"
372
+ raise ValueError(msg)
373
+
374
+ def key_down(self, key: str):
375
+ """Press and hold a key."""
376
+ playwright_key = self.get_key(key)
377
+ self.page.keyboard.down(playwright_key)
378
+
379
+ def key_press(self, key: str):
380
+ """Press a key."""
381
+ playwright_key = self.get_key(key)
382
+ self.page.keyboard.press(playwright_key)
383
+
384
+ def key_up(self, key: str):
385
+ """Release a key."""
386
+ playwright_key = self.get_key(key)
387
+ self.page.keyboard.up(playwright_key)
388
+
389
+ def _setup_console_listener(self, page: Page):
390
+ """Set up console message listener for the page."""
391
+
392
+ def on_console(msg):
393
+ self.console_messages.append(
394
+ {"type": msg.type, "text": msg.text, "timestamp": time.time(), "location": msg.location}
395
+ )
396
+
397
+ page.on("console", on_console)
398
+
399
+ def get_console_output(self) -> list[dict[str, Any]]:
400
+ """Get all console messages and clear the buffer."""
401
+ with self._lock:
402
+ messages = self.console_messages.copy()
403
+ self.console_messages.clear()
404
+ return messages
@@ -0,0 +1,33 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ from dataclasses import dataclass
5
+
6
+ from web_browser_utils import ScreenshotMode
7
+
8
+
9
+ @dataclass
10
+ class ClientConfig:
11
+ """Configuration for the web_browser client"""
12
+
13
+ port: int = int(os.getenv("WEB_BROWSER_PORT", "8009"))
14
+ autoscreenshot: bool = os.getenv("WEB_BROWSER_AUTOSCREENSHOT", "1") == "1"
15
+ screenshot_mode: ScreenshotMode = ScreenshotMode(
16
+ os.getenv("WEB_BROWSER_SCREENSHOT_MODE", ScreenshotMode.SAVE.value)
17
+ )
18
+
19
+
20
+ @dataclass
21
+ class ServerConfig:
22
+ """Configuration for the web_browser server"""
23
+
24
+ port: int = int(os.getenv("WEB_BROWSER_PORT", "8009"))
25
+ window_width: int = int(os.getenv("WEB_BROWSER_WINDOW_WIDTH", 1024))
26
+ window_height: int = int(os.getenv("WEB_BROWSER_WINDOW_HEIGHT", 768))
27
+ headless: bool = os.getenv("WEB_BROWSER_HEADLESS", "1") != "0"
28
+ screenshot_delay: float = float(os.getenv("WEB_BROWSER_SCREENSHOT_DELAY", 0.2))
29
+ browser_type: str = os.getenv("WEB_BROWSER_BROWSER_TYPE", "chromium")
30
+ reconnect_timeout: float = float(os.getenv("WEB_BROWSER_RECONNECT_TIMEOUT", 15))
31
+ chromium_executable_path: str | None = os.getenv("WEB_BROWSER_CHROMIUM_EXECUTABLE_PATH")
32
+ firefox_executable_path: str | None = os.getenv("WEB_BROWSER_FIREFOX_EXECUTABLE_PATH")
33
+ crosshair_id: str = "__web_browser_crosshair__"