codex-a2a 1.3.2__tar.gz → 1.3.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/.pre-commit-config.yaml +11 -2
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/CONTRIBUTING.md +2 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/PKG-INFO +6 -6
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/docs/compatibility.md +3 -1
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/docs/conformance-triage.md +1 -1
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/docs/conformance.md +1 -1
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/docs/maintainer-architecture.md +10 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/pyproject.toml +5 -5
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/scripts/README.md +1 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/scripts/validate_baseline.sh +2 -1
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/execution/discovery_runtime.py +22 -16
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/execution/exec_runtime.py +9 -3
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/execution/review_runtime.py +33 -31
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/execution/thread_lifecycle_runtime.py +18 -16
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/server/application.py +15 -13
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/server/output_negotiation.py +0 -109
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/server/request_handler.py +148 -64
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/upstream/client.py +6 -4
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/upstream/stream_bridge.py +2 -2
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a.egg-info/PKG-INFO +6 -6
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a.egg-info/SOURCES.txt +5 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a.egg-info/requires.txt +5 -5
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/execution/test_discovery_exec_runtime.py +100 -0
- codex_a2a-1.3.4/tests/execution/test_watch_lifecycle.py +69 -0
- codex_a2a-1.3.4/tests/fixtures/sdk_task_store_main_0a3fb68.sql +19 -0
- codex_a2a-1.3.4/tests/scripts/test_validate_baseline_script.py +89 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/server/test_request_handler.py +73 -43
- codex_a2a-1.3.4/tests/server/test_request_handler_lifecycle.py +343 -0
- codex_a2a-1.3.4/tests/server/test_sdk_upgrade.py +379 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/upstream/test_codex_client_params.py +22 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/uv.lock +319 -247
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/.github/dependabot.yml +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/.github/workflows/ci.yml +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/.github/workflows/compatibility.yml +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/.github/workflows/dependency-health.yml +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/.github/workflows/publish.yml +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/.gitignore +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/.secrets.baseline +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/AGENTS.md +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/LICENSE +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/README.md +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/SECURITY.md +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/docs/a2a-extension-baseline.md +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/docs/architecture.md +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/docs/extension-specifications.md +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/docs/guide.md +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/docs/inspection/README.md +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/docs/inspection/error_redaction_policy.md +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/docs/inspection/release_integrity_policy.md +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/mypy.ini +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/scripts/audit_low_call_sites.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/scripts/check_codex_app_server_schema.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/scripts/check_dead_code.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/scripts/conformance.sh +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/scripts/dependency_health.sh +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/scripts/health_common.sh +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/scripts/publish_github_release.sh +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/scripts/smoke_live_codex_turn.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/scripts/smoke_test_built_cli.sh +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/scripts/smoke_test_live_codex.sh +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/scripts/sync_codex_docs.sh +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/scripts/tck_auth_plugin.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/scripts/validate_runtime_matrix.sh +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/setup.cfg +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/__init__.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/a2a_proto.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/auth.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/cli.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/client/__init__.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/client/agent_card.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/client/auth.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/client/client.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/client/config.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/client/errors.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/client/extension_negotiation.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/client/manager.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/client/network_policy.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/client/payload_text.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/client/request_context.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/config.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/contracts/__init__.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/contracts/extension_registry.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/contracts/extension_specs.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/contracts/extensions.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/contracts/runtime_output.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/execution/__init__.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/execution/executor.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/execution/output_mapping.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/execution/request_metadata.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/execution/request_overrides.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/execution/response_emitter.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/execution/session_runtime.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/execution/stream_chunks.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/execution/stream_interrupts.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/execution/stream_processor.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/execution/stream_state.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/execution/streaming.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/execution/tool_call_payloads.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/execution/watch_events.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/input_mapping.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/jsonrpc/__init__.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/jsonrpc/application.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/jsonrpc/discovery_control.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/jsonrpc/discovery_params.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/jsonrpc/discovery_payload_mapping.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/jsonrpc/discovery_query.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/jsonrpc/dispatch.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/jsonrpc/errors.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/jsonrpc/exec_control.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/jsonrpc/exec_control_params.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/jsonrpc/hooks.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/jsonrpc/interrupt_lifecycle.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/jsonrpc/interrupt_params.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/jsonrpc/interrupt_recovery.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/jsonrpc/interrupt_recovery_params.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/jsonrpc/interrupts.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/jsonrpc/owner_guard.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/jsonrpc/params.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/jsonrpc/params_common.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/jsonrpc/payload_mapping.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/jsonrpc/query_params.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/jsonrpc/request_models.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/jsonrpc/review_control.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/jsonrpc/review_control_params.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/jsonrpc/session_query.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/jsonrpc/thread_lifecycle_control.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/jsonrpc/thread_lifecycle_params.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/jsonrpc/turn_control.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/jsonrpc/turn_control_params.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/logging_context.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/media_modes.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/metrics.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/payload_helpers.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/profile/__init__.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/profile/runtime.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/protocol_versions.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/py.typed +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/redact.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/server/__init__.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/server/agent_card.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/server/call_context.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/server/database.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/server/http_middlewares.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/server/migrations.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/server/openapi.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/server/openapi_contract_fragments.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/server/push_config_store.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/server/runtime_limits.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/server/runtime_state.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/server/runtime_state_schema.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/server/task_store.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/skill_handles.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/upstream/__init__.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/upstream/conversation_facade.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/upstream/discovery_payloads.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/upstream/interrupt_bridge.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/upstream/interrupts.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/upstream/models.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/upstream/notification_mapping.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/upstream/request_mapping.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/upstream/startup.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a/upstream/transport.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a.egg-info/dependency_links.txt +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a.egg-info/entry_points.txt +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/src/codex_a2a.egg-info/top_level.txt +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/__init__.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/client/__init__.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/client/test_agent_card.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/client/test_cli.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/client/test_client_flow.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/client/test_client_http_headers.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/client/test_client_manager.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/client/test_errors.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/client/test_lifecycle.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/client/test_network_policy.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/client/test_payload_text.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/client/test_request_context.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/config/__init__.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/config/test_settings.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/contracts/__init__.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/contracts/test_extension_contract_consistency.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/contracts/test_extension_registry.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/execution/__init__.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/execution/test_agent_errors.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/execution/test_cancellation.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/execution/test_codex_agent_session_binding.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/execution/test_directory_validation.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/execution/test_error_redaction.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/execution/test_metrics.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/execution/test_request_metadata.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/execution/test_review_runtime.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/execution/test_session_ownership.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/execution/test_session_persistence.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/execution/test_session_runtime.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/execution/test_stream_chunks.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/execution/test_stream_interrupts.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/execution/test_streaming_output_contract.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/execution/test_thread_lifecycle_runtime.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/execution/test_tool_call_payloads.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/fixtures/codex_app_server/command_execution_output_delta.json +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/fixtures/codex_app_server/file_change_output_delta.json +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/jsonrpc/__init__.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/jsonrpc/test_codex_discovery_extension.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/jsonrpc/test_codex_exec_extension.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/jsonrpc/test_codex_session_extension.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/jsonrpc/test_codex_thread_lifecycle_extension.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/jsonrpc/test_codex_turn_review_extension.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/jsonrpc/test_dispatch.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/jsonrpc/test_error_redaction.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/jsonrpc/test_guard_hooks.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/jsonrpc/test_interrupt_lifecycle.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/jsonrpc/test_interrupt_params.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/jsonrpc/test_interrupt_protocol_handlers.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/jsonrpc/test_jsonrpc_models.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/jsonrpc/test_protocol_payload_mapping.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/package/__init__.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/package/test_logging.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/package/test_publish_github_release_script.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/package/test_release_distribution_contract.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/package/test_typing_contract.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/package/test_version.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/profile/__init__.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/profile/test_profile.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/scripts/__init__.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/scripts/test_audit_low_call_sites.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/scripts/test_check_codex_app_server_schema.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/scripts/test_script_health_contract.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/scripts/test_tck_auth_plugin.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/server/__init__.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/server/test_agent_card.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/server/test_auth.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/server/test_call_context_builder.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/server/test_cli.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/server/test_database.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/server/test_database_app_persistence.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/server/test_http_boundary.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/server/test_migrations.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/server/test_output_negotiation.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/server/test_push_config_store.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/server/test_runtime_limits.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/server/test_runtime_state.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/server/test_task_store.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/server/test_transport_contract.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/support/__init__.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/support/context.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/support/dummy_clients.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/support/fixtures.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/support/http_auth.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/support/jsonrpc_errors.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/support/settings.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/test_a2a_proto.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/test_input_mapping.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/test_protocol_versions.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/test_redact.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/test_skill_handles.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/upstream/__init__.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/upstream/test_interrupt_bridge.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/upstream/test_interrupt_persistence.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/upstream/test_modular_upstream_components.py +0 -0
- {codex_a2a-1.3.2 → codex_a2a-1.3.4}/tests/upstream/test_request_mapping.py +0 -0
|
@@ -6,12 +6,21 @@ repos:
|
|
|
6
6
|
- id: trailing-whitespace
|
|
7
7
|
- id: end-of-file-fixer
|
|
8
8
|
- id: check-yaml
|
|
9
|
-
- repo:
|
|
10
|
-
rev: v0.14.14
|
|
9
|
+
- repo: local
|
|
11
10
|
hooks:
|
|
12
11
|
- id: ruff
|
|
12
|
+
name: ruff check (uv)
|
|
13
|
+
entry: uv run --locked --extra dev ruff check --force-exclude
|
|
14
|
+
language: system
|
|
15
|
+
types_or: [python, pyi, jupyter]
|
|
16
|
+
require_serial: true
|
|
13
17
|
args: ["--fix"]
|
|
14
18
|
- id: ruff-format
|
|
19
|
+
name: ruff format (uv)
|
|
20
|
+
entry: uv run --locked --extra dev ruff format --force-exclude
|
|
21
|
+
language: system
|
|
22
|
+
types_or: [python, pyi, jupyter]
|
|
23
|
+
require_serial: true
|
|
15
24
|
- repo: https://github.com/Yelp/detect-secrets
|
|
16
25
|
rev: v1.5.0
|
|
17
26
|
hooks:
|
|
@@ -72,6 +72,8 @@ bash -n scripts/smoke_test_built_cli.sh
|
|
|
72
72
|
|
|
73
73
|
If `pre-commit` rewrites files, review the rewritten output and re-run the checks until the working tree is clean.
|
|
74
74
|
|
|
75
|
+
Ruff's version is declared in the `dev` extra in `pyproject.toml` and resolved in `uv.lock`. The local pre-commit hooks run `uv run --locked --extra dev ruff`, so direct commands, hooks, and CI use the same project dependency. To upgrade Ruff, update that dependency and regenerate `uv.lock`; there is no separate Ruff hook revision to maintain.
|
|
76
|
+
|
|
75
77
|
## Compatibility Expectations
|
|
76
78
|
|
|
77
79
|
- The repository targets Python 3.11 through 3.14. CI uses 3.13 for the full quality gate and exercises 3.11, 3.12, and 3.14 in the runtime matrix.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codex-a2a
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.4
|
|
4
4
|
Summary: Codex A2A runtime adapter
|
|
5
5
|
Author: liujuanjuan1984@Intelligent-Internet
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -23,14 +23,14 @@ Classifier: Topic :: Internet :: WWW/HTTP
|
|
|
23
23
|
Requires-Python: >=3.11
|
|
24
24
|
Description-Content-Type: text/markdown
|
|
25
25
|
License-File: LICENSE
|
|
26
|
-
Requires-Dist: a2a-sdk==1.1.
|
|
26
|
+
Requires-Dist: a2a-sdk==1.1.5
|
|
27
27
|
Requires-Dist: aiosqlite<1.0,>=0.20
|
|
28
28
|
Requires-Dist: fastapi<0.142,>=0.121
|
|
29
29
|
Requires-Dist: httpx<0.29,>=0.28.1
|
|
30
|
-
Requires-Dist: protobuf<
|
|
30
|
+
Requires-Dist: protobuf<8.0,>=6.33.5
|
|
31
31
|
Requires-Dist: pydantic<3.0,>=2.6
|
|
32
32
|
Requires-Dist: pydantic-settings<3.0,>=2.2
|
|
33
|
-
Requires-Dist: sqlalchemy<3.0,>=2.0
|
|
33
|
+
Requires-Dist: sqlalchemy[asyncio]<3.0,>=2.0
|
|
34
34
|
Requires-Dist: sse-starlette<4.0,>=2.1
|
|
35
35
|
Requires-Dist: uvicorn<0.53,>=0.29
|
|
36
36
|
Provides-Extra: dev
|
|
@@ -40,8 +40,8 @@ Requires-Dist: pygments<3.0,>=2.20.0; extra == "dev"
|
|
|
40
40
|
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
41
41
|
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
|
|
42
42
|
Requires-Dist: pytest-cov<8.0,>=5.0; extra == "dev"
|
|
43
|
-
Requires-Dist: diff-cover<
|
|
44
|
-
Requires-Dist: ruff
|
|
43
|
+
Requires-Dist: diff-cover<11,>=9; extra == "dev"
|
|
44
|
+
Requires-Dist: ruff==0.16.9; extra == "dev"
|
|
45
45
|
Requires-Dist: mypy<2.4,>=1.11; extra == "dev"
|
|
46
46
|
Dynamic: license-file
|
|
47
47
|
|
|
@@ -7,7 +7,9 @@ This document explains the compatibility promises this repository currently trie
|
|
|
7
7
|
| Layer | Supported contract | Evidence and boundary |
|
|
8
8
|
| --- | --- | --- |
|
|
9
9
|
| Python | 3.11–3.14 | Package classifiers cover all four versions; CI runs 3.13 as the quality gate and 3.11, 3.12, and 3.14 in the runtime matrix. |
|
|
10
|
-
| A2A Python SDK | Exactly `a2a-sdk==1.1.
|
|
10
|
+
| A2A Python SDK | Exactly `a2a-sdk==1.1.5` | Pinned in `pyproject.toml`; this is the [official A2A Python SDK](https://github.com/a2aproject/a2a-python), not a fork. |
|
|
11
|
+
| Protocol Buffers | `protobuf>=6.33.5,<8.0` | The lockfile selects 7.36.2. SDK 1.1.5 supports protobuf 7; Google API Core, common protos, and proto-plus must resolve within the same range. Task retrieval delegates validation and history trimming to the SDK. |
|
|
12
|
+
| SQLAlchemy | `sqlalchemy[asyncio]>=2.0,<3.0` | The `asyncio` extra explicitly installs `greenlet` for the async persistence engine, including standalone wheel installations. The lockfile selects the development version. |
|
|
11
13
|
| A2A protocol | `1.0` wire line | The released upstream A2A specification is normative for portable core semantics; the current compatible release is `v1.0.1`. SDK compatibility with other protocol versions does not extend this adapter's claim. |
|
|
12
14
|
| Inbound A2A transports | JSON-RPC and HTTP+JSON | Both are repository-owned runtime surfaces. gRPC is not exposed by this adapter. |
|
|
13
15
|
| Codex local runtime | Codex CLI/App Server | The local [Apache-2.0 Codex CLI](https://github.com/openai/codex) is the upstream process boundary. Scheduled smoke tests install the latest stable CLI and complete a real local App Server turn. |
|
|
@@ -5,7 +5,7 @@ This document is the standing triage template for local `./scripts/conformance.s
|
|
|
5
5
|
## Authorities Used For Triage
|
|
6
6
|
|
|
7
7
|
- The latest compatible released upstream A2A specification is authoritative; currently this is `v1.0.1` for the repository's advertised `1.0` wire line.
|
|
8
|
-
- `a2a-sdk==1.1.
|
|
8
|
+
- `a2a-sdk==1.1.5` as installed in this repository.
|
|
9
9
|
- The default A2A protocol version advertised by this repository: `1.0`.
|
|
10
10
|
- TCK assertions are non-normative observations and may lag the released specification.
|
|
11
11
|
- Repository compatibility policy:
|
|
@@ -74,7 +74,7 @@ When a TCK run fails, inspect the raw report before changing the runtime:
|
|
|
74
74
|
|
|
75
75
|
- Some failures may point to real runtime gaps.
|
|
76
76
|
- Some failures may reflect an outdated embedded specification or a TCK-specific interpretation. Resolve those disagreements against the latest compatible released A2A specification.
|
|
77
|
-
- Some failures may come from TCK assumptions that do not match `a2a-sdk==1.1.
|
|
77
|
+
- Some failures may come from TCK assumptions that do not match `a2a-sdk==1.1.5`.
|
|
78
78
|
- Some failures may come from older A2A naming or schema expectations that no longer match the repository's `1.0` contract.
|
|
79
79
|
- Some failures may be local experiment artifacts from the dummy-backed runtime.
|
|
80
80
|
|
|
@@ -74,6 +74,16 @@ flowchart TD
|
|
|
74
74
|
- **Session State**: Stores the binding of `context_id` to `session_id`.
|
|
75
75
|
- **Interrupt Store**: Stores pending interrupt requests to survive service restarts.
|
|
76
76
|
|
|
77
|
+
## Background Streams and Shutdown
|
|
78
|
+
|
|
79
|
+
Background streams use SDK Source/Sink queues: producers persist once before
|
|
80
|
+
broadcasting, and slow or disconnected subscribers cannot block other consumers.
|
|
81
|
+
Shutdown drains SDK and adapter tasks before closing clients and stores.
|
|
82
|
+
|
|
83
|
+
Use the [standard upgrade procedure](./guide.md#released-cli-self-start) and restart;
|
|
84
|
+
the task-store format is unchanged. SDK upgrade regressions run in normal CI and
|
|
85
|
+
can be checked with `uv run pytest --no-cov tests/server/test_sdk_upgrade.py`.
|
|
86
|
+
|
|
77
87
|
## Configuration Layering
|
|
78
88
|
|
|
79
89
|
Configuration is handled in `src/codex_a2a/config.py` using `pydantic-settings`. It is categorized by prefix:
|
|
@@ -25,14 +25,14 @@ classifiers = [
|
|
|
25
25
|
"Topic :: Internet :: WWW/HTTP",
|
|
26
26
|
]
|
|
27
27
|
dependencies = [
|
|
28
|
-
"a2a-sdk==1.1.
|
|
28
|
+
"a2a-sdk==1.1.5",
|
|
29
29
|
"aiosqlite>=0.20,<1.0",
|
|
30
30
|
"fastapi>=0.121,<0.142",
|
|
31
31
|
"httpx>=0.28.1,<0.29",
|
|
32
|
-
"protobuf>=6.33.5,<
|
|
32
|
+
"protobuf>=6.33.5,<8.0",
|
|
33
33
|
"pydantic>=2.6,<3.0",
|
|
34
34
|
"pydantic-settings>=2.2,<3.0",
|
|
35
|
-
"sqlalchemy>=2.0,<3.0",
|
|
35
|
+
"sqlalchemy[asyncio]>=2.0,<3.0",
|
|
36
36
|
"sse-starlette>=2.1,<4.0",
|
|
37
37
|
"uvicorn>=0.29,<0.53",
|
|
38
38
|
]
|
|
@@ -45,8 +45,8 @@ dev = [
|
|
|
45
45
|
"pytest>=8.0",
|
|
46
46
|
"pytest-asyncio>=0.23",
|
|
47
47
|
"pytest-cov>=5.0,<8.0",
|
|
48
|
-
"diff-cover>=9,<
|
|
49
|
-
"ruff
|
|
48
|
+
"diff-cover>=9,<11",
|
|
49
|
+
"ruff==0.16.9",
|
|
50
50
|
"mypy>=1.11,<2.4",
|
|
51
51
|
]
|
|
52
52
|
|
|
@@ -38,6 +38,7 @@ The `Publish` workflow now separates build, PyPI publish, and GitHub Release syn
|
|
|
38
38
|
- `validate_baseline.sh` now includes a conservative private dead-code check before type-checking and test execution.
|
|
39
39
|
- `audit_low_call_sites.py` is intentionally advisory only. Use it to surface low-call-count candidates, then inspect the actual consumer chain before removing an abstraction.
|
|
40
40
|
- `validate_baseline.sh` now blocks on runtime dependency vulnerability audit, while `dependency_health.sh` remains focused on broader dependency review (`outdated` + dev audit).
|
|
41
|
+
- The baseline makes up to three runtime audit attempts (the initial attempt plus at most two retries), with a fresh cache per attempt. If every attempt fails, it returns the last audit exit code and stops before package build and wheel smoke testing. A successful retry allows validation to continue.
|
|
41
42
|
- [`.github/dependabot.yml`](../.github/dependabot.yml) prefers a single weekly grouped Dependabot PR for `uv`, while the repository scripts remain the explicit audit and validation entrypoints.
|
|
42
43
|
- End-user runtime startup does not use repository scripts. Prefer the published CLI command documented in [README.md](../README.md) and [docs/guide.md](../docs/guide.md).
|
|
43
44
|
- Keep long-form documentation changes in `docs/` to avoid divergence.
|
|
@@ -19,8 +19,9 @@ run_pip_audit() {
|
|
|
19
19
|
if XDG_CACHE_HOME="${audit_cache_dir}" uv run pip-audit --requirement "${requirement_file}"; then
|
|
20
20
|
rm -rf "${audit_cache_dir}"
|
|
21
21
|
return 0
|
|
22
|
+
else
|
|
23
|
+
status=$?
|
|
22
24
|
fi
|
|
23
|
-
status=$?
|
|
24
25
|
rm -rf "${audit_cache_dir}"
|
|
25
26
|
if [[ "${attempt}" -ge "${max_attempts}" ]]; then
|
|
26
27
|
echo "pip-audit failed after ${attempt} attempts" >&2
|
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import logging
|
|
5
5
|
import uuid
|
|
6
|
+
from contextlib import aclosing
|
|
6
7
|
from dataclasses import dataclass
|
|
7
8
|
from typing import TYPE_CHECKING, Any
|
|
8
9
|
|
|
@@ -94,22 +95,27 @@ class CodexDiscoveryRuntime:
|
|
|
94
95
|
|
|
95
96
|
async def _run_watch(self, *, handle: DiscoveryWatchHandle, event_queue) -> None: # noqa: ANN001
|
|
96
97
|
append = False
|
|
97
|
-
async
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
98
|
+
async with aclosing(self._client.stream_events(stop_event=handle.stop_event)) as events:
|
|
99
|
+
async for event in events:
|
|
100
|
+
payload = self._payload_from_event(event, events=handle.events)
|
|
101
|
+
if payload is None:
|
|
102
|
+
continue
|
|
103
|
+
await enqueue_artifact_update(
|
|
104
|
+
event_queue=event_queue,
|
|
105
|
+
task_id=handle.task_id,
|
|
106
|
+
context_id=handle.context_id,
|
|
107
|
+
artifact_id=f"{handle.task_id}:discovery",
|
|
108
|
+
part=new_data_part(payload),
|
|
109
|
+
append=append,
|
|
110
|
+
last_chunk=None,
|
|
111
|
+
artifact_metadata={
|
|
112
|
+
"codex": {"discovery_watch": {"events": sorted(handle.events)}}
|
|
113
|
+
},
|
|
114
|
+
event_metadata={
|
|
115
|
+
"codex": {"discovery_watch": {"events": sorted(handle.events)}}
|
|
116
|
+
},
|
|
117
|
+
)
|
|
118
|
+
append = True
|
|
113
119
|
|
|
114
120
|
def _payload_from_event(
|
|
115
121
|
self,
|
|
@@ -278,10 +278,16 @@ class CodexExecRuntime:
|
|
|
278
278
|
)
|
|
279
279
|
finally:
|
|
280
280
|
handle.stop_event.set()
|
|
281
|
+
child_tasks: list[asyncio.Future] = [exec_task]
|
|
281
282
|
if pending_event_task is not None:
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
283
|
+
child_tasks.append(pending_event_task)
|
|
284
|
+
for child_task in child_tasks:
|
|
285
|
+
if not child_task.done() and not (
|
|
286
|
+
isinstance(child_task, asyncio.Task) and child_task.cancelling()
|
|
287
|
+
):
|
|
288
|
+
child_task.cancel()
|
|
289
|
+
await asyncio.gather(*child_tasks, return_exceptions=True)
|
|
290
|
+
await stream_iter.aclose()
|
|
285
291
|
|
|
286
292
|
async def _emit_output_delta(
|
|
287
293
|
self,
|
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import logging
|
|
5
5
|
import uuid
|
|
6
|
+
from contextlib import aclosing
|
|
6
7
|
from dataclasses import dataclass
|
|
7
8
|
from typing import TYPE_CHECKING, Any
|
|
8
9
|
|
|
@@ -132,39 +133,40 @@ class CodexReviewRuntime:
|
|
|
132
133
|
)
|
|
133
134
|
append = True
|
|
134
135
|
|
|
135
|
-
async
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
136
|
+
async with aclosing(self._client.stream_events(stop_event=handle.stop_event)) as events:
|
|
137
|
+
async for event in events:
|
|
138
|
+
payload = self._payload_from_event(event, handle=handle)
|
|
139
|
+
if payload is None:
|
|
140
|
+
continue
|
|
141
|
+
is_terminal = payload["event"] in {"review.completed", "review.failed"}
|
|
142
|
+
await enqueue_artifact_update(
|
|
143
|
+
event_queue=event_queue,
|
|
144
|
+
task_id=handle.task_id,
|
|
145
|
+
context_id=handle.context_id,
|
|
146
|
+
artifact_id=f"{handle.task_id}:review-watch",
|
|
147
|
+
part=new_data_part(payload),
|
|
148
|
+
append=append,
|
|
149
|
+
last_chunk=is_terminal,
|
|
150
|
+
artifact_metadata=metadata,
|
|
151
|
+
event_metadata=metadata,
|
|
152
|
+
)
|
|
153
|
+
append = True
|
|
154
|
+
if is_terminal:
|
|
155
|
+
await event_queue.enqueue_event(
|
|
156
|
+
TaskStatusUpdateEvent(
|
|
157
|
+
task_id=handle.task_id,
|
|
158
|
+
context_id=handle.context_id,
|
|
159
|
+
status=TaskStatus(
|
|
160
|
+
state=(
|
|
161
|
+
TaskState.TASK_STATE_COMPLETED
|
|
162
|
+
if payload["event"] == "review.completed"
|
|
163
|
+
else TaskState.TASK_STATE_FAILED
|
|
164
|
+
),
|
|
162
165
|
),
|
|
163
|
-
|
|
164
|
-
|
|
166
|
+
metadata=metadata,
|
|
167
|
+
)
|
|
165
168
|
)
|
|
166
|
-
|
|
167
|
-
break
|
|
169
|
+
break
|
|
168
170
|
|
|
169
171
|
def _started_payload(self, handle: ReviewWatchHandle) -> dict[str, Any] | None:
|
|
170
172
|
if "review.started" not in handle.events:
|
|
@@ -5,6 +5,7 @@ import hashlib
|
|
|
5
5
|
import json
|
|
6
6
|
import logging
|
|
7
7
|
import uuid
|
|
8
|
+
from contextlib import aclosing
|
|
8
9
|
from dataclasses import dataclass
|
|
9
10
|
from typing import TYPE_CHECKING, Any, TypeGuard
|
|
10
11
|
|
|
@@ -212,22 +213,23 @@ class CodexThreadLifecycleRuntime:
|
|
|
212
213
|
}
|
|
213
214
|
}
|
|
214
215
|
try:
|
|
215
|
-
async
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
216
|
+
async with aclosing(self._client.stream_events(stop_event=handle.stop_event)) as events:
|
|
217
|
+
async for event in events:
|
|
218
|
+
payload = self._payload_from_event(event, handle=handle)
|
|
219
|
+
if payload is None:
|
|
220
|
+
continue
|
|
221
|
+
await enqueue_artifact_update(
|
|
222
|
+
event_queue=event_queue,
|
|
223
|
+
task_id=handle.task_id,
|
|
224
|
+
context_id=handle.context_id,
|
|
225
|
+
artifact_id=f"{handle.task_id}:thread-lifecycle",
|
|
226
|
+
part=new_data_part(payload),
|
|
227
|
+
append=append,
|
|
228
|
+
last_chunk=None,
|
|
229
|
+
artifact_metadata=metadata,
|
|
230
|
+
event_metadata=metadata,
|
|
231
|
+
)
|
|
232
|
+
append = True
|
|
231
233
|
except asyncio.CancelledError:
|
|
232
234
|
release_reason = "task_cancel"
|
|
233
235
|
raise
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
-
from contextlib import asynccontextmanager
|
|
4
|
+
from contextlib import AsyncExitStack, asynccontextmanager
|
|
5
5
|
from typing import Any
|
|
6
6
|
|
|
7
7
|
import uvicorn
|
|
@@ -288,22 +288,24 @@ def create_app(settings: Settings) -> FastAPI:
|
|
|
288
288
|
persistence_summary["database_url"],
|
|
289
289
|
persistence_summary["sqlite_tuning"],
|
|
290
290
|
)
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
291
|
+
async with AsyncExitStack() as cleanup:
|
|
292
|
+
if shared_database_engine is not None:
|
|
293
|
+
cleanup.push_async_callback(shared_database_engine.dispose)
|
|
294
|
+
await task_store_runtime.startup()
|
|
295
|
+
cleanup.push_async_callback(task_store_runtime.shutdown)
|
|
296
|
+
await push_config_store_runtime.startup()
|
|
297
|
+
cleanup.push_async_callback(push_config_store_runtime.shutdown)
|
|
298
|
+
await runtime_state_runtime.startup()
|
|
299
|
+
cleanup.push_async_callback(runtime_state_runtime.shutdown)
|
|
300
|
+
cleanup.push_async_callback(client.close)
|
|
301
|
+
cleanup.push_async_callback(a2a_client_manager.close_all)
|
|
302
|
+
# Callbacks run in reverse order. Producers may still need clients
|
|
303
|
+
# and stores while unwinding, even if another cleanup callback fails.
|
|
304
|
+
cleanup.push_async_callback(handler.aclose)
|
|
295
305
|
await client.restore_persisted_interrupt_requests()
|
|
296
306
|
await client.startup_preflight()
|
|
297
307
|
await thread_lifecycle_runtime.reconcile_persisted_watches()
|
|
298
308
|
yield
|
|
299
|
-
finally:
|
|
300
|
-
await a2a_client_manager.close_all()
|
|
301
|
-
await client.close()
|
|
302
|
-
await runtime_state_runtime.shutdown()
|
|
303
|
-
await push_config_store_runtime.shutdown()
|
|
304
|
-
await task_store_runtime.shutdown()
|
|
305
|
-
if shared_database_engine is not None:
|
|
306
|
-
await shared_database_engine.dispose()
|
|
307
309
|
|
|
308
310
|
context_builder = IdentityAwareCallContextBuilder()
|
|
309
311
|
jsonrpc_methods = {
|
|
@@ -1,19 +1,15 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import asyncio
|
|
4
3
|
import json
|
|
5
4
|
from collections.abc import Iterable
|
|
6
5
|
from typing import Any, cast
|
|
7
6
|
|
|
8
|
-
from a2a.server.events import EventConsumer
|
|
9
|
-
from a2a.server.tasks import ResultAggregator, TaskManager
|
|
10
7
|
from a2a.types import (
|
|
11
8
|
Artifact,
|
|
12
9
|
Message,
|
|
13
10
|
Part,
|
|
14
11
|
Task,
|
|
15
12
|
TaskArtifactUpdateEvent,
|
|
16
|
-
TaskState,
|
|
17
13
|
TaskStatusUpdateEvent,
|
|
18
14
|
)
|
|
19
15
|
from google.protobuf.message import Message as ProtoMessage # type: ignore[import-untyped]
|
|
@@ -168,111 +164,6 @@ def apply_accepted_output_modes(
|
|
|
168
164
|
return payload
|
|
169
165
|
|
|
170
166
|
|
|
171
|
-
class NegotiatingResultAggregator(ResultAggregator):
|
|
172
|
-
def __init__(
|
|
173
|
-
self,
|
|
174
|
-
task_manager: TaskManager,
|
|
175
|
-
accepted_output_modes: Iterable[str] | None,
|
|
176
|
-
) -> None:
|
|
177
|
-
super().__init__(task_manager)
|
|
178
|
-
self._accepted_output_modes = normalize_accepted_output_modes(accepted_output_modes)
|
|
179
|
-
|
|
180
|
-
def _transform_event(self, event: Any) -> Any | None:
|
|
181
|
-
negotiated_event = apply_accepted_output_modes(event, self._accepted_output_modes)
|
|
182
|
-
if negotiated_event is None:
|
|
183
|
-
return None
|
|
184
|
-
return annotate_output_negotiation_metadata(negotiated_event, self._accepted_output_modes)
|
|
185
|
-
|
|
186
|
-
async def _persist_output_negotiation_metadata(self, event: Any) -> None:
|
|
187
|
-
if not isinstance(event, TaskArtifactUpdateEvent):
|
|
188
|
-
return
|
|
189
|
-
|
|
190
|
-
accepted_output_modes = extract_accepted_output_modes_from_metadata(event.metadata)
|
|
191
|
-
if accepted_output_modes is None:
|
|
192
|
-
return
|
|
193
|
-
|
|
194
|
-
task = await self.task_manager.ensure_task(event)
|
|
195
|
-
merged_metadata = merge_output_negotiation_metadata(task.metadata, accepted_output_modes)
|
|
196
|
-
if merged_metadata == task.metadata:
|
|
197
|
-
return
|
|
198
|
-
task.ClearField("metadata")
|
|
199
|
-
if merged_metadata is not None:
|
|
200
|
-
task.metadata.CopyFrom(merged_metadata)
|
|
201
|
-
await self.task_manager._save_task(task)
|
|
202
|
-
|
|
203
|
-
async def consume_and_emit(self, consumer: EventConsumer): # noqa: ANN201
|
|
204
|
-
async for event in consumer.consume_all():
|
|
205
|
-
transformed_event = self._transform_event(event)
|
|
206
|
-
if transformed_event is None:
|
|
207
|
-
continue
|
|
208
|
-
await self._persist_output_negotiation_metadata(transformed_event)
|
|
209
|
-
await self.task_manager.process(transformed_event)
|
|
210
|
-
yield transformed_event
|
|
211
|
-
|
|
212
|
-
async def consume_all(self, consumer: EventConsumer) -> Task | Message | None:
|
|
213
|
-
async for event in consumer.consume_all():
|
|
214
|
-
transformed_event = self._transform_event(event)
|
|
215
|
-
if transformed_event is None:
|
|
216
|
-
continue
|
|
217
|
-
if isinstance(transformed_event, Message):
|
|
218
|
-
self._message = transformed_event
|
|
219
|
-
return transformed_event
|
|
220
|
-
await self._persist_output_negotiation_metadata(transformed_event)
|
|
221
|
-
await self.task_manager.process(transformed_event)
|
|
222
|
-
return await self.task_manager.get_task()
|
|
223
|
-
|
|
224
|
-
async def consume_and_break_on_interrupt(
|
|
225
|
-
self,
|
|
226
|
-
consumer: EventConsumer,
|
|
227
|
-
blocking: bool = True,
|
|
228
|
-
event_callback=None, # noqa: ANN001
|
|
229
|
-
) -> tuple[Task | Message | None, bool, asyncio.Task | None]:
|
|
230
|
-
event_stream = consumer.consume_all()
|
|
231
|
-
interrupted = False
|
|
232
|
-
bg_task: asyncio.Task | None = None
|
|
233
|
-
async for event in event_stream:
|
|
234
|
-
transformed_event = self._transform_event(event)
|
|
235
|
-
if transformed_event is None:
|
|
236
|
-
continue
|
|
237
|
-
if isinstance(transformed_event, Message):
|
|
238
|
-
self._message = transformed_event
|
|
239
|
-
return transformed_event, False, None
|
|
240
|
-
await self._persist_output_negotiation_metadata(transformed_event)
|
|
241
|
-
await self.task_manager.process(transformed_event)
|
|
242
|
-
|
|
243
|
-
should_interrupt = False
|
|
244
|
-
is_auth_required = (
|
|
245
|
-
isinstance(transformed_event, Task | TaskStatusUpdateEvent)
|
|
246
|
-
and transformed_event.status.state == TaskState.TASK_STATE_AUTH_REQUIRED
|
|
247
|
-
)
|
|
248
|
-
if is_auth_required:
|
|
249
|
-
should_interrupt = True
|
|
250
|
-
elif not blocking:
|
|
251
|
-
should_interrupt = True
|
|
252
|
-
|
|
253
|
-
if should_interrupt:
|
|
254
|
-
bg_task = asyncio.create_task(
|
|
255
|
-
self._continue_consuming(event_stream, event_callback)
|
|
256
|
-
)
|
|
257
|
-
interrupted = True
|
|
258
|
-
break
|
|
259
|
-
return await self.task_manager.get_task(), interrupted, bg_task
|
|
260
|
-
|
|
261
|
-
async def _continue_consuming(
|
|
262
|
-
self,
|
|
263
|
-
event_stream,
|
|
264
|
-
event_callback=None, # noqa: ANN001
|
|
265
|
-
) -> None:
|
|
266
|
-
async for event in event_stream:
|
|
267
|
-
transformed_event = self._transform_event(event)
|
|
268
|
-
if transformed_event is None:
|
|
269
|
-
continue
|
|
270
|
-
await self._persist_output_negotiation_metadata(transformed_event)
|
|
271
|
-
await self.task_manager.process(transformed_event)
|
|
272
|
-
if event_callback:
|
|
273
|
-
await event_callback()
|
|
274
|
-
|
|
275
|
-
|
|
276
167
|
def _filter_task(task: Task, accepted_modes: frozenset[str]) -> Task:
|
|
277
168
|
filtered_history: list[Message] = []
|
|
278
169
|
for message in task.history or []:
|