synth-ai 0.2.13.dev1__py3-none-any.whl → 0.2.14__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of synth-ai might be problematic. Click here for more details.
- examples/multi_step/configs/README_verilog_rl.md +77 -0
- examples/multi_step/configs/VERILOG_REWARDS.md +90 -0
- examples/multi_step/configs/VERILOG_RL_CHECKLIST.md +183 -0
- examples/multi_step/configs/crafter_eval_synth_qwen4b.toml +35 -0
- examples/multi_step/configs/crafter_eval_text_only_groq_qwen32b.toml +36 -0
- examples/multi_step/configs/crafter_rl_stepwise_hosted_judge.toml +17 -5
- examples/multi_step/configs/crafter_synth_backend.md +40 -0
- examples/multi_step/configs/verilog_eval_groq_qwen32b.toml +31 -0
- examples/multi_step/configs/verilog_eval_synth_qwen8b.toml +33 -0
- examples/multi_step/configs/verilog_rl_lora.toml +190 -0
- examples/multi_step/judges/crafter_backend_judge.py +220 -0
- examples/multi_step/judges/verilog_backend_judge.py +234 -0
- examples/multi_step/readme.md +48 -0
- examples/multi_step/verilog_rl_lora.md +218 -0
- examples/qwen_coder/configs/coder_lora_30b.toml +1 -1
- examples/sft/evaluate.py +2 -0
- examples/sft/generate_traces.py +2 -0
- examples/swe/task_app/grpo_swe_mini.py +56 -26
- examples/swe/task_app/hosted/rollout.py +42 -0
- examples/swe/task_app/hosted/test_service.py +5 -6
- examples/task_apps/IMAGE_ONLY_EVAL_QUICKSTART.md +258 -0
- examples/task_apps/TESTING.md +275 -0
- examples/task_apps/__init__.py +0 -0
- examples/task_apps/crafter/CREATE_SFT_DATASET.md +273 -0
- examples/task_apps/crafter/EVAL_IMAGE_ONLY_RESULTS.md +152 -0
- examples/task_apps/crafter/FILTER_COMMAND_STATUS.md +174 -0
- examples/task_apps/crafter/FILTER_COMMAND_SUCCESS.md +268 -0
- examples/task_apps/crafter/QUERY_EXAMPLES.md +203 -0
- examples/task_apps/crafter/README_IMAGE_ONLY_EVAL.md +316 -0
- examples/task_apps/crafter/__init__.py +0 -0
- examples/task_apps/crafter/eval_image_only_gpt4o.toml +28 -0
- examples/task_apps/crafter/eval_text_only_groq_llama.toml +36 -0
- examples/task_apps/crafter/filter_sft_dataset.toml +16 -0
- examples/task_apps/crafter/task_app/__init__.py +5 -0
- examples/{warming_up_to_rl → task_apps/crafter}/task_app/grpo_crafter.py +324 -21
- examples/{warming_up_to_rl → task_apps/crafter}/task_app/grpo_crafter_task_app.py +1 -1
- examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/envs/crafter/environment.py +10 -0
- examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/envs/crafter/policy.py +76 -7
- examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/envs/crafter/react_agent.py +17 -2
- examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/inference/openai_client.py +25 -3
- examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/policy_routes.py +77 -4
- examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/rollout.py +117 -9
- examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/test_service.py +5 -6
- examples/task_apps/crafter/task_app/synth_envs_hosted/utils.py +218 -0
- examples/task_apps/dev/pokemon_emerald/__init__.py +2 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/README.md +811 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/__init__.py +120 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/action.py +160 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/memory.py +155 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/perception.py +69 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/planning.py +96 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/simple.py +1502 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/system_prompt.py +4 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/grab_map.py +68 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/manual.py +216 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/__init__.py +35 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/emerald_utils.py +631 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/emulator.py +1544 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/enums.py +1428 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/memory_reader.py +4848 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/types.py +41 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/utils.py +298 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pyproject.toml +95 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/run.py +204 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/server/__init__.py +0 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/server/app.py +2152 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/server/client.py +429 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/server/frame_server.py +155 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/README.md +78 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/__init__.py +0 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/run_tests.py +122 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_agent_direct.py +76 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_agent_prompts.py +413 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_battle_state_formatting.py +204 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_dialogue_detection.py +133 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_dialogue_detection_comprehensive.py +229 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_direct_agent_emulator.py +300 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_fps_adjustment_pytest.py +205 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_house_to_outside_direct.py +200 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_house_to_outside_transition.py +284 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_map_ground_truth_comparison.py +468 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_memory_map.py +575 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_server_map_validation.py +311 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_torchic_state.py +259 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/__init__.py +0 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/anticheat.py +372 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/checkpoint.py +296 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/error_handler.py +275 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/get_local_ip.py +22 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/helpers.py +44 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/llm_logger.py +514 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/map_formatter.py +415 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/map_stitcher.py +1763 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/map_stitcher_singleton.py +33 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/map_trimmer.py +106 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/map_visualizer.py +334 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/ocr_dialogue.py +1020 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/recording.py +188 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/state_formatter.py +1481 -0
- examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/vlm.py +862 -0
- examples/task_apps/dev/pokemon_emerald/modal_app.py +114 -0
- examples/task_apps/dev/pokemon_emerald/task_app/README.md +81 -0
- examples/task_apps/dev/pokemon_emerald/task_app/__init__.py +6 -0
- examples/task_apps/dev/pokemon_emerald/task_app/pokemon_emerald.py +685 -0
- examples/task_apps/enron/__init__.py +1 -0
- examples/task_apps/enron/eval_groq_qwen32.toml +16 -0
- examples/task_apps/enron/filter_sft.toml +5 -0
- examples/task_apps/enron/task_app/README.md +14 -0
- examples/task_apps/enron/task_app/__init__.py +1 -0
- examples/task_apps/enron/task_app/grpo_enron.py +906 -0
- examples/task_apps/enron/task_app/grpo_enron_task_app.py +146 -0
- examples/task_apps/enron/tests/__init__.py +4 -0
- examples/task_apps/enron/tests/conftest.py +115 -0
- examples/task_apps/enron/tests/integration/__init__.py +4 -0
- examples/task_apps/enron/tests/integration/test_enron_eval.py +179 -0
- examples/task_apps/enron/tests/integration/test_enron_rollout.py +135 -0
- examples/task_apps/enron/tests/unit/__init__.py +4 -0
- examples/task_apps/enron/tests/unit/test_enron_environment.py +126 -0
- examples/task_apps/math/__init__.py +0 -0
- examples/{rl/task_app → task_apps/math}/math_single_step.py +19 -10
- examples/task_apps/pokemon_battle/__init__.py +2 -0
- examples/task_apps/pokemon_battle/modal_app.py +104 -0
- examples/task_apps/pokemon_battle/task_app/README.md +68 -0
- examples/task_apps/pokemon_battle/task_app/__init__.py +6 -0
- examples/task_apps/pokemon_battle/task_app/pokemon_showdown.py +932 -0
- examples/task_apps/pokemon_red/EVAL_IMAGE_ONLY_COMPLETE.md +283 -0
- examples/task_apps/pokemon_red/EVAL_IMAGE_ONLY_STATUS.md +155 -0
- examples/task_apps/pokemon_red/README.md +357 -0
- examples/task_apps/pokemon_red/README_IMAGE_ONLY_EVAL.md +415 -0
- examples/task_apps/pokemon_red/__init__.py +3 -0
- examples/task_apps/pokemon_red/eval_image_only_gpt4o.toml +29 -0
- examples/task_apps/pokemon_red/eval_pokemon_red_policy.py +225 -0
- examples/task_apps/pokemon_red/pallet_town_rl_config.toml +75 -0
- examples/task_apps/pokemon_red/task_app.py +799 -0
- examples/task_apps/pokemon_red/test_pallet_town_rewards.py +193 -0
- examples/task_apps/sokoban/README.md +307 -0
- examples/task_apps/sokoban/__init__.py +3 -0
- examples/task_apps/sokoban/eval_groq_qwen32.toml +16 -0
- examples/task_apps/sokoban/eval_openai_gpt5.toml +16 -0
- examples/task_apps/sokoban/filter_sft.toml +5 -0
- examples/task_apps/sokoban/task_app.py +1058 -0
- examples/task_apps/sokoban/tests/__init__.py +4 -0
- examples/task_apps/sokoban/tests/conftest.py +113 -0
- examples/task_apps/sokoban/tests/integration/__init__.py +4 -0
- examples/task_apps/sokoban/tests/integration/test_sokoban_eval.py +57 -0
- examples/task_apps/sokoban/tests/integration/test_sokoban_rollout.py +198 -0
- examples/task_apps/sokoban/tests/unit/__init__.py +4 -0
- examples/task_apps/sokoban/tests/unit/test_sokoban_environment.py +114 -0
- examples/task_apps/verilog/__init__.py +1 -0
- examples/task_apps/verilog/eval_groq_qwen32b.toml +24 -0
- examples/task_apps/verilog/filter_sft.toml +5 -0
- examples/task_apps/verilog/task_app/README.md +12 -0
- examples/task_apps/verilog/task_app/__init__.py +1 -0
- examples/task_apps/verilog/task_app/grpo_verilog.py +1166 -0
- examples/task_apps/verilog/task_app/grpo_verilog_task_app.py +145 -0
- examples/task_apps/verilog/tests/__init__.py +4 -0
- examples/task_apps/verilog/tests/conftest.py +115 -0
- examples/task_apps/verilog/tests/integration/__init__.py +4 -0
- examples/task_apps/verilog/tests/integration/test_verilog_eval.py +181 -0
- examples/task_apps/verilog/tests/integration/test_verilog_rollout.py +55 -0
- examples/task_apps/verilog/tests/unit/__init__.py +4 -0
- examples/task_apps/verilog/tests/unit/test_verilog_scoring.py +118 -0
- examples/vlm/crafter_openai_vlm_agent.py +4 -4
- examples/vlm/run_crafter_vlm_benchmark.py +4 -4
- examples/warming_up_to_rl/groq_test.py +2 -0
- examples/warming_up_to_rl/run_local_rollout.py +2 -0
- examples/warming_up_to_rl/run_local_rollout_modal.py +2 -0
- examples/warming_up_to_rl/run_local_rollout_parallel.py +2 -0
- examples/warming_up_to_rl/run_local_rollout_traced.py +2 -0
- examples/warming_up_to_rl/run_rollout_remote.py +2 -0
- examples/workflows/__init__.py +0 -0
- examples/workflows/math_rl/__init__.py +0 -0
- examples/workflows/math_rl/download_dataset.py +80 -0
- synth_ai/__init__.py +2 -2
- synth_ai/api/models/supported.py +1 -0
- synth_ai/api/train/builders.py +25 -11
- synth_ai/api/train/cli.py +12 -6
- synth_ai/api/train/configs/__init__.py +10 -10
- synth_ai/api/train/configs/rl.py +5 -4
- synth_ai/api/train/configs/sft.py +4 -3
- synth_ai/api/train/env_resolver.py +5 -2
- synth_ai/api/train/supported_algos.py +10 -5
- synth_ai/api/train/utils.py +7 -4
- synth_ai/cli/__init__.py +48 -59
- synth_ai/cli/_modal_wrapper.py +3 -2
- synth_ai/cli/_storage.py +4 -3
- synth_ai/cli/_validate_task_app.py +11 -0
- synth_ai/cli/balance.py +4 -3
- synth_ai/cli/calc.py +2 -2
- synth_ai/cli/demo.py +14 -7
- synth_ai/cli/legacy_root_backup.py +1 -1
- synth_ai/cli/recent.py +1 -1
- synth_ai/cli/rl_demo.py +8 -7
- synth_ai/cli/root.py +0 -97
- synth_ai/cli/status.py +1 -1
- synth_ai/cli/task_apps.py +1922 -190
- synth_ai/cli/traces.py +1 -1
- synth_ai/cli/tui.py +57 -0
- synth_ai/cli/turso.py +1 -1
- synth_ai/cli/watch.py +1 -1
- synth_ai/demos/demo_task_apps/crafter/grpo_crafter_task_app.py +29 -17
- synth_ai/environments/examples/crafter_classic/environment.py +1 -1
- synth_ai/environments/examples/enron/engine.py +7 -2
- synth_ai/environments/examples/enron/environment.py +68 -0
- synth_ai/environments/examples/red/engine.py +27 -0
- synth_ai/environments/examples/red/engine_helpers/memory_map.py +7 -0
- synth_ai/environments/examples/red/engine_helpers/reward_library/pallet_town_progression.py +477 -0
- synth_ai/environments/examples/red/engine_helpers/state_extraction.py +32 -0
- synth_ai/environments/examples/red/environment.py +60 -0
- synth_ai/environments/examples/sokoban/taskset.py +116 -0
- synth_ai/environments/examples/verilog/engine.py +104 -12
- synth_ai/evals/client.py +58 -61
- synth_ai/jobs/client.py +16 -4
- synth_ai/judge_schemas.py +9 -9
- synth_ai/py.typed +0 -0
- synth_ai/task/__init__.py +24 -5
- synth_ai/task/apps/__init__.py +1 -0
- synth_ai/task/config.py +257 -0
- synth_ai/task/contracts.py +138 -39
- synth_ai/task/proxy.py +48 -56
- synth_ai/task/rubrics/__init__.py +56 -0
- synth_ai/task/rubrics/loaders.py +152 -0
- synth_ai/task/rubrics/models.py +57 -0
- synth_ai/task/rubrics/scoring.py +116 -0
- synth_ai/{rubrics/validators.py → task/rubrics/strict.py} +53 -30
- synth_ai/task/server.py +8 -7
- synth_ai/task/trace_correlation_helpers.py +315 -0
- synth_ai/task/validators.py +413 -6
- synth_ai/tracing_v3/abstractions.py +3 -3
- synth_ai/tracing_v3/decorators.py +7 -3
- synth_ai/tracing_v3/llm_call_record_helpers.py +5 -5
- synth_ai/tracing_v3/replica_sync.py +4 -4
- synth_ai/tracing_v3/serialization.py +5 -5
- synth_ai/tracing_v3/session_tracer.py +16 -6
- synth_ai/tracing_v3/storage/base.py +29 -29
- synth_ai/tracing_v3/storage/config.py +3 -3
- synth_ai/tracing_v3/trace_utils.py +317 -0
- synth_ai/tracing_v3/turso/daemon.py +8 -7
- synth_ai/tracing_v3/turso/native_manager.py +66 -43
- synth_ai/tracing_v3/utils.py +3 -3
- synth_ai/tui/__init__.py +5 -0
- synth_ai/tui/__main__.py +13 -0
- synth_ai/tui/cli/__init__.py +1 -0
- synth_ai/tui/cli/query_experiments.py +164 -0
- synth_ai/tui/cli/query_experiments_v3.py +164 -0
- synth_ai/tui/dashboard.py +906 -0
- {synth_ai-0.2.13.dev1.dist-info → synth_ai-0.2.14.dist-info}/METADATA +4 -1
- {synth_ai-0.2.13.dev1.dist-info → synth_ai-0.2.14.dist-info}/RECORD +278 -126
- examples/agora_ex/README_MoE.md +0 -224
- examples/agora_ex/__init__.py +0 -7
- examples/agora_ex/agora_ex.py +0 -65
- examples/agora_ex/agora_ex_task_app.py +0 -590
- examples/agora_ex/configs/rl_lora_qwen3_moe_2xh200.toml +0 -121
- examples/agora_ex/reward_fn_grpo-human.py +0 -129
- examples/agora_ex/system_prompt_CURRENT.md +0 -63
- examples/agora_ex/task_app/agora_ex_task_app.py +0 -590
- examples/agora_ex/task_app/reward_fn_grpo-human.py +0 -129
- examples/agora_ex/task_app/system_prompt_CURRENT.md +0 -63
- examples/warming_up_to_rl/task_app/synth_envs_hosted/utils.py +0 -62
- synth_ai/rubrics/__init__.py +0 -22
- synth_ai/task/rubrics.py +0 -219
- /examples/{warming_up_to_rl → task_apps/crafter}/task_app/README.md +0 -0
- /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/README.md +0 -0
- /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/__init__.py +0 -0
- /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/branching.py +0 -0
- /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/environment_routes.py +0 -0
- /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/envs/__init__.py +0 -0
- /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/envs/crafter/__init__.py +0 -0
- /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/envs/crafter/app.py +0 -0
- /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/envs/crafter/shared.py +0 -0
- /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/envs/crafter/tools.py +0 -0
- /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/hosted_app.py +0 -0
- /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/inference/__init__.py +0 -0
- /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/main.py +0 -0
- /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/registry.py +0 -0
- /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/storage/__init__.py +0 -0
- /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/storage/volume.py +0 -0
- /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/test_agents.py +0 -0
- /examples/{rl/task_app → task_apps/math}/README.md +0 -0
- /examples/{rl/task_app → task_apps/math}/math_task_app.py +0 -0
- /examples/{rl → workflows/math_rl}/configs/eval_base_qwen.toml +0 -0
- /examples/{rl → workflows/math_rl}/configs/eval_rl_qwen.toml +0 -0
- /examples/{rl → workflows/math_rl}/configs/rl_from_base_qwen.toml +0 -0
- /examples/{rl → workflows/math_rl}/configs/rl_from_base_qwen17.toml +0 -0
- /examples/{rl → workflows/math_rl}/configs/rl_from_ft_qwen.toml +0 -0
- /examples/{rl → workflows/math_rl}/run_eval.py +0 -0
- /examples/{rl → workflows/math_rl}/run_rl_and_save.py +0 -0
- {synth_ai-0.2.13.dev1.dist-info → synth_ai-0.2.14.dist-info}/WHEEL +0 -0
- {synth_ai-0.2.13.dev1.dist-info → synth_ai-0.2.14.dist-info}/entry_points.txt +0 -0
- {synth_ai-0.2.13.dev1.dist-info → synth_ai-0.2.14.dist-info}/licenses/LICENSE +0 -0
- {synth_ai-0.2.13.dev1.dist-info → synth_ai-0.2.14.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Error handling and recovery utilities for the Pokemon agent.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
import sys
|
|
8
|
+
import time
|
|
9
|
+
import signal
|
|
10
|
+
import traceback
|
|
11
|
+
import subprocess
|
|
12
|
+
from typing import Optional, Callable
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ErrorHandler:
|
|
16
|
+
"""Manages error recovery and graceful shutdowns"""
|
|
17
|
+
|
|
18
|
+
def __init__(self, max_consecutive_errors=3, recovery_delay=2.0):
|
|
19
|
+
"""
|
|
20
|
+
Initialize error handler.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
max_consecutive_errors: Max errors before triggering recovery
|
|
24
|
+
recovery_delay: Delay in seconds before retrying after errors
|
|
25
|
+
"""
|
|
26
|
+
self.consecutive_errors = 0
|
|
27
|
+
self.max_consecutive_errors = max_consecutive_errors
|
|
28
|
+
self.recovery_delay = recovery_delay
|
|
29
|
+
self.total_errors = 0
|
|
30
|
+
self.shutdown_requested = False
|
|
31
|
+
|
|
32
|
+
# Callbacks
|
|
33
|
+
self.on_shutdown = None
|
|
34
|
+
self.on_recovery = None
|
|
35
|
+
|
|
36
|
+
# Install signal handlers
|
|
37
|
+
self._install_signal_handlers()
|
|
38
|
+
|
|
39
|
+
def _install_signal_handlers(self):
|
|
40
|
+
"""Install signal handlers for graceful shutdown"""
|
|
41
|
+
signal.signal(signal.SIGINT, self._signal_handler)
|
|
42
|
+
signal.signal(signal.SIGTERM, self._signal_handler)
|
|
43
|
+
|
|
44
|
+
def _signal_handler(self, signum, frame):
|
|
45
|
+
"""Handle shutdown signals"""
|
|
46
|
+
print(f"\n🛑 Received signal {signum}, initiating graceful shutdown...")
|
|
47
|
+
self.shutdown_requested = True
|
|
48
|
+
|
|
49
|
+
if self.on_shutdown:
|
|
50
|
+
try:
|
|
51
|
+
self.on_shutdown()
|
|
52
|
+
except:
|
|
53
|
+
pass
|
|
54
|
+
|
|
55
|
+
# Give a moment for cleanup
|
|
56
|
+
time.sleep(0.5)
|
|
57
|
+
sys.exit(0)
|
|
58
|
+
|
|
59
|
+
def handle_error(self, error: Exception, context: str = "") -> bool:
|
|
60
|
+
"""
|
|
61
|
+
Handle an error with potential recovery.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
error: The exception that occurred
|
|
65
|
+
context: Additional context about where the error occurred
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
bool: True if recovery should be attempted, False if fatal
|
|
69
|
+
"""
|
|
70
|
+
self.consecutive_errors += 1
|
|
71
|
+
self.total_errors += 1
|
|
72
|
+
|
|
73
|
+
# Log the error
|
|
74
|
+
print(f"❌ Error in {context}: {str(error)}")
|
|
75
|
+
if self.consecutive_errors > 1:
|
|
76
|
+
print(f" (Error {self.consecutive_errors}/{self.max_consecutive_errors})")
|
|
77
|
+
|
|
78
|
+
# Check if we should attempt recovery
|
|
79
|
+
if self.consecutive_errors >= self.max_consecutive_errors:
|
|
80
|
+
print(f"⚠️ Too many consecutive errors, initiating recovery...")
|
|
81
|
+
return self.attempt_recovery()
|
|
82
|
+
|
|
83
|
+
# Simple delay before continuing
|
|
84
|
+
time.sleep(self.recovery_delay)
|
|
85
|
+
return True
|
|
86
|
+
|
|
87
|
+
def attempt_recovery(self) -> bool:
|
|
88
|
+
"""
|
|
89
|
+
Attempt to recover from errors.
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
bool: True if recovery successful, False otherwise
|
|
93
|
+
"""
|
|
94
|
+
try:
|
|
95
|
+
print("🔄 Attempting recovery...")
|
|
96
|
+
|
|
97
|
+
# Call recovery callback if set
|
|
98
|
+
if self.on_recovery:
|
|
99
|
+
success = self.on_recovery()
|
|
100
|
+
if success:
|
|
101
|
+
self.reset_error_counter()
|
|
102
|
+
print("✅ Recovery successful")
|
|
103
|
+
return True
|
|
104
|
+
|
|
105
|
+
# Default recovery: just reset and continue
|
|
106
|
+
self.reset_error_counter()
|
|
107
|
+
time.sleep(self.recovery_delay * 2) # Longer delay for recovery
|
|
108
|
+
return True
|
|
109
|
+
|
|
110
|
+
except Exception as e:
|
|
111
|
+
print(f"❌ Recovery failed: {e}")
|
|
112
|
+
return False
|
|
113
|
+
|
|
114
|
+
def reset_error_counter(self):
|
|
115
|
+
"""Reset the consecutive error counter"""
|
|
116
|
+
if self.consecutive_errors > 0:
|
|
117
|
+
print(f"✅ Resetting error counter (was {self.consecutive_errors})")
|
|
118
|
+
self.consecutive_errors = 0
|
|
119
|
+
|
|
120
|
+
def track_success(self):
|
|
121
|
+
"""Track a successful operation to reset error counter"""
|
|
122
|
+
if self.consecutive_errors > 0:
|
|
123
|
+
self.consecutive_errors = 0
|
|
124
|
+
|
|
125
|
+
def is_shutdown_requested(self) -> bool:
|
|
126
|
+
"""Check if shutdown has been requested"""
|
|
127
|
+
return self.shutdown_requested
|
|
128
|
+
|
|
129
|
+
def get_error_stats(self) -> dict:
|
|
130
|
+
"""Get error statistics"""
|
|
131
|
+
return {
|
|
132
|
+
'consecutive_errors': self.consecutive_errors,
|
|
133
|
+
'total_errors': self.total_errors,
|
|
134
|
+
'max_consecutive': self.max_consecutive_errors
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class ServerRestartHandler:
|
|
139
|
+
"""Handles server process restart on failures"""
|
|
140
|
+
|
|
141
|
+
def __init__(self, restart_threshold=5):
|
|
142
|
+
"""
|
|
143
|
+
Initialize server restart handler.
|
|
144
|
+
|
|
145
|
+
Args:
|
|
146
|
+
restart_threshold: Number of failures before restart
|
|
147
|
+
"""
|
|
148
|
+
self.restart_threshold = restart_threshold
|
|
149
|
+
self.failure_count = 0
|
|
150
|
+
self.server_process = None
|
|
151
|
+
self.server_cmd = []
|
|
152
|
+
self.server_env = {}
|
|
153
|
+
|
|
154
|
+
def set_server_process(self, process: subprocess.Popen, cmd: list, env: dict = None):
|
|
155
|
+
"""
|
|
156
|
+
Set the server process to manage.
|
|
157
|
+
|
|
158
|
+
Args:
|
|
159
|
+
process: The subprocess.Popen instance
|
|
160
|
+
cmd: Command used to start the server
|
|
161
|
+
env: Environment variables for the server
|
|
162
|
+
"""
|
|
163
|
+
self.server_process = process
|
|
164
|
+
self.server_cmd = cmd
|
|
165
|
+
self.server_env = env or {}
|
|
166
|
+
|
|
167
|
+
def check_and_restart(self) -> bool:
|
|
168
|
+
"""
|
|
169
|
+
Check if restart is needed and perform it.
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
bool: True if restarted successfully
|
|
173
|
+
"""
|
|
174
|
+
self.failure_count += 1
|
|
175
|
+
|
|
176
|
+
if self.failure_count >= self.restart_threshold:
|
|
177
|
+
return self.restart_server()
|
|
178
|
+
|
|
179
|
+
return False
|
|
180
|
+
|
|
181
|
+
def restart_server(self) -> bool:
|
|
182
|
+
"""
|
|
183
|
+
Restart the server process.
|
|
184
|
+
|
|
185
|
+
Returns:
|
|
186
|
+
bool: True if restarted successfully
|
|
187
|
+
"""
|
|
188
|
+
if not self.server_cmd:
|
|
189
|
+
print("❌ No server command configured for restart")
|
|
190
|
+
return False
|
|
191
|
+
|
|
192
|
+
try:
|
|
193
|
+
print("🔄 Restarting server process...")
|
|
194
|
+
|
|
195
|
+
# Kill existing process
|
|
196
|
+
if self.server_process:
|
|
197
|
+
try:
|
|
198
|
+
self.server_process.terminate()
|
|
199
|
+
time.sleep(1)
|
|
200
|
+
if self.server_process.poll() is None:
|
|
201
|
+
self.server_process.kill()
|
|
202
|
+
except:
|
|
203
|
+
pass
|
|
204
|
+
|
|
205
|
+
# Start new process
|
|
206
|
+
self.server_process = subprocess.Popen(
|
|
207
|
+
self.server_cmd,
|
|
208
|
+
env={**os.environ, **self.server_env},
|
|
209
|
+
stdout=subprocess.PIPE,
|
|
210
|
+
stderr=subprocess.STDOUT,
|
|
211
|
+
universal_newlines=True,
|
|
212
|
+
bufsize=1
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
print(f"✅ Server restarted with PID {self.server_process.pid}")
|
|
216
|
+
|
|
217
|
+
# Give it time to initialize
|
|
218
|
+
time.sleep(3)
|
|
219
|
+
|
|
220
|
+
# Reset failure count
|
|
221
|
+
self.failure_count = 0
|
|
222
|
+
return True
|
|
223
|
+
|
|
224
|
+
except Exception as e:
|
|
225
|
+
print(f"❌ Failed to restart server: {e}")
|
|
226
|
+
return False
|
|
227
|
+
|
|
228
|
+
def reset_failure_count(self):
|
|
229
|
+
"""Reset the failure counter"""
|
|
230
|
+
self.failure_count = 0
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
# Global error handler instance
|
|
234
|
+
_error_handler = None
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def get_error_handler() -> ErrorHandler:
|
|
238
|
+
"""Get or create the global error handler"""
|
|
239
|
+
global _error_handler
|
|
240
|
+
if _error_handler is None:
|
|
241
|
+
_error_handler = ErrorHandler()
|
|
242
|
+
return _error_handler
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def handle_agent_error(error: Exception, context: str = "") -> bool:
|
|
246
|
+
"""
|
|
247
|
+
Handle an agent error using the global error handler.
|
|
248
|
+
|
|
249
|
+
Args:
|
|
250
|
+
error: The exception that occurred
|
|
251
|
+
context: Context about where the error occurred
|
|
252
|
+
|
|
253
|
+
Returns:
|
|
254
|
+
bool: True if recovery should be attempted
|
|
255
|
+
"""
|
|
256
|
+
handler = get_error_handler()
|
|
257
|
+
return handler.handle_error(error, context)
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def reset_error_counter():
|
|
261
|
+
"""Reset the global error counter"""
|
|
262
|
+
handler = get_error_handler()
|
|
263
|
+
handler.reset_error_counter()
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def install_shutdown_handler(callback: Optional[Callable] = None):
|
|
267
|
+
"""
|
|
268
|
+
Install a shutdown handler.
|
|
269
|
+
|
|
270
|
+
Args:
|
|
271
|
+
callback: Optional callback to run on shutdown
|
|
272
|
+
"""
|
|
273
|
+
handler = get_error_handler()
|
|
274
|
+
if callback:
|
|
275
|
+
handler.on_shutdown = callback
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Get local IP address for network interface display
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import socket
|
|
7
|
+
|
|
8
|
+
def get_local_ip():
|
|
9
|
+
"""Get the local IP address of this machine"""
|
|
10
|
+
try:
|
|
11
|
+
# Connect to a remote address to determine local IP
|
|
12
|
+
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
|
|
13
|
+
# Use Google DNS as target (doesn't actually connect)
|
|
14
|
+
s.connect(("8.8.8.8", 80))
|
|
15
|
+
local_ip = s.getsockname()[0]
|
|
16
|
+
return local_ip
|
|
17
|
+
except Exception:
|
|
18
|
+
# Fallback to localhost
|
|
19
|
+
return "127.0.0.1"
|
|
20
|
+
|
|
21
|
+
if __name__ == "__main__":
|
|
22
|
+
print(f"Local IP: {get_local_ip()}")
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import time
|
|
2
|
+
import base64
|
|
3
|
+
from io import BytesIO
|
|
4
|
+
import cv2
|
|
5
|
+
from PIL import Image
|
|
6
|
+
|
|
7
|
+
def frame_to_base64(frame):
|
|
8
|
+
"""Convert PIL Image frame to base64 encoded PNG"""
|
|
9
|
+
if hasattr(frame, 'convert'): # It's a PIL Image
|
|
10
|
+
# Resize the PIL Image to 640x480
|
|
11
|
+
resized_frame = frame.resize((640, 480), Image.Resampling.NEAREST)
|
|
12
|
+
buffered = BytesIO()
|
|
13
|
+
resized_frame.save(buffered, format="PNG")
|
|
14
|
+
return base64.b64encode(buffered.getvalue()).decode('utf-8')
|
|
15
|
+
elif hasattr(frame, 'shape'): # It's a numpy array
|
|
16
|
+
# Convert numpy array to PIL Image first
|
|
17
|
+
resized_frame = cv2.resize(frame, (640, 480), interpolation=cv2.INTER_NEAREST)
|
|
18
|
+
img = Image.fromarray(resized_frame)
|
|
19
|
+
buffered = BytesIO()
|
|
20
|
+
img.save(buffered, format="PNG")
|
|
21
|
+
return base64.b64encode(buffered.getvalue()).decode('utf-8')
|
|
22
|
+
else:
|
|
23
|
+
raise ValueError(f"Unsupported frame type: {type(frame)}")
|
|
24
|
+
|
|
25
|
+
def add_text_update(text, category=None, socket_queue=None, text_updates=None):
|
|
26
|
+
"""Add text to the text updates list with optional category"""
|
|
27
|
+
timestamp = time.strftime("%H:%M:%S", time.localtime())
|
|
28
|
+
|
|
29
|
+
if category:
|
|
30
|
+
formatted_text = f"[{timestamp}] [{category}]: {text}"
|
|
31
|
+
else:
|
|
32
|
+
formatted_text = f"[{timestamp}] [DEBUG]: {text}"
|
|
33
|
+
|
|
34
|
+
if text_updates is not None:
|
|
35
|
+
text_updates.append(formatted_text)
|
|
36
|
+
# Keep only the last 100 updates
|
|
37
|
+
if len(text_updates) > 100:
|
|
38
|
+
text_updates.pop(0)
|
|
39
|
+
|
|
40
|
+
print(formatted_text)
|
|
41
|
+
|
|
42
|
+
# Emit update via WebSocket
|
|
43
|
+
if socket_queue is not None:
|
|
44
|
+
socket_queue.put(('text_update', {'text': formatted_text}))
|