atomicguard 2.30.0__tar.gz → 2.32.0__tar.gz
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.
- {atomicguard-2.30.0/src/atomicguard.egg-info → atomicguard-2.32.0}/PKG-INFO +1 -1
- {atomicguard-2.30.0 → atomicguard-2.32.0}/pyproject.toml +1 -1
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/__init__.py +1 -1
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/dsl/ast.py +3 -1
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/dsl/codegen.py +2 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/dsl/parser.py +17 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/dsl/semantic.py +10 -0
- atomicguard-2.32.0/src/atomicguard/contrib/generators/pydantic_ai_generator.py +108 -0
- atomicguard-2.32.0/src/atomicguard/contrib/guards/json_schema_guard.py +47 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/domain/models.py +2 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0/src/atomicguard.egg-info}/PKG-INFO +1 -1
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard.egg-info/SOURCES.txt +2 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/LICENSE +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/README.md +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/setup.cfg +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/__main__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/application/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/application/action_pair.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/application/agent.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/application/agent_rl.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/application/builder.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/application/feedback_summarizer.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/application/policy_export.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/application/runner.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/application/workflow.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/application/workflow_factory.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/cli/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/cli/_queue.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/cli/run.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/cli/runner.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/dispatch/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/dispatch/dspddl_catalogue.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/dispatch/workflow_status_guard.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/dsl/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/dsl/api.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/dsl/desugar.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/dsl/errors.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/effectors/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/effectors/bash_executor.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/generators/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/generators/command_template.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/generators/embedding_intent.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/guards/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/guards/all_passed_guard.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/guards/always_pass_guard.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/guards/exit_code_guard.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/guards/intent_guard.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/guards/parallel.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/guards/pattern_guard.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/guards/rendered_command_guard.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/guards/script_result_guard.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/registries.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/switchboard/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/switchboard/cache.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/switchboard/embedding_classifier.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/switchboard/examples/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/switchboard/examples/demo.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/switchboard/examples/smoke_embedding.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/switchboard/handlers/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/switchboard/handlers/tmux_forward_handler.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/switchboard/handlers/workflow_handler.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/switchboard/protocols.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/switchboard/registry_seed.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/switchboard/results.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/switchboard/switchboard.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/switchboard/tests/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/switchboard/tests/conftest.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/switchboard/tests/test_embedding_classifier.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/switchboard/tests/test_protocols.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/switchboard/tests/test_registry_seed.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/switchboard/tests/test_switchboard.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/switchboard/tests/test_tmux_forward_handler.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/switchboard/tests/test_workflow_handler.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/domain/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/domain/exceptions.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/domain/extraction.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/domain/feedback_summarizer.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/domain/guard_composition.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/domain/gym.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/domain/interfaces.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/domain/multiagent.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/domain/policy_export.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/domain/prompts.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/domain/rl/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/domain/rl/actions.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/domain/rl/models.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/domain/rl/reward.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/domain/rl/state.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/domain/rl/transitions.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/domain/runner.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/domain/workflow.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/guards/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/guards/dynamic/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/guards/dynamic/test_runner.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/guards/interactive/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/guards/interactive/human.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/guards/static/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/guards/static/imports.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/guards/static/syntax.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/gym/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/gym/__main__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/effectors/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/effectors/multi_dispatch_effector.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/effectors/tmux_broadcast_effector.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/effectors/tmux_session_effector.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/effectors/workflow_effector.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/generators/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/generators/subprocess_generator.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/guards/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/guards/container_subprocess_guard.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/guards/diff_empty_guard.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/guards/human_review_adapter.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/gym/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/gym/diff_parser.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/gym/precommit.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/gym/precommit_data/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/gym/precommit_data/dataset.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/gym/precommit_data/schemas.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/gym/precommit_generators.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/human_guard_db.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/human_guard_stdin.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/llm/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/llm/factory.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/llm/huggingface.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/llm/mock.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/llm/ollama.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/persistence/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/persistence/filesystem.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/persistence/memory.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/persistence/sqlite.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/policy_registry.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/queue_inprocess.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/queue_sqlite.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/registry.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/rl/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/rl/checkpoint.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/rl/environment.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/rl/policy.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/rl/replay_buffer.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/rl/rewards.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/status_callback.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/run_policy.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/schemas/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/tools/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/tools/__main__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/tools/export_training.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/tools/export_workflow.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/training/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/training/curriculum.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/training/trainer.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/visualization/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/visualization/html_exporter.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/visualization/workflow_config_exporter.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/web/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/web/__main__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/web/config_loader.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/web/dag_reader.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/web/dependencies.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/web/discovery.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/web/experiment_locator.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/web/policy_loader.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/web/rl_loader.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/web/routes/__init__.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/web/routes/ap_catalogue_pages.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/web/routes/gym_pages.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/web/routes/library_pages.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/web/routes/ollama_pages.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/web/routes/pages.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/web/routes/policy_pages.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/web/routes/rl_pages.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/web/routes/run_pages.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/web/routes/spark_pages.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/web/routes/training_pages.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/web/routes/workflow_pages.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/web/routes/ws_routes.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/web/server.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/web/training_launcher.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/web/utils.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/web/ws.py +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard.egg-info/dependency_links.txt +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard.egg-info/entry_points.txt +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard.egg-info/requires.txt +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard.egg-info/top_level.txt +0 -0
- {atomicguard-2.30.0 → atomicguard-2.32.0}/tests/test_run_policy.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: atomicguard
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.32.0
|
|
4
4
|
Summary: A Dual-State Agent Framework for reliable LLM code generation with guard-validated loops
|
|
5
5
|
Author-email: Matthew Thompson <thompsonson@gmail.com>
|
|
6
6
|
Maintainer-email: Matthew Thompson <thompsonson@gmail.com>
|
|
@@ -4,7 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from dataclasses import dataclass, field
|
|
6
6
|
|
|
7
|
-
type Atom = str | int | bool | tuple["Atom", ...]
|
|
7
|
+
type Atom = str | int | float | bool | tuple["Atom", ...]
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
@dataclass(frozen=True)
|
|
@@ -171,6 +171,8 @@ class WorkflowNode:
|
|
|
171
171
|
model: str = ""
|
|
172
172
|
provider: str = ""
|
|
173
173
|
rmax: int = 3
|
|
174
|
+
intent_examples: tuple[str, ...] = ()
|
|
175
|
+
intent_threshold: float | None = None
|
|
174
176
|
action_pairs: tuple[ActionPairNode, ...] = ()
|
|
175
177
|
guards: tuple[GuardFormNode, ...] = ()
|
|
176
178
|
duplicate_fields: tuple[str, ...] = ()
|
|
@@ -88,6 +88,8 @@ class _ASTTransformer(Transformer[Any, Any]):
|
|
|
88
88
|
model=cast(str, fields.get(":model", "")),
|
|
89
89
|
provider=cast(str, fields.get(":provider", "")),
|
|
90
90
|
rmax=cast(int, fields.get(":rmax", 3)),
|
|
91
|
+
intent_examples=cast("tuple[str, ...]", fields.get(":intent-examples", ())),
|
|
92
|
+
intent_threshold=cast("float | None", fields.get(":intent-threshold")),
|
|
91
93
|
action_pairs=tuple(action_pairs),
|
|
92
94
|
guards=tuple(guards),
|
|
93
95
|
duplicate_fields=tuple(duplicates),
|
|
@@ -114,6 +116,15 @@ class _ASTTransformer(Transformer[Any, Any]):
|
|
|
114
116
|
def workflow_rmax(self, items: list[Any]) -> _Field:
|
|
115
117
|
return _Field(":rmax", items[0])
|
|
116
118
|
|
|
119
|
+
def workflow_intent_examples(self, items: list[Any]) -> _Field:
|
|
120
|
+
return _Field(":intent-examples", items[0])
|
|
121
|
+
|
|
122
|
+
def workflow_intent_threshold(self, items: list[Any]) -> _Field:
|
|
123
|
+
return _Field(":intent-threshold", items[0])
|
|
124
|
+
|
|
125
|
+
def string_list(self, items: list[Any]) -> tuple[str, ...]:
|
|
126
|
+
return tuple(cast(str, item) for item in items)
|
|
127
|
+
|
|
117
128
|
def spec_source(self, items: list[Any]) -> SpecSource:
|
|
118
129
|
value = items[0]
|
|
119
130
|
if isinstance(value, str):
|
|
@@ -462,12 +473,18 @@ class _ASTTransformer(Transformer[Any, Any]):
|
|
|
462
473
|
def INTEGER(self, token: Token) -> int: # noqa: N802
|
|
463
474
|
return int(str(token))
|
|
464
475
|
|
|
476
|
+
def FLOAT(self, token: Token) -> float: # noqa: N802
|
|
477
|
+
return float(str(token))
|
|
478
|
+
|
|
465
479
|
def BOOLEAN(self, token: Token) -> bool: # noqa: N802
|
|
466
480
|
return str(token) == "true"
|
|
467
481
|
|
|
468
482
|
def integer(self, items: list[Any]) -> Atom:
|
|
469
483
|
return cast(Atom, items[0])
|
|
470
484
|
|
|
485
|
+
def float(self, items: list[Any]) -> Atom:
|
|
486
|
+
return cast(Atom, items[0])
|
|
487
|
+
|
|
471
488
|
def boolean(self, items: list[Any]) -> Atom:
|
|
472
489
|
return cast(Atom, items[0])
|
|
473
490
|
|
|
@@ -35,6 +35,16 @@ def validate_guard_forms(node: WorkflowNode) -> None:
|
|
|
35
35
|
|
|
36
36
|
def validate_definition(definition: WorkflowDefinition) -> None:
|
|
37
37
|
"""Validate DS-PDDL semantics that depend on the whole workflow."""
|
|
38
|
+
if definition.intent_threshold is not None and not (
|
|
39
|
+
0.0 <= definition.intent_threshold <= 1.0
|
|
40
|
+
):
|
|
41
|
+
raise DSPDDLValidationError(
|
|
42
|
+
f"Workflow '{definition.slug}' has invalid intent_threshold: "
|
|
43
|
+
f"{definition.intent_threshold}. Expected 0.0 <= intent_threshold <= 1.0. "
|
|
44
|
+
"This checks type/range only — it makes no claim about whether the "
|
|
45
|
+
"value is reachable by any particular classifier."
|
|
46
|
+
)
|
|
47
|
+
|
|
38
48
|
ap_ids: set[str] = set()
|
|
39
49
|
for ap_def in definition.action_pairs:
|
|
40
50
|
if ap_def.ap_id in ap_ids:
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"""Generator that wraps a PydanticAI Agent for LLM calls.
|
|
2
|
+
|
|
3
|
+
The generator calls the LLM and returns the raw text response.
|
|
4
|
+
Validation is delegated to the guard (JSONSchemaGuard).
|
|
5
|
+
|
|
6
|
+
Configurable from DS-PDDL via :config:
|
|
7
|
+
model — LLM model name (e.g. deepseek/deepseek-v4-flash)
|
|
8
|
+
provider — API provider (openrouter, openai, ollama, huggingface)
|
|
9
|
+
retries — PydanticAI Agent retries (default 0 — DSA owns correction)
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import asyncio
|
|
15
|
+
import os
|
|
16
|
+
import re
|
|
17
|
+
import uuid
|
|
18
|
+
from datetime import datetime
|
|
19
|
+
|
|
20
|
+
from pydantic_ai import Agent
|
|
21
|
+
|
|
22
|
+
from atomicguard.domain.interfaces import GeneratorInterface
|
|
23
|
+
from atomicguard.domain.models import (
|
|
24
|
+
ActionPairId,
|
|
25
|
+
Artifact,
|
|
26
|
+
ArtifactId,
|
|
27
|
+
ArtifactStatus,
|
|
28
|
+
Context,
|
|
29
|
+
ContextSnapshot,
|
|
30
|
+
WorkflowId,
|
|
31
|
+
)
|
|
32
|
+
from atomicguard.domain.prompts import PromptTemplate
|
|
33
|
+
from atomicguard.infrastructure.llm.factory import create_llm_model
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class PydanticAIGenerator(GeneratorInterface):
|
|
37
|
+
"""LLM generator.
|
|
38
|
+
|
|
39
|
+
Config (from DS-PDDL :config):
|
|
40
|
+
model — LLM model name (required)
|
|
41
|
+
provider — API provider (default: openrouter)
|
|
42
|
+
retries — PydanticAI retry count (default: 0)
|
|
43
|
+
api_key — optional, falls back to LLM_API_KEY env var
|
|
44
|
+
base_url — optional, falls back to OpenRouter default
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
def __init__(
|
|
48
|
+
self,
|
|
49
|
+
*,
|
|
50
|
+
model: str = "",
|
|
51
|
+
provider: str = "",
|
|
52
|
+
retries: int = 0,
|
|
53
|
+
api_key: str = "",
|
|
54
|
+
base_url: str = "",
|
|
55
|
+
timeout: float = 180.0,
|
|
56
|
+
) -> None:
|
|
57
|
+
resolved_provider = provider or "openrouter"
|
|
58
|
+
resolved_api_key = (
|
|
59
|
+
api_key
|
|
60
|
+
or os.environ.get("LLM_API_KEY", "")
|
|
61
|
+
or os.environ.get("OPENAI_API_KEY", "")
|
|
62
|
+
or os.environ.get("OPENROUTER_API_KEY", "")
|
|
63
|
+
)
|
|
64
|
+
resolved_base_url = base_url or "https://openrouter.ai/api/v1"
|
|
65
|
+
|
|
66
|
+
ai_model = create_llm_model(
|
|
67
|
+
provider=resolved_provider,
|
|
68
|
+
model=model,
|
|
69
|
+
base_url=resolved_base_url,
|
|
70
|
+
api_key=resolved_api_key,
|
|
71
|
+
timeout=timeout,
|
|
72
|
+
)
|
|
73
|
+
self._agent = Agent(ai_model, output_type=str, retries=retries)
|
|
74
|
+
|
|
75
|
+
def generate(
|
|
76
|
+
self,
|
|
77
|
+
context: Context,
|
|
78
|
+
template: PromptTemplate,
|
|
79
|
+
action_pair_id: str = "unknown",
|
|
80
|
+
workflow_id: str = "unknown",
|
|
81
|
+
workflow_ref: str | None = None, # noqa: ARG002
|
|
82
|
+
) -> Artifact:
|
|
83
|
+
prompt = template.render(context)
|
|
84
|
+
result = asyncio.run(self._agent.run(prompt))
|
|
85
|
+
|
|
86
|
+
content = result.output.strip()
|
|
87
|
+
match = re.search(r"```(?:json)?\n(.*?)\n```", content, re.DOTALL)
|
|
88
|
+
if match:
|
|
89
|
+
content = match.group(1).strip()
|
|
90
|
+
|
|
91
|
+
return Artifact(
|
|
92
|
+
artifact_id=ArtifactId(str(uuid.uuid4())),
|
|
93
|
+
workflow_id=WorkflowId(workflow_id),
|
|
94
|
+
content=content,
|
|
95
|
+
previous_attempt_id=None,
|
|
96
|
+
parent_action_pair_id=None,
|
|
97
|
+
action_pair_id=ActionPairId(action_pair_id),
|
|
98
|
+
created_at=datetime.now().isoformat(),
|
|
99
|
+
attempt_number=1,
|
|
100
|
+
status=ArtifactStatus.PENDING,
|
|
101
|
+
guard_result=None,
|
|
102
|
+
context=ContextSnapshot(
|
|
103
|
+
workflow_id=workflow_id,
|
|
104
|
+
specification=context.specification,
|
|
105
|
+
constraints="",
|
|
106
|
+
feedback_history=(),
|
|
107
|
+
),
|
|
108
|
+
)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""Guard that validates artifact JSON against a JSON Schema file."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import re
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
from atomicguard.domain.interfaces import GuardInterface
|
|
10
|
+
from atomicguard.domain.models import GuardResult
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class JSONSchemaGuard(GuardInterface):
|
|
14
|
+
"""Validates artifact JSON content against a JSON Schema file.
|
|
15
|
+
|
|
16
|
+
Config (:config in DS-PDDL):
|
|
17
|
+
schema — path to JSON Schema file (resolved from project root)
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def __init__(self, schema: str = "") -> None:
|
|
21
|
+
self._schema_path = schema
|
|
22
|
+
|
|
23
|
+
def validate(self, artifact: object, **kwargs: object) -> GuardResult: # noqa: ARG002
|
|
24
|
+
import jsonschema # noqa: PLC0415
|
|
25
|
+
|
|
26
|
+
content = getattr(artifact, "content", "")
|
|
27
|
+
if not isinstance(content, str):
|
|
28
|
+
return GuardResult(
|
|
29
|
+
passed=False, feedback="Artifact content is not a string"
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
content = content.strip()
|
|
33
|
+
match = re.search(r"```(?:json)?\n(.*?)\n```", content, re.DOTALL)
|
|
34
|
+
if match:
|
|
35
|
+
content = match.group(1).strip()
|
|
36
|
+
|
|
37
|
+
try:
|
|
38
|
+
schema = json.loads(Path(self._schema_path).read_text())
|
|
39
|
+
data = json.loads(content)
|
|
40
|
+
jsonschema.validate(data, schema)
|
|
41
|
+
except json.JSONDecodeError as exc:
|
|
42
|
+
return GuardResult(passed=False, feedback=f"Invalid JSON: {exc}")
|
|
43
|
+
except jsonschema.ValidationError as exc:
|
|
44
|
+
return GuardResult(passed=False, feedback=f"Schema violation: {exc}")
|
|
45
|
+
except FileNotFoundError as exc:
|
|
46
|
+
return GuardResult(passed=False, feedback=f"Schema file not found: {exc}")
|
|
47
|
+
return GuardResult(passed=True)
|
|
@@ -511,6 +511,8 @@ class WorkflowDefinition:
|
|
|
511
511
|
model: str = ""
|
|
512
512
|
provider: str = ""
|
|
513
513
|
rmax: int = 3
|
|
514
|
+
intent_examples: tuple[str, ...] = ()
|
|
515
|
+
intent_threshold: float | None = None
|
|
514
516
|
action_pairs: tuple[ActionPairDefinition, ...] = ()
|
|
515
517
|
source_policy_slug: str = "" # provenance: policy that generated this workflow
|
|
516
518
|
policy_derived_requires: tuple[
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: atomicguard
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.32.0
|
|
4
4
|
Summary: A Dual-State Agent Framework for reliable LLM code generation with guard-validated loops
|
|
5
5
|
Author-email: Matthew Thompson <thompsonson@gmail.com>
|
|
6
6
|
Maintainer-email: Matthew Thompson <thompsonson@gmail.com>
|
|
@@ -42,11 +42,13 @@ src/atomicguard/contrib/effectors/bash_executor.py
|
|
|
42
42
|
src/atomicguard/contrib/generators/__init__.py
|
|
43
43
|
src/atomicguard/contrib/generators/command_template.py
|
|
44
44
|
src/atomicguard/contrib/generators/embedding_intent.py
|
|
45
|
+
src/atomicguard/contrib/generators/pydantic_ai_generator.py
|
|
45
46
|
src/atomicguard/contrib/guards/__init__.py
|
|
46
47
|
src/atomicguard/contrib/guards/all_passed_guard.py
|
|
47
48
|
src/atomicguard/contrib/guards/always_pass_guard.py
|
|
48
49
|
src/atomicguard/contrib/guards/exit_code_guard.py
|
|
49
50
|
src/atomicguard/contrib/guards/intent_guard.py
|
|
51
|
+
src/atomicguard/contrib/guards/json_schema_guard.py
|
|
50
52
|
src/atomicguard/contrib/guards/parallel.py
|
|
51
53
|
src/atomicguard/contrib/guards/pattern_guard.py
|
|
52
54
|
src/atomicguard/contrib/guards/rendered_command_guard.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/application/feedback_summarizer.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/dispatch/dspddl_catalogue.py
RENAMED
|
File without changes
|
{atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/dispatch/workflow_status_guard.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/effectors/bash_executor.py
RENAMED
|
File without changes
|
|
File without changes
|
{atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/generators/command_template.py
RENAMED
|
File without changes
|
{atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/generators/embedding_intent.py
RENAMED
|
File without changes
|
|
File without changes
|
{atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/guards/all_passed_guard.py
RENAMED
|
File without changes
|
{atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/guards/always_pass_guard.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/guards/rendered_command_guard.py
RENAMED
|
File without changes
|
{atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/guards/script_result_guard.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/switchboard/examples/__init__.py
RENAMED
|
File without changes
|
{atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/switchboard/examples/demo.py
RENAMED
|
File without changes
|
|
File without changes
|
{atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/switchboard/handlers/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/switchboard/registry_seed.py
RENAMED
|
File without changes
|
|
File without changes
|
{atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/switchboard/switchboard.py
RENAMED
|
File without changes
|
{atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/switchboard/tests/__init__.py
RENAMED
|
File without changes
|
{atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/contrib/switchboard/tests/conftest.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/effectors/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/generators/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/guards/diff_empty_guard.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/gym/precommit_generators.py
RENAMED
|
File without changes
|
|
File without changes
|
{atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/human_guard_stdin.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/persistence/__init__.py
RENAMED
|
File without changes
|
{atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/persistence/filesystem.py
RENAMED
|
File without changes
|
{atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/persistence/memory.py
RENAMED
|
File without changes
|
{atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/persistence/sqlite.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/infrastructure/rl/replay_buffer.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{atomicguard-2.30.0 → atomicguard-2.32.0}/src/atomicguard/visualization/workflow_config_exporter.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|