agent-os-kernel 1.1.0__py3-none-any.whl → 1.2.0__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.
- agent_os/__init__.py +66 -4
- agent_os/agents_compat.py +286 -0
- agent_os/base_agent.py +308 -0
- agent_os/cli.py +1079 -19
- agent_os/integrations/__init__.py +37 -2
- agent_os/integrations/openai_adapter.py +502 -0
- agent_os/integrations/semantic_kernel_adapter.py +569 -0
- agent_os/stateless.py +349 -0
- agent_os_kernel-1.2.0.dist-info/METADATA +676 -0
- agent_os_kernel-1.2.0.dist-info/RECORD +1053 -0
- {agent_os_kernel-1.1.0.dist-info → agent_os_kernel-1.2.0.dist-info}/entry_points.txt +0 -1
- modules/amb/.github/workflows/ci.yml +102 -0
- modules/amb/.github/workflows/publish.yml +146 -0
- modules/amb/.gitignore +134 -0
- modules/amb/CHANGELOG.md +118 -0
- modules/amb/CONTRIBUTING.md +141 -0
- modules/amb/LICENSE +21 -0
- modules/amb/README.md +188 -0
- modules/amb/amb_core/__init__.py +175 -0
- modules/amb/amb_core/adapters/__init__.py +55 -0
- modules/amb/amb_core/adapters/aws_sqs_broker.py +374 -0
- modules/amb/amb_core/adapters/azure_servicebus_broker.py +338 -0
- modules/amb/amb_core/adapters/kafka_broker.py +258 -0
- modules/amb/amb_core/adapters/nats_broker.py +283 -0
- modules/amb/amb_core/adapters/rabbitmq_broker.py +233 -0
- modules/amb/amb_core/adapters/redis_broker.py +260 -0
- modules/amb/amb_core/broker.py +143 -0
- modules/amb/amb_core/bus.py +479 -0
- modules/amb/amb_core/cloudevents.py +507 -0
- modules/amb/amb_core/dlq.py +343 -0
- modules/amb/amb_core/hf_utils.py +534 -0
- modules/amb/amb_core/memory_broker.py +408 -0
- modules/amb/amb_core/models.py +139 -0
- modules/amb/amb_core/persistence.py +527 -0
- modules/amb/amb_core/schema.py +292 -0
- modules/amb/amb_core/tracing.py +356 -0
- modules/amb/examples/advanced_features.py +223 -0
- modules/amb/examples/backpressure_demo.py +225 -0
- modules/amb/examples/basic_usage.py +117 -0
- modules/amb/examples/tracing_demo.py +104 -0
- modules/amb/experiments/README.md +52 -0
- modules/amb/experiments/reproduce_results.py +467 -0
- modules/amb/experiments/results.json +324 -0
- modules/amb/paper/README.md +40 -0
- modules/amb/paper/paper.tex +365 -0
- modules/amb/paper/whitepaper.md +377 -0
- modules/amb/pyproject.toml +117 -0
- modules/amb/tests/__init__.py +1 -0
- modules/amb/tests/test_backpressure_priority.py +280 -0
- modules/amb/tests/test_bus.py +198 -0
- modules/amb/tests/test_cloudevents.py +443 -0
- modules/amb/tests/test_features.py +531 -0
- modules/amb/tests/test_models.py +74 -0
- modules/amb/tests/test_tracing.py +254 -0
- modules/atr/.github/workflows/ci.yml +101 -0
- modules/atr/.github/workflows/publish.yml +140 -0
- modules/atr/.gitignore +134 -0
- modules/atr/.pre-commit-config.yaml +37 -0
- modules/atr/CHANGELOG.md +39 -0
- modules/atr/CONTRIBUTING.md +96 -0
- modules/atr/IMPLEMENTATION_SUMMARY.md +143 -0
- modules/atr/README.md +180 -0
- modules/atr/atr/__init__.py +638 -0
- modules/atr/atr/access.py +346 -0
- modules/atr/atr/composition.py +643 -0
- modules/atr/atr/decorator.py +355 -0
- modules/atr/atr/executor.py +382 -0
- modules/atr/atr/health.py +555 -0
- modules/atr/atr/hf_utils.py +447 -0
- modules/atr/atr/injection.py +420 -0
- modules/atr/atr/metrics.py +438 -0
- modules/atr/atr/policies.py +401 -0
- modules/atr/atr/py.typed +2 -0
- modules/atr/atr/registry.py +450 -0
- modules/atr/atr/schema.py +478 -0
- modules/atr/atr/tools/safe/__init__.py +73 -0
- modules/atr/atr/tools/safe/calculator.py +380 -0
- modules/atr/atr/tools/safe/datetime_tool.py +441 -0
- modules/atr/atr/tools/safe/file_reader.py +400 -0
- modules/atr/atr/tools/safe/http_client.py +314 -0
- modules/atr/atr/tools/safe/json_parser.py +372 -0
- modules/atr/atr/tools/safe/text_tool.py +526 -0
- modules/atr/atr/tools/safe/toolkit.py +173 -0
- modules/atr/docs/PYPI_SETUP.md +113 -0
- modules/atr/examples/README.md +27 -0
- modules/atr/examples/demo.py +144 -0
- modules/atr/examples/sandbox_demo.py +218 -0
- modules/atr/experiments/README.md +69 -0
- modules/atr/experiments/reproduce_results.py +509 -0
- modules/atr/experiments/results/.gitkeep +0 -0
- modules/atr/experiments/results/results_20260123_140334.json +71 -0
- modules/atr/paper/README.md +36 -0
- modules/atr/paper/figures/.gitkeep +0 -0
- modules/atr/paper/references.bib +84 -0
- modules/atr/paper/structure.tex +293 -0
- modules/atr/paper/whitepaper.md +234 -0
- modules/atr/pyproject.toml +148 -0
- modules/atr/requirements.txt +1 -0
- modules/atr/setup.py +30 -0
- modules/atr/tests/__init__.py +1 -0
- modules/atr/tests/test_decorator.py +317 -0
- modules/atr/tests/test_executor.py +245 -0
- modules/atr/tests/test_integration_executor.py +184 -0
- modules/atr/tests/test_registry.py +312 -0
- modules/atr/tests/test_schema.py +182 -0
- modules/atr/tests/test_v2_features.py +708 -0
- modules/caas/.dockerignore +63 -0
- modules/caas/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
- modules/caas/.github/ISSUE_TEMPLATE/custom.md +10 -0
- modules/caas/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- modules/caas/.github/workflows/ci.yml +100 -0
- modules/caas/.github/workflows/lint.yml +39 -0
- modules/caas/.github/workflows/publish-pypi.yml +124 -0
- modules/caas/.gitignore +73 -0
- modules/caas/.pre-commit-config.yaml +33 -0
- modules/caas/CHANGELOG.md +58 -0
- modules/caas/CONTRIBUTING.md +346 -0
- modules/caas/Dockerfile +41 -0
- modules/caas/LICENSE +21 -0
- modules/caas/MANIFEST.in +11 -0
- modules/caas/README.md +158 -0
- modules/caas/benchmarks/README.md +255 -0
- modules/caas/benchmarks/create_hf_dataset.py +502 -0
- modules/caas/benchmarks/data/sample_corpus/README.md +86 -0
- modules/caas/benchmarks/data/sample_corpus/auth_module.py +211 -0
- modules/caas/benchmarks/data/sample_corpus/contribution_guide.md +185 -0
- modules/caas/benchmarks/data/sample_corpus/remote_work_policy.html +57 -0
- modules/caas/benchmarks/hf_dataset/README.md +214 -0
- modules/caas/benchmarks/hf_dataset/caas_benchmark_corpus.py +73 -0
- modules/caas/benchmarks/hf_dataset/corpus_preview.json +193 -0
- modules/caas/benchmarks/results/README.md +66 -0
- modules/caas/benchmarks/results/evaluation_2026-01-20.json +121 -0
- modules/caas/benchmarks/run_evaluation.py +561 -0
- modules/caas/benchmarks/statistical_tests.py +289 -0
- modules/caas/benchmarks/verify_sample_corpus.py +83 -0
- modules/caas/docker-compose.yml +38 -0
- modules/caas/docs/CONTEXT_TRIAD.md +462 -0
- modules/caas/docs/CONTRIBUTING.md +346 -0
- modules/caas/docs/ETHICS_AND_LIMITATIONS.md +336 -0
- modules/caas/docs/HEURISTIC_ROUTER.md +442 -0
- modules/caas/docs/IMPLEMENTATION_SUMMARY.md +363 -0
- modules/caas/docs/IMPLEMENTATION_SUMMARY_CONTEXT_TRIAD.md +277 -0
- modules/caas/docs/IMPLEMENTATION_SUMMARY_HEURISTIC_ROUTER.md +231 -0
- modules/caas/docs/IMPLEMENTATION_SUMMARY_METADATA_INJECTION.md +258 -0
- modules/caas/docs/IMPLEMENTATION_SUMMARY_PRAGMATIC_TRUTH.md +212 -0
- modules/caas/docs/IMPLEMENTATION_SUMMARY_TRUST_GATEWAY.md +319 -0
- modules/caas/docs/LAYER_1_PRIMITIVE.md +202 -0
- modules/caas/docs/METADATA_INJECTION.md +404 -0
- modules/caas/docs/PRAGMATIC_TRUTH.md +431 -0
- modules/caas/docs/RELATED_WORK.md +312 -0
- modules/caas/docs/RELEASE_CHECKLIST.md +219 -0
- modules/caas/docs/RELEASE_GUIDE.md +285 -0
- modules/caas/docs/REPRODUCIBILITY.md +386 -0
- modules/caas/docs/SLIDING_WINDOW.md +387 -0
- modules/caas/docs/STRUCTURE_AWARE_INDEXING.md +158 -0
- modules/caas/docs/TESTING.md +259 -0
- modules/caas/docs/THREAT_MODEL.md +247 -0
- modules/caas/docs/TRUST_GATEWAY.md +575 -0
- modules/caas/docs/VFS.md +298 -0
- modules/caas/examples/agents/enterprise_security_agent.py +414 -0
- modules/caas/examples/agents/intelligent_document_analyzer.py +380 -0
- modules/caas/examples/demos/demo.py +309 -0
- modules/caas/examples/demos/demo_context_triad.py +225 -0
- modules/caas/examples/demos/demo_conversation_manager.py +285 -0
- modules/caas/examples/demos/demo_heuristic_router.py +133 -0
- modules/caas/examples/demos/demo_metadata_injection.py +198 -0
- modules/caas/examples/demos/demo_pragmatic_truth.py +303 -0
- modules/caas/examples/demos/demo_structure_aware.py +140 -0
- modules/caas/examples/demos/demo_time_decay.py +247 -0
- modules/caas/examples/demos/demo_trust_gateway.py +383 -0
- modules/caas/examples/multi_agent/README.md +159 -0
- modules/caas/examples/multi_agent/research_team.py +369 -0
- modules/caas/examples/multi_agent/vfs_collaboration.py +393 -0
- modules/caas/examples/usage/auth_module.py +142 -0
- modules/caas/examples/usage/usage_example.py +173 -0
- modules/caas/experiments/README.md +42 -0
- modules/caas/experiments/reproduce_results.py +462 -0
- modules/caas/paper/ARXIV_METADATA.md +145 -0
- modules/caas/paper/ARXIV_README.md +47 -0
- modules/caas/paper/CHECKLIST.md +103 -0
- modules/caas/paper/GITHUB_RELEASE_NOTES.md +105 -0
- modules/caas/paper/README.md +71 -0
- modules/caas/paper/abstract.md +24 -0
- modules/caas/paper/arxiv_submission.tar +0 -0
- modules/caas/paper/arxiv_submission.zip +0 -0
- modules/caas/paper/build_pdf.py +355 -0
- modules/caas/paper/experiments.md +149 -0
- modules/caas/paper/figures/.gitkeep +0 -0
- modules/caas/paper/figures/README.md +237 -0
- modules/caas/paper/figures/fig1_system_architecture.png +0 -0
- modules/caas/paper/figures/fig1_system_architecture.svg +198 -0
- modules/caas/paper/figures/fig2_context_triad.png +0 -0
- modules/caas/paper/figures/fig2_context_triad.svg +105 -0
- modules/caas/paper/figures/fig3_ablation_results.png +0 -0
- modules/caas/paper/figures/fig3_ablation_results.svg +113 -0
- modules/caas/paper/figures/fig4_routing_latency.png +0 -0
- modules/caas/paper/figures/fig4_routing_latency.svg +97 -0
- modules/caas/paper/intro.md +103 -0
- modules/caas/paper/latex/figures/fig1_system_architecture.png +0 -0
- modules/caas/paper/latex/figures/fig2_context_triad.png +0 -0
- modules/caas/paper/latex/figures/fig3_ablation_results.png +0 -0
- modules/caas/paper/latex/figures/fig4_routing_latency.png +0 -0
- modules/caas/paper/latex/main.tex +468 -0
- modules/caas/paper/latex/references.bib +140 -0
- modules/caas/paper/method.md +350 -0
- modules/caas/paper/outline.md +123 -0
- modules/caas/paper/related_work.md +101 -0
- modules/caas/paper/tables/.gitkeep +0 -0
- modules/caas/paper/tables/results_tables.md +50 -0
- modules/caas/pyproject.toml +172 -0
- modules/caas/requirements.txt +11 -0
- modules/caas/src/caas/__init__.py +232 -0
- modules/caas/src/caas/api/__init__.py +7 -0
- modules/caas/src/caas/api/server.py +1326 -0
- modules/caas/src/caas/caching.py +832 -0
- modules/caas/src/caas/cli.py +208 -0
- modules/caas/src/caas/conversation.py +221 -0
- modules/caas/src/caas/decay.py +118 -0
- modules/caas/src/caas/detection/__init__.py +7 -0
- modules/caas/src/caas/detection/detector.py +236 -0
- modules/caas/src/caas/enrichment.py +127 -0
- modules/caas/src/caas/gateway/__init__.py +24 -0
- modules/caas/src/caas/gateway/trust_gateway.py +471 -0
- modules/caas/src/caas/hf_utils.py +477 -0
- modules/caas/src/caas/ingestion/__init__.py +21 -0
- modules/caas/src/caas/ingestion/processors.py +251 -0
- modules/caas/src/caas/ingestion/structure_parser.py +185 -0
- modules/caas/src/caas/models.py +354 -0
- modules/caas/src/caas/pragmatic_truth.py +441 -0
- modules/caas/src/caas/routing/__init__.py +8 -0
- modules/caas/src/caas/routing/heuristic_router.py +242 -0
- modules/caas/src/caas/storage/__init__.py +7 -0
- modules/caas/src/caas/storage/store.py +450 -0
- modules/caas/src/caas/triad.py +472 -0
- modules/caas/src/caas/tuning/__init__.py +7 -0
- modules/caas/src/caas/tuning/tuner.py +322 -0
- modules/caas/src/caas/vfs/__init__.py +12 -0
- modules/caas/src/caas/vfs/filesystem.py +450 -0
- modules/caas/tests/__init__.py +3 -0
- modules/caas/tests/conftest.py +8 -0
- modules/caas/tests/test_caching.py +628 -0
- modules/caas/tests/test_context_triad.py +385 -0
- modules/caas/tests/test_conversation_manager.py +289 -0
- modules/caas/tests/test_functionality.py +215 -0
- modules/caas/tests/test_heuristic_router.py +370 -0
- modules/caas/tests/test_metadata_injection.py +328 -0
- modules/caas/tests/test_pragmatic_truth.py +322 -0
- modules/caas/tests/test_structure_aware_indexing.py +283 -0
- modules/caas/tests/test_time_decay.py +268 -0
- modules/caas/tests/test_trust_gateway.py +445 -0
- modules/caas/tests/test_vfs.py +298 -0
- modules/cmvk/.github/FUNDING.yml +9 -0
- modules/cmvk/.github/dependabot.yml +54 -0
- modules/cmvk/.github/workflows/ci.yml +205 -0
- modules/cmvk/.github/workflows/publish.yml +143 -0
- modules/cmvk/.gitignore +147 -0
- modules/cmvk/.pre-commit-config.yaml +58 -0
- modules/cmvk/CHANGELOG.md +146 -0
- modules/cmvk/CITATION.cff +48 -0
- modules/cmvk/CONTRIBUTING.md +229 -0
- modules/cmvk/Dockerfile +87 -0
- modules/cmvk/HF_MODEL_CARD.md +185 -0
- modules/cmvk/LICENSE +21 -0
- modules/cmvk/README.md +149 -0
- modules/cmvk/SECURITY.md +114 -0
- modules/cmvk/config/prompts/generator_v1.txt +23 -0
- modules/cmvk/config/prompts/verifier_hostile.txt +32 -0
- modules/cmvk/config/settings.yaml +40 -0
- modules/cmvk/coverage_html/.gitignore +2 -0
- modules/cmvk/coverage_html/class_index.html +658 -0
- modules/cmvk/coverage_html/coverage_html_cb_188fc9a4.js +735 -0
- modules/cmvk/coverage_html/favicon_32_cb_c827f16f.png +0 -0
- modules/cmvk/coverage_html/function_index.html +1978 -0
- modules/cmvk/coverage_html/index.html +255 -0
- modules/cmvk/coverage_html/keybd_closed_cb_900cfef5.png +0 -0
- modules/cmvk/coverage_html/status.json +1 -0
- modules/cmvk/coverage_html/style_cb_5c747636.css +389 -0
- modules/cmvk/coverage_html/z_2c49bd2ed3e01e38___init___py.html +315 -0
- modules/cmvk/coverage_html/z_2c49bd2ed3e01e38_audit_py.html +499 -0
- modules/cmvk/coverage_html/z_2c49bd2ed3e01e38_benchmarks_py.html +575 -0
- modules/cmvk/coverage_html/z_2c49bd2ed3e01e38_constitutional_py.html +1001 -0
- modules/cmvk/coverage_html/z_2c49bd2ed3e01e38_hf_utils_py.html +398 -0
- modules/cmvk/coverage_html/z_2c49bd2ed3e01e38_metrics_py.html +570 -0
- modules/cmvk/coverage_html/z_2c49bd2ed3e01e38_profiles_py.html +397 -0
- modules/cmvk/coverage_html/z_2c49bd2ed3e01e38_types_py.html +109 -0
- modules/cmvk/coverage_html/z_2c49bd2ed3e01e38_verification_py.html +1053 -0
- modules/cmvk/docs/DIAGRAMS.md +325 -0
- modules/cmvk/docs/architecture.md +345 -0
- modules/cmvk/docs/features.md +308 -0
- modules/cmvk/docs/getting_started.md +279 -0
- modules/cmvk/docs/innovation_layer.md +377 -0
- modules/cmvk/docs/safety.md +281 -0
- modules/cmvk/docs/traceability.md +150 -0
- modules/cmvk/examples/basic_example.py +62 -0
- modules/cmvk/examples/demo_complete_pipeline.py +209 -0
- modules/cmvk/examples/demo_innovation_layer.py +197 -0
- modules/cmvk/examples/example.py +112 -0
- modules/cmvk/examples/model_diversity_comparison.py +110 -0
- modules/cmvk/examples/real_api_integration.py +121 -0
- modules/cmvk/examples/test_full_pipeline.py +303 -0
- modules/cmvk/experiments/FEATURE_2_LATERAL_THINKING.md +187 -0
- modules/cmvk/experiments/README.md +216 -0
- modules/cmvk/experiments/ablation_runner.py +666 -0
- modules/cmvk/experiments/baseline_runner.py +158 -0
- modules/cmvk/experiments/blind_spot_benchmark.py +364 -0
- modules/cmvk/experiments/datasets/README.md +85 -0
- modules/cmvk/experiments/datasets/humaneval_50.json +352 -0
- modules/cmvk/experiments/datasets/humaneval_full.json +1150 -0
- modules/cmvk/experiments/datasets/humaneval_sample.json +32 -0
- modules/cmvk/experiments/datasets/sabotage.json +262 -0
- modules/cmvk/experiments/datasets/sample.json +40 -0
- modules/cmvk/experiments/demo_with_traces.py +110 -0
- modules/cmvk/experiments/efficiency_curve.py +259 -0
- modules/cmvk/experiments/experiment_runner.py +243 -0
- modules/cmvk/experiments/paper_data_generator.py +183 -0
- modules/cmvk/experiments/reproduce_results.py +407 -0
- modules/cmvk/experiments/reproducible_runner.py +352 -0
- modules/cmvk/experiments/sabotage_stress_test.py +311 -0
- modules/cmvk/experiments/test_lateral_thinking.py +116 -0
- modules/cmvk/experiments/test_prosecutor.py +41 -0
- modules/cmvk/experiments/visualize_results.py +735 -0
- modules/cmvk/logs/traces/demo_HumanEval_0_20260121-204900.json +36 -0
- modules/cmvk/notebooks/analysis.ipynb +124 -0
- modules/cmvk/paper/PAPER.md +561 -0
- modules/cmvk/paper/arxiv_checklist.md +230 -0
- modules/cmvk/paper/cmvk_neurips.aux +77 -0
- modules/cmvk/paper/cmvk_neurips.bbl +81 -0
- modules/cmvk/paper/cmvk_neurips.blg +48 -0
- modules/cmvk/paper/cmvk_neurips.out +16 -0
- modules/cmvk/paper/cmvk_neurips.pdf +0 -0
- modules/cmvk/paper/cmvk_neurips.tex +309 -0
- modules/cmvk/paper/figures/ablation.png +0 -0
- modules/cmvk/paper/figures/ablation.svg +39 -0
- modules/cmvk/paper/figures/architecture.png +0 -0
- modules/cmvk/paper/figures/architecture.svg +115 -0
- modules/cmvk/paper/figures/results_bar.png +0 -0
- modules/cmvk/paper/figures/results_bar.svg +70 -0
- modules/cmvk/paper/generate_figures.py +383 -0
- modules/cmvk/paper/neurips_2024.sty +101 -0
- modules/cmvk/paper/references.bib +98 -0
- modules/cmvk/paper/structure.tex +200 -0
- modules/cmvk/pyproject.toml +189 -0
- modules/cmvk/requirements-dev.txt +19 -0
- modules/cmvk/requirements.txt +14 -0
- modules/cmvk/src/cmvk/__init__.py +216 -0
- modules/cmvk/src/cmvk/audit.py +400 -0
- modules/cmvk/src/cmvk/benchmarks.py +476 -0
- modules/cmvk/src/cmvk/constitutional.py +902 -0
- modules/cmvk/src/cmvk/hf_utils.py +299 -0
- modules/cmvk/src/cmvk/metrics.py +471 -0
- modules/cmvk/src/cmvk/profiles.py +298 -0
- modules/cmvk/src/cmvk/py.typed +0 -0
- modules/cmvk/src/cmvk/types.py +10 -0
- modules/cmvk/src/cmvk/verification.py +954 -0
- modules/cmvk/src/cross_model_verification_kernel/__init__.py +91 -0
- modules/cmvk/src/cross_model_verification_kernel/__main__.py +10 -0
- modules/cmvk/src/cross_model_verification_kernel/agents/__init__.py +16 -0
- modules/cmvk/src/cross_model_verification_kernel/agents/base_agent.py +142 -0
- modules/cmvk/src/cross_model_verification_kernel/agents/generator_openai.py +223 -0
- modules/cmvk/src/cross_model_verification_kernel/agents/verifier_anthropic.py +448 -0
- modules/cmvk/src/cross_model_verification_kernel/agents/verifier_gemini.py +481 -0
- modules/cmvk/src/cross_model_verification_kernel/cli.py +570 -0
- modules/cmvk/src/cross_model_verification_kernel/core/__init__.py +26 -0
- modules/cmvk/src/cross_model_verification_kernel/core/graph_memory.py +308 -0
- modules/cmvk/src/cross_model_verification_kernel/core/kernel.py +413 -0
- modules/cmvk/src/cross_model_verification_kernel/core/trace_logger.py +75 -0
- modules/cmvk/src/cross_model_verification_kernel/core/types.py +121 -0
- modules/cmvk/src/cross_model_verification_kernel/datasets/__init__.py +20 -0
- modules/cmvk/src/cross_model_verification_kernel/datasets/humaneval_loader.py +271 -0
- modules/cmvk/src/cross_model_verification_kernel/generator.py +118 -0
- modules/cmvk/src/cross_model_verification_kernel/kernel.py +292 -0
- modules/cmvk/src/cross_model_verification_kernel/models.py +111 -0
- modules/cmvk/src/cross_model_verification_kernel/py.typed +1 -0
- modules/cmvk/src/cross_model_verification_kernel/simple_kernel.py +185 -0
- modules/cmvk/src/cross_model_verification_kernel/tools/__init__.py +94 -0
- modules/cmvk/src/cross_model_verification_kernel/tools/huggingface_upload.py +394 -0
- modules/cmvk/src/cross_model_verification_kernel/tools/sandbox.py +159 -0
- modules/cmvk/src/cross_model_verification_kernel/tools/statistics.py +468 -0
- modules/cmvk/src/cross_model_verification_kernel/tools/visualizer.py +312 -0
- modules/cmvk/src/cross_model_verification_kernel/tools/web_search.py +86 -0
- modules/cmvk/src/cross_model_verification_kernel/verifier.py +257 -0
- modules/cmvk/tests/__init__.py +3 -0
- modules/cmvk/tests/conftest.py +61 -0
- modules/cmvk/tests/integration/__init__.py +1 -0
- modules/cmvk/tests/integration/test_anthropic_verifier.py +269 -0
- modules/cmvk/tests/integration/test_integration.py +53 -0
- modules/cmvk/tests/integration/test_lateral_thinking_integration.py +199 -0
- modules/cmvk/tests/integration/test_lateral_thinking_witness.py +208 -0
- modules/cmvk/tests/integration/test_prosecutor_mode.py +131 -0
- modules/cmvk/tests/test_constitutional.py +611 -0
- modules/cmvk/tests/test_enhanced_features.py +603 -0
- modules/cmvk/tests/test_verification.py +255 -0
- modules/cmvk/tests/unit/__init__.py +1 -0
- modules/cmvk/tests/unit/test_agents.py +64 -0
- modules/cmvk/tests/unit/test_cli.py +224 -0
- modules/cmvk/tests/unit/test_core.py +126 -0
- modules/cmvk/tests/unit/test_humaneval_loader.py +197 -0
- modules/cmvk/tests/unit/test_kernel.py +255 -0
- modules/cmvk/tests/unit/test_reproducibility.py +160 -0
- modules/cmvk/tests/unit/test_trace_logger.py +115 -0
- modules/cmvk/tests/unit/test_visualizer.py +218 -0
- modules/control-plane/.github/ISSUE_TEMPLATE/bug_report.yml +82 -0
- modules/control-plane/.github/ISSUE_TEMPLATE/config.yml +11 -0
- modules/control-plane/.github/ISSUE_TEMPLATE/feature_request.yml +104 -0
- modules/control-plane/.github/ISSUE_TEMPLATE/question.yml +70 -0
- modules/control-plane/.github/ISSUE_TEMPLATE/security_vulnerability.yml +84 -0
- modules/control-plane/.github/discussions.yml +73 -0
- modules/control-plane/.github/pull_request_template.md +82 -0
- modules/control-plane/.github/workflows/publish.yml +146 -0
- modules/control-plane/.github/workflows/release.yml +39 -0
- modules/control-plane/.github/workflows/tests.yml +58 -0
- modules/control-plane/.gitignore +55 -0
- modules/control-plane/CHANGELOG.md +203 -0
- modules/control-plane/CONTRIBUTING.md +311 -0
- modules/control-plane/CONTRIBUTORS.md +88 -0
- modules/control-plane/Dockerfile +82 -0
- modules/control-plane/LICENSE +21 -0
- modules/control-plane/MANIFEST.in +17 -0
- modules/control-plane/README.md +1264 -0
- modules/control-plane/ROADMAP.md +228 -0
- modules/control-plane/SECURITY.md +210 -0
- modules/control-plane/SUPPORT.md +106 -0
- modules/control-plane/acp-cli.py +212 -0
- modules/control-plane/benchmark/README.md +257 -0
- modules/control-plane/benchmark/__init__.py +19 -0
- modules/control-plane/benchmark/red_team_dataset.py +517 -0
- modules/control-plane/benchmark.py +563 -0
- modules/control-plane/build_and_publish.sh +130 -0
- modules/control-plane/docker-compose.yml +74 -0
- modules/control-plane/docs/ABLATION_STUDIES.md +528 -0
- modules/control-plane/docs/ADAPTER_GUIDE.md +544 -0
- modules/control-plane/docs/ADVANCED_FEATURES.md +543 -0
- modules/control-plane/docs/AIOS_COMPARISON.md +296 -0
- modules/control-plane/docs/BIBLIOGRAPHY.md +367 -0
- modules/control-plane/docs/CASE_STUDIES.md +645 -0
- modules/control-plane/docs/DOCKER_DEPLOYMENT.md +184 -0
- modules/control-plane/docs/ECOSYSTEM_STATUS.md +98 -0
- modules/control-plane/docs/HF_MODEL_CARD.md +168 -0
- modules/control-plane/docs/KERNEL_V1_RELEASE.md +454 -0
- modules/control-plane/docs/LAYER3_FRAMEWORK.md +227 -0
- modules/control-plane/docs/LIMITATIONS.md +523 -0
- modules/control-plane/docs/PYPI_PUBLISHING.md +195 -0
- modules/control-plane/docs/README.md +58 -0
- modules/control-plane/docs/RELATED_WORK.md +319 -0
- modules/control-plane/docs/RELEASE_v1.1.0.md +252 -0
- modules/control-plane/docs/REPRODUCIBILITY.md +540 -0
- modules/control-plane/docs/RESEARCH_FOUNDATION.md +197 -0
- modules/control-plane/docs/api/CORE.md +270 -0
- modules/control-plane/docs/architecture/architecture.md +120 -0
- modules/control-plane/docs/community/ANNOUNCEMENT_TEMPLATES.md +52 -0
- modules/control-plane/docs/guides/IMPLEMENTATION.md +225 -0
- modules/control-plane/docs/guides/PHILOSOPHY.md +354 -0
- modules/control-plane/docs/guides/QUICKSTART.md +217 -0
- modules/control-plane/examples/README.md +138 -0
- modules/control-plane/examples/a2a_demo.py +410 -0
- modules/control-plane/examples/adapter_demo.py +347 -0
- modules/control-plane/examples/advanced_features.py +403 -0
- modules/control-plane/examples/basic_usage.py +261 -0
- modules/control-plane/examples/benchmark_demo.py +186 -0
- modules/control-plane/examples/compliance_demo.py +333 -0
- modules/control-plane/examples/configuration.py +265 -0
- modules/control-plane/examples/getting_started.py +178 -0
- modules/control-plane/examples/hibernation_and_time_travel_demo.py +406 -0
- modules/control-plane/examples/interactive_tutorial.ipynb +497 -0
- modules/control-plane/examples/kernel_interceptor_demo.py +202 -0
- modules/control-plane/examples/kernel_v1_demo.py +273 -0
- modules/control-plane/examples/langchain_demo.py +281 -0
- modules/control-plane/examples/lifecycle_demo.py +724 -0
- modules/control-plane/examples/mcp_demo.py +378 -0
- modules/control-plane/examples/ml_safety_demo.py +157 -0
- modules/control-plane/examples/multimodal_demo.py +347 -0
- modules/control-plane/examples/observability_demo.py +370 -0
- modules/control-plane/examples/use_cases.py +336 -0
- modules/control-plane/experiments/long_horizon_purge.py +235 -0
- modules/control-plane/experiments/multi_agent_rag.py +165 -0
- modules/control-plane/experiments/reproduce_results.py +667 -0
- modules/control-plane/paper/ARXIV_SUBMISSION_INFO.txt +122 -0
- modules/control-plane/paper/ETHICS_STATEMENT.md +248 -0
- modules/control-plane/paper/PAPER_CHECKLIST.md +72 -0
- modules/control-plane/paper/Paper.pdf +0 -0
- modules/control-plane/paper/README.md +71 -0
- modules/control-plane/paper/appendix.md +152 -0
- modules/control-plane/paper/architecture.md +15 -0
- modules/control-plane/paper/arxiv/figures/ablation_chart.png +0 -0
- modules/control-plane/paper/arxiv/figures/architecture.png +0 -0
- modules/control-plane/paper/arxiv/figures/constraint_graphs.png +0 -0
- modules/control-plane/paper/arxiv/figures/results_chart.png +0 -0
- modules/control-plane/paper/arxiv/main.aux +97 -0
- modules/control-plane/paper/arxiv/main.bbl +112 -0
- modules/control-plane/paper/arxiv/main.blg +48 -0
- modules/control-plane/paper/arxiv/main.out +33 -0
- modules/control-plane/paper/arxiv/main.pdf +0 -0
- modules/control-plane/paper/arxiv/main.tex +479 -0
- modules/control-plane/paper/arxiv/references.bib +234 -0
- modules/control-plane/paper/arxiv_submission.tar +0 -0
- modules/control-plane/paper/arxiv_submission.zip +0 -0
- modules/control-plane/paper/build.sh +68 -0
- modules/control-plane/paper/figures/README.md +47 -0
- modules/control-plane/paper/figures/ablation_chart.pdf +0 -0
- modules/control-plane/paper/figures/ablation_chart.png +0 -0
- modules/control-plane/paper/figures/architecture.pdf +0 -0
- modules/control-plane/paper/figures/architecture.png +0 -0
- modules/control-plane/paper/figures/constraint_graphs.pdf +0 -0
- modules/control-plane/paper/figures/constraint_graphs.png +0 -0
- modules/control-plane/paper/figures/generate_figures.py +252 -0
- modules/control-plane/paper/figures/results_chart.pdf +0 -0
- modules/control-plane/paper/figures/results_chart.png +0 -0
- modules/control-plane/paper/main.md +273 -0
- modules/control-plane/paper/main.tex +214 -0
- modules/control-plane/paper/main_arxiv.aux +53 -0
- modules/control-plane/paper/main_arxiv.out +17 -0
- modules/control-plane/paper/main_arxiv.pdf +0 -0
- modules/control-plane/paper/main_arxiv.tex +264 -0
- modules/control-plane/paper/references.bib +234 -0
- modules/control-plane/pyproject.toml +124 -0
- modules/control-plane/reproducibility/ABLATIONS.md +136 -0
- modules/control-plane/reproducibility/README.md +288 -0
- modules/control-plane/reproducibility/commands.md +467 -0
- modules/control-plane/reproducibility/docker_config/Dockerfile +39 -0
- modules/control-plane/reproducibility/experiment_configs/purge_config.json +46 -0
- modules/control-plane/reproducibility/experiment_configs/rag_config.json +36 -0
- modules/control-plane/reproducibility/hardware_specs.md +317 -0
- modules/control-plane/reproducibility/requirements_frozen.txt +0 -0
- modules/control-plane/reproducibility/run_all_experiments.sh +45 -0
- modules/control-plane/reproducibility/seeds.json +106 -0
- modules/control-plane/scripts/prepare_pypi.py +46 -0
- modules/control-plane/scripts/prepare_release.py +176 -0
- modules/control-plane/scripts/upload_dataset_to_hf.py +316 -0
- modules/control-plane/setup.py +69 -0
- modules/control-plane/src/agent_control_plane/__init__.py +639 -0
- modules/control-plane/src/agent_control_plane/a2a_adapter.py +541 -0
- modules/control-plane/src/agent_control_plane/adapter.py +415 -0
- modules/control-plane/src/agent_control_plane/agent_hibernation.py +364 -0
- modules/control-plane/src/agent_control_plane/agent_kernel.py +464 -0
- modules/control-plane/src/agent_control_plane/compliance.py +718 -0
- modules/control-plane/src/agent_control_plane/constraint_graphs.py +475 -0
- modules/control-plane/src/agent_control_plane/control_plane.py +848 -0
- modules/control-plane/src/agent_control_plane/example_executors.py +193 -0
- modules/control-plane/src/agent_control_plane/execution_engine.py +229 -0
- modules/control-plane/src/agent_control_plane/flight_recorder.py +600 -0
- modules/control-plane/src/agent_control_plane/governance_layer.py +432 -0
- modules/control-plane/src/agent_control_plane/hf_utils.py +561 -0
- modules/control-plane/src/agent_control_plane/interfaces/__init__.py +53 -0
- modules/control-plane/src/agent_control_plane/interfaces/kernel_interface.py +359 -0
- modules/control-plane/src/agent_control_plane/interfaces/plugin_interface.py +495 -0
- modules/control-plane/src/agent_control_plane/interfaces/protocol_interfaces.py +385 -0
- modules/control-plane/src/agent_control_plane/kernel_space.py +707 -0
- modules/control-plane/src/agent_control_plane/langchain_adapter.py +422 -0
- modules/control-plane/src/agent_control_plane/lifecycle.py +3111 -0
- modules/control-plane/src/agent_control_plane/mcp_adapter.py +517 -0
- modules/control-plane/src/agent_control_plane/ml_safety.py +560 -0
- modules/control-plane/src/agent_control_plane/multimodal.py +724 -0
- modules/control-plane/src/agent_control_plane/mute_agent.py +419 -0
- modules/control-plane/src/agent_control_plane/observability.py +785 -0
- modules/control-plane/src/agent_control_plane/orchestrator.py +480 -0
- modules/control-plane/src/agent_control_plane/plugin_registry.py +748 -0
- modules/control-plane/src/agent_control_plane/policy_engine.py +525 -0
- modules/control-plane/src/agent_control_plane/shadow_mode.py +307 -0
- modules/control-plane/src/agent_control_plane/signals.py +491 -0
- modules/control-plane/src/agent_control_plane/supervisor_agents.py +427 -0
- modules/control-plane/src/agent_control_plane/time_travel_debugger.py +554 -0
- modules/control-plane/src/agent_control_plane/tool_registry.py +350 -0
- modules/control-plane/src/agent_control_plane/vfs.py +695 -0
- modules/control-plane/tests/README.md +33 -0
- modules/control-plane/tests/test_a2a_adapter.py +336 -0
- modules/control-plane/tests/test_adapter.py +422 -0
- modules/control-plane/tests/test_advanced_features.py +389 -0
- modules/control-plane/tests/test_benchmark.py +223 -0
- modules/control-plane/tests/test_compliance.py +214 -0
- modules/control-plane/tests/test_control_plane.py +295 -0
- modules/control-plane/tests/test_hibernation.py +274 -0
- modules/control-plane/tests/test_kernel_interception.py +284 -0
- modules/control-plane/tests/test_langchain_adapter.py +258 -0
- modules/control-plane/tests/test_lifecycle.py +1174 -0
- modules/control-plane/tests/test_mcp_adapter.py +293 -0
- modules/control-plane/tests/test_ml_safety.py +142 -0
- modules/control-plane/tests/test_multimodal.py +317 -0
- modules/control-plane/tests/test_new_features.py +435 -0
- modules/control-plane/tests/test_observability.py +338 -0
- modules/control-plane/tests/test_time_travel.py +387 -0
- modules/emk/.github/workflows/ci.yml +105 -0
- modules/emk/.github/workflows/publish.yml +144 -0
- modules/emk/.gitignore +74 -0
- modules/emk/CHANGELOG.md +41 -0
- modules/emk/CONTRIBUTING.md +295 -0
- modules/emk/IMPLEMENTATION.md +174 -0
- modules/emk/LICENSE +21 -0
- modules/emk/MANIFEST.in +8 -0
- modules/emk/README.md +135 -0
- modules/emk/RELEASE_NOTES.md +82 -0
- modules/emk/SECURITY.md +52 -0
- modules/emk/codecov.yml +39 -0
- modules/emk/docs/MEMORY_MANAGEMENT.md +285 -0
- modules/emk/emk/__init__.py +106 -0
- modules/emk/emk/hf_utils.py +419 -0
- modules/emk/emk/indexer.py +144 -0
- modules/emk/emk/py.typed +0 -0
- modules/emk/emk/schema.py +204 -0
- modules/emk/emk/sleep_cycle.py +345 -0
- modules/emk/emk/store.py +479 -0
- modules/emk/examples/basic_usage.py +123 -0
- modules/emk/examples/memory_features_demo.py +154 -0
- modules/emk/experiments/README.md +59 -0
- modules/emk/experiments/reproduce_results.py +461 -0
- modules/emk/experiments/results.json +61 -0
- modules/emk/paper/structure.tex +192 -0
- modules/emk/paper/whitepaper.md +273 -0
- modules/emk/pyproject.toml +91 -0
- modules/emk/setup.py +5 -0
- modules/emk/tests/test_file_adapter.py +195 -0
- modules/emk/tests/test_indexer.py +174 -0
- modules/emk/tests/test_init.py +55 -0
- modules/emk/tests/test_negative_memory.py +83 -0
- modules/emk/tests/test_schema.py +150 -0
- modules/emk/tests/test_semantic_rules.py +175 -0
- modules/emk/tests/test_sleep_cycle.py +335 -0
- modules/emk/tests/test_store_anti_patterns.py +239 -0
- modules/iatp/.github/workflows/docker-build.yml +124 -0
- modules/iatp/.github/workflows/publish.yml +174 -0
- modules/iatp/.github/workflows/python-package.yml +121 -0
- modules/iatp/.gitignore +67 -0
- modules/iatp/.pre-commit-config.yaml +64 -0
- modules/iatp/CHANGELOG.md +120 -0
- modules/iatp/Dockerfile +91 -0
- modules/iatp/IMPLEMENTATION_SUMMARY.md +218 -0
- modules/iatp/MANIFEST.in +9 -0
- modules/iatp/README.md +180 -0
- modules/iatp/docker/Dockerfile.agent +27 -0
- modules/iatp/docker/Dockerfile.sidecar-python +86 -0
- modules/iatp/docker/README.md +258 -0
- modules/iatp/docker-compose.yml +194 -0
- modules/iatp/docs/ARCHITECTURE.md +243 -0
- modules/iatp/docs/CLI_GUIDE.md +220 -0
- modules/iatp/docs/DEPLOYMENT.md +304 -0
- modules/iatp/examples/README.md +132 -0
- modules/iatp/examples/backend_agent.py +39 -0
- modules/iatp/examples/client.py +168 -0
- modules/iatp/examples/demo_attestation_reputation.py +274 -0
- modules/iatp/examples/demo_client.py +240 -0
- modules/iatp/examples/demo_rbac.py +143 -0
- modules/iatp/examples/integration_demo.py +245 -0
- modules/iatp/examples/manifests/coder_agent.json +20 -0
- modules/iatp/examples/manifests/reviewer_agent.json +19 -0
- modules/iatp/examples/manifests/secure_bank.json +14 -0
- modules/iatp/examples/manifests/standard_agent.json +14 -0
- modules/iatp/examples/manifests/untrusted_honeypot.json +14 -0
- modules/iatp/examples/run_secure_bank_sidecar.py +85 -0
- modules/iatp/examples/run_sidecar.py +105 -0
- modules/iatp/examples/run_untrusted_sidecar.py +77 -0
- modules/iatp/examples/secure_bank_agent.py +138 -0
- modules/iatp/examples/test_untrusted.py +82 -0
- modules/iatp/examples/untrusted_agent.py +119 -0
- modules/iatp/experiments/README.md +58 -0
- modules/iatp/experiments/cascading_hallucination/README.md +149 -0
- modules/iatp/experiments/cascading_hallucination/agent_a_user.py +41 -0
- modules/iatp/experiments/cascading_hallucination/agent_b_summarizer.py +54 -0
- modules/iatp/experiments/cascading_hallucination/agent_c_database.py +47 -0
- modules/iatp/experiments/cascading_hallucination/proof_of_concept.py +290 -0
- modules/iatp/experiments/cascading_hallucination/run_experiment.py +226 -0
- modules/iatp/experiments/cascading_hallucination/sidecar_c.py +61 -0
- modules/iatp/experiments/reproduce_results.py +574 -0
- modules/iatp/experiments/results.json +2336 -0
- modules/iatp/iatp/__init__.py +164 -0
- modules/iatp/iatp/attestation.py +401 -0
- modules/iatp/iatp/cli.py +253 -0
- modules/iatp/iatp/hf_utils.py +469 -0
- modules/iatp/iatp/ipc_pipes.py +578 -0
- modules/iatp/iatp/main.py +410 -0
- modules/iatp/iatp/models/__init__.py +445 -0
- modules/iatp/iatp/policy_engine.py +335 -0
- modules/iatp/iatp/py.typed +2 -0
- modules/iatp/iatp/recovery.py +319 -0
- modules/iatp/iatp/security/__init__.py +268 -0
- modules/iatp/iatp/sidecar/__init__.py +517 -0
- modules/iatp/iatp/telemetry/__init__.py +162 -0
- modules/iatp/iatp/tests/__init__.py +1 -0
- modules/iatp/iatp/tests/test_attestation.py +368 -0
- modules/iatp/iatp/tests/test_cli.py +129 -0
- modules/iatp/iatp/tests/test_models.py +128 -0
- modules/iatp/iatp/tests/test_policy_engine.py +345 -0
- modules/iatp/iatp/tests/test_recovery.py +279 -0
- modules/iatp/iatp/tests/test_security.py +220 -0
- modules/iatp/iatp/tests/test_sidecar.py +165 -0
- modules/iatp/iatp/tests/test_telemetry.py +173 -0
- modules/iatp/paper/BLOG.md +307 -0
- modules/iatp/paper/PAPER.md +236 -0
- modules/iatp/paper/RFC_SUBMISSION.md +299 -0
- modules/iatp/paper/whitepaper.md +369 -0
- modules/iatp/proto/README.md +200 -0
- modules/iatp/proto/generate_stubs.py +81 -0
- modules/iatp/proto/iatp.proto +552 -0
- modules/iatp/pyproject.toml +180 -0
- modules/iatp/requirements-dev.txt +2 -0
- modules/iatp/requirements.txt +6 -0
- modules/iatp/setup.py +60 -0
- modules/iatp/sidecar/README.md +487 -0
- modules/iatp/sidecar/go/Dockerfile +32 -0
- modules/iatp/sidecar/go/README.md +237 -0
- modules/iatp/sidecar/go/go.mod +8 -0
- modules/iatp/sidecar/go/main.go +488 -0
- modules/iatp/spec/001-handshake.md +436 -0
- modules/iatp/spec/002-reversibility.md +394 -0
- modules/iatp/spec/schema/capability_manifest.json +266 -0
- modules/iatp/test_integration.py +310 -0
- modules/mcp-kernel-server/README.md +261 -0
- modules/mcp-kernel-server/pyproject.toml +60 -0
- modules/mcp-kernel-server/src/mcp_kernel_server/__init__.py +26 -0
- modules/mcp-kernel-server/src/mcp_kernel_server/cli.py +229 -0
- modules/mcp-kernel-server/src/mcp_kernel_server/resources.py +215 -0
- modules/mcp-kernel-server/src/mcp_kernel_server/server.py +562 -0
- modules/mcp-kernel-server/src/mcp_kernel_server/tools.py +1172 -0
- modules/mute-agent/.github/workflows/safety_check.yml +45 -0
- modules/mute-agent/.gitignore +53 -0
- modules/mute-agent/ARCHITECTURE.md +531 -0
- modules/mute-agent/BENCHMARK_GUIDE.md +384 -0
- modules/mute-agent/COMPLETION_SUMMARY.md +293 -0
- modules/mute-agent/EXPERIMENT_SUMMARY.md +318 -0
- modules/mute-agent/IMPLEMENTATION_SUMMARY.md +212 -0
- modules/mute-agent/LICENSE +21 -0
- modules/mute-agent/PHASE3_SUMMARY.md +297 -0
- modules/mute-agent/README.md +360 -0
- modules/mute-agent/STEEL_MAN_RESULTS.md +353 -0
- modules/mute-agent/USAGE.md +505 -0
- modules/mute-agent/V2_IMPLEMENTATION_SUMMARY.md +253 -0
- modules/mute-agent/V2_STEEL_MAN_IMPLEMENTATION.md +274 -0
- modules/mute-agent/VERIFICATION_REPORT.md +435 -0
- modules/mute-agent/charts/cost_comparison.png +0 -0
- modules/mute-agent/charts/cost_vs_ambiguity.png +0 -0
- modules/mute-agent/charts/metrics_comparison.png +0 -0
- modules/mute-agent/charts/scenario_breakdown.png +0 -0
- modules/mute-agent/charts/trace_attack_blocked.html +140 -0
- modules/mute-agent/charts/trace_attack_blocked.png +0 -0
- modules/mute-agent/charts/trace_failure.html +140 -0
- modules/mute-agent/charts/trace_failure.png +0 -0
- modules/mute-agent/charts/trace_success.html +140 -0
- modules/mute-agent/charts/trace_success.png +0 -0
- modules/mute-agent/examples/__init__.py +1 -0
- modules/mute-agent/examples/advanced_example.py +384 -0
- modules/mute-agent/examples/graph_debugger_demo.py +241 -0
- modules/mute-agent/examples/listener_example.py +297 -0
- modules/mute-agent/examples/simple_example.py +242 -0
- modules/mute-agent/examples/steel_man_demo.py +297 -0
- modules/mute-agent/experiments/README.md +135 -0
- modules/mute-agent/experiments/__init__.py +3 -0
- modules/mute-agent/experiments/agent_comparison.csv +6 -0
- modules/mute-agent/experiments/agent_comparison_50runs.csv +6 -0
- modules/mute-agent/experiments/ambiguity_test.py +335 -0
- modules/mute-agent/experiments/ambiguity_test_results.csv +31 -0
- modules/mute-agent/experiments/ambiguity_test_results_50runs.csv +51 -0
- modules/mute-agent/experiments/baseline_agent.py +189 -0
- modules/mute-agent/experiments/benchmark.py +402 -0
- modules/mute-agent/experiments/demo.py +172 -0
- modules/mute-agent/experiments/generate_cost_curve.py +474 -0
- modules/mute-agent/experiments/jailbreak_test.py +137 -0
- modules/mute-agent/experiments/latent_state_scenario.py +361 -0
- modules/mute-agent/experiments/mute_agent_experiment.py +349 -0
- modules/mute-agent/experiments/run_extended_experiment.py +40 -0
- modules/mute-agent/experiments/run_v2_experiments.py +266 -0
- modules/mute-agent/experiments/run_v2_experiments_auto.py +247 -0
- modules/mute-agent/experiments/v2_scenarios/README.md +214 -0
- modules/mute-agent/experiments/v2_scenarios/__init__.py +4 -0
- modules/mute-agent/experiments/v2_scenarios/scenario_1_deep_dependency.py +325 -0
- modules/mute-agent/experiments/v2_scenarios/scenario_2_adversarial.py +328 -0
- modules/mute-agent/experiments/v2_scenarios/scenario_3_false_positive.py +303 -0
- modules/mute-agent/experiments/v2_scenarios/scenario_4_performance.py +319 -0
- modules/mute-agent/experiments/visualize.py +400 -0
- modules/mute-agent/mute_agent/__init__.py +66 -0
- modules/mute-agent/mute_agent/core/__init__.py +1 -0
- modules/mute-agent/mute_agent/core/execution_agent.py +164 -0
- modules/mute-agent/mute_agent/core/handshake_protocol.py +199 -0
- modules/mute-agent/mute_agent/core/reasoning_agent.py +236 -0
- modules/mute-agent/mute_agent/knowledge_graph/__init__.py +1 -0
- modules/mute-agent/mute_agent/knowledge_graph/graph_elements.py +63 -0
- modules/mute-agent/mute_agent/knowledge_graph/multidimensional_graph.py +168 -0
- modules/mute-agent/mute_agent/knowledge_graph/subgraph.py +222 -0
- modules/mute-agent/mute_agent/listener/__init__.py +41 -0
- modules/mute-agent/mute_agent/listener/adapters/__init__.py +29 -0
- modules/mute-agent/mute_agent/listener/adapters/base_adapter.py +187 -0
- modules/mute-agent/mute_agent/listener/adapters/caas_adapter.py +342 -0
- modules/mute-agent/mute_agent/listener/adapters/control_plane_adapter.py +434 -0
- modules/mute-agent/mute_agent/listener/adapters/iatp_adapter.py +330 -0
- modules/mute-agent/mute_agent/listener/adapters/scak_adapter.py +249 -0
- modules/mute-agent/mute_agent/listener/listener.py +608 -0
- modules/mute-agent/mute_agent/listener/state_observer.py +434 -0
- modules/mute-agent/mute_agent/listener/threshold_config.py +311 -0
- modules/mute-agent/mute_agent/super_system/__init__.py +1 -0
- modules/mute-agent/mute_agent/super_system/router.py +202 -0
- modules/mute-agent/mute_agent/visualization/__init__.py +8 -0
- modules/mute-agent/mute_agent/visualization/graph_debugger.py +495 -0
- modules/mute-agent/requirements-dev.txt +6 -0
- modules/mute-agent/requirements.txt +9 -0
- modules/mute-agent/setup.py +64 -0
- modules/mute-agent/src/__init__.py +0 -0
- modules/mute-agent/src/agents/__init__.py +0 -0
- modules/mute-agent/src/agents/baseline_agent.py +524 -0
- modules/mute-agent/src/agents/interactive_agent.py +113 -0
- modules/mute-agent/src/agents/mute_agent.py +622 -0
- modules/mute-agent/src/benchmarks/__init__.py +0 -0
- modules/mute-agent/src/benchmarks/evaluator.py +481 -0
- modules/mute-agent/src/benchmarks/scenarios.json +985 -0
- modules/mute-agent/src/core/__init__.py +0 -0
- modules/mute-agent/src/core/mock_state.py +320 -0
- modules/mute-agent/src/core/tools.py +441 -0
- modules/nexus/__init__.py +49 -0
- modules/nexus/arbiter.py +357 -0
- modules/nexus/client.py +464 -0
- modules/nexus/dmz.py +417 -0
- modules/nexus/escrow.py +428 -0
- modules/nexus/exceptions.py +284 -0
- modules/nexus/registry.py +391 -0
- modules/nexus/reputation.py +423 -0
- modules/nexus/schemas/__init__.py +49 -0
- modules/nexus/schemas/compliance.py +274 -0
- modules/nexus/schemas/escrow.py +249 -0
- modules/nexus/schemas/manifest.py +223 -0
- modules/nexus/schemas/receipt.py +206 -0
- modules/observability/README.md +192 -0
- modules/observability/alertmanager/alertmanager.yml +116 -0
- modules/observability/alerts/agent-os-alerts.yaml +197 -0
- modules/observability/docker-compose.yml +128 -0
- modules/observability/grafana/dashboards/agent-os-amb.json +448 -0
- modules/observability/grafana/dashboards/agent-os-cmvk.json +441 -0
- modules/observability/grafana/dashboards/agent-os-overview.json +268 -0
- modules/observability/grafana/dashboards/agent-os-performance.json +15 -0
- modules/observability/grafana/dashboards/agent-os-safety.json +50 -0
- modules/observability/grafana/provisioning/dashboards/dashboards.yml +15 -0
- modules/observability/grafana/provisioning/datasources/datasources.yml +33 -0
- modules/observability/otel/otel-collector-config.yml +61 -0
- modules/observability/prometheus/prometheus.yml +63 -0
- modules/observability/pyproject.toml +53 -0
- modules/observability/scripts/export_dashboards.py +55 -0
- modules/observability/src/agent_os_observability/__init__.py +25 -0
- modules/observability/src/agent_os_observability/dashboards.py +896 -0
- modules/observability/src/agent_os_observability/metrics.py +396 -0
- modules/observability/src/agent_os_observability/server.py +221 -0
- modules/observability/src/agent_os_observability/tracer.py +226 -0
- modules/primitives/.gitignore +8 -0
- modules/primitives/README.md +62 -0
- modules/primitives/agent_primitives/__init__.py +22 -0
- modules/primitives/agent_primitives/failures.py +82 -0
- modules/primitives/agent_primitives/py.typed +0 -0
- modules/primitives/pyproject.toml +68 -0
- modules/scak/.github/copilot-instructions.md +396 -0
- modules/scak/.github/workflows/release.yml +117 -0
- modules/scak/.gitignore +32 -0
- modules/scak/CHANGELOG.md +173 -0
- modules/scak/CITATION.cff +62 -0
- modules/scak/CONTRIBUTING.md +429 -0
- modules/scak/Dockerfile +58 -0
- modules/scak/ENTERPRISE_FEATURES.md +518 -0
- modules/scak/IMPLEMENTATION_SUMMARY.md +206 -0
- modules/scak/LIMITATIONS.md +565 -0
- modules/scak/MANIFEST.in +16 -0
- modules/scak/NOVELTY.md +535 -0
- modules/scak/README.md +928 -0
- modules/scak/RESEARCH.md +670 -0
- modules/scak/agent_kernel/__init__.py +66 -0
- modules/scak/agent_kernel/analyzer.py +432 -0
- modules/scak/agent_kernel/auditor.py +31 -0
- modules/scak/agent_kernel/completeness_auditor.py +234 -0
- modules/scak/agent_kernel/detector.py +200 -0
- modules/scak/agent_kernel/kernel.py +741 -0
- modules/scak/agent_kernel/memory_manager.py +82 -0
- modules/scak/agent_kernel/models.py +372 -0
- modules/scak/agent_kernel/nudge_mechanism.py +260 -0
- modules/scak/agent_kernel/outcome_analyzer.py +335 -0
- modules/scak/agent_kernel/patcher.py +579 -0
- modules/scak/agent_kernel/semantic_analyzer.py +313 -0
- modules/scak/agent_kernel/semantic_purge.py +346 -0
- modules/scak/agent_kernel/simulator.py +447 -0
- modules/scak/agent_kernel/teacher.py +82 -0
- modules/scak/agent_kernel/triage.py +149 -0
- modules/scak/build_and_publish.ps1 +74 -0
- modules/scak/build_and_publish.sh +74 -0
- modules/scak/cli.py +471 -0
- modules/scak/dashboard.py +462 -0
- modules/scak/datasets/DATASET_CARD.md +219 -0
- modules/scak/datasets/README.md +143 -0
- modules/scak/datasets/gaia_vague_queries/vague_queries.json +262 -0
- modules/scak/datasets/hf_upload/README.md +219 -0
- modules/scak/datasets/hf_upload/scak_gaia_laziness.jsonl +50 -0
- modules/scak/datasets/prepare_hf_datasets.py +145 -0
- modules/scak/datasets/red_team/jailbreak_patterns.json +202 -0
- modules/scak/docker-compose.yml +99 -0
- modules/scak/docs/Adaptive-Memory-Hierarchy.md +319 -0
- modules/scak/docs/Data-Contracts-and-Schemas.md +285 -0
- modules/scak/docs/Dual-Loop-Architecture.md +344 -0
- modules/scak/docs/Enhanced-Features.md +612 -0
- modules/scak/docs/LANGCHAIN_INTEGRATION.md +572 -0
- modules/scak/docs/README.md +128 -0
- modules/scak/docs/Reference-Implementations.md +163 -0
- modules/scak/docs/SCAK_V2.md +374 -0
- modules/scak/docs/Three-Failure-Types.md +178 -0
- modules/scak/examples/basic_example.py +155 -0
- modules/scak/examples/circuit_breaker_lazy_eval_demo.py +243 -0
- modules/scak/examples/langchain_integration_example.py +339 -0
- modules/scak/examples/layer4_demo.py +243 -0
- modules/scak/examples/production_features_demo.py +353 -0
- modules/scak/examples/quick_demo.py +79 -0
- modules/scak/examples/scak_v2_demo.py +252 -0
- modules/scak/experiments/README.md +438 -0
- modules/scak/experiments/ablation_studies/README.md +192 -0
- modules/scak/experiments/ablation_studies/ablation_no_audit.py +116 -0
- modules/scak/experiments/ablation_studies/ablation_no_purge.py +133 -0
- modules/scak/experiments/chaos_engineering/README.md +332 -0
- modules/scak/experiments/context_efficiency_test.py +328 -0
- modules/scak/experiments/gaia_benchmark/README.md +208 -0
- modules/scak/experiments/laziness_benchmark.py +179 -0
- modules/scak/experiments/long_horizon_task_experiment.py +252 -0
- modules/scak/experiments/multi_agent_rag_experiment.py +284 -0
- modules/scak/experiments/results/ablation_table.md +12 -0
- modules/scak/experiments/results/long_horizon.json +36 -0
- modules/scak/experiments/results/multi_agent_rag.json +66 -0
- modules/scak/experiments/run_comprehensive_ablations.py +332 -0
- modules/scak/experiments/test_auditor_patcher_integration.py +251 -0
- modules/scak/notebooks/getting_started.ipynb +33 -0
- modules/scak/paper/ARXIV_SUBMISSION_METADATA.txt +109 -0
- modules/scak/paper/PAPER_CHECKLIST.md +304 -0
- modules/scak/paper/Paper.pdf +0 -0
- modules/scak/paper/README.md +113 -0
- modules/scak/paper/appendix.md +351 -0
- modules/scak/paper/arxiv/bibliography.bib +284 -0
- modules/scak/paper/arxiv/fig1_ooda_architecture.pdf +0 -0
- modules/scak/paper/arxiv/fig2_memory_hierarchy.pdf +0 -0
- modules/scak/paper/arxiv/fig3_gaia_results.pdf +0 -0
- modules/scak/paper/arxiv/fig4_ablation_heatmap.pdf +0 -0
- modules/scak/paper/arxiv/fig5_context_reduction.pdf +0 -0
- modules/scak/paper/arxiv/fig6_mttr_boxplot.pdf +0 -0
- modules/scak/paper/arxiv/main.aux +103 -0
- modules/scak/paper/arxiv/main.bbl +113 -0
- modules/scak/paper/arxiv/main.blg +55 -0
- modules/scak/paper/arxiv/main.out +31 -0
- modules/scak/paper/arxiv/main.pdf +0 -0
- modules/scak/paper/arxiv/main.tex +482 -0
- modules/scak/paper/arxiv_submission/bibliography.bib +284 -0
- modules/scak/paper/arxiv_submission/fig1_ooda_architecture.pdf +0 -0
- modules/scak/paper/arxiv_submission/fig2_memory_hierarchy.pdf +0 -0
- modules/scak/paper/arxiv_submission/fig3_gaia_results.pdf +0 -0
- modules/scak/paper/arxiv_submission/fig4_ablation_heatmap.pdf +0 -0
- modules/scak/paper/arxiv_submission/fig5_context_reduction.pdf +0 -0
- modules/scak/paper/arxiv_submission/fig6_mttr_boxplot.pdf +0 -0
- modules/scak/paper/arxiv_submission/main.aux +103 -0
- modules/scak/paper/arxiv_submission/main.bbl +113 -0
- modules/scak/paper/arxiv_submission/main.blg +55 -0
- modules/scak/paper/arxiv_submission/main.out +31 -0
- modules/scak/paper/arxiv_submission/main.pdf +0 -0
- modules/scak/paper/arxiv_submission/main.tex +482 -0
- modules/scak/paper/arxiv_submission.tar.gz +0 -0
- modules/scak/paper/bibliography.bib +284 -0
- modules/scak/paper/build.sh +55 -0
- modules/scak/paper/figures/README.md +32 -0
- modules/scak/paper/figures/fig1_ooda_architecture.md +75 -0
- modules/scak/paper/figures/fig1_ooda_architecture.pdf +0 -0
- modules/scak/paper/figures/fig1_ooda_architecture.png +0 -0
- modules/scak/paper/figures/fig2_memory_hierarchy.md +83 -0
- modules/scak/paper/figures/fig2_memory_hierarchy.pdf +0 -0
- modules/scak/paper/figures/fig2_memory_hierarchy.png +0 -0
- modules/scak/paper/figures/fig3_gaia_results.md +64 -0
- modules/scak/paper/figures/fig3_gaia_results.pdf +0 -0
- modules/scak/paper/figures/fig3_gaia_results.png +0 -0
- modules/scak/paper/figures/fig4_ablation_heatmap.md +64 -0
- modules/scak/paper/figures/fig4_ablation_heatmap.pdf +0 -0
- modules/scak/paper/figures/fig4_ablation_heatmap.png +0 -0
- modules/scak/paper/figures/fig5_context_reduction.md +71 -0
- modules/scak/paper/figures/fig5_context_reduction.pdf +0 -0
- modules/scak/paper/figures/fig5_context_reduction.png +0 -0
- modules/scak/paper/figures/fig6_mttr_boxplot.md +80 -0
- modules/scak/paper/figures/fig6_mttr_boxplot.pdf +0 -0
- modules/scak/paper/figures/fig6_mttr_boxplot.png +0 -0
- modules/scak/paper/figures/generate_figures.py +463 -0
- modules/scak/paper/main.aux +103 -0
- modules/scak/paper/main.bbl +113 -0
- modules/scak/paper/main.blg +55 -0
- modules/scak/paper/main.md +192 -0
- modules/scak/paper/main.out +31 -0
- modules/scak/paper/main.pdf +0 -0
- modules/scak/paper/main.tex +482 -0
- modules/scak/reproducibility/ABLATIONS.md +225 -0
- modules/scak/reproducibility/Dockerfile.reproducibility +34 -0
- modules/scak/reproducibility/README.md +421 -0
- modules/scak/reproducibility/requirements-pinned.txt +32 -0
- modules/scak/reproducibility/run_all_experiments.py +395 -0
- modules/scak/reproducibility/seed_control.py +53 -0
- modules/scak/reproducibility/statistical_analysis.py +302 -0
- modules/scak/requirements.txt +50 -0
- modules/scak/setup.py +93 -0
- modules/scak/src/__init__.py +124 -0
- modules/scak/src/agents/__init__.py +13 -0
- modules/scak/src/agents/conflict_resolution.py +732 -0
- modules/scak/src/agents/orchestrator.py +761 -0
- modules/scak/src/agents/pubsub.py +484 -0
- modules/scak/src/agents/shadow_teacher.py +344 -0
- modules/scak/src/agents/swarm.py +661 -0
- modules/scak/src/agents/worker.py +357 -0
- modules/scak/src/integrations/__init__.py +81 -0
- modules/scak/src/integrations/cmvk_adapter.py +430 -0
- modules/scak/src/integrations/control_plane_adapter.py +601 -0
- modules/scak/src/integrations/langchain_integration.py +902 -0
- modules/scak/src/interfaces/__init__.py +59 -0
- modules/scak/src/interfaces/llm_clients.py +505 -0
- modules/scak/src/interfaces/openapi_tools.py +611 -0
- modules/scak/src/interfaces/plugin_system.py +605 -0
- modules/scak/src/interfaces/protocols.py +365 -0
- modules/scak/src/interfaces/telemetry.py +464 -0
- modules/scak/src/interfaces/tool_registry.py +547 -0
- modules/scak/src/kernel/__init__.py +100 -0
- modules/scak/src/kernel/auditor.py +305 -0
- modules/scak/src/kernel/circuit_breaker.py +398 -0
- modules/scak/src/kernel/core.py +724 -0
- modules/scak/src/kernel/distributed.py +667 -0
- modules/scak/src/kernel/evolution.py +455 -0
- modules/scak/src/kernel/failover.py +621 -0
- modules/scak/src/kernel/governance.py +710 -0
- modules/scak/src/kernel/governance_v2.py +603 -0
- modules/scak/src/kernel/lazy_evaluator.py +514 -0
- modules/scak/src/kernel/load_testing.py +633 -0
- modules/scak/src/kernel/memory.py +945 -0
- modules/scak/src/kernel/patcher.py +581 -0
- modules/scak/src/kernel/rubric.py +419 -0
- modules/scak/src/kernel/schemas.py +390 -0
- modules/scak/src/kernel/skill_mapper.py +309 -0
- modules/scak/src/kernel/triage.py +149 -0
- modules/scak/src/mocks/__init__.py +99 -0
- modules/scak/tests/__init__.py +1 -0
- modules/scak/tests/test_circuit_breaker.py +403 -0
- modules/scak/tests/test_conflict_resolution.py +287 -0
- modules/scak/tests/test_dual_loop.py +463 -0
- modules/scak/tests/test_enhanced_features.py +421 -0
- modules/scak/tests/test_failover_and_load.py +438 -0
- modules/scak/tests/test_governance.py +185 -0
- modules/scak/tests/test_kernel.py +359 -0
- modules/scak/tests/test_langchain_integration.py +451 -0
- modules/scak/tests/test_lazy_evaluator.py +465 -0
- modules/scak/tests/test_llm_clients.py +122 -0
- modules/scak/tests/test_memory_controller.py +528 -0
- modules/scak/tests/test_orchestrator.py +181 -0
- modules/scak/tests/test_phase3_integration.py +265 -0
- modules/scak/tests/test_pubsub_swarm.py +203 -0
- modules/scak/tests/test_reference_implementations.py +240 -0
- modules/scak/tests/test_rubric.py +363 -0
- modules/scak/tests/test_scak_v2.py +651 -0
- modules/scak/tests/test_skill_mapper.py +217 -0
- modules/scak/tests/test_specific_failures.py +393 -0
- modules/scak/tests/test_tool_registry.py +264 -0
- modules/scak/tests/test_tools_and_plugins.py +303 -0
- modules/scak/tests/test_triage.py +596 -0
- modules/scak/tests/test_write_through.py +319 -0
- agent_os_kernel-1.1.0.dist-info/METADATA +0 -400
- agent_os_kernel-1.1.0.dist-info/RECORD +0 -12
- {agent_os_kernel-1.1.0.dist-info → agent_os_kernel-1.2.0.dist-info}/WHEEL +0 -0
- {agent_os_kernel-1.1.0.dist-info → agent_os_kernel-1.2.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,1174 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tests for Agent Lifecycle Management (v0.2.0)
|
|
3
|
+
|
|
4
|
+
This module tests the comprehensive lifecycle management features:
|
|
5
|
+
- ACP-001: Agent Health Checks
|
|
6
|
+
- ACP-002: Agent Auto-Recovery
|
|
7
|
+
- ACP-003: Circuit Breaker
|
|
8
|
+
- ACP-004: Agent Scaling
|
|
9
|
+
- ACP-005: Distributed Coordination
|
|
10
|
+
- ACP-006: Agent Dependency Graph
|
|
11
|
+
- ACP-007: Graceful Shutdown
|
|
12
|
+
- ACP-008: Resource Quotas
|
|
13
|
+
- ACP-009: Agent Observability
|
|
14
|
+
- ACP-010: Hot Reload
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import pytest
|
|
18
|
+
import asyncio
|
|
19
|
+
from datetime import datetime, timedelta
|
|
20
|
+
from unittest.mock import Mock, AsyncMock, patch, MagicMock
|
|
21
|
+
import sys
|
|
22
|
+
|
|
23
|
+
from agent_control_plane.lifecycle import (
|
|
24
|
+
# Health Monitoring
|
|
25
|
+
HealthMonitor,
|
|
26
|
+
HealthCheckConfig,
|
|
27
|
+
HealthCheckResult,
|
|
28
|
+
HealthStatus,
|
|
29
|
+
|
|
30
|
+
# Auto-Recovery
|
|
31
|
+
AutoRecoveryManager,
|
|
32
|
+
RecoveryConfig,
|
|
33
|
+
RecoveryEvent,
|
|
34
|
+
|
|
35
|
+
# Circuit Breaker
|
|
36
|
+
CircuitBreaker,
|
|
37
|
+
CircuitBreakerConfig,
|
|
38
|
+
CircuitBreakerOpenError,
|
|
39
|
+
CircuitState,
|
|
40
|
+
CircuitBreakerRegistry,
|
|
41
|
+
|
|
42
|
+
# Scaling
|
|
43
|
+
AgentScaler,
|
|
44
|
+
ScalingConfig,
|
|
45
|
+
AgentReplica,
|
|
46
|
+
AgentState,
|
|
47
|
+
|
|
48
|
+
# Distributed Coordination
|
|
49
|
+
DistributedCoordinator,
|
|
50
|
+
LeaderElectionConfig,
|
|
51
|
+
CoordinationRole,
|
|
52
|
+
|
|
53
|
+
# Dependency Graph
|
|
54
|
+
DependencyGraph,
|
|
55
|
+
AgentDependency,
|
|
56
|
+
|
|
57
|
+
# Graceful Shutdown
|
|
58
|
+
GracefulShutdownManager,
|
|
59
|
+
ShutdownConfig,
|
|
60
|
+
ShutdownPhase,
|
|
61
|
+
|
|
62
|
+
# Resource Quotas
|
|
63
|
+
ResourceQuotaManager,
|
|
64
|
+
AgentResourceQuota,
|
|
65
|
+
|
|
66
|
+
# Observability
|
|
67
|
+
AgentObservabilityProvider,
|
|
68
|
+
|
|
69
|
+
# Hot Reload
|
|
70
|
+
HotReloadManager,
|
|
71
|
+
HotReloadConfig,
|
|
72
|
+
|
|
73
|
+
# Main Control Plane
|
|
74
|
+
EnhancedAgentControlPlane,
|
|
75
|
+
create_control_plane,
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
# ============================================================================
|
|
80
|
+
# Test Fixtures
|
|
81
|
+
# ============================================================================
|
|
82
|
+
|
|
83
|
+
class MockAgent:
|
|
84
|
+
"""Mock agent for testing"""
|
|
85
|
+
|
|
86
|
+
def __init__(self, name: str = "mock-agent"):
|
|
87
|
+
self.name = name
|
|
88
|
+
self.started = False
|
|
89
|
+
self.stopped = False
|
|
90
|
+
self._is_alive = True
|
|
91
|
+
self._is_ready = True
|
|
92
|
+
self._state = {}
|
|
93
|
+
|
|
94
|
+
async def start(self):
|
|
95
|
+
self.started = True
|
|
96
|
+
|
|
97
|
+
async def stop(self):
|
|
98
|
+
self.stopped = True
|
|
99
|
+
|
|
100
|
+
def is_alive(self) -> bool:
|
|
101
|
+
return self._is_alive
|
|
102
|
+
|
|
103
|
+
def is_ready(self) -> bool:
|
|
104
|
+
return self._is_ready
|
|
105
|
+
|
|
106
|
+
async def liveness_check(self) -> bool:
|
|
107
|
+
return self._is_alive
|
|
108
|
+
|
|
109
|
+
async def readiness_check(self) -> bool:
|
|
110
|
+
return self._is_ready
|
|
111
|
+
|
|
112
|
+
def get_state(self) -> dict:
|
|
113
|
+
return self._state.copy()
|
|
114
|
+
|
|
115
|
+
def set_state(self, state: dict):
|
|
116
|
+
self._state = state.copy()
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
@pytest.fixture
|
|
120
|
+
def mock_agent():
|
|
121
|
+
"""Create a mock agent"""
|
|
122
|
+
return MockAgent()
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@pytest.fixture
|
|
126
|
+
def health_config():
|
|
127
|
+
"""Create health check config"""
|
|
128
|
+
return HealthCheckConfig(
|
|
129
|
+
liveness_interval_seconds=0.1,
|
|
130
|
+
liveness_timeout_seconds=1.0,
|
|
131
|
+
liveness_failure_threshold=2,
|
|
132
|
+
readiness_interval_seconds=0.1,
|
|
133
|
+
readiness_timeout_seconds=1.0,
|
|
134
|
+
readiness_failure_threshold=1
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
@pytest.fixture
|
|
139
|
+
def recovery_config():
|
|
140
|
+
"""Create recovery config"""
|
|
141
|
+
return RecoveryConfig(
|
|
142
|
+
enabled=True,
|
|
143
|
+
max_restarts=3,
|
|
144
|
+
restart_delay_seconds=0.1,
|
|
145
|
+
restart_delay_max_seconds=1.0,
|
|
146
|
+
restart_delay_multiplier=2.0
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
# ============================================================================
|
|
151
|
+
# ACP-001: Health Check Tests
|
|
152
|
+
# ============================================================================
|
|
153
|
+
|
|
154
|
+
class TestHealthMonitor:
|
|
155
|
+
"""Tests for health monitoring functionality"""
|
|
156
|
+
|
|
157
|
+
@pytest.mark.asyncio
|
|
158
|
+
async def test_register_agent(self, health_config):
|
|
159
|
+
"""Test agent registration for health monitoring"""
|
|
160
|
+
monitor = HealthMonitor(config=health_config)
|
|
161
|
+
agent = MockAgent("test-agent")
|
|
162
|
+
|
|
163
|
+
monitor.register_agent("test-agent", agent)
|
|
164
|
+
|
|
165
|
+
assert "test-agent" in monitor._agents
|
|
166
|
+
assert monitor.get_agent_health("test-agent") == HealthStatus.UNKNOWN
|
|
167
|
+
|
|
168
|
+
@pytest.mark.asyncio
|
|
169
|
+
async def test_liveness_check_success(self, health_config):
|
|
170
|
+
"""Test successful liveness check"""
|
|
171
|
+
monitor = HealthMonitor(config=health_config)
|
|
172
|
+
agent = MockAgent()
|
|
173
|
+
agent._is_alive = True
|
|
174
|
+
|
|
175
|
+
monitor.register_agent("test-agent", agent)
|
|
176
|
+
result = await monitor._check_liveness("test-agent")
|
|
177
|
+
|
|
178
|
+
assert result.healthy is True
|
|
179
|
+
assert result.status == HealthStatus.HEALTHY
|
|
180
|
+
|
|
181
|
+
@pytest.mark.asyncio
|
|
182
|
+
async def test_liveness_check_failure(self, health_config):
|
|
183
|
+
"""Test failed liveness check"""
|
|
184
|
+
monitor = HealthMonitor(config=health_config)
|
|
185
|
+
agent = MockAgent()
|
|
186
|
+
agent._is_alive = False
|
|
187
|
+
|
|
188
|
+
monitor.register_agent("test-agent", agent)
|
|
189
|
+
result = await monitor._check_liveness("test-agent")
|
|
190
|
+
|
|
191
|
+
assert result.healthy is False
|
|
192
|
+
assert result.status == HealthStatus.UNHEALTHY
|
|
193
|
+
|
|
194
|
+
@pytest.mark.asyncio
|
|
195
|
+
async def test_readiness_check_success(self, health_config):
|
|
196
|
+
"""Test successful readiness check"""
|
|
197
|
+
monitor = HealthMonitor(config=health_config)
|
|
198
|
+
agent = MockAgent()
|
|
199
|
+
agent._is_ready = True
|
|
200
|
+
|
|
201
|
+
monitor.register_agent("test-agent", agent)
|
|
202
|
+
result = await monitor._check_readiness("test-agent")
|
|
203
|
+
|
|
204
|
+
assert result.healthy is True
|
|
205
|
+
|
|
206
|
+
@pytest.mark.asyncio
|
|
207
|
+
async def test_readiness_check_failure(self, health_config):
|
|
208
|
+
"""Test failed readiness check"""
|
|
209
|
+
monitor = HealthMonitor(config=health_config)
|
|
210
|
+
agent = MockAgent()
|
|
211
|
+
agent._is_ready = False
|
|
212
|
+
|
|
213
|
+
monitor.register_agent("test-agent", agent)
|
|
214
|
+
result = await monitor._check_readiness("test-agent")
|
|
215
|
+
|
|
216
|
+
assert result.healthy is False
|
|
217
|
+
assert result.status == HealthStatus.DEGRADED
|
|
218
|
+
|
|
219
|
+
@pytest.mark.asyncio
|
|
220
|
+
async def test_custom_health_check(self, health_config):
|
|
221
|
+
"""Test custom health check function"""
|
|
222
|
+
monitor = HealthMonitor(config=health_config)
|
|
223
|
+
|
|
224
|
+
async def custom_liveness():
|
|
225
|
+
return True
|
|
226
|
+
|
|
227
|
+
monitor.register_agent(
|
|
228
|
+
"test-agent",
|
|
229
|
+
MockAgent(),
|
|
230
|
+
custom_liveness=custom_liveness
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
result = await monitor._check_liveness("test-agent")
|
|
234
|
+
assert result.healthy is True
|
|
235
|
+
|
|
236
|
+
@pytest.mark.asyncio
|
|
237
|
+
async def test_unregister_agent(self, health_config):
|
|
238
|
+
"""Test agent unregistration"""
|
|
239
|
+
monitor = HealthMonitor(config=health_config)
|
|
240
|
+
monitor.register_agent("test-agent", MockAgent())
|
|
241
|
+
|
|
242
|
+
monitor.unregister_agent("test-agent")
|
|
243
|
+
|
|
244
|
+
assert "test-agent" not in monitor._agents
|
|
245
|
+
assert monitor.get_agent_health("test-agent") == HealthStatus.UNKNOWN
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
# ============================================================================
|
|
249
|
+
# ACP-002: Auto-Recovery Tests
|
|
250
|
+
# ============================================================================
|
|
251
|
+
|
|
252
|
+
class TestAutoRecovery:
|
|
253
|
+
"""Tests for auto-recovery functionality"""
|
|
254
|
+
|
|
255
|
+
@pytest.mark.asyncio
|
|
256
|
+
async def test_register_agent(self, recovery_config):
|
|
257
|
+
"""Test agent registration for recovery"""
|
|
258
|
+
recovery = AutoRecoveryManager(config=recovery_config)
|
|
259
|
+
|
|
260
|
+
recovery.register_agent(
|
|
261
|
+
"test-agent",
|
|
262
|
+
factory=lambda: MockAgent()
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
assert "test-agent" in recovery._agent_factories
|
|
266
|
+
assert recovery.get_restart_count("test-agent") == 0
|
|
267
|
+
|
|
268
|
+
@pytest.mark.asyncio
|
|
269
|
+
async def test_handle_failure_recovery(self, recovery_config):
|
|
270
|
+
"""Test successful recovery after failure"""
|
|
271
|
+
recovery = AutoRecoveryManager(config=recovery_config)
|
|
272
|
+
|
|
273
|
+
recovery.register_agent(
|
|
274
|
+
"test-agent",
|
|
275
|
+
factory=lambda: MockAgent()
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
new_agent = await recovery.handle_failure("test-agent", Exception("Test failure"))
|
|
279
|
+
|
|
280
|
+
assert new_agent is not None
|
|
281
|
+
assert recovery.get_restart_count("test-agent") == 1
|
|
282
|
+
|
|
283
|
+
@pytest.mark.asyncio
|
|
284
|
+
async def test_max_restarts_limit(self, recovery_config):
|
|
285
|
+
"""Test max restarts limit is respected"""
|
|
286
|
+
recovery_config.max_restarts = 2
|
|
287
|
+
recovery = AutoRecoveryManager(config=recovery_config)
|
|
288
|
+
|
|
289
|
+
fail_count = 0
|
|
290
|
+
def failing_factory():
|
|
291
|
+
nonlocal fail_count
|
|
292
|
+
fail_count += 1
|
|
293
|
+
if fail_count < 3:
|
|
294
|
+
raise Exception("Factory failure")
|
|
295
|
+
return MockAgent()
|
|
296
|
+
|
|
297
|
+
recovery.register_agent("test-agent", factory=failing_factory)
|
|
298
|
+
|
|
299
|
+
# Simulate multiple failures
|
|
300
|
+
recovery._restart_counts["test-agent"] = 2
|
|
301
|
+
|
|
302
|
+
result = await recovery.handle_failure("test-agent")
|
|
303
|
+
|
|
304
|
+
# Should not recover when at max restarts (depending on config)
|
|
305
|
+
# The behavior depends on on_max_restarts setting
|
|
306
|
+
|
|
307
|
+
@pytest.mark.asyncio
|
|
308
|
+
async def test_recovery_history(self, recovery_config):
|
|
309
|
+
"""Test recovery history tracking"""
|
|
310
|
+
recovery = AutoRecoveryManager(config=recovery_config)
|
|
311
|
+
recovery.register_agent("test-agent", factory=lambda: MockAgent())
|
|
312
|
+
|
|
313
|
+
await recovery.handle_failure("test-agent")
|
|
314
|
+
|
|
315
|
+
history = recovery.get_recovery_history("test-agent")
|
|
316
|
+
assert len(history) >= 1
|
|
317
|
+
assert any(e.event_type in ("failure", "recovery_success") for e in history)
|
|
318
|
+
|
|
319
|
+
@pytest.mark.asyncio
|
|
320
|
+
async def test_reset_restart_count(self, recovery_config):
|
|
321
|
+
"""Test manual restart count reset"""
|
|
322
|
+
recovery = AutoRecoveryManager(config=recovery_config)
|
|
323
|
+
recovery.register_agent("test-agent", factory=lambda: MockAgent())
|
|
324
|
+
|
|
325
|
+
recovery._restart_counts["test-agent"] = 5
|
|
326
|
+
recovery.reset_restart_count("test-agent")
|
|
327
|
+
|
|
328
|
+
assert recovery.get_restart_count("test-agent") == 0
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
# ============================================================================
|
|
332
|
+
# ACP-003: Circuit Breaker Tests
|
|
333
|
+
# ============================================================================
|
|
334
|
+
|
|
335
|
+
class TestCircuitBreaker:
|
|
336
|
+
"""Tests for circuit breaker functionality"""
|
|
337
|
+
|
|
338
|
+
@pytest.mark.asyncio
|
|
339
|
+
async def test_initial_state_closed(self):
|
|
340
|
+
"""Test circuit breaker starts in closed state"""
|
|
341
|
+
breaker = CircuitBreaker(name="test")
|
|
342
|
+
assert breaker.state == CircuitState.CLOSED
|
|
343
|
+
assert breaker.is_closed is True
|
|
344
|
+
|
|
345
|
+
@pytest.mark.asyncio
|
|
346
|
+
async def test_opens_after_failures(self):
|
|
347
|
+
"""Test circuit opens after threshold failures"""
|
|
348
|
+
config = CircuitBreakerConfig(failure_threshold=3)
|
|
349
|
+
breaker = CircuitBreaker(name="test", config=config)
|
|
350
|
+
|
|
351
|
+
for i in range(3):
|
|
352
|
+
await breaker._on_failure(Exception("Test failure"))
|
|
353
|
+
|
|
354
|
+
assert breaker.state == CircuitState.OPEN
|
|
355
|
+
assert breaker.is_open is True
|
|
356
|
+
|
|
357
|
+
@pytest.mark.asyncio
|
|
358
|
+
async def test_rejects_when_open(self):
|
|
359
|
+
"""Test requests are rejected when circuit is open"""
|
|
360
|
+
breaker = CircuitBreaker(name="test", failure_threshold=1)
|
|
361
|
+
|
|
362
|
+
await breaker._on_failure(Exception("Test failure"))
|
|
363
|
+
|
|
364
|
+
with pytest.raises(CircuitBreakerOpenError):
|
|
365
|
+
await breaker._before_call()
|
|
366
|
+
|
|
367
|
+
@pytest.mark.asyncio
|
|
368
|
+
async def test_half_open_after_timeout(self):
|
|
369
|
+
"""Test circuit transitions to half-open after recovery timeout"""
|
|
370
|
+
config = CircuitBreakerConfig(
|
|
371
|
+
failure_threshold=1,
|
|
372
|
+
recovery_timeout_seconds=0.1
|
|
373
|
+
)
|
|
374
|
+
breaker = CircuitBreaker(name="test", config=config)
|
|
375
|
+
|
|
376
|
+
await breaker._on_failure(Exception("Test failure"))
|
|
377
|
+
assert breaker.state == CircuitState.OPEN
|
|
378
|
+
|
|
379
|
+
# Wait for recovery timeout
|
|
380
|
+
await asyncio.sleep(0.15)
|
|
381
|
+
|
|
382
|
+
# Next call should transition to half-open
|
|
383
|
+
await breaker._before_call()
|
|
384
|
+
assert breaker.state == CircuitState.HALF_OPEN
|
|
385
|
+
|
|
386
|
+
@pytest.mark.asyncio
|
|
387
|
+
async def test_closes_after_successful_half_open(self):
|
|
388
|
+
"""Test circuit closes after successful calls in half-open"""
|
|
389
|
+
config = CircuitBreakerConfig(
|
|
390
|
+
failure_threshold=1,
|
|
391
|
+
success_threshold=2,
|
|
392
|
+
recovery_timeout_seconds=0.1
|
|
393
|
+
)
|
|
394
|
+
breaker = CircuitBreaker(name="test", config=config)
|
|
395
|
+
|
|
396
|
+
# Open the circuit
|
|
397
|
+
await breaker._on_failure(Exception("Test failure"))
|
|
398
|
+
await asyncio.sleep(0.15)
|
|
399
|
+
|
|
400
|
+
# Transition to half-open and succeed
|
|
401
|
+
await breaker._before_call()
|
|
402
|
+
await breaker._on_success()
|
|
403
|
+
await breaker._on_success()
|
|
404
|
+
|
|
405
|
+
assert breaker.state == CircuitState.CLOSED
|
|
406
|
+
|
|
407
|
+
@pytest.mark.asyncio
|
|
408
|
+
async def test_decorator_usage(self):
|
|
409
|
+
"""Test circuit breaker as decorator"""
|
|
410
|
+
breaker = CircuitBreaker(name="test", failure_threshold=3)
|
|
411
|
+
|
|
412
|
+
@breaker
|
|
413
|
+
async def test_func():
|
|
414
|
+
return "success"
|
|
415
|
+
|
|
416
|
+
result = await test_func()
|
|
417
|
+
assert result == "success"
|
|
418
|
+
|
|
419
|
+
@pytest.mark.asyncio
|
|
420
|
+
async def test_context_manager_usage(self):
|
|
421
|
+
"""Test circuit breaker as context manager"""
|
|
422
|
+
breaker = CircuitBreaker(name="test")
|
|
423
|
+
|
|
424
|
+
async with breaker:
|
|
425
|
+
pass # Success
|
|
426
|
+
|
|
427
|
+
metrics = breaker.get_metrics()
|
|
428
|
+
assert metrics.total_successes >= 1
|
|
429
|
+
|
|
430
|
+
def test_manual_reset(self):
|
|
431
|
+
"""Test manual circuit reset"""
|
|
432
|
+
breaker = CircuitBreaker(name="test")
|
|
433
|
+
breaker._state = CircuitState.OPEN
|
|
434
|
+
breaker._failure_count = 10
|
|
435
|
+
|
|
436
|
+
breaker.reset()
|
|
437
|
+
|
|
438
|
+
assert breaker.state == CircuitState.CLOSED
|
|
439
|
+
assert breaker._failure_count == 0
|
|
440
|
+
|
|
441
|
+
def test_circuit_breaker_registry(self):
|
|
442
|
+
"""Test circuit breaker registry"""
|
|
443
|
+
registry = CircuitBreakerRegistry()
|
|
444
|
+
|
|
445
|
+
breaker1 = registry.get_or_create("agent-1")
|
|
446
|
+
breaker2 = registry.get_or_create("agent-1")
|
|
447
|
+
breaker3 = registry.get_or_create("agent-2")
|
|
448
|
+
|
|
449
|
+
assert breaker1 is breaker2
|
|
450
|
+
assert breaker1 is not breaker3
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
# ============================================================================
|
|
454
|
+
# ACP-004: Agent Scaling Tests
|
|
455
|
+
# ============================================================================
|
|
456
|
+
|
|
457
|
+
class TestAgentScaler:
|
|
458
|
+
"""Tests for agent scaling functionality"""
|
|
459
|
+
|
|
460
|
+
@pytest.mark.asyncio
|
|
461
|
+
async def test_register_agent_type(self):
|
|
462
|
+
"""Test agent type registration"""
|
|
463
|
+
scaler = AgentScaler()
|
|
464
|
+
|
|
465
|
+
scaler.register_agent_type(
|
|
466
|
+
agent_type="test-agent",
|
|
467
|
+
factory=lambda: MockAgent(),
|
|
468
|
+
replicas=2
|
|
469
|
+
)
|
|
470
|
+
|
|
471
|
+
assert "test-agent" in scaler._agent_types
|
|
472
|
+
|
|
473
|
+
@pytest.mark.asyncio
|
|
474
|
+
async def test_scale_to(self):
|
|
475
|
+
"""Test scaling to specific replica count"""
|
|
476
|
+
scaler = AgentScaler()
|
|
477
|
+
scaler.register_agent_type("test-agent", factory=lambda: MockAgent())
|
|
478
|
+
|
|
479
|
+
await scaler.scale_to("test-agent", 3)
|
|
480
|
+
|
|
481
|
+
assert scaler.get_replica_count("test-agent") == 3
|
|
482
|
+
|
|
483
|
+
@pytest.mark.asyncio
|
|
484
|
+
async def test_scale_up(self):
|
|
485
|
+
"""Test scaling up"""
|
|
486
|
+
scaler = AgentScaler()
|
|
487
|
+
scaler.register_agent_type("test-agent", factory=lambda: MockAgent())
|
|
488
|
+
|
|
489
|
+
await scaler.scale_to("test-agent", 2)
|
|
490
|
+
await scaler.scale_up("test-agent", 2)
|
|
491
|
+
|
|
492
|
+
assert scaler.get_replica_count("test-agent") == 4
|
|
493
|
+
|
|
494
|
+
@pytest.mark.asyncio
|
|
495
|
+
async def test_scale_down(self):
|
|
496
|
+
"""Test scaling down"""
|
|
497
|
+
scaler = AgentScaler()
|
|
498
|
+
scaler.register_agent_type("test-agent", factory=lambda: MockAgent())
|
|
499
|
+
|
|
500
|
+
await scaler.scale_to("test-agent", 4)
|
|
501
|
+
await scaler.scale_down("test-agent", 2)
|
|
502
|
+
|
|
503
|
+
assert scaler.get_replica_count("test-agent") == 2
|
|
504
|
+
|
|
505
|
+
@pytest.mark.asyncio
|
|
506
|
+
async def test_get_replica_load_balanced(self):
|
|
507
|
+
"""Test round-robin load balancing"""
|
|
508
|
+
scaler = AgentScaler()
|
|
509
|
+
scaler.register_agent_type("test-agent", factory=lambda: MockAgent())
|
|
510
|
+
|
|
511
|
+
await scaler.scale_to("test-agent", 3)
|
|
512
|
+
|
|
513
|
+
replicas = set()
|
|
514
|
+
for _ in range(6):
|
|
515
|
+
replica = await scaler.get_replica("test-agent")
|
|
516
|
+
replicas.add(id(replica))
|
|
517
|
+
|
|
518
|
+
# Should have gotten all 3 replicas
|
|
519
|
+
assert len(replicas) == 3
|
|
520
|
+
|
|
521
|
+
@pytest.mark.asyncio
|
|
522
|
+
async def test_max_replicas_limit(self):
|
|
523
|
+
"""Test max replicas limit is respected"""
|
|
524
|
+
config = ScalingConfig(max_replicas=5)
|
|
525
|
+
scaler = AgentScaler()
|
|
526
|
+
scaler.register_agent_type("test-agent", factory=lambda: MockAgent(), config=config)
|
|
527
|
+
|
|
528
|
+
await scaler.scale_to("test-agent", 10)
|
|
529
|
+
|
|
530
|
+
assert scaler.get_replica_count("test-agent") == 5
|
|
531
|
+
|
|
532
|
+
|
|
533
|
+
# ============================================================================
|
|
534
|
+
# ACP-005: Distributed Coordination Tests
|
|
535
|
+
# ============================================================================
|
|
536
|
+
|
|
537
|
+
class TestDistributedCoordinator:
|
|
538
|
+
"""Tests for distributed coordination functionality"""
|
|
539
|
+
|
|
540
|
+
@pytest.mark.asyncio
|
|
541
|
+
async def test_single_node_becomes_leader(self):
|
|
542
|
+
"""Test single node becomes leader"""
|
|
543
|
+
coordinator = DistributedCoordinator(node_id="node-1", peers=[])
|
|
544
|
+
|
|
545
|
+
await coordinator.start()
|
|
546
|
+
await asyncio.sleep(0.1) # Allow election to complete
|
|
547
|
+
|
|
548
|
+
assert coordinator.is_leader is True
|
|
549
|
+
assert coordinator.role == CoordinationRole.LEADER
|
|
550
|
+
|
|
551
|
+
await coordinator.stop()
|
|
552
|
+
|
|
553
|
+
@pytest.mark.asyncio
|
|
554
|
+
async def test_acquire_release_lock(self):
|
|
555
|
+
"""Test distributed lock acquisition and release"""
|
|
556
|
+
coordinator = DistributedCoordinator(node_id="node-1")
|
|
557
|
+
|
|
558
|
+
acquired = await coordinator.acquire_lock("resource-1", timeout=1.0)
|
|
559
|
+
assert acquired is True
|
|
560
|
+
|
|
561
|
+
coordinator.release_lock("resource-1")
|
|
562
|
+
|
|
563
|
+
# Should be able to acquire again
|
|
564
|
+
acquired = await coordinator.acquire_lock("resource-1", timeout=1.0)
|
|
565
|
+
assert acquired is True
|
|
566
|
+
|
|
567
|
+
@pytest.mark.asyncio
|
|
568
|
+
async def test_lock_context_manager(self):
|
|
569
|
+
"""Test lock as context manager"""
|
|
570
|
+
coordinator = DistributedCoordinator(node_id="node-1")
|
|
571
|
+
|
|
572
|
+
async with coordinator.lock("resource-1"):
|
|
573
|
+
# Lock should be held
|
|
574
|
+
assert "resource-1" in coordinator._lock_holders
|
|
575
|
+
|
|
576
|
+
# Lock should be released
|
|
577
|
+
assert "resource-1" not in coordinator._lock_holders
|
|
578
|
+
|
|
579
|
+
@pytest.mark.asyncio
|
|
580
|
+
async def test_get_leader_info(self):
|
|
581
|
+
"""Test getting leader information"""
|
|
582
|
+
coordinator = DistributedCoordinator(node_id="node-1", peers=[])
|
|
583
|
+
|
|
584
|
+
await coordinator.start()
|
|
585
|
+
await asyncio.sleep(0.1)
|
|
586
|
+
|
|
587
|
+
info = coordinator.get_leader_info()
|
|
588
|
+
|
|
589
|
+
assert info is not None
|
|
590
|
+
assert info.leader_id == "node-1"
|
|
591
|
+
|
|
592
|
+
await coordinator.stop()
|
|
593
|
+
|
|
594
|
+
|
|
595
|
+
# ============================================================================
|
|
596
|
+
# ACP-006: Dependency Graph Tests
|
|
597
|
+
# ============================================================================
|
|
598
|
+
|
|
599
|
+
class TestDependencyGraph:
|
|
600
|
+
"""Tests for dependency graph functionality"""
|
|
601
|
+
|
|
602
|
+
def test_add_agent(self):
|
|
603
|
+
"""Test adding agents to the graph"""
|
|
604
|
+
graph = DependencyGraph()
|
|
605
|
+
|
|
606
|
+
graph.add_agent("api-server", depends_on=["database", "cache"])
|
|
607
|
+
graph.add_agent("database", depends_on=[])
|
|
608
|
+
graph.add_agent("cache", depends_on=[])
|
|
609
|
+
|
|
610
|
+
assert len(graph._agents) == 3
|
|
611
|
+
|
|
612
|
+
def test_get_dependencies(self):
|
|
613
|
+
"""Test getting agent dependencies"""
|
|
614
|
+
graph = DependencyGraph()
|
|
615
|
+
graph.add_agent("api-server", depends_on=["database", "cache"])
|
|
616
|
+
|
|
617
|
+
deps = graph.get_dependencies("api-server")
|
|
618
|
+
|
|
619
|
+
assert "database" in deps
|
|
620
|
+
assert "cache" in deps
|
|
621
|
+
|
|
622
|
+
def test_get_dependents(self):
|
|
623
|
+
"""Test getting agents that depend on an agent"""
|
|
624
|
+
graph = DependencyGraph()
|
|
625
|
+
graph.add_agent("database", depends_on=[])
|
|
626
|
+
graph.add_agent("api-server", depends_on=["database"])
|
|
627
|
+
graph.add_agent("worker", depends_on=["database"])
|
|
628
|
+
|
|
629
|
+
dependents = graph.get_dependents("database")
|
|
630
|
+
|
|
631
|
+
assert "api-server" in dependents
|
|
632
|
+
assert "worker" in dependents
|
|
633
|
+
|
|
634
|
+
def test_circular_dependency_detection(self):
|
|
635
|
+
"""Test circular dependency detection"""
|
|
636
|
+
graph = DependencyGraph()
|
|
637
|
+
graph.add_agent("a", depends_on=["b"])
|
|
638
|
+
graph.add_agent("b", depends_on=["c"])
|
|
639
|
+
graph.add_agent("c", depends_on=["a"]) # Circular!
|
|
640
|
+
|
|
641
|
+
assert graph.has_circular_dependency() is True
|
|
642
|
+
|
|
643
|
+
def test_no_circular_dependency(self):
|
|
644
|
+
"""Test no circular dependency in valid graph"""
|
|
645
|
+
graph = DependencyGraph()
|
|
646
|
+
graph.add_agent("a", depends_on=["b"])
|
|
647
|
+
graph.add_agent("b", depends_on=["c"])
|
|
648
|
+
graph.add_agent("c", depends_on=[])
|
|
649
|
+
|
|
650
|
+
assert graph.has_circular_dependency() is False
|
|
651
|
+
|
|
652
|
+
def test_startup_order(self):
|
|
653
|
+
"""Test correct startup order"""
|
|
654
|
+
graph = DependencyGraph()
|
|
655
|
+
graph.add_agent("api-server", depends_on=["database", "cache"])
|
|
656
|
+
graph.add_agent("database", depends_on=[])
|
|
657
|
+
graph.add_agent("cache", depends_on=[])
|
|
658
|
+
|
|
659
|
+
order = graph.get_startup_order()
|
|
660
|
+
|
|
661
|
+
# database and cache should come before api-server
|
|
662
|
+
assert order.index("database") < order.index("api-server")
|
|
663
|
+
assert order.index("cache") < order.index("api-server")
|
|
664
|
+
|
|
665
|
+
def test_parallel_startup_groups(self):
|
|
666
|
+
"""Test parallel startup group generation"""
|
|
667
|
+
graph = DependencyGraph()
|
|
668
|
+
graph.add_agent("api-server", depends_on=["database", "cache"])
|
|
669
|
+
graph.add_agent("database", depends_on=[])
|
|
670
|
+
graph.add_agent("cache", depends_on=[])
|
|
671
|
+
|
|
672
|
+
groups = graph.get_parallel_startup_groups()
|
|
673
|
+
|
|
674
|
+
assert len(groups) == 2
|
|
675
|
+
# First group should contain database and cache
|
|
676
|
+
assert set(groups[0]) == {"database", "cache"}
|
|
677
|
+
# Second group should contain api-server
|
|
678
|
+
assert groups[1] == ["api-server"]
|
|
679
|
+
|
|
680
|
+
def test_shutdown_order(self):
|
|
681
|
+
"""Test shutdown order is reverse of startup"""
|
|
682
|
+
graph = DependencyGraph()
|
|
683
|
+
graph.add_agent("api-server", depends_on=["database"])
|
|
684
|
+
graph.add_agent("database", depends_on=[])
|
|
685
|
+
|
|
686
|
+
startup = graph.get_startup_order()
|
|
687
|
+
shutdown = graph.get_shutdown_order()
|
|
688
|
+
|
|
689
|
+
assert shutdown == list(reversed(startup))
|
|
690
|
+
|
|
691
|
+
def test_validate_missing_dependency(self):
|
|
692
|
+
"""Test validation catches missing dependencies"""
|
|
693
|
+
graph = DependencyGraph()
|
|
694
|
+
graph.add_agent("api-server", depends_on=["database"])
|
|
695
|
+
# database not added
|
|
696
|
+
|
|
697
|
+
errors = graph.validate()
|
|
698
|
+
|
|
699
|
+
assert len(errors) > 0
|
|
700
|
+
assert any("missing" in e.lower() for e in errors)
|
|
701
|
+
|
|
702
|
+
|
|
703
|
+
# ============================================================================
|
|
704
|
+
# ACP-007: Graceful Shutdown Tests
|
|
705
|
+
# ============================================================================
|
|
706
|
+
|
|
707
|
+
class TestGracefulShutdown:
|
|
708
|
+
"""Tests for graceful shutdown functionality"""
|
|
709
|
+
|
|
710
|
+
@pytest.mark.asyncio
|
|
711
|
+
async def test_register_operation(self):
|
|
712
|
+
"""Test registering in-flight operations"""
|
|
713
|
+
manager = GracefulShutdownManager()
|
|
714
|
+
|
|
715
|
+
op_id = manager.register_operation(
|
|
716
|
+
agent_id="test-agent",
|
|
717
|
+
operation_type="verification",
|
|
718
|
+
data={"claim_id": "123"}
|
|
719
|
+
)
|
|
720
|
+
|
|
721
|
+
assert op_id is not None
|
|
722
|
+
assert manager.get_in_flight_count() == 1
|
|
723
|
+
|
|
724
|
+
@pytest.mark.asyncio
|
|
725
|
+
async def test_complete_operation(self):
|
|
726
|
+
"""Test completing operations"""
|
|
727
|
+
manager = GracefulShutdownManager()
|
|
728
|
+
|
|
729
|
+
op_id = manager.register_operation("test-agent", "verification")
|
|
730
|
+
manager.complete_operation(op_id)
|
|
731
|
+
|
|
732
|
+
assert manager.get_in_flight_count() == 0
|
|
733
|
+
|
|
734
|
+
@pytest.mark.asyncio
|
|
735
|
+
async def test_shutdown_drains_operations(self):
|
|
736
|
+
"""Test shutdown waits for operations to complete"""
|
|
737
|
+
config = ShutdownConfig(drain_timeout_seconds=1.0)
|
|
738
|
+
manager = GracefulShutdownManager(config=config)
|
|
739
|
+
|
|
740
|
+
op_id = manager.register_operation("test-agent", "verification")
|
|
741
|
+
|
|
742
|
+
# Complete operation after short delay
|
|
743
|
+
async def complete_later():
|
|
744
|
+
await asyncio.sleep(0.1)
|
|
745
|
+
manager.complete_operation(op_id)
|
|
746
|
+
|
|
747
|
+
asyncio.create_task(complete_later())
|
|
748
|
+
|
|
749
|
+
result = await manager.shutdown()
|
|
750
|
+
|
|
751
|
+
assert result["status"] == "stopped" or manager.phase == ShutdownPhase.TERMINATED
|
|
752
|
+
|
|
753
|
+
@pytest.mark.asyncio
|
|
754
|
+
async def test_shutdown_hooks(self):
|
|
755
|
+
"""Test shutdown hooks are called"""
|
|
756
|
+
manager = GracefulShutdownManager()
|
|
757
|
+
|
|
758
|
+
hook_called = False
|
|
759
|
+
|
|
760
|
+
async def shutdown_hook():
|
|
761
|
+
nonlocal hook_called
|
|
762
|
+
hook_called = True
|
|
763
|
+
|
|
764
|
+
manager.add_shutdown_hook(shutdown_hook)
|
|
765
|
+
await manager.shutdown()
|
|
766
|
+
|
|
767
|
+
assert hook_called is True
|
|
768
|
+
|
|
769
|
+
@pytest.mark.asyncio
|
|
770
|
+
async def test_no_new_operations_during_shutdown(self):
|
|
771
|
+
"""Test new operations are rejected during shutdown"""
|
|
772
|
+
manager = GracefulShutdownManager()
|
|
773
|
+
manager._phase = ShutdownPhase.DRAINING
|
|
774
|
+
|
|
775
|
+
with pytest.raises(RuntimeError):
|
|
776
|
+
manager.register_operation("test-agent", "verification")
|
|
777
|
+
|
|
778
|
+
|
|
779
|
+
# ============================================================================
|
|
780
|
+
# ACP-008: Resource Quota Tests
|
|
781
|
+
# ============================================================================
|
|
782
|
+
|
|
783
|
+
class TestResourceQuotas:
|
|
784
|
+
"""Tests for resource quota functionality"""
|
|
785
|
+
|
|
786
|
+
def test_set_quota(self):
|
|
787
|
+
"""Test setting resource quota"""
|
|
788
|
+
manager = ResourceQuotaManager()
|
|
789
|
+
|
|
790
|
+
quota = AgentResourceQuota(
|
|
791
|
+
memory_mb=512,
|
|
792
|
+
cpu_percent=25.0,
|
|
793
|
+
max_concurrent_operations=10
|
|
794
|
+
)
|
|
795
|
+
|
|
796
|
+
manager.set_quota("test-agent", quota)
|
|
797
|
+
|
|
798
|
+
assert manager.get_quota("test-agent") is not None
|
|
799
|
+
|
|
800
|
+
def test_can_execute_within_quota(self):
|
|
801
|
+
"""Test execution allowed within quota"""
|
|
802
|
+
manager = ResourceQuotaManager()
|
|
803
|
+
manager.set_quota("test-agent", AgentResourceQuota(
|
|
804
|
+
max_concurrent_operations=10
|
|
805
|
+
))
|
|
806
|
+
|
|
807
|
+
assert manager.can_execute("test-agent") is True
|
|
808
|
+
|
|
809
|
+
def test_cannot_execute_at_limit(self):
|
|
810
|
+
"""Test execution denied at concurrent limit"""
|
|
811
|
+
manager = ResourceQuotaManager()
|
|
812
|
+
manager.set_quota("test-agent", AgentResourceQuota(
|
|
813
|
+
max_concurrent_operations=2
|
|
814
|
+
))
|
|
815
|
+
|
|
816
|
+
# Record 2 operations
|
|
817
|
+
manager.record_operation_start("test-agent")
|
|
818
|
+
manager.record_operation_start("test-agent")
|
|
819
|
+
|
|
820
|
+
assert manager.can_execute("test-agent") is False
|
|
821
|
+
|
|
822
|
+
def test_operation_tracking(self):
|
|
823
|
+
"""Test operation start/end tracking"""
|
|
824
|
+
manager = ResourceQuotaManager()
|
|
825
|
+
manager.set_quota("test-agent", AgentResourceQuota())
|
|
826
|
+
|
|
827
|
+
manager.record_operation_start("test-agent")
|
|
828
|
+
usage = manager.get_usage("test-agent")
|
|
829
|
+
assert usage.concurrent_operations == 1
|
|
830
|
+
|
|
831
|
+
manager.record_operation_end("test-agent")
|
|
832
|
+
usage = manager.get_usage("test-agent")
|
|
833
|
+
assert usage.concurrent_operations == 0
|
|
834
|
+
|
|
835
|
+
def test_resource_usage_update(self):
|
|
836
|
+
"""Test resource usage updates"""
|
|
837
|
+
manager = ResourceQuotaManager()
|
|
838
|
+
manager.set_quota("test-agent", AgentResourceQuota())
|
|
839
|
+
|
|
840
|
+
manager.update_resource_usage("test-agent", memory_mb=256.0, cpu_percent=15.0)
|
|
841
|
+
|
|
842
|
+
usage = manager.get_usage("test-agent")
|
|
843
|
+
assert usage.memory_mb == 256.0
|
|
844
|
+
assert usage.cpu_percent == 15.0
|
|
845
|
+
|
|
846
|
+
def test_check_quota_violations(self):
|
|
847
|
+
"""Test quota violation detection"""
|
|
848
|
+
manager = ResourceQuotaManager()
|
|
849
|
+
manager.set_quota("test-agent", AgentResourceQuota(
|
|
850
|
+
memory_mb=512,
|
|
851
|
+
cpu_percent=25.0
|
|
852
|
+
))
|
|
853
|
+
|
|
854
|
+
# Exceed memory
|
|
855
|
+
manager.update_resource_usage("test-agent", memory_mb=600.0)
|
|
856
|
+
|
|
857
|
+
violations = manager.check_quota_violations()
|
|
858
|
+
|
|
859
|
+
assert "test-agent" in violations
|
|
860
|
+
assert any("Memory" in v for v in violations["test-agent"])
|
|
861
|
+
|
|
862
|
+
|
|
863
|
+
# ============================================================================
|
|
864
|
+
# ACP-009: Observability Tests
|
|
865
|
+
# ============================================================================
|
|
866
|
+
|
|
867
|
+
class TestAgentObservability:
|
|
868
|
+
"""Tests for agent observability functionality"""
|
|
869
|
+
|
|
870
|
+
def test_record_metric(self):
|
|
871
|
+
"""Test metric recording"""
|
|
872
|
+
provider = AgentObservabilityProvider()
|
|
873
|
+
|
|
874
|
+
provider.record_metric(
|
|
875
|
+
agent_id="test-agent",
|
|
876
|
+
name="latency_ms",
|
|
877
|
+
value=150.5,
|
|
878
|
+
labels={"operation": "verify"}
|
|
879
|
+
)
|
|
880
|
+
|
|
881
|
+
metrics = provider.get_metrics("test-agent")
|
|
882
|
+
assert len(metrics) > 0
|
|
883
|
+
assert metrics[0].name == "latency_ms"
|
|
884
|
+
|
|
885
|
+
def test_increment_counter(self):
|
|
886
|
+
"""Test counter increment"""
|
|
887
|
+
provider = AgentObservabilityProvider()
|
|
888
|
+
|
|
889
|
+
provider.increment_counter("test-agent", "requests_total")
|
|
890
|
+
provider.increment_counter("test-agent", "requests_total")
|
|
891
|
+
|
|
892
|
+
# Counter should have value 2
|
|
893
|
+
metrics = provider.get_metrics("test-agent", "requests_total")
|
|
894
|
+
assert len(metrics) == 2
|
|
895
|
+
|
|
896
|
+
def test_set_gauge(self):
|
|
897
|
+
"""Test gauge setting"""
|
|
898
|
+
provider = AgentObservabilityProvider()
|
|
899
|
+
|
|
900
|
+
provider.set_gauge("test-agent", "active_connections", 5.0)
|
|
901
|
+
|
|
902
|
+
metrics = provider.get_metrics("test-agent", "active_connections")
|
|
903
|
+
assert len(metrics) == 1
|
|
904
|
+
assert metrics[0].value == 5.0
|
|
905
|
+
|
|
906
|
+
def test_log_entry(self):
|
|
907
|
+
"""Test log entry creation"""
|
|
908
|
+
provider = AgentObservabilityProvider()
|
|
909
|
+
|
|
910
|
+
provider.log(
|
|
911
|
+
agent_id="test-agent",
|
|
912
|
+
level="info",
|
|
913
|
+
message="Test message",
|
|
914
|
+
context={"key": "value"}
|
|
915
|
+
)
|
|
916
|
+
|
|
917
|
+
logs = provider.get_logs("test-agent")
|
|
918
|
+
assert len(logs) == 1
|
|
919
|
+
assert logs[0].message == "Test message"
|
|
920
|
+
|
|
921
|
+
def test_prometheus_export(self):
|
|
922
|
+
"""Test Prometheus format export"""
|
|
923
|
+
provider = AgentObservabilityProvider()
|
|
924
|
+
|
|
925
|
+
provider.increment_counter("test-agent", "requests")
|
|
926
|
+
provider.set_gauge("test-agent", "memory_usage", 256.0)
|
|
927
|
+
|
|
928
|
+
prometheus_text = provider.export_prometheus()
|
|
929
|
+
|
|
930
|
+
assert "requests" in prometheus_text
|
|
931
|
+
assert "memory_usage" in prometheus_text
|
|
932
|
+
|
|
933
|
+
def test_agent_summary(self):
|
|
934
|
+
"""Test agent summary generation"""
|
|
935
|
+
provider = AgentObservabilityProvider()
|
|
936
|
+
|
|
937
|
+
provider.record_metric("test-agent", "metric1", 1.0)
|
|
938
|
+
provider.log("test-agent", "info", "Message 1")
|
|
939
|
+
|
|
940
|
+
summary = provider.get_agent_summary("test-agent")
|
|
941
|
+
|
|
942
|
+
assert summary["agent_id"] == "test-agent"
|
|
943
|
+
assert summary["total_metrics"] > 0
|
|
944
|
+
assert summary["total_logs"] > 0
|
|
945
|
+
|
|
946
|
+
|
|
947
|
+
# ============================================================================
|
|
948
|
+
# ACP-010: Hot Reload Tests
|
|
949
|
+
# ============================================================================
|
|
950
|
+
|
|
951
|
+
class TestHotReload:
|
|
952
|
+
"""Tests for hot reload functionality"""
|
|
953
|
+
|
|
954
|
+
def test_register_agent(self):
|
|
955
|
+
"""Test agent registration for hot reload"""
|
|
956
|
+
manager = HotReloadManager()
|
|
957
|
+
|
|
958
|
+
manager.register_agent(
|
|
959
|
+
agent_id="test-agent",
|
|
960
|
+
module_name="test_module",
|
|
961
|
+
class_name="TestAgent"
|
|
962
|
+
)
|
|
963
|
+
|
|
964
|
+
assert "test-agent" in manager._agents
|
|
965
|
+
|
|
966
|
+
@pytest.mark.asyncio
|
|
967
|
+
async def test_check_for_changes_no_change(self):
|
|
968
|
+
"""Test change detection when no changes"""
|
|
969
|
+
manager = HotReloadManager()
|
|
970
|
+
manager.register_agent("test-agent", "test_module", "TestAgent")
|
|
971
|
+
|
|
972
|
+
# Force a version
|
|
973
|
+
manager._versions["test-agent"] = "abc123"
|
|
974
|
+
|
|
975
|
+
# Should detect change since computed version will differ
|
|
976
|
+
# (module doesn't exist, so version will be different)
|
|
977
|
+
has_changes = await manager.check_for_changes("test-agent")
|
|
978
|
+
# Behavior depends on whether module exists
|
|
979
|
+
|
|
980
|
+
def test_get_agent_version(self):
|
|
981
|
+
"""Test getting agent version"""
|
|
982
|
+
manager = HotReloadManager()
|
|
983
|
+
manager.register_agent("test-agent", "test_module", "TestAgent")
|
|
984
|
+
|
|
985
|
+
version = manager.get_agent_version("test-agent")
|
|
986
|
+
|
|
987
|
+
assert version is not None
|
|
988
|
+
|
|
989
|
+
def test_reload_history(self):
|
|
990
|
+
"""Test reload history tracking"""
|
|
991
|
+
manager = HotReloadManager()
|
|
992
|
+
|
|
993
|
+
history = manager.get_reload_history()
|
|
994
|
+
|
|
995
|
+
assert isinstance(history, list)
|
|
996
|
+
|
|
997
|
+
|
|
998
|
+
# ============================================================================
|
|
999
|
+
# Enhanced Control Plane Tests
|
|
1000
|
+
# ============================================================================
|
|
1001
|
+
|
|
1002
|
+
class TestEnhancedControlPlane:
|
|
1003
|
+
"""Tests for the enhanced agent control plane"""
|
|
1004
|
+
|
|
1005
|
+
def test_create_control_plane(self):
|
|
1006
|
+
"""Test control plane creation"""
|
|
1007
|
+
control_plane = create_control_plane(
|
|
1008
|
+
health_check_interval=30.0,
|
|
1009
|
+
auto_recovery=True
|
|
1010
|
+
)
|
|
1011
|
+
|
|
1012
|
+
assert control_plane is not None
|
|
1013
|
+
assert isinstance(control_plane, EnhancedAgentControlPlane)
|
|
1014
|
+
|
|
1015
|
+
def test_register_agent(self):
|
|
1016
|
+
"""Test agent registration"""
|
|
1017
|
+
control_plane = create_control_plane()
|
|
1018
|
+
|
|
1019
|
+
agent_id = control_plane.register(
|
|
1020
|
+
MockAgent,
|
|
1021
|
+
replicas=2,
|
|
1022
|
+
dependencies=[]
|
|
1023
|
+
)
|
|
1024
|
+
|
|
1025
|
+
assert agent_id == "MockAgent"
|
|
1026
|
+
assert "MockAgent" in control_plane._registrations
|
|
1027
|
+
|
|
1028
|
+
def test_register_with_resources(self):
|
|
1029
|
+
"""Test agent registration with resource quota"""
|
|
1030
|
+
control_plane = create_control_plane()
|
|
1031
|
+
|
|
1032
|
+
control_plane.register(
|
|
1033
|
+
MockAgent,
|
|
1034
|
+
replicas=1,
|
|
1035
|
+
resources=AgentResourceQuota(
|
|
1036
|
+
memory_mb=512,
|
|
1037
|
+
cpu_percent=25
|
|
1038
|
+
)
|
|
1039
|
+
)
|
|
1040
|
+
|
|
1041
|
+
quota = control_plane.quota_manager.get_quota("MockAgent")
|
|
1042
|
+
assert quota is not None
|
|
1043
|
+
assert quota.memory_mb == 512
|
|
1044
|
+
|
|
1045
|
+
def test_register_with_circuit_breaker(self):
|
|
1046
|
+
"""Test agent registration with circuit breaker"""
|
|
1047
|
+
control_plane = create_control_plane()
|
|
1048
|
+
|
|
1049
|
+
breaker = CircuitBreaker(
|
|
1050
|
+
name="test",
|
|
1051
|
+
failure_threshold=5,
|
|
1052
|
+
recovery_timeout=60
|
|
1053
|
+
)
|
|
1054
|
+
|
|
1055
|
+
control_plane.register(
|
|
1056
|
+
MockAgent,
|
|
1057
|
+
circuit_breaker=breaker
|
|
1058
|
+
)
|
|
1059
|
+
|
|
1060
|
+
registered_breaker = control_plane.get_circuit_breaker("MockAgent")
|
|
1061
|
+
assert registered_breaker is breaker
|
|
1062
|
+
|
|
1063
|
+
@pytest.mark.asyncio
|
|
1064
|
+
async def test_start_all(self):
|
|
1065
|
+
"""Test starting all agents"""
|
|
1066
|
+
control_plane = create_control_plane()
|
|
1067
|
+
|
|
1068
|
+
control_plane.register(MockAgent, replicas=1)
|
|
1069
|
+
|
|
1070
|
+
result = await control_plane.start_all()
|
|
1071
|
+
|
|
1072
|
+
assert result["status"] == "started"
|
|
1073
|
+
|
|
1074
|
+
await control_plane.stop_all()
|
|
1075
|
+
|
|
1076
|
+
@pytest.mark.asyncio
|
|
1077
|
+
async def test_stop_all(self):
|
|
1078
|
+
"""Test stopping all agents"""
|
|
1079
|
+
control_plane = create_control_plane()
|
|
1080
|
+
control_plane.register(MockAgent, replicas=1)
|
|
1081
|
+
|
|
1082
|
+
await control_plane.start_all()
|
|
1083
|
+
result = await control_plane.stop_all()
|
|
1084
|
+
|
|
1085
|
+
assert result["status"] == "stopped"
|
|
1086
|
+
|
|
1087
|
+
def test_get_status(self):
|
|
1088
|
+
"""Test getting control plane status"""
|
|
1089
|
+
control_plane = create_control_plane()
|
|
1090
|
+
control_plane.register(MockAgent)
|
|
1091
|
+
|
|
1092
|
+
status = control_plane.get_status()
|
|
1093
|
+
|
|
1094
|
+
assert "running" in status
|
|
1095
|
+
assert "registered_agents" in status
|
|
1096
|
+
assert "MockAgent" in status["registered_agents"]
|
|
1097
|
+
|
|
1098
|
+
|
|
1099
|
+
# ============================================================================
|
|
1100
|
+
# Integration Tests
|
|
1101
|
+
# ============================================================================
|
|
1102
|
+
|
|
1103
|
+
class TestIntegration:
|
|
1104
|
+
"""Integration tests for lifecycle management"""
|
|
1105
|
+
|
|
1106
|
+
@pytest.mark.asyncio
|
|
1107
|
+
async def test_full_lifecycle(self):
|
|
1108
|
+
"""Test complete agent lifecycle"""
|
|
1109
|
+
control_plane = create_control_plane(
|
|
1110
|
+
health_check_interval=1.0,
|
|
1111
|
+
auto_recovery=True
|
|
1112
|
+
)
|
|
1113
|
+
|
|
1114
|
+
# Register agents with dependencies
|
|
1115
|
+
control_plane.register(MockAgent, agent_id="database", replicas=1)
|
|
1116
|
+
control_plane.register(
|
|
1117
|
+
MockAgent,
|
|
1118
|
+
agent_id="api-server",
|
|
1119
|
+
replicas=2,
|
|
1120
|
+
dependencies=["database"],
|
|
1121
|
+
resources=AgentResourceQuota(memory_mb=256)
|
|
1122
|
+
)
|
|
1123
|
+
|
|
1124
|
+
# Start all
|
|
1125
|
+
result = await control_plane.start_all()
|
|
1126
|
+
assert result["status"] == "started"
|
|
1127
|
+
|
|
1128
|
+
# Check health
|
|
1129
|
+
health = control_plane.get_all_health_status()
|
|
1130
|
+
assert len(health) > 0
|
|
1131
|
+
|
|
1132
|
+
# Get metrics
|
|
1133
|
+
metrics = control_plane.get_metrics()
|
|
1134
|
+
assert isinstance(metrics, str)
|
|
1135
|
+
|
|
1136
|
+
# Stop all
|
|
1137
|
+
result = await control_plane.stop_all()
|
|
1138
|
+
assert result["status"] == "stopped"
|
|
1139
|
+
|
|
1140
|
+
@pytest.mark.asyncio
|
|
1141
|
+
async def test_dependency_order(self):
|
|
1142
|
+
"""Test agents start in dependency order"""
|
|
1143
|
+
control_plane = create_control_plane()
|
|
1144
|
+
|
|
1145
|
+
start_order = []
|
|
1146
|
+
|
|
1147
|
+
class TrackedAgent(MockAgent):
|
|
1148
|
+
async def start(self):
|
|
1149
|
+
start_order.append(self.name)
|
|
1150
|
+
await super().start()
|
|
1151
|
+
|
|
1152
|
+
control_plane.register(
|
|
1153
|
+
lambda: TrackedAgent("cache"),
|
|
1154
|
+
agent_id="cache",
|
|
1155
|
+
replicas=1
|
|
1156
|
+
)
|
|
1157
|
+
control_plane.register(
|
|
1158
|
+
lambda: TrackedAgent("database"),
|
|
1159
|
+
agent_id="database",
|
|
1160
|
+
replicas=1
|
|
1161
|
+
)
|
|
1162
|
+
control_plane.register(
|
|
1163
|
+
lambda: TrackedAgent("api"),
|
|
1164
|
+
agent_id="api",
|
|
1165
|
+
replicas=1,
|
|
1166
|
+
dependencies=["database", "cache"]
|
|
1167
|
+
)
|
|
1168
|
+
|
|
1169
|
+
# The dependency graph should ensure database and cache start before api
|
|
1170
|
+
# (Note: this is validated by the dependency graph tests above)
|
|
1171
|
+
|
|
1172
|
+
|
|
1173
|
+
if __name__ == "__main__":
|
|
1174
|
+
pytest.main([__file__, "-v"])
|