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.
Files changed (207) hide show
  1. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/.github/workflows/ci.yml +3 -1
  2. codex_a2a-0.6.2/.github/workflows/dependency-health.yml +32 -0
  3. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/.github/workflows/publish.yml +15 -1
  4. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/.gitignore +2 -0
  5. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/PKG-INFO +7 -2
  6. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/pyproject.toml +6 -1
  7. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/scripts/README.md +3 -0
  8. codex_a2a-0.6.2/scripts/dependency_health.sh +26 -0
  9. codex_a2a-0.6.2/scripts/health_common.sh +23 -0
  10. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/scripts/validate_baseline.sh +12 -0
  11. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/stream_interrupts.py +13 -5
  12. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/session_control.py +16 -0
  13. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/session_query.py +16 -0
  14. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/upstream/conversation_facade.py +115 -4
  15. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/upstream/interrupts.py +17 -0
  16. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/upstream/models.py +4 -0
  17. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a.egg-info/PKG-INFO +7 -2
  18. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a.egg-info/SOURCES.txt +5 -0
  19. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a.egg-info/requires.txt +6 -1
  20. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/test_stream_interrupts.py +31 -2
  21. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/jsonrpc/test_codex_session_extension.py +77 -0
  22. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/package/test_release_distribution_contract.py +27 -0
  23. codex_a2a-0.6.2/tests/scripts/__init__.py +1 -0
  24. codex_a2a-0.6.2/tests/scripts/test_script_health_contract.py +43 -0
  25. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/upstream/test_codex_client_params.py +105 -1
  26. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/upstream/test_modular_upstream_components.py +3 -0
  27. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/uv.lock +300 -25
  28. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/.pre-commit-config.yaml +0 -0
  29. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/.secrets.baseline +0 -0
  30. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/AGENTS.md +0 -0
  31. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/CONTRIBUTING.md +0 -0
  32. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/LICENSE +0 -0
  33. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/README.md +0 -0
  34. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/SECURITY.md +0 -0
  35. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/docs/architecture.md +0 -0
  36. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/docs/compatibility.md +0 -0
  37. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/docs/extension-specifications.md +0 -0
  38. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/docs/guide.md +0 -0
  39. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/docs/maintainer-architecture.md +0 -0
  40. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/mypy.ini +0 -0
  41. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/scripts/publish_github_release.sh +0 -0
  42. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/scripts/smoke_test_built_cli.sh +0 -0
  43. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/scripts/sync_codex_docs.sh +0 -0
  44. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/scripts/validate_runtime_matrix.sh +0 -0
  45. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/setup.cfg +0 -0
  46. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/__init__.py +0 -0
  47. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/auth.py +0 -0
  48. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/cli.py +0 -0
  49. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/client/__init__.py +0 -0
  50. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/client/agent_card.py +0 -0
  51. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/client/auth.py +0 -0
  52. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/client/client.py +0 -0
  53. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/client/config.py +0 -0
  54. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/client/errors.py +0 -0
  55. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/client/manager.py +0 -0
  56. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/client/payload_text.py +0 -0
  57. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/client/request_context.py +0 -0
  58. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/client/types.py +0 -0
  59. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/config.py +0 -0
  60. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/contracts/__init__.py +0 -0
  61. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/contracts/extensions.py +0 -0
  62. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/contracts/runtime_output.py +0 -0
  63. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/__init__.py +0 -0
  64. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/cancellation.py +0 -0
  65. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/directory_policy.py +0 -0
  66. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/discovery_runtime.py +0 -0
  67. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/exec_runtime.py +0 -0
  68. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/executor.py +0 -0
  69. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/output_mapping.py +0 -0
  70. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/request_metadata.py +0 -0
  71. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/request_overrides.py +0 -0
  72. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/response_emitter.py +0 -0
  73. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/review_runtime.py +0 -0
  74. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/session_runtime.py +0 -0
  75. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/stream_chunks.py +0 -0
  76. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/stream_processor.py +0 -0
  77. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/stream_state.py +0 -0
  78. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/streaming.py +0 -0
  79. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/thread_lifecycle_runtime.py +0 -0
  80. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/execution/tool_call_payloads.py +0 -0
  81. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/input_mapping.py +0 -0
  82. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/__init__.py +0 -0
  83. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/application.py +0 -0
  84. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/control_params.py +0 -0
  85. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/discovery_control.py +0 -0
  86. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/discovery_params.py +0 -0
  87. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/discovery_payload_mapping.py +0 -0
  88. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/discovery_query.py +0 -0
  89. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/dispatch.py +0 -0
  90. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/errors.py +0 -0
  91. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/exec_control.py +0 -0
  92. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/hooks.py +0 -0
  93. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/interrupt_lifecycle.py +0 -0
  94. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/interrupt_params.py +0 -0
  95. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/interrupt_recovery.py +0 -0
  96. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/interrupt_recovery_params.py +0 -0
  97. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/interrupts.py +0 -0
  98. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/params.py +0 -0
  99. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/params_common.py +0 -0
  100. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/payload_mapping.py +0 -0
  101. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/query_params.py +0 -0
  102. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/review_control.py +0 -0
  103. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/review_control_params.py +0 -0
  104. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/thread_lifecycle_control.py +0 -0
  105. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/thread_lifecycle_params.py +0 -0
  106. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/turn_control.py +0 -0
  107. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/jsonrpc/turn_control_params.py +0 -0
  108. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/logging_context.py +0 -0
  109. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/media_modes.py +0 -0
  110. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/metrics.py +0 -0
  111. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/parts/text.py +0 -0
  112. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/profile/__init__.py +0 -0
  113. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/profile/runtime.py +0 -0
  114. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/py.typed +0 -0
  115. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/server/__init__.py +0 -0
  116. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/server/agent_card.py +0 -0
  117. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/server/application.py +0 -0
  118. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/server/call_context.py +0 -0
  119. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/server/database.py +0 -0
  120. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/server/http_middlewares.py +0 -0
  121. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/server/migrations.py +0 -0
  122. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/server/openapi.py +0 -0
  123. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/server/output_negotiation.py +0 -0
  124. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/server/request_handler.py +0 -0
  125. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/server/runtime_state.py +0 -0
  126. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/server/task_store.py +0 -0
  127. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/upstream/__init__.py +0 -0
  128. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/upstream/client.py +0 -0
  129. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/upstream/exec_facade.py +0 -0
  130. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/upstream/interrupt_bridge.py +0 -0
  131. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/upstream/notification_mapping.py +0 -0
  132. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/upstream/request_mapping.py +0 -0
  133. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/upstream/startup.py +0 -0
  134. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/upstream/stream_bridge.py +0 -0
  135. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a/upstream/transport.py +0 -0
  136. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a.egg-info/dependency_links.txt +0 -0
  137. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a.egg-info/entry_points.txt +0 -0
  138. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/src/codex_a2a.egg-info/top_level.txt +0 -0
  139. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/__init__.py +0 -0
  140. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/client/__init__.py +0 -0
  141. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/client/test_agent_card.py +0 -0
  142. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/client/test_cli.py +0 -0
  143. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/client/test_client_flow.py +0 -0
  144. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/client/test_client_manager.py +0 -0
  145. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/client/test_errors.py +0 -0
  146. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/client/test_lifecycle.py +0 -0
  147. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/client/test_payload_text.py +0 -0
  148. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/client/test_request_context.py +0 -0
  149. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/client/test_types.py +0 -0
  150. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/config/__init__.py +0 -0
  151. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/config/test_settings.py +0 -0
  152. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/contracts/__init__.py +0 -0
  153. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/contracts/test_extension_contract_consistency.py +0 -0
  154. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/__init__.py +0 -0
  155. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/test_agent_errors.py +0 -0
  156. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/test_cancellation.py +0 -0
  157. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/test_codex_agent_session_binding.py +0 -0
  158. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/test_directory_validation.py +0 -0
  159. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/test_discovery_exec_runtime.py +0 -0
  160. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/test_metrics.py +0 -0
  161. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/test_review_runtime.py +0 -0
  162. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/test_session_ownership.py +0 -0
  163. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/test_session_persistence.py +0 -0
  164. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/test_session_runtime.py +0 -0
  165. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/test_stream_chunks.py +0 -0
  166. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/test_streaming_output_contract.py +0 -0
  167. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/test_thread_lifecycle_runtime.py +0 -0
  168. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/execution/test_tool_call_payloads.py +0 -0
  169. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/fixtures/codex_app_server/command_execution_output_delta.json +0 -0
  170. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/fixtures/codex_app_server/file_change_output_delta.json +0 -0
  171. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/jsonrpc/__init__.py +0 -0
  172. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/jsonrpc/test_codex_discovery_extension.py +0 -0
  173. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/jsonrpc/test_codex_exec_extension.py +0 -0
  174. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/jsonrpc/test_codex_thread_lifecycle_extension.py +0 -0
  175. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/jsonrpc/test_codex_turn_review_extension.py +0 -0
  176. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/jsonrpc/test_dispatch.py +0 -0
  177. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/jsonrpc/test_guard_hooks.py +0 -0
  178. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/jsonrpc/test_jsonrpc_models.py +0 -0
  179. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/package/__init__.py +0 -0
  180. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/package/test_logging.py +0 -0
  181. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/package/test_publish_github_release_script.py +0 -0
  182. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/package/test_typing_contract.py +0 -0
  183. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/package/test_version.py +0 -0
  184. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/parts/__init__.py +0 -0
  185. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/parts/test_text.py +0 -0
  186. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/profile/__init__.py +0 -0
  187. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/profile/test_profile.py +0 -0
  188. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/server/__init__.py +0 -0
  189. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/server/test_agent_card.py +0 -0
  190. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/server/test_auth.py +0 -0
  191. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/server/test_call_context_builder.py +0 -0
  192. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/server/test_cli.py +0 -0
  193. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/server/test_database.py +0 -0
  194. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/server/test_database_app_persistence.py +0 -0
  195. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/server/test_migrations.py +0 -0
  196. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/server/test_request_handler.py +0 -0
  197. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/server/test_runtime_state.py +0 -0
  198. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/server/test_task_store.py +0 -0
  199. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/server/test_transport_contract.py +0 -0
  200. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/support/__init__.py +0 -0
  201. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/support/context.py +0 -0
  202. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/support/dummy_clients.py +0 -0
  203. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/support/fixtures.py +0 -0
  204. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/support/settings.py +0 -0
  205. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/test_input_mapping.py +0 -0
  206. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/upstream/__init__.py +0 -0
  207. {codex_a2a-0.6.0 → codex_a2a-0.6.2}/tests/upstream/test_interrupt_persistence.py +0 -0
@@ -1,4 +1,4 @@
1
- name: CI
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
@@ -43,6 +43,8 @@ logs/
43
43
  run/
44
44
  .codex-a2a/
45
45
  *.db
46
+ *.db-shm
47
+ *.db-wal
46
48
 
47
49
  # Unit test / coverage reports
48
50
  htmlcov/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codex-a2a
3
- Version: 0.6.0
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.111,>=0.110
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.110,<0.111",
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
- details: dict[str, Any] = {
193
- "permission": _first_nested_string(
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
- ("permission",),
196
- ("metadata", "raw", "permission"),
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 CodexMessage, _TurnTracker
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
- return session_id.strip()
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._rpc_request("turn/start", params)
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._rpc_request("turn/start", params)
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.0
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.111,>=0.110
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.111,>=0.110
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