codex-a2a 0.6.0__tar.gz → 0.6.2__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-0.6.0 → codex_a2a-0.6.2}/.github/workflows/ci.yml +3 -1
- codex_a2a-0.6.2/.github/workflows/dependency-health.yml +32 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/.github/workflows/publish.yml +15 -1
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/.gitignore +2 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/PKG-INFO +7 -2
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/pyproject.toml +6 -1
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/scripts/README.md +3 -0
- codex_a2a-0.6.2/scripts/dependency_health.sh +26 -0
- codex_a2a-0.6.2/scripts/health_common.sh +23 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/scripts/validate_baseline.sh +12 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/stream_interrupts.py +13 -5
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/session_control.py +16 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/session_query.py +16 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/upstream/conversation_facade.py +115 -4
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/upstream/interrupts.py +17 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/upstream/models.py +4 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a.egg-info/PKG-INFO +7 -2
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a.egg-info/SOURCES.txt +5 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a.egg-info/requires.txt +6 -1
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/test_stream_interrupts.py +31 -2
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/jsonrpc/test_codex_session_extension.py +77 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/package/test_release_distribution_contract.py +27 -0
- codex_a2a-0.6.2/tests/scripts/__init__.py +1 -0
- codex_a2a-0.6.2/tests/scripts/test_script_health_contract.py +43 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/upstream/test_codex_client_params.py +105 -1
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/upstream/test_modular_upstream_components.py +3 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/uv.lock +300 -25
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/.pre-commit-config.yaml +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/.secrets.baseline +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/AGENTS.md +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/CONTRIBUTING.md +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/LICENSE +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/README.md +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/SECURITY.md +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/docs/architecture.md +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/docs/compatibility.md +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/docs/extension-specifications.md +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/docs/guide.md +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/docs/maintainer-architecture.md +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/mypy.ini +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/scripts/publish_github_release.sh +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/scripts/smoke_test_built_cli.sh +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/scripts/sync_codex_docs.sh +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/scripts/validate_runtime_matrix.sh +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/setup.cfg +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/__init__.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/auth.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/cli.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/client/__init__.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/client/agent_card.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/client/auth.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/client/client.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/client/config.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/client/errors.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/client/manager.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/client/payload_text.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/client/request_context.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/client/types.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/config.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/contracts/__init__.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/contracts/extensions.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/contracts/runtime_output.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/__init__.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/cancellation.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/directory_policy.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/discovery_runtime.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/exec_runtime.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/executor.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/output_mapping.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/request_metadata.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/request_overrides.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/response_emitter.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/review_runtime.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/session_runtime.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/stream_chunks.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/stream_processor.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/stream_state.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/streaming.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/thread_lifecycle_runtime.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/tool_call_payloads.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/input_mapping.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/__init__.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/application.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/control_params.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/discovery_control.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/discovery_params.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/discovery_payload_mapping.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/discovery_query.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/dispatch.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/errors.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/exec_control.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/hooks.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/interrupt_lifecycle.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/interrupt_params.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/interrupt_recovery.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/interrupt_recovery_params.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/interrupts.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/params.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/params_common.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/payload_mapping.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/query_params.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/review_control.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/review_control_params.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/thread_lifecycle_control.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/thread_lifecycle_params.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/turn_control.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/turn_control_params.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/logging_context.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/media_modes.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/metrics.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/parts/text.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/profile/__init__.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/profile/runtime.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/py.typed +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/server/__init__.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/server/agent_card.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/server/application.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/server/call_context.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/server/database.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/server/http_middlewares.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/server/migrations.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/server/openapi.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/server/output_negotiation.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/server/request_handler.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/server/runtime_state.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/server/task_store.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/upstream/__init__.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/upstream/client.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/upstream/exec_facade.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/upstream/interrupt_bridge.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/upstream/notification_mapping.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/upstream/request_mapping.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/upstream/startup.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/upstream/stream_bridge.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/upstream/transport.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a.egg-info/dependency_links.txt +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a.egg-info/entry_points.txt +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a.egg-info/top_level.txt +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/__init__.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/client/__init__.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/client/test_agent_card.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/client/test_cli.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/client/test_client_flow.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/client/test_client_manager.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/client/test_errors.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/client/test_lifecycle.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/client/test_payload_text.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/client/test_request_context.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/client/test_types.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/config/__init__.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/config/test_settings.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/contracts/__init__.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/contracts/test_extension_contract_consistency.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/__init__.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/test_agent_errors.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/test_cancellation.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/test_codex_agent_session_binding.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/test_directory_validation.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/test_discovery_exec_runtime.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/test_metrics.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/test_review_runtime.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/test_session_ownership.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/test_session_persistence.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/test_session_runtime.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/test_stream_chunks.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/test_streaming_output_contract.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/test_thread_lifecycle_runtime.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/test_tool_call_payloads.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/fixtures/codex_app_server/command_execution_output_delta.json +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/fixtures/codex_app_server/file_change_output_delta.json +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/jsonrpc/__init__.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/jsonrpc/test_codex_discovery_extension.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/jsonrpc/test_codex_exec_extension.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/jsonrpc/test_codex_thread_lifecycle_extension.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/jsonrpc/test_codex_turn_review_extension.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/jsonrpc/test_dispatch.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/jsonrpc/test_guard_hooks.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/jsonrpc/test_jsonrpc_models.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/package/__init__.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/package/test_logging.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/package/test_publish_github_release_script.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/package/test_typing_contract.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/package/test_version.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/parts/__init__.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/parts/test_text.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/profile/__init__.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/profile/test_profile.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/server/__init__.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/server/test_agent_card.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/server/test_auth.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/server/test_call_context_builder.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/server/test_cli.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/server/test_database.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/server/test_database_app_persistence.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/server/test_migrations.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/server/test_request_handler.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/server/test_runtime_state.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/server/test_task_store.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/server/test_transport_contract.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/support/__init__.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/support/context.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/support/dummy_clients.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/support/fixtures.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/support/settings.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/test_input_mapping.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/upstream/__init__.py +0 -0
- {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/upstream/test_interrupt_persistence.py +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
name:
|
|
1
|
+
name: Validation
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
4
|
pull_request:
|
|
@@ -11,6 +11,7 @@ permissions:
|
|
|
11
11
|
|
|
12
12
|
jobs:
|
|
13
13
|
quality-gate:
|
|
14
|
+
name: Validation Baseline
|
|
14
15
|
runs-on: ubuntu-latest
|
|
15
16
|
|
|
16
17
|
steps:
|
|
@@ -34,6 +35,7 @@ jobs:
|
|
|
34
35
|
run: bash ./scripts/validate_baseline.sh
|
|
35
36
|
|
|
36
37
|
runtime-matrix:
|
|
38
|
+
name: Runtime Matrix (Python ${{ matrix.python-version }})
|
|
37
39
|
runs-on: ubuntu-latest
|
|
38
40
|
strategy:
|
|
39
41
|
fail-fast: false
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: Dependency Health
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
schedule:
|
|
6
|
+
# 03:00 UTC on day-of-month 1
|
|
7
|
+
- cron: "0 3 1 * *"
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
dependency-health:
|
|
14
|
+
name: Dependency Health Audit
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- name: Checkout
|
|
19
|
+
uses: actions/checkout@v5
|
|
20
|
+
|
|
21
|
+
- name: Setup Python
|
|
22
|
+
uses: actions/setup-python@v6
|
|
23
|
+
with:
|
|
24
|
+
python-version: "3.13"
|
|
25
|
+
|
|
26
|
+
- name: Setup uv
|
|
27
|
+
uses: astral-sh/setup-uv@v7
|
|
28
|
+
with:
|
|
29
|
+
enable-cache: false
|
|
30
|
+
|
|
31
|
+
- name: Run dependency health checks
|
|
32
|
+
run: bash ./scripts/dependency_health.sh
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
name: Publish
|
|
1
|
+
name: Release Publish
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
4
|
push:
|
|
@@ -18,6 +18,7 @@ on:
|
|
|
18
18
|
|
|
19
19
|
jobs:
|
|
20
20
|
build_release_artifacts:
|
|
21
|
+
name: Build Release Artifacts
|
|
21
22
|
runs-on: ubuntu-latest
|
|
22
23
|
permissions:
|
|
23
24
|
contents: read
|
|
@@ -42,6 +43,17 @@ jobs:
|
|
|
42
43
|
with:
|
|
43
44
|
enable-cache: true
|
|
44
45
|
|
|
46
|
+
- name: Sync dependencies
|
|
47
|
+
run: uv sync --all-extras --frozen
|
|
48
|
+
|
|
49
|
+
- name: Export runtime requirements for vulnerability audit
|
|
50
|
+
run: >
|
|
51
|
+
uv export --format requirements.txt --no-dev --locked --no-emit-project
|
|
52
|
+
--output-file /tmp/runtime-requirements.txt >/dev/null
|
|
53
|
+
|
|
54
|
+
- name: Run runtime dependency vulnerability audit
|
|
55
|
+
run: uv run pip-audit --requirement /tmp/runtime-requirements.txt
|
|
56
|
+
|
|
45
57
|
- name: Resolve release tag
|
|
46
58
|
id: release_tag
|
|
47
59
|
run: echo "tag=${RELEASE_TAG}" >> "$GITHUB_OUTPUT"
|
|
@@ -103,6 +115,7 @@ jobs:
|
|
|
103
115
|
if-no-files-found: error
|
|
104
116
|
|
|
105
117
|
publish_pypi:
|
|
118
|
+
name: Publish to PyPI
|
|
106
119
|
runs-on: ubuntu-latest
|
|
107
120
|
needs: build_release_artifacts
|
|
108
121
|
if: github.event_name == 'push' || inputs.publish_to_pypi
|
|
@@ -120,6 +133,7 @@ jobs:
|
|
|
120
133
|
uses: pypa/gh-action-pypi-publish@release/v1
|
|
121
134
|
|
|
122
135
|
publish_github_release:
|
|
136
|
+
name: Sync GitHub Release
|
|
123
137
|
runs-on: ubuntu-latest
|
|
124
138
|
needs:
|
|
125
139
|
- build_release_artifacts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codex-a2a
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.2
|
|
4
4
|
Summary: Codex A2A runtime adapter
|
|
5
5
|
Author: liujuanjuan1984@Intelligent-Internet
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -24,15 +24,20 @@ Description-Content-Type: text/markdown
|
|
|
24
24
|
License-File: LICENSE
|
|
25
25
|
Requires-Dist: a2a-sdk==0.3.25
|
|
26
26
|
Requires-Dist: aiosqlite<1.0,>=0.20
|
|
27
|
-
Requires-Dist: fastapi<0.
|
|
27
|
+
Requires-Dist: fastapi<0.122,>=0.121
|
|
28
28
|
Requires-Dist: httpx<0.29,>=0.28.1
|
|
29
|
+
Requires-Dist: protobuf<7.0,>=6.33.5
|
|
30
|
+
Requires-Dist: pyasn1<1.0,>=0.6.3
|
|
29
31
|
Requires-Dist: pydantic<3.0,>=2.6
|
|
30
32
|
Requires-Dist: pydantic-settings<3.0,>=2.2
|
|
33
|
+
Requires-Dist: requests<3.0,>=2.33.0
|
|
31
34
|
Requires-Dist: sqlalchemy<3.0,>=2.0
|
|
32
35
|
Requires-Dist: sse-starlette<3.0,>=2.1
|
|
33
36
|
Requires-Dist: uvicorn<0.30,>=0.29
|
|
34
37
|
Provides-Extra: dev
|
|
38
|
+
Requires-Dist: pip-audit<3.0,>=2.9; extra == "dev"
|
|
35
39
|
Requires-Dist: pre-commit>=3.7; extra == "dev"
|
|
40
|
+
Requires-Dist: pygments<3.0,>=2.20.0; extra == "dev"
|
|
36
41
|
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
37
42
|
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
|
|
38
43
|
Requires-Dist: pytest-cov<8.0,>=5.0; extra == "dev"
|
|
@@ -26,10 +26,13 @@ classifiers = [
|
|
|
26
26
|
dependencies = [
|
|
27
27
|
"a2a-sdk==0.3.25",
|
|
28
28
|
"aiosqlite>=0.20,<1.0",
|
|
29
|
-
"fastapi>=0.
|
|
29
|
+
"fastapi>=0.121,<0.122",
|
|
30
30
|
"httpx>=0.28.1,<0.29",
|
|
31
|
+
"protobuf>=6.33.5,<7.0",
|
|
32
|
+
"pyasn1>=0.6.3,<1.0",
|
|
31
33
|
"pydantic>=2.6,<3.0",
|
|
32
34
|
"pydantic-settings>=2.2,<3.0",
|
|
35
|
+
"requests>=2.33.0,<3.0",
|
|
33
36
|
"sqlalchemy>=2.0,<3.0",
|
|
34
37
|
"sse-starlette>=2.1,<3.0",
|
|
35
38
|
"uvicorn>=0.29,<0.30",
|
|
@@ -37,7 +40,9 @@ dependencies = [
|
|
|
37
40
|
|
|
38
41
|
[project.optional-dependencies]
|
|
39
42
|
dev = [
|
|
43
|
+
"pip-audit>=2.9,<3.0",
|
|
40
44
|
"pre-commit>=3.7",
|
|
45
|
+
"pygments>=2.20.0,<3.0",
|
|
41
46
|
"pytest>=8.0",
|
|
42
47
|
"pytest-asyncio>=0.23",
|
|
43
48
|
"pytest-cov>=5.0,<8.0",
|
|
@@ -14,6 +14,7 @@ This document only explains the remaining repository-local maintainer scripts. U
|
|
|
14
14
|
|
|
15
15
|
- [`scripts/validate_baseline.sh`](./validate_baseline.sh): run the default local validation baseline used by contributors and CI.
|
|
16
16
|
- [`scripts/validate_runtime_matrix.sh`](./validate_runtime_matrix.sh): run the reduced runtime-only validation used by the multi-version CI matrix.
|
|
17
|
+
- [`scripts/dependency_health.sh`](./dependency_health.sh): run the standalone dependency review flow (`sync`/`pip check`, outdated package listing, and dev vulnerability audit).
|
|
17
18
|
- [`scripts/smoke_test_built_cli.sh`](./smoke_test_built_cli.sh): validate that a built wheel can be installed through `uv tool` and becomes healthy.
|
|
18
19
|
- [`scripts/sync_codex_docs.sh`](./sync_codex_docs.sh): refresh local upstream Codex reference snapshots when maintainers need them.
|
|
19
20
|
|
|
@@ -27,5 +28,7 @@ The `Publish` workflow now separates build, PyPI publish, and GitHub Release syn
|
|
|
27
28
|
|
|
28
29
|
## Notes
|
|
29
30
|
|
|
31
|
+
- `validate_baseline.sh` and `dependency_health.sh` intentionally remain separate entrypoints and share common prerequisites through [`health_common.sh`](./health_common.sh).
|
|
32
|
+
- `validate_baseline.sh` now blocks on runtime dependency vulnerability audit, while `dependency_health.sh` remains focused on broader dependency review (`outdated` + dev audit).
|
|
30
33
|
- 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).
|
|
31
34
|
- Keep long-form documentation changes in `docs/` to avoid divergence.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Run the standalone dependency health checks used by the dedicated workflow.
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
# shellcheck source=./health_common.sh
|
|
6
|
+
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/health_common.sh"
|
|
7
|
+
|
|
8
|
+
run_shared_repo_health_prerequisites "dependency-health"
|
|
9
|
+
|
|
10
|
+
echo "[dependency-health] list outdated packages"
|
|
11
|
+
uv pip list --outdated
|
|
12
|
+
|
|
13
|
+
dev_requirements="$(mktemp)"
|
|
14
|
+
trap 'rm -f "${dev_requirements}"' EXIT
|
|
15
|
+
|
|
16
|
+
echo "[dependency-health] export dev extra requirements"
|
|
17
|
+
uv export \
|
|
18
|
+
--format requirements.txt \
|
|
19
|
+
--extra dev \
|
|
20
|
+
--no-dev \
|
|
21
|
+
--locked \
|
|
22
|
+
--no-emit-project \
|
|
23
|
+
--output-file "${dev_requirements}" >/dev/null
|
|
24
|
+
|
|
25
|
+
echo "[dependency-health] run dev dependency vulnerability audit"
|
|
26
|
+
uv run pip-audit --requirement "${dev_requirements}"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Shared prerequisites for repository health-check scripts.
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
6
|
+
ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
|
7
|
+
|
|
8
|
+
run_shared_repo_health_prerequisites() {
|
|
9
|
+
local label="${1:-health}"
|
|
10
|
+
|
|
11
|
+
cd "$ROOT_DIR"
|
|
12
|
+
|
|
13
|
+
if ! command -v uv >/dev/null 2>&1; then
|
|
14
|
+
echo "uv not found in PATH" >&2
|
|
15
|
+
exit 1
|
|
16
|
+
fi
|
|
17
|
+
|
|
18
|
+
echo "[${label}] sync locked environment"
|
|
19
|
+
uv sync --all-extras --frozen
|
|
20
|
+
|
|
21
|
+
echo "[${label}] verify dependency compatibility"
|
|
22
|
+
uv pip check
|
|
23
|
+
}
|
|
@@ -11,6 +11,18 @@ uv run pre-commit run --all-files
|
|
|
11
11
|
uv run mypy --config-file mypy.ini
|
|
12
12
|
uv run pytest
|
|
13
13
|
|
|
14
|
+
runtime_requirements="$(mktemp)"
|
|
15
|
+
trap 'rm -f "${runtime_requirements}"' EXIT
|
|
16
|
+
|
|
17
|
+
uv export \
|
|
18
|
+
--format requirements.txt \
|
|
19
|
+
--no-dev \
|
|
20
|
+
--locked \
|
|
21
|
+
--no-emit-project \
|
|
22
|
+
--output-file "${runtime_requirements}" >/dev/null
|
|
23
|
+
|
|
24
|
+
uv run pip-audit --requirement "${runtime_requirements}"
|
|
25
|
+
|
|
14
26
|
rm -f dist/codex_a2a-*.whl dist/codex_a2a-*.tar.gz
|
|
15
27
|
build_warning_filters="ignore::UserWarning:vcs_versioning._backends._git,ignore::UserWarning:vcs_versioning.overrides"
|
|
16
28
|
PYTHONWARNINGS="${build_warning_filters}${PYTHONWARNINGS:+,${PYTHONWARNINGS}}" uv build --no-sources
|
|
@@ -3,6 +3,8 @@ from __future__ import annotations
|
|
|
3
3
|
from collections.abc import Mapping
|
|
4
4
|
from typing import Any
|
|
5
5
|
|
|
6
|
+
from codex_a2a.upstream.interrupts import resolve_permission_interrupt_semantic
|
|
7
|
+
|
|
6
8
|
_INTERRUPT_ASKED_EVENT_TYPES = {
|
|
7
9
|
"permission.asked",
|
|
8
10
|
"question.asked",
|
|
@@ -189,12 +191,18 @@ def extract_interrupt_asked_event(event: Mapping[str, Any]) -> dict[str, Any] |
|
|
|
189
191
|
if not normalized_request_id:
|
|
190
192
|
return None
|
|
191
193
|
if event_type == "permission.asked":
|
|
192
|
-
|
|
193
|
-
|
|
194
|
+
permission = _first_nested_string(
|
|
195
|
+
props,
|
|
196
|
+
("permission",),
|
|
197
|
+
("metadata", "raw", "permission"),
|
|
198
|
+
) or resolve_permission_interrupt_semantic(
|
|
199
|
+
_first_nested_string(
|
|
194
200
|
props,
|
|
195
|
-
("
|
|
196
|
-
|
|
197
|
-
|
|
201
|
+
("metadata", "method"),
|
|
202
|
+
)
|
|
203
|
+
)
|
|
204
|
+
details: dict[str, Any] = {
|
|
205
|
+
"permission": permission,
|
|
198
206
|
"patterns": extract_interrupt_patterns(props),
|
|
199
207
|
"always": extract_string_list(_nested_value(props, "always"))
|
|
200
208
|
or extract_string_list(_nested_value(props, "metadata", "raw", "always")),
|
|
@@ -35,6 +35,7 @@ from codex_a2a.jsonrpc.payload_mapping import (
|
|
|
35
35
|
as_a2a_message,
|
|
36
36
|
message_to_item,
|
|
37
37
|
)
|
|
38
|
+
from codex_a2a.upstream.models import CodexRPCError, is_thread_not_found_error
|
|
38
39
|
|
|
39
40
|
if TYPE_CHECKING:
|
|
40
41
|
from codex_a2a.jsonrpc.application import CodexSessionQueryJSONRPCApplication
|
|
@@ -187,6 +188,21 @@ async def handle_session_control_request(
|
|
|
187
188
|
data={"type": "UPSTREAM_UNREACHABLE", "session_id": session_id},
|
|
188
189
|
),
|
|
189
190
|
)
|
|
191
|
+
except CodexRPCError as exc:
|
|
192
|
+
if is_thread_not_found_error(exc):
|
|
193
|
+
return app._generate_error_response(
|
|
194
|
+
base_request.id,
|
|
195
|
+
JSONRPCError(
|
|
196
|
+
code=ERR_SESSION_NOT_FOUND,
|
|
197
|
+
message="Session not found",
|
|
198
|
+
data={"type": "SESSION_NOT_FOUND", "session_id": session_id},
|
|
199
|
+
),
|
|
200
|
+
)
|
|
201
|
+
logger.exception("Codex session control JSON-RPC method failed")
|
|
202
|
+
return app._generate_error_response(
|
|
203
|
+
base_request.id,
|
|
204
|
+
A2AError(root=InternalError(message=str(exc))),
|
|
205
|
+
)
|
|
190
206
|
except Exception as exc:
|
|
191
207
|
logger.exception("Codex session control JSON-RPC method failed")
|
|
192
208
|
return app._generate_error_response(
|
|
@@ -24,6 +24,7 @@ from codex_a2a.jsonrpc.payload_mapping import (
|
|
|
24
24
|
as_a2a_session_task,
|
|
25
25
|
extract_raw_items,
|
|
26
26
|
)
|
|
27
|
+
from codex_a2a.upstream.models import CodexRPCError, is_thread_not_found_error
|
|
27
28
|
|
|
28
29
|
if TYPE_CHECKING:
|
|
29
30
|
from codex_a2a.jsonrpc.application import CodexSessionQueryJSONRPCApplication
|
|
@@ -81,6 +82,21 @@ async def handle_session_query_request(
|
|
|
81
82
|
data={"type": "UPSTREAM_UNREACHABLE"},
|
|
82
83
|
),
|
|
83
84
|
)
|
|
85
|
+
except CodexRPCError as exc:
|
|
86
|
+
if is_thread_not_found_error(exc) and session_id is not None:
|
|
87
|
+
return app._generate_error_response(
|
|
88
|
+
base_request.id,
|
|
89
|
+
JSONRPCError(
|
|
90
|
+
code=ERR_SESSION_NOT_FOUND,
|
|
91
|
+
message="Session not found",
|
|
92
|
+
data={"type": "SESSION_NOT_FOUND", "session_id": session_id},
|
|
93
|
+
),
|
|
94
|
+
)
|
|
95
|
+
logger.exception("Codex session query JSON-RPC method failed")
|
|
96
|
+
return app._generate_error_response(
|
|
97
|
+
base_request.id,
|
|
98
|
+
A2AError(root=InternalError(message=str(exc))),
|
|
99
|
+
)
|
|
84
100
|
except Exception as exc:
|
|
85
101
|
logger.exception("Codex session query JSON-RPC method failed")
|
|
86
102
|
return app._generate_error_response(
|
|
@@ -7,7 +7,12 @@ from typing import Any
|
|
|
7
7
|
|
|
8
8
|
from codex_a2a.execution.request_overrides import RequestExecutionOptions
|
|
9
9
|
from codex_a2a.input_mapping import build_turn_input_from_normalized_items
|
|
10
|
-
from codex_a2a.upstream.models import
|
|
10
|
+
from codex_a2a.upstream.models import (
|
|
11
|
+
CodexMessage,
|
|
12
|
+
CodexRPCError,
|
|
13
|
+
_TurnTracker,
|
|
14
|
+
is_thread_not_found_error,
|
|
15
|
+
)
|
|
11
16
|
from codex_a2a.upstream.request_mapping import (
|
|
12
17
|
apply_thread_start_execution_options,
|
|
13
18
|
apply_turn_start_execution_options,
|
|
@@ -37,6 +42,8 @@ class CodexConversationFacade:
|
|
|
37
42
|
self._rpc_request = rpc_request
|
|
38
43
|
self._get_or_create_tracker = get_or_create_tracker
|
|
39
44
|
self._turn_trackers = turn_trackers
|
|
45
|
+
self._loaded_thread_ids: set[str] = set()
|
|
46
|
+
self._thread_resume_locks: dict[str, asyncio.Lock] = {}
|
|
40
47
|
|
|
41
48
|
async def create_session(
|
|
42
49
|
self,
|
|
@@ -67,7 +74,9 @@ class CodexConversationFacade:
|
|
|
67
74
|
session_id = thread.get("id")
|
|
68
75
|
if not isinstance(session_id, str) or not session_id.strip():
|
|
69
76
|
raise RuntimeError("codex thread/start response missing thread id")
|
|
70
|
-
|
|
77
|
+
session_id = session_id.strip()
|
|
78
|
+
self._loaded_thread_ids.add(session_id)
|
|
79
|
+
return session_id
|
|
71
80
|
|
|
72
81
|
async def list_sessions(self, *, query: dict[str, Any]) -> list[dict[str, Any]]:
|
|
73
82
|
rpc_params: dict[str, Any] = {}
|
|
@@ -98,6 +107,7 @@ class CodexConversationFacade:
|
|
|
98
107
|
thread = normalize_thread_summary(result.get("thread"))
|
|
99
108
|
if thread is None:
|
|
100
109
|
raise RuntimeError("codex thread/fork response missing thread")
|
|
110
|
+
self._loaded_thread_ids.add(thread["id"])
|
|
101
111
|
return thread
|
|
102
112
|
|
|
103
113
|
async def thread_archive(self, thread_id: str) -> None:
|
|
@@ -113,6 +123,7 @@ class CodexConversationFacade:
|
|
|
113
123
|
thread = normalize_thread_summary(result.get("thread"))
|
|
114
124
|
if thread is None:
|
|
115
125
|
raise RuntimeError("codex thread/unarchive response missing thread")
|
|
126
|
+
self._loaded_thread_ids.add(thread["id"])
|
|
116
127
|
return thread
|
|
117
128
|
|
|
118
129
|
async def thread_metadata_update(
|
|
@@ -216,7 +227,12 @@ class CodexConversationFacade:
|
|
|
216
227
|
default_model_id=self._model_id,
|
|
217
228
|
)
|
|
218
229
|
|
|
219
|
-
result = await self.
|
|
230
|
+
result = await self._start_turn(
|
|
231
|
+
session_id,
|
|
232
|
+
params,
|
|
233
|
+
directory=directory,
|
|
234
|
+
execution_options=execution_options,
|
|
235
|
+
)
|
|
220
236
|
if not isinstance(result, dict):
|
|
221
237
|
raise RuntimeError("codex turn/start response missing result object")
|
|
222
238
|
turn = result.get("turn")
|
|
@@ -268,7 +284,12 @@ class CodexConversationFacade:
|
|
|
268
284
|
execution_options=coerce_request_execution_options(execution_options),
|
|
269
285
|
default_model_id=self._model_id,
|
|
270
286
|
)
|
|
271
|
-
result = await self.
|
|
287
|
+
result = await self._start_turn(
|
|
288
|
+
session_id,
|
|
289
|
+
params,
|
|
290
|
+
directory=directory,
|
|
291
|
+
execution_options=execution_options,
|
|
292
|
+
)
|
|
272
293
|
if not isinstance(result, dict):
|
|
273
294
|
raise RuntimeError("codex turn/start response missing result object")
|
|
274
295
|
turn = result.get("turn")
|
|
@@ -279,6 +300,96 @@ class CodexConversationFacade:
|
|
|
279
300
|
raise RuntimeError("codex turn/start response missing turn id")
|
|
280
301
|
return {"ok": True, "session_id": session_id, "turn_id": turn_id.strip()}
|
|
281
302
|
|
|
303
|
+
async def _start_turn(
|
|
304
|
+
self,
|
|
305
|
+
session_id: str,
|
|
306
|
+
params: dict[str, Any],
|
|
307
|
+
*,
|
|
308
|
+
directory: str | None,
|
|
309
|
+
execution_options: RequestExecutionOptions | None,
|
|
310
|
+
) -> Any:
|
|
311
|
+
await self._ensure_thread_loaded(
|
|
312
|
+
session_id,
|
|
313
|
+
directory=directory,
|
|
314
|
+
execution_options=execution_options,
|
|
315
|
+
)
|
|
316
|
+
try:
|
|
317
|
+
result = await self._rpc_request("turn/start", params)
|
|
318
|
+
except CodexRPCError as exc:
|
|
319
|
+
if not is_thread_not_found_error(exc):
|
|
320
|
+
raise
|
|
321
|
+
self._loaded_thread_ids.discard(session_id)
|
|
322
|
+
await self._ensure_thread_loaded(
|
|
323
|
+
session_id,
|
|
324
|
+
directory=directory,
|
|
325
|
+
execution_options=execution_options,
|
|
326
|
+
force_resume=True,
|
|
327
|
+
)
|
|
328
|
+
result = await self._rpc_request("turn/start", params)
|
|
329
|
+
self._loaded_thread_ids.add(session_id)
|
|
330
|
+
return result
|
|
331
|
+
|
|
332
|
+
async def _ensure_thread_loaded(
|
|
333
|
+
self,
|
|
334
|
+
session_id: str,
|
|
335
|
+
*,
|
|
336
|
+
directory: str | None,
|
|
337
|
+
execution_options: RequestExecutionOptions | None,
|
|
338
|
+
force_resume: bool = False,
|
|
339
|
+
) -> None:
|
|
340
|
+
if not force_resume and session_id in self._loaded_thread_ids:
|
|
341
|
+
return
|
|
342
|
+
|
|
343
|
+
lock = self._thread_resume_locks.setdefault(session_id, asyncio.Lock())
|
|
344
|
+
async with lock:
|
|
345
|
+
if not force_resume and session_id in self._loaded_thread_ids:
|
|
346
|
+
return
|
|
347
|
+
|
|
348
|
+
if not force_resume:
|
|
349
|
+
loaded_threads = await self._list_loaded_thread_ids()
|
|
350
|
+
self._loaded_thread_ids.update(loaded_threads)
|
|
351
|
+
if session_id in self._loaded_thread_ids:
|
|
352
|
+
return
|
|
353
|
+
|
|
354
|
+
await self._resume_thread(
|
|
355
|
+
session_id,
|
|
356
|
+
directory=directory,
|
|
357
|
+
execution_options=execution_options,
|
|
358
|
+
)
|
|
359
|
+
self._loaded_thread_ids.add(session_id)
|
|
360
|
+
|
|
361
|
+
async def _list_loaded_thread_ids(self) -> set[str]:
|
|
362
|
+
result = await self._rpc_request("thread/loaded/list", {})
|
|
363
|
+
if not isinstance(result, dict):
|
|
364
|
+
return set()
|
|
365
|
+
data = result.get("data")
|
|
366
|
+
if not isinstance(data, list):
|
|
367
|
+
return set()
|
|
368
|
+
loaded: set[str] = set()
|
|
369
|
+
for item in data:
|
|
370
|
+
if isinstance(item, str) and item.strip():
|
|
371
|
+
loaded.add(item.strip())
|
|
372
|
+
return loaded
|
|
373
|
+
|
|
374
|
+
async def _resume_thread(
|
|
375
|
+
self,
|
|
376
|
+
session_id: str,
|
|
377
|
+
*,
|
|
378
|
+
directory: str | None,
|
|
379
|
+
execution_options: RequestExecutionOptions | None,
|
|
380
|
+
) -> Any:
|
|
381
|
+
params: dict[str, Any] = {"threadId": session_id}
|
|
382
|
+
if directory:
|
|
383
|
+
params["cwd"] = directory
|
|
384
|
+
elif self._workspace_root:
|
|
385
|
+
params["cwd"] = self._workspace_root
|
|
386
|
+
apply_thread_start_execution_options(
|
|
387
|
+
params,
|
|
388
|
+
execution_options=coerce_request_execution_options(execution_options),
|
|
389
|
+
default_model_id=self._model_id,
|
|
390
|
+
)
|
|
391
|
+
return await self._rpc_request("thread/resume", params)
|
|
392
|
+
|
|
282
393
|
async def turn_steer(
|
|
283
394
|
self,
|
|
284
395
|
thread_id: str,
|
|
@@ -5,6 +5,13 @@ from collections.abc import Mapping
|
|
|
5
5
|
from dataclasses import dataclass
|
|
6
6
|
from typing import Any
|
|
7
7
|
|
|
8
|
+
_PERMISSION_INTERRUPT_METHOD_MAP = {
|
|
9
|
+
"item/commandExecution/requestApproval": "command_execution",
|
|
10
|
+
"execCommandApproval": "command_execution",
|
|
11
|
+
"item/fileChange/requestApproval": "file_change",
|
|
12
|
+
"applyPatchApproval": "apply_patch",
|
|
13
|
+
}
|
|
14
|
+
|
|
8
15
|
|
|
9
16
|
def _normalized_string(value: Any) -> str | None:
|
|
10
17
|
if not isinstance(value, str):
|
|
@@ -87,6 +94,13 @@ def _extract_mapping(params: dict[str, Any], key: str) -> dict[str, Any] | None:
|
|
|
87
94
|
return dict(value)
|
|
88
95
|
|
|
89
96
|
|
|
97
|
+
def resolve_permission_interrupt_semantic(method: str | None) -> str | None:
|
|
98
|
+
normalized_method = _normalized_string(method)
|
|
99
|
+
if normalized_method is None:
|
|
100
|
+
return None
|
|
101
|
+
return _PERMISSION_INTERRUPT_METHOD_MAP.get(normalized_method)
|
|
102
|
+
|
|
103
|
+
|
|
90
104
|
class InterruptRequestError(RuntimeError):
|
|
91
105
|
def __init__(
|
|
92
106
|
self,
|
|
@@ -149,6 +163,9 @@ def build_codex_permission_interrupt_properties(
|
|
|
149
163
|
)
|
|
150
164
|
if display_message is not None:
|
|
151
165
|
properties["display_message"] = display_message
|
|
166
|
+
permission = resolve_permission_interrupt_semantic(method)
|
|
167
|
+
if permission is not None:
|
|
168
|
+
properties["permission"] = permission
|
|
152
169
|
patterns = _extract_permission_patterns(params)
|
|
153
170
|
if patterns:
|
|
154
171
|
properties["patterns"] = patterns
|
|
@@ -24,6 +24,10 @@ class CodexRPCError(RuntimeError):
|
|
|
24
24
|
self.data = data
|
|
25
25
|
|
|
26
26
|
|
|
27
|
+
def is_thread_not_found_error(exc: BaseException) -> bool:
|
|
28
|
+
return isinstance(exc, CodexRPCError) and "thread not found" in str(exc).strip().lower()
|
|
29
|
+
|
|
30
|
+
|
|
27
31
|
@dataclass
|
|
28
32
|
class _PendingRpcRequest:
|
|
29
33
|
request_id: str
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codex-a2a
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.2
|
|
4
4
|
Summary: Codex A2A runtime adapter
|
|
5
5
|
Author: liujuanjuan1984@Intelligent-Internet
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -24,15 +24,20 @@ Description-Content-Type: text/markdown
|
|
|
24
24
|
License-File: LICENSE
|
|
25
25
|
Requires-Dist: a2a-sdk==0.3.25
|
|
26
26
|
Requires-Dist: aiosqlite<1.0,>=0.20
|
|
27
|
-
Requires-Dist: fastapi<0.
|
|
27
|
+
Requires-Dist: fastapi<0.122,>=0.121
|
|
28
28
|
Requires-Dist: httpx<0.29,>=0.28.1
|
|
29
|
+
Requires-Dist: protobuf<7.0,>=6.33.5
|
|
30
|
+
Requires-Dist: pyasn1<1.0,>=0.6.3
|
|
29
31
|
Requires-Dist: pydantic<3.0,>=2.6
|
|
30
32
|
Requires-Dist: pydantic-settings<3.0,>=2.2
|
|
33
|
+
Requires-Dist: requests<3.0,>=2.33.0
|
|
31
34
|
Requires-Dist: sqlalchemy<3.0,>=2.0
|
|
32
35
|
Requires-Dist: sse-starlette<3.0,>=2.1
|
|
33
36
|
Requires-Dist: uvicorn<0.30,>=0.29
|
|
34
37
|
Provides-Extra: dev
|
|
38
|
+
Requires-Dist: pip-audit<3.0,>=2.9; extra == "dev"
|
|
35
39
|
Requires-Dist: pre-commit>=3.7; extra == "dev"
|
|
40
|
+
Requires-Dist: pygments<3.0,>=2.20.0; extra == "dev"
|
|
36
41
|
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
37
42
|
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
|
|
38
43
|
Requires-Dist: pytest-cov<8.0,>=5.0; extra == "dev"
|
|
@@ -10,6 +10,7 @@ mypy.ini
|
|
|
10
10
|
pyproject.toml
|
|
11
11
|
uv.lock
|
|
12
12
|
.github/workflows/ci.yml
|
|
13
|
+
.github/workflows/dependency-health.yml
|
|
13
14
|
.github/workflows/publish.yml
|
|
14
15
|
docs/architecture.md
|
|
15
16
|
docs/compatibility.md
|
|
@@ -17,6 +18,8 @@ docs/extension-specifications.md
|
|
|
17
18
|
docs/guide.md
|
|
18
19
|
docs/maintainer-architecture.md
|
|
19
20
|
scripts/README.md
|
|
21
|
+
scripts/dependency_health.sh
|
|
22
|
+
scripts/health_common.sh
|
|
20
23
|
scripts/publish_github_release.sh
|
|
21
24
|
scripts/smoke_test_built_cli.sh
|
|
22
25
|
scripts/sync_codex_docs.sh
|
|
@@ -177,6 +180,8 @@ tests/parts/__init__.py
|
|
|
177
180
|
tests/parts/test_text.py
|
|
178
181
|
tests/profile/__init__.py
|
|
179
182
|
tests/profile/test_profile.py
|
|
183
|
+
tests/scripts/__init__.py
|
|
184
|
+
tests/scripts/test_script_health_contract.py
|
|
180
185
|
tests/server/__init__.py
|
|
181
186
|
tests/server/test_agent_card.py
|
|
182
187
|
tests/server/test_auth.py
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
a2a-sdk==0.3.25
|
|
2
2
|
aiosqlite<1.0,>=0.20
|
|
3
|
-
fastapi<0.
|
|
3
|
+
fastapi<0.122,>=0.121
|
|
4
4
|
httpx<0.29,>=0.28.1
|
|
5
|
+
protobuf<7.0,>=6.33.5
|
|
6
|
+
pyasn1<1.0,>=0.6.3
|
|
5
7
|
pydantic<3.0,>=2.6
|
|
6
8
|
pydantic-settings<3.0,>=2.2
|
|
9
|
+
requests<3.0,>=2.33.0
|
|
7
10
|
sqlalchemy<3.0,>=2.0
|
|
8
11
|
sse-starlette<3.0,>=2.1
|
|
9
12
|
uvicorn<0.30,>=0.29
|
|
10
13
|
|
|
11
14
|
[dev]
|
|
15
|
+
pip-audit<3.0,>=2.9
|
|
12
16
|
pre-commit>=3.7
|
|
17
|
+
pygments<3.0,>=2.20.0
|
|
13
18
|
pytest>=8.0
|
|
14
19
|
pytest-asyncio>=0.23
|
|
15
20
|
pytest-cov<8.0,>=5.0
|