opencode-a2a 0.7.1__tar.gz → 0.8.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. opencode_a2a-0.8.0/.github/dependabot.yml +16 -0
  2. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/CONTRIBUTING.md +5 -4
  3. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/PKG-INFO +7 -3
  4. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/README.md +5 -1
  5. opencode_a2a-0.8.0/docs/architecture.md +101 -0
  6. opencode_a2a-0.8.0/docs/compatibility.md +147 -0
  7. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/docs/extension-specifications.md +1 -1
  8. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/docs/guide.md +5 -1
  9. opencode_a2a-0.8.0/docs/maintainer-architecture.md +132 -0
  10. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/pyproject.toml +1 -1
  11. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/scripts/README.md +3 -1
  12. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/scripts/doctor.sh +10 -0
  13. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/client/polling.py +3 -9
  14. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/execution/executor.py +1 -7
  15. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/execution/request_context.py +12 -23
  16. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/execution/stream_runtime.py +15 -1
  17. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/jsonrpc/handlers/common.py +261 -41
  18. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/jsonrpc/handlers/interrupt_callbacks.py +9 -9
  19. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/jsonrpc/handlers/interrupt_queries.py +9 -11
  20. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/jsonrpc/handlers/provider_discovery.py +25 -50
  21. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/jsonrpc/handlers/session_control.py +90 -144
  22. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/jsonrpc/handlers/session_lifecycle.py +209 -259
  23. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/jsonrpc/handlers/session_queries.py +34 -49
  24. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/jsonrpc/handlers/workspace_control.py +158 -106
  25. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/jsonrpc/methods.py +84 -94
  26. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/jsonrpc/params.py +37 -78
  27. opencode_a2a-0.8.0/src/opencode_a2a/metadata_access.py +39 -0
  28. opencode_a2a-0.8.0/src/opencode_a2a/output_modes.py +386 -0
  29. opencode_a2a-0.8.0/src/opencode_a2a/parsing.py +86 -0
  30. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/server/application.py +44 -4
  31. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/server/rest_tasks.py +48 -29
  32. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/server/task_store.py +6 -13
  33. opencode_a2a-0.8.0/src/opencode_a2a/task_states.py +12 -0
  34. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a.egg-info/PKG-INFO +7 -3
  35. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a.egg-info/SOURCES.txt +9 -0
  36. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a.egg-info/requires.txt +1 -1
  37. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/execution/test_streaming_output_contract_blocks.py +4 -2
  38. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/scripts/test_script_health_contract.py +13 -0
  39. opencode_a2a-0.8.0/tests/server/test_output_negotiation.py +217 -0
  40. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/server/test_transport_contract.py +60 -0
  41. opencode_a2a-0.8.0/tests/test_metadata_access.py +49 -0
  42. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/uv.lock +123 -112
  43. opencode_a2a-0.7.1/src/opencode_a2a/output_modes.py +0 -29
  44. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/.github/workflows/dependency-review.yml +0 -0
  45. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/.github/workflows/publish.yml +0 -0
  46. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/.github/workflows/validate.yml +0 -0
  47. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/.gitignore +0 -0
  48. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/.pre-commit-config.yaml +0 -0
  49. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/.secrets.baseline +0 -0
  50. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/AGENTS.md +0 -0
  51. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/CODE_OF_CONDUCT.md +0 -0
  52. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/LICENSE +0 -0
  53. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/SECURITY.md +0 -0
  54. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/SUPPORT.md +0 -0
  55. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/docs/conformance-triage.md +0 -0
  56. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/docs/conformance.md +0 -0
  57. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/scripts/check_coverage.py +0 -0
  58. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/scripts/conformance.sh +0 -0
  59. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/scripts/dependency_health.sh +0 -0
  60. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/scripts/health_common.sh +0 -0
  61. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/scripts/lint.sh +0 -0
  62. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/scripts/smoke_test_built_cli.sh +0 -0
  63. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/setup.cfg +0 -0
  64. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/__init__.py +0 -0
  65. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/auth.py +0 -0
  66. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/cli.py +0 -0
  67. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/client/__init__.py +0 -0
  68. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/client/agent_card.py +0 -0
  69. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/client/auth.py +0 -0
  70. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/client/client.py +0 -0
  71. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/client/config.py +0 -0
  72. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/client/error_mapping.py +0 -0
  73. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/client/errors.py +0 -0
  74. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/client/payload_text.py +0 -0
  75. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/client/request_context.py +0 -0
  76. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/config.py +0 -0
  77. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/contracts/__init__.py +0 -0
  78. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/contracts/extensions.py +0 -0
  79. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/execution/__init__.py +0 -0
  80. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/execution/coordinator.py +0 -0
  81. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/execution/event_helpers.py +0 -0
  82. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/execution/metrics.py +0 -0
  83. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/execution/session_manager.py +0 -0
  84. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/execution/stream_events.py +0 -0
  85. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/execution/stream_state.py +0 -0
  86. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/execution/tool_error_mapping.py +0 -0
  87. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/execution/tool_orchestration.py +0 -0
  88. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/execution/upstream_error_translator.py +0 -0
  89. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/invocation.py +0 -0
  90. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/jsonrpc/__init__.py +0 -0
  91. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/jsonrpc/application.py +0 -0
  92. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/jsonrpc/dispatch.py +0 -0
  93. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/jsonrpc/error_responses.py +0 -0
  94. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/jsonrpc/handlers/__init__.py +0 -0
  95. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/opencode_upstream_client.py +0 -0
  96. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/parts/__init__.py +0 -0
  97. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/parts/mapping.py +0 -0
  98. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/parts/text.py +0 -0
  99. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/profile/__init__.py +0 -0
  100. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/profile/runtime.py +0 -0
  101. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/protocol_versions.py +0 -0
  102. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/py.typed +0 -0
  103. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/runtime_state.py +0 -0
  104. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/sandbox_policy.py +0 -0
  105. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/server/__init__.py +0 -0
  106. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/server/agent_card.py +0 -0
  107. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/server/client_manager.py +0 -0
  108. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/server/lifespan.py +0 -0
  109. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/server/middleware.py +0 -0
  110. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/server/migrations.py +0 -0
  111. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/server/openapi.py +0 -0
  112. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/server/request_parsing.py +0 -0
  113. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/server/state_store.py +0 -0
  114. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/trace_context.py +0 -0
  115. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a/upstream_taxonomy.py +0 -0
  116. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a.egg-info/dependency_links.txt +0 -0
  117. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a.egg-info/entry_points.txt +0 -0
  118. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/src/opencode_a2a.egg-info/top_level.txt +0 -0
  119. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/__init__.py +0 -0
  120. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/client/__init__.py +0 -0
  121. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/client/test_agent_card.py +0 -0
  122. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/client/test_client_config.py +0 -0
  123. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/client/test_client_facade.py +0 -0
  124. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/client/test_error_mapping.py +0 -0
  125. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/client/test_payload_text.py +0 -0
  126. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/client/test_polling.py +0 -0
  127. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/client/test_request_context.py +0 -0
  128. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/config/__init__.py +0 -0
  129. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/config/test_settings.py +0 -0
  130. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/conftest.py +0 -0
  131. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/contracts/__init__.py +0 -0
  132. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/contracts/test_extension_contract_consistency.py +0 -0
  133. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/execution/__init__.py +0 -0
  134. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/execution/test_agent_errors.py +0 -0
  135. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/execution/test_agent_helpers.py +0 -0
  136. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/execution/test_cancellation.py +0 -0
  137. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/execution/test_directory_validation.py +0 -0
  138. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/execution/test_metrics.py +0 -0
  139. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/execution/test_multipart_input.py +0 -0
  140. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/execution/test_opencode_agent_session_binding.py +0 -0
  141. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/execution/test_session_lock_lifecycle.py +0 -0
  142. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/execution/test_session_ownership.py +0 -0
  143. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/execution/test_streaming_output_contract_core.py +0 -0
  144. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/execution/test_streaming_output_contract_interrupts.py +0 -0
  145. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/execution/test_streaming_output_contract_logging.py +0 -0
  146. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/jsonrpc/__init__.py +0 -0
  147. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/jsonrpc/test_dispatch_registry.py +0 -0
  148. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/jsonrpc/test_error_responses.py +0 -0
  149. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/jsonrpc/test_jsonrpc_methods.py +0 -0
  150. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/jsonrpc/test_jsonrpc_params.py +0 -0
  151. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/jsonrpc/test_jsonrpc_unsupported_method.py +0 -0
  152. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/jsonrpc/test_opencode_session_extension_commands.py +0 -0
  153. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/jsonrpc/test_opencode_session_extension_interrupts.py +0 -0
  154. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/jsonrpc/test_opencode_session_extension_lifecycle.py +0 -0
  155. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/jsonrpc/test_opencode_session_extension_prompt_async.py +0 -0
  156. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/jsonrpc/test_opencode_session_extension_queries.py +0 -0
  157. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/jsonrpc/test_opencode_workspace_control_extension.py +0 -0
  158. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/package/__init__.py +0 -0
  159. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/package/test_logging.py +0 -0
  160. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/package/test_typing_contract.py +0 -0
  161. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/package/test_version.py +0 -0
  162. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/parts/__init__.py +0 -0
  163. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/parts/test_parts_text.py +0 -0
  164. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/profile/__init__.py +0 -0
  165. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/profile/test_profile_runtime.py +0 -0
  166. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/scripts/__init__.py +0 -0
  167. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/server/__init__.py +0 -0
  168. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/server/test_a2a_client_manager.py +0 -0
  169. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/server/test_agent_card.py +0 -0
  170. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/server/test_app_behaviors.py +0 -0
  171. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/server/test_auth.py +0 -0
  172. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/server/test_call_context_builder.py +0 -0
  173. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/server/test_cancel_contract.py +0 -0
  174. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/server/test_cli.py +0 -0
  175. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/server/test_database_app_persistence.py +0 -0
  176. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/server/test_state_store.py +0 -0
  177. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/server/test_task_store_factory.py +0 -0
  178. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/support/__init__.py +0 -0
  179. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/support/helpers.py +0 -0
  180. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/support/session_extensions.py +0 -0
  181. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/support/streaming_output.py +0 -0
  182. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/test_trace_context.py +0 -0
  183. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/upstream/__init__.py +0 -0
  184. {opencode_a2a-0.7.1 → opencode_a2a-0.8.0}/tests/upstream/test_opencode_upstream_client_params.py +0 -0
@@ -0,0 +1,16 @@
1
+ version: 2
2
+
3
+ updates:
4
+ - package-ecosystem: "uv"
5
+ directory: "/"
6
+ schedule:
7
+ interval: "weekly"
8
+ open-pull-requests-limit: 1
9
+ commit-message:
10
+ prefix: "deps"
11
+ labels:
12
+ - "dependencies"
13
+ groups:
14
+ uv-all-updates:
15
+ patterns:
16
+ - "*"
@@ -44,10 +44,11 @@ uv run opencode-a2a serve
44
44
  Run the default validation baseline before opening a PR:
45
45
 
46
46
  ```bash
47
- uv run pre-commit run --all-files
48
- uv run pytest
47
+ bash ./scripts/doctor.sh
49
48
  ```
50
49
 
50
+ `doctor.sh` is the primary repository validation entrypoint. It currently runs locked-environment sync, dependency compatibility checks, `pre-commit`, `mypy`, `pytest`, the repository coverage gate, package build, and a built-wheel smoke test.
51
+
51
52
  If you change shell scripts, also run `bash -n` on each modified script, for example:
52
53
 
53
54
  ```bash
@@ -63,7 +64,7 @@ bash ./scripts/conformance.sh
63
64
 
64
65
  Treat that output as investigation input. Do not fold it into `doctor.sh` or the default CI quality gate unless the repository explicitly decides to promote a specific experiment into a maintained policy.
65
66
 
66
- If you change extension methods, extension metadata, or Agent Card/OpenAPI contract surfaces, also run:
67
+ If you change extension methods, extension metadata, or Agent Card/OpenAPI contract surfaces, also make sure the targeted contract checks stay green:
67
68
 
68
69
  ```bash
69
70
  uv run pytest tests/contracts/test_extension_contract_consistency.py
@@ -107,7 +108,7 @@ Update docs together with code whenever you change:
107
108
  - user-facing request or response shapes
108
109
  - operational scripts
109
110
 
110
- Keep compatibility guidance centralized in [docs/guide.md](docs/guide.md) unless a new standalone document is clearly necessary.
111
+ Keep usage details in [docs/guide.md](docs/guide.md) and compatibility-sensitive stability guidance in [docs/compatibility.md](docs/compatibility.md).
111
112
 
112
113
  When changing extension contracts, update [`src/opencode_a2a/contracts/extensions.py`](src/opencode_a2a/contracts/extensions.py) first and keep these generated/documented surfaces aligned:
113
114
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: opencode-a2a
3
- Version: 0.7.1
3
+ Version: 0.8.0
4
4
  Summary: OpenCode A2A runtime
5
5
  Author: liujuanjuan1984@Intelligent-Internet
6
6
  License-Expression: Apache-2.0
@@ -19,7 +19,7 @@ Classifier: Topic :: Internet :: WWW/HTTP
19
19
  Requires-Python: >=3.11
20
20
  Description-Content-Type: text/markdown
21
21
  License-File: LICENSE
22
- Requires-Dist: a2a-sdk==0.3.25
22
+ Requires-Dist: a2a-sdk==0.3.26
23
23
  Requires-Dist: aiosqlite<1.0,>=0.20
24
24
  Requires-Dist: fastapi<1.0,>=0.110
25
25
  Requires-Dist: httpx<1.0,>=0.27
@@ -139,7 +139,7 @@ curl http://127.0.0.1:8000/.well-known/agent-card.json
139
139
  - Declared supported protocol lines: `0.3`, `1.0`
140
140
  - `0.3` is the stable interoperability baseline for the current runtime surface.
141
141
  - `1.0` currently covers version negotiation plus protocol-aware JSON-RPC and REST error shaping, while transport payloads, enums, pagination, signatures, and interface-level protocol declarations still follow the shipped SDK baseline.
142
- - The detailed compatibility matrix and machine-readable support boundary are documented in [`docs/guide.md`](docs/guide.md).
142
+ - The detailed compatibility matrix and machine-readable support boundary are documented in [`docs/guide.md`](docs/guide.md) and [`docs/compatibility.md`](docs/compatibility.md).
143
143
 
144
144
  ## Peering Node / Outbound Access
145
145
 
@@ -203,7 +203,11 @@ Read before deployment:
203
203
 
204
204
  ## Further Reading
205
205
 
206
+ - [docs/architecture.md](docs/architecture.md) Service responsibility boundaries and request flow.
207
+ - [docs/maintainer-architecture.md](docs/maintainer-architecture.md) Internal module boundaries and maintainer call chains.
208
+ - [docs/compatibility.md](docs/compatibility.md) Compatibility-sensitive surface and contract-honesty guidance.
206
209
  - [docs/guide.md](docs/guide.md) Usage guide, transport details, streaming behavior, extensions, and examples.
210
+ - [docs/conformance.md](docs/conformance.md) External TCK experiment workflow and artifact handling.
207
211
  - [SECURITY.md](SECURITY.md) Threat model, deployment caveats, and vulnerability disclosure guidance.
208
212
 
209
213
  ## Development
@@ -98,7 +98,7 @@ curl http://127.0.0.1:8000/.well-known/agent-card.json
98
98
  - Declared supported protocol lines: `0.3`, `1.0`
99
99
  - `0.3` is the stable interoperability baseline for the current runtime surface.
100
100
  - `1.0` currently covers version negotiation plus protocol-aware JSON-RPC and REST error shaping, while transport payloads, enums, pagination, signatures, and interface-level protocol declarations still follow the shipped SDK baseline.
101
- - The detailed compatibility matrix and machine-readable support boundary are documented in [`docs/guide.md`](docs/guide.md).
101
+ - The detailed compatibility matrix and machine-readable support boundary are documented in [`docs/guide.md`](docs/guide.md) and [`docs/compatibility.md`](docs/compatibility.md).
102
102
 
103
103
  ## Peering Node / Outbound Access
104
104
 
@@ -162,7 +162,11 @@ Read before deployment:
162
162
 
163
163
  ## Further Reading
164
164
 
165
+ - [docs/architecture.md](docs/architecture.md) Service responsibility boundaries and request flow.
166
+ - [docs/maintainer-architecture.md](docs/maintainer-architecture.md) Internal module boundaries and maintainer call chains.
167
+ - [docs/compatibility.md](docs/compatibility.md) Compatibility-sensitive surface and contract-honesty guidance.
165
168
  - [docs/guide.md](docs/guide.md) Usage guide, transport details, streaming behavior, extensions, and examples.
169
+ - [docs/conformance.md](docs/conformance.md) External TCK experiment workflow and artifact handling.
166
170
  - [SECURITY.md](SECURITY.md) Threat model, deployment caveats, and vulnerability disclosure guidance.
167
171
 
168
172
  ## Development
@@ -0,0 +1,101 @@
1
+ # Architecture Guide
2
+
3
+ This document explains what `opencode-a2a` is responsible for, what remains inside OpenCode, and how requests move through the adapter boundary.
4
+
5
+ ## System Role
6
+
7
+ `opencode-a2a` is an adapter layer between A2A clients and an OpenCode runtime.
8
+
9
+ It is responsible for:
10
+
11
+ - exposing A2A-facing HTTP+JSON and JSON-RPC endpoints
12
+ - normalizing transport, streaming, session, and interrupt contracts
13
+ - applying authentication, logging, persistence, and deployment-side guardrails
14
+ - hosting an outbound A2A client for peer calls triggered by CLI usage or `a2a_call`
15
+
16
+ It is not responsible for:
17
+
18
+ - replacing OpenCode's own provider or model selection internals
19
+ - hard multi-tenant isolation inside one shared deployment by default
20
+ - acting as a general OpenCode process supervisor
21
+
22
+ ## Adapter Layers
23
+
24
+ ```mermaid
25
+ flowchart LR
26
+ Client["A2A Client / Hub / Gateway"] --> Gateway["opencode-a2a"]
27
+ Gateway --> Contracts["A2A contracts\ntransport/session/interrupt"]
28
+ Gateway --> Ops["Auth / logging / persistence / deployment boundary"]
29
+ Contracts --> OpenCode["OpenCode runtime"]
30
+ Ops --> OpenCode
31
+ Gateway --> Peer["Embedded outbound A2A client"]
32
+ ```
33
+
34
+ This view emphasizes service responsibility boundaries rather than internal module structure. The root [README](../README.md) keeps the overview path for first-time readers, while [maintainer-architecture.md](./maintainer-architecture.md) covers module boundaries and request call chains for contributors.
35
+
36
+ ## Request Flow
37
+
38
+ ### Standard send/stream flow
39
+
40
+ 1. A client calls the REST or JSON-RPC endpoint.
41
+ 2. FastAPI middleware validates auth, request size, protocol version, and logging policy.
42
+ 3. The adapter maps transport payloads into the OpenCode-facing execution path.
43
+ 4. The execution layer calls the upstream OpenCode runtime and consumes its stream or unary response.
44
+ 5. The service maps the result back into shared A2A-facing task, message, and stream event contracts.
45
+
46
+ ### Streaming flow
47
+
48
+ For streaming requests, the adapter does more than simple passthrough:
49
+
50
+ - classifies stream blocks into shared types such as `text`, `reasoning`, and `tool_call`
51
+ - preserves stable event and message identity where possible
52
+ - emits shared interrupt lifecycle state
53
+ - avoids duplicate final snapshots when streaming already produced the final text
54
+
55
+ Detailed streaming contract: [Usage Guide](guide.md)
56
+
57
+ ### Session flow
58
+
59
+ The service keeps a shared session continuation contract around `metadata.shared.session.id` and adapter-derived `contextId`, so clients can continue work without binding directly to raw OpenCode session IDs.
60
+
61
+ ### Outbound peer flow
62
+
63
+ The same process can also act as an embedded A2A client:
64
+
65
+ - CLI calls route through the local client facade
66
+ - server-side `a2a_call` tool execution uses the same outbound client settings
67
+ - outbound auth, timeouts, and transport preferences are configured independently from inbound auth
68
+
69
+ ## Boundary Model
70
+
71
+ The adapter improves the runtime boundary, but it is not a full trust-boundary replacement.
72
+
73
+ ### What the adapter boundary helps with
74
+
75
+ - stable A2A-facing contract shape
76
+ - auth enforcement on A2A entrypoints
77
+ - payload logging controls
78
+ - lightweight persistence for SDK task rows plus adapter-managed runtime state
79
+ - compatibility metadata for clients and operators
80
+
81
+ ### What still belongs to the OpenCode runtime boundary
82
+
83
+ - provider credential consumption
84
+ - workspace side effects
85
+ - upstream model/provider behavior
86
+ - host-level process supervision and isolation
87
+
88
+ That is why deployments should still be treated as trusted or controlled unless stronger isolation is added outside this repository.
89
+
90
+ ## Documentation Split
91
+
92
+ Use the docs by responsibility:
93
+
94
+ - [README](../README.md): project overview, install/start path, and entry navigation
95
+ - [Compatibility Guide](compatibility.md): compatibility-sensitive surface and stability expectations
96
+ - [Usage Guide](guide.md): runtime configuration, transport contracts, extensions, and examples
97
+ - [Maintainer Architecture Guide](maintainer-architecture.md): internal module boundaries, request call chains, and persistence touchpoints
98
+ - [Extension Specifications](extension-specifications.md): stable extension URI/spec index and disclosure policy
99
+ - [Conformance Notes](conformance.md): external TCK experiment workflow
100
+ - [Contributing Guide](../CONTRIBUTING.md): contributor workflow and validation
101
+ - [Security Policy](../SECURITY.md): threat model and disclosure guidance
@@ -0,0 +1,147 @@
1
+ # Compatibility Guide
2
+
3
+ This document explains the compatibility promises `opencode-a2a` currently tries to uphold for A2A consumers, operators, and maintainers.
4
+
5
+ ## Runtime Support
6
+
7
+ - Python versions: 3.11, 3.12, 3.13
8
+ - A2A SDK line: `0.3.x`
9
+ - Default advertised protocol line: `0.3`
10
+ - Declared supported protocol lines: `0.3`, `1.0`
11
+
12
+ The repository pins the SDK version in `pyproject.toml`. Upgrade the SDK deliberately rather than relying on floating dependency resolution.
13
+
14
+ ## Contract Honesty
15
+
16
+ Machine-readable discovery surfaces must reflect actual runtime behavior:
17
+
18
+ - public Agent Card
19
+ - authenticated extended card
20
+ - OpenAPI metadata
21
+ - JSON-RPC wire contract
22
+ - compatibility profile
23
+
24
+ If runtime support is not actually implemented, do not publish it as a supported machine-readable capability.
25
+
26
+ Consumer guidance:
27
+
28
+ - Treat the core A2A send / stream / task methods as the portable baseline.
29
+ - Treat `urn:a2a:*` entries in this repository as shared repo-family conventions, not as a claim that they are part of the A2A core baseline.
30
+ - Treat `opencode.*` methods and `metadata.opencode.*` fields as provider-private OpenCode control and discovery surfaces layered on top of the portable A2A baseline.
31
+ - Treat [extension-specifications.md](./extension-specifications.md) as the stable URI/spec index, not as the main usage guide.
32
+
33
+ ## Normative Sources
34
+
35
+ When docs or reference material disagree, treat these as normative in this order:
36
+
37
+ - runtime behavior validated by tests
38
+ - machine-readable discovery output such as Agent Card, authenticated extended card, and OpenAPI metadata
39
+ - repository-owned docs in `README.md`, `docs/`, and `CONTRIBUTING.md`
40
+
41
+ External TCK runs and local conformance experiments are investigation inputs. They do not override the repository's declared contract by themselves.
42
+
43
+ ## Compatibility-Sensitive Surface
44
+
45
+ This repository still ships as an alpha project. Within that alpha line, these declared surfaces should not drift silently:
46
+
47
+ - core A2A send / stream / task methods
48
+ - version negotiation and protocol-aware error shaping
49
+ - shared session-binding metadata
50
+ - shared model-selection metadata
51
+ - shared streaming metadata
52
+ - declared custom JSON-RPC extension methods
53
+ - authenticated extended card and OpenAPI wire-contract metadata
54
+
55
+ Changes to those surfaces should be treated as compatibility-sensitive and should include corresponding test updates.
56
+
57
+ Service-level behavior layered on top of those core methods should also be declared explicitly when interoperability depends on it. Current examples:
58
+
59
+ - `tasks/resubscribe` replay-once behavior for terminal updates
60
+ - first-terminal-state-wins task persistence policy
61
+ - task-scoped `acceptedOutputModes` negotiation persistence across send / stream / get / resubscribe
62
+ - request-body rejection behavior for oversized transport payloads
63
+
64
+ ## Deployment Profile
65
+
66
+ The current service profile is intentionally:
67
+
68
+ - single-tenant
69
+ - shared-workspace
70
+ - adapter boundary around one OpenCode deployment
71
+
72
+ One deployed instance should be treated as a single-tenant trust boundary, not as a secure multi-tenant runtime boundary.
73
+
74
+ Execution-environment boundary fields published through the runtime profile are declarative deployment metadata. They are not promises that every host-side approval, sandbox escalation, or filesystem change will be reflected live per request.
75
+
76
+ ## Persistence Compatibility
77
+
78
+ Task durability is deployment-dependent:
79
+
80
+ - `A2A_TASK_STORE_BACKEND=database` preserves SDK task rows plus adapter-managed session and interrupt state across restarts
81
+ - `A2A_TASK_STORE_BACKEND=memory` keeps the service in an ephemeral development profile
82
+
83
+ Task-store behavior that should remain stable for clients:
84
+
85
+ - once a task reaches a terminal state, later conflicting writes are dropped on a first-terminal-state-wins basis
86
+ - task-store I/O failures are surfaced as stable service errors instead of leaking backend-specific exceptions
87
+ - accepted output-mode negotiation for a task is persisted with the task so later reads keep the same filtered output contract
88
+ - adapter-managed migrations only own adapter state tables; SDK-managed task schema remains SDK-owned
89
+
90
+ The default SQLite-first profile is intended for local or controlled single-instance deployments. Wider SQLAlchemy dialect compatibility should be treated as implementation latitude rather than a strong public promise unless explicitly documented later.
91
+
92
+ ## Extension Stability
93
+
94
+ - Shared metadata and extension contracts should stay synchronized across Agent Card, OpenAPI, and runtime behavior.
95
+ - Public Agent Card should stay intentionally minimal. Detailed extension params belong in the authenticated extended card and OpenAPI, not back in the anonymous discovery surface.
96
+ - Deployment-conditional methods must be declared as conditional rather than silently disappearing.
97
+ - `opencode.sessions.prompt_async` input-part passthrough is compatibility-sensitive. Changes to supported part types, passthrough field semantics, or rejection behavior should be treated as wire-level changes.
98
+ - `opencode.sessions.shell` is compatibility-sensitive as a deployment-conditional shell snapshot surface. It should not silently widen into a general interactive shell API.
99
+ - `opencode.workspaces.*` and `opencode.worktrees.*` are boundary-sensitive and should remain explicitly provider-private, operator-scoped, and deployment-conditional where applicable.
100
+ - Interrupt callback and recovery methods are compatibility-sensitive because clients may depend on request ID lifecycle, expiry semantics, and identity scoping.
101
+ - Agent Card media modes and `acceptedOutputModes` handling are compatibility-sensitive. Changes to declared chat modes, to task-scoped negotiation persistence, or to `DataPart` -> `TextPart` downgrade behavior should be treated as wire-level changes.
102
+ - Agent Card and OpenAPI publication of `protocol_compatibility`, `service_behaviors`, and runtime feature toggles is compatibility-sensitive discoverability surface.
103
+
104
+ ## Extension Boundary Governance
105
+
106
+ When evaluating or evolving `opencode.*` methods, this repository uses the following rules:
107
+
108
+ - The adapter may document, validate, route, and normalize stable upstream-facing behavior, but it should not grow into a general replacement for upstream private runtime internals or host-level control planes.
109
+ - New `opencode.*` methods default to provider-private extension status.
110
+ - Read-only discovery, compatibility-preserving projections, and low-risk control methods are preferred over stronger mutating or destructive provider controls.
111
+ - A2A core object mappings should be used only for stable, low-ambiguity read projections.
112
+ - Subtask/subagent fan-out, task-tool internals, and similar upstream execution mechanisms should stay framed as upstream runtime behavior even when passthrough compatibility exists.
113
+
114
+ Each new extension proposal should answer:
115
+
116
+ - what client value exists beyond the current chat/session flow?
117
+ - is the upstream behavior stable enough to carry as a maintained contract?
118
+ - should the surface be provider-private, deployment-conditional, or excluded?
119
+ - are authorization and destructive-side-effect boundaries enforceable?
120
+ - can the result shape avoid overfitting OpenCode internals into fake A2A core semantics?
121
+
122
+ ## Extension Taxonomy
123
+
124
+ This repository distinguishes between three layers:
125
+
126
+ - core A2A surface
127
+ - standard send / stream / task methods
128
+ - shared extensions
129
+ - repo-family conventions such as session binding, model selection, stream hints, and interrupt callbacks
130
+ - OpenCode-specific extensions
131
+ - `opencode.*` JSON-RPC methods plus `metadata.opencode.*`
132
+
133
+ Important note:
134
+
135
+ - `urn:a2a:*` extension URIs used here should be read as shared conventions in this repository family.
136
+ - They are not a claim that those extensions are part of the A2A core baseline.
137
+ - `opencode.*` methods are intentionally product-specific. They improve OpenCode-aware workflows but should not be assumed to transfer unchanged to unrelated A2A agents.
138
+
139
+ ## Non-Goals
140
+
141
+ This repository does not currently promise:
142
+
143
+ - hard multi-tenant isolation inside one instance
144
+ - generic provider-auth orchestration on behalf of OpenCode
145
+ - a claim that all declared `1.0` protocol surfaces are fully implemented beyond the documented compatibility matrix
146
+
147
+ Those areas may evolve later, but they should not be implied by current machine-readable discovery output.
@@ -1,6 +1,6 @@
1
1
  # Extension Specifications
2
2
 
3
- This document is the stable specification surface referenced by the extension URIs published in the Agent Card. It is intentionally a compact URI/spec index, not the main consumer guide. For runtime behavior, request/response examples, and client integration guidance, see [`guide.md`](./guide.md).
3
+ This document is the stable specification surface referenced by the extension URIs published in the Agent Card. It is intentionally a compact URI/spec index, not the main consumer guide. For runtime behavior, request/response examples, and client integration guidance, see [`guide.md`](./guide.md). For compatibility-sensitive surface and contract-honesty guidance, see [`compatibility.md`](./compatibility.md).
4
4
 
5
5
  ## SDK Compatibility Note
6
6
 
@@ -1,6 +1,6 @@
1
1
  # Usage Guide
2
2
 
3
- This guide covers configuration, authentication, API behavior, streaming re-subscription, and A2A client examples. It is the canonical document for implementation-level protocol contracts and JSON-RPC extension details; README stays at overview level.
3
+ This guide covers configuration, authentication, API behavior, streaming re-subscription, and A2A client examples. It is the canonical document for implementation-level protocol contracts and JSON-RPC extension details; [README](../README.md) stays at overview level, [architecture.md](./architecture.md) explains the service boundary, [maintainer-architecture.md](./maintainer-architecture.md) covers the internal module view for contributors, and [compatibility.md](./compatibility.md) defines the compatibility-sensitive surface.
4
4
 
5
5
  ## Transport Contracts
6
6
 
@@ -199,6 +199,8 @@ If one deployment works while another fails against the same upstream provider,
199
199
  - Main chat requests that explicitly send `configuration.acceptedOutputModes` must stay compatible with the declared chat output modes.
200
200
  - Current main chat requests must continue accepting `text/plain`; requests that only accept `application/json` or other incompatible modes are rejected before execution starts.
201
201
  - `application/json` is additive structured-output support for incremental `tool_call` payloads. It does not guarantee that ordinary assistant prose can always be losslessly represented as JSON, so consumers that expect normal chat text should keep accepting `text/plain`.
202
+ - When a client accepts `text/plain` but not `application/json`, structured `tool_call` payloads are downgraded to compact JSON text instead of being silently dropped.
203
+ - Accepted output-mode negotiation is persisted as task-scoped metadata so later `tasks/get` and `tasks/resubscribe` reads keep the same filtered response contract as the original `message/send` or `message:stream` request.
202
204
  - Main chat input supports structured A2A `parts` passthrough:
203
205
  - `TextPart` is forwarded as an OpenCode text part.
204
206
  - `FilePart(FileWithBytes)` is forwarded as a `file` part with a `data:` URL.
@@ -220,6 +222,8 @@ If one deployment works while another fails against the same upstream provider,
220
222
  - `message.part.delta` and `message.part.updated` are merged per `part_id`; out-of-order deltas are buffered and replayed when the corresponding `part.updated` arrives.
221
223
  - Structured `tool` parts are emitted as `tool_call` blocks backed by `DataPart(data={...})`, while `text` and `reasoning` continue to use `TextPart`.
222
224
  - `tool_call` block payloads are normalized structured objects that may expose fields such as `call_id`, `tool`, `status`, `title`, `subtitle`, `input`, `output`, and `error`.
225
+ - If `application/json` is not accepted but `text/plain` is still accepted, those `tool_call` blocks are downgraded to stable compact JSON text so text-only clients retain the same observable state transitions.
226
+ - When a request restricts `acceptedOutputModes`, the stream applies the same output filtering before persistence so later task snapshots do not re-expose filtered structured blocks.
223
227
  - Final status event metadata may include normalized token usage at `metadata.shared.usage` with fields such as `input_tokens`, `output_tokens`, `total_tokens`, optional `reasoning_tokens`, optional `cache_tokens.read_tokens` / `cache_tokens.write_tokens`, and optional `cost`.
224
228
  - Usage is extracted from documented info payloads and supported usage parts such as `step-finish`; non-usage parts with similar fields are ignored.
225
229
  - Interrupt events (`permission.asked` / `question.asked`) are mapped to `TaskStatusUpdateEvent(final=false, state=input-required)` with details at `metadata.shared.interrupt`, including `request_id`, interrupt `type`, `phase=asked`, and a normalized minimal callback payload.
@@ -0,0 +1,132 @@
1
+ # Maintainer Architecture Guide
2
+
3
+ This document describes the internal structure, module boundaries, and main request call chains of `opencode-a2a`. It is intended for maintainers and contributors. Use [architecture.md](./architecture.md) for the higher-level service boundary view and [guide.md](./guide.md) for deployment-facing runtime configuration.
4
+
5
+ ## Core Component Map
6
+
7
+ ```mermaid
8
+ flowchart TD
9
+ subgraph Inbound["Server Layer (src/opencode_a2a/server/)"]
10
+ App["application.py (FastAPI assembly)"]
11
+ Middleware["middleware.py"]
12
+ AgentCard["agent_card.py / openapi.py"]
13
+ end
14
+
15
+ subgraph Execution["Execution Layer (src/opencode_a2a/execution/)"]
16
+ Executor["executor.py"]
17
+ Coordinator["coordinator.py"]
18
+ StreamRuntime["stream_runtime.py"]
19
+ ToolOrch["tool_orchestration.py"]
20
+ end
21
+
22
+ subgraph Upstream["OpenCode Upstream Layer"]
23
+ UpstreamClient["opencode_upstream_client.py"]
24
+ Invocation["invocation.py"]
25
+ end
26
+
27
+ subgraph Extensions["Extension / Contract Layer"]
28
+ Jsonrpc["jsonrpc/"]
29
+ Contracts["contracts/extensions.py"]
30
+ Profile["profile/runtime.py"]
31
+ end
32
+
33
+ subgraph Persistence["Persistence Layer"]
34
+ TaskStore["server/task_store.py"]
35
+ StateStore["server/state_store.py"]
36
+ Migrations["server/migrations.py"]
37
+ end
38
+
39
+ Inbound --> Execution
40
+ Inbound --> Extensions
41
+ Execution --> Upstream
42
+ Inbound --> Persistence
43
+ Execution --> Persistence
44
+ ```
45
+
46
+ ## Request Call Chain
47
+
48
+ ### Inbound Message Send / Stream
49
+
50
+ 1. `server/application.py` assembles the FastAPI app, SDK adapters, and middleware stack.
51
+ 2. `server/middleware.py` handles auth, request sizing, protocol negotiation, logging, and response headers.
52
+ 3. The SDK-backed handler delegates execution to `execution/executor.py`.
53
+ 4. The execution layer coordinates session continuity, stream handling, tool calls, and error translation through:
54
+ - `execution/coordinator.py`
55
+ - `execution/stream_runtime.py`
56
+ - `execution/tool_orchestration.py`
57
+ 5. `opencode_upstream_client.py` sends requests to the upstream OpenCode runtime.
58
+ 6. The adapter maps upstream responses back into A2A tasks, messages, artifacts, and stream events.
59
+
60
+ ### JSON-RPC Extension Path
61
+
62
+ 1. `jsonrpc/application.py` owns the adapter-specific JSON-RPC application boundary.
63
+ 2. `jsonrpc/dispatch.py` and handler modules under `jsonrpc/handlers/` route provider-private methods.
64
+ 3. `contracts/extensions.py` remains the SSOT for extension metadata exposed through Agent Card and OpenAPI.
65
+ 4. Tests under `tests/contracts/` and `tests/jsonrpc/` guard contract drift.
66
+
67
+ ### Outbound Peer Call Path
68
+
69
+ 1. CLI or server-side tool execution asks `server/client_manager.py` for an outbound client.
70
+ 2. `client/` builds and configures the embedded A2A client facade.
71
+ 3. Outbound peer responses are normalized before being reintroduced into the local runtime surface.
72
+
73
+ ## Module Responsibilities
74
+
75
+ ### Server Layer
76
+
77
+ - `server/application.py`: app assembly, route wiring, request handler customization, and top-level lifecycle integration
78
+ - `server/middleware.py`: auth, protocol negotiation, payload/body guards, logging, and response decoration
79
+ - `server/agent_card.py` / `server/openapi.py`: machine-readable contract publication
80
+ - `server/rest_tasks.py`: SDK-owned REST task routes plus adapter-specific list behavior
81
+
82
+ ### Execution Layer
83
+
84
+ - `execution/executor.py`: main orchestration entrypoint
85
+ - `execution/coordinator.py`: OpenCode session coordination and request shaping
86
+ - `execution/stream_runtime.py` / `execution/stream_events.py`: stream normalization and event conversion
87
+ - `execution/tool_orchestration.py`: embedded peer-call tool handling
88
+ - `execution/upstream_error_translator.py` / `execution/tool_error_mapping.py`: upstream-facing error normalization
89
+
90
+ ### Extension and Contract Layer
91
+
92
+ - `contracts/extensions.py`: SSOT for extension metadata, compatibility profile, and wire-contract payloads
93
+ - `jsonrpc/`: provider-private JSON-RPC extension surface
94
+ - `profile/runtime.py`: runtime profile that feeds Agent Card, OpenAPI, and compatibility metadata
95
+ - `protocol_versions.py`: protocol normalization and negotiation helpers
96
+
97
+ ### Persistence Layer
98
+
99
+ - `server/task_store.py`: SDK task store construction plus adapter policy wrappers
100
+ - `server/state_store.py`: session binding and interrupt repositories
101
+ - `server/migrations.py`: adapter-managed state schema migrations
102
+
103
+ ### Client Layer
104
+
105
+ - `client/`: outbound peer card discovery, request context, auth handling, polling fallback, and error mapping
106
+
107
+ ## Key Persistence Points
108
+
109
+ - SDK task rows stored through the configured task store backend
110
+ - adapter-managed session binding / ownership state
111
+ - interrupt request bindings and tombstones
112
+ - pending preferred-session claims
113
+
114
+ The custom migration runner owns only adapter-managed state tables; SDK-managed task schema still follows the SDK path.
115
+
116
+ ## Configuration Layering
117
+
118
+ Configuration is handled in [config.py](../src/opencode_a2a/config.py) with `pydantic-settings`.
119
+
120
+ - `A2A_*`: inbound runtime, outbound peer client, protocol, persistence, and deployment metadata
121
+ - `OPENCODE_*`: upstream OpenCode connection and request behavior
122
+
123
+ ## Practical Reading Order
124
+
125
+ For maintainers new to the codebase, this order usually gives the fastest payoff:
126
+
127
+ 1. `README.md`
128
+ 2. `docs/architecture.md`
129
+ 3. `src/opencode_a2a/server/application.py`
130
+ 4. `src/opencode_a2a/execution/executor.py`
131
+ 5. `src/opencode_a2a/contracts/extensions.py`
132
+ 6. `docs/guide.md`
@@ -24,7 +24,7 @@ classifiers = [
24
24
  "Topic :: Internet :: WWW/HTTP",
25
25
  ]
26
26
  dependencies = [
27
- "a2a-sdk==0.3.25",
27
+ "a2a-sdk==0.3.26",
28
28
  "aiosqlite>=0.20,<1.0",
29
29
  "fastapi>=0.110,<1.0",
30
30
  "httpx>=0.27,<1.0",
@@ -11,7 +11,7 @@ Executable scripts live in this directory. This file is the entry index for the
11
11
 
12
12
  ## Other Scripts
13
13
 
14
- - [`doctor.sh`](./doctor.sh): primary local development regression entrypoint (uv sync + lint + tests + coverage)
14
+ - [`doctor.sh`](./doctor.sh): primary local development regression entrypoint (uv sync + dependency compatibility + lint + mypy + tests + coverage + built-wheel smoke test)
15
15
  - [`conformance.sh`](./conformance.sh): local/manual external A2A conformance experiment entrypoint; caches the official TCK, can launch a dummy-backed local SUT, and preserves raw artifacts under `run/conformance/`
16
16
  - [`dependency_health.sh`](./dependency_health.sh): development dependency review entrypoint (`sync`/`pip check` + outdated + dev audit), while blocking CI/publish audits focus on runtime dependencies
17
17
  - [`check_coverage.py`](./check_coverage.py): enforces the overall coverage floor and per-file minimums for critical modules
@@ -21,4 +21,6 @@ Executable scripts live in this directory. This file is the entry index for the
21
21
  ## Notes
22
22
 
23
23
  - `doctor.sh` and `dependency_health.sh` intentionally remain separate entrypoints and share common prerequisites through [`health_common.sh`](./health_common.sh).
24
+ - `doctor.sh` covers the default local validation baseline, while `dependency_health.sh` remains focused on standalone dependency review and audit flow.
25
+ - [`.github/dependabot.yml`](../.github/dependabot.yml) prefers a single weekly grouped Dependabot PR for `uv`, while `dependency_health.sh` remains the explicit review/audit entrypoint.
24
26
  - External conformance experiments remain intentionally separate from the default regression path. See [`../docs/conformance.md`](../docs/conformance.md).
@@ -9,8 +9,18 @@ run_shared_repo_health_prerequisites "doctor"
9
9
  echo "[doctor] run lint"
10
10
  uv run pre-commit run --all-files
11
11
 
12
+ echo "[doctor] run type checks"
13
+ uv run mypy src/opencode_a2a
14
+
12
15
  echo "[doctor] run tests"
13
16
  uv run pytest
14
17
 
15
18
  echo "[doctor] enforce coverage policy"
16
19
  uv run python ./scripts/check_coverage.py
20
+
21
+ echo "[doctor] build release artifacts"
22
+ rm -f dist/opencode_a2a-*.whl dist/opencode_a2a-*.tar.gz
23
+ uv build --no-sources
24
+
25
+ echo "[doctor] smoke test built wheel"
26
+ bash ./scripts/smoke_test_built_cli.sh dist/opencode_a2a-*.whl
@@ -6,14 +6,8 @@ from dataclasses import dataclass
6
6
 
7
7
  from a2a.types import TaskState
8
8
 
9
- _TERMINAL_TASK_STATES = frozenset(
10
- {
11
- TaskState.completed,
12
- TaskState.canceled,
13
- TaskState.failed,
14
- TaskState.rejected,
15
- }
16
- )
9
+ from ..task_states import TERMINAL_TASK_STATES
10
+
17
11
  _AUTO_POLLING_TASK_STATES = frozenset(
18
12
  {
19
13
  TaskState.submitted,
@@ -37,7 +31,7 @@ class PollingFallbackPolicy:
37
31
  return state in _AUTO_POLLING_TASK_STATES
38
32
 
39
33
  def is_terminal_state(self, state: TaskState) -> bool:
40
- return state in _TERMINAL_TASK_STATES
34
+ return state in TERMINAL_TASK_STATES
41
35
 
42
36
  def next_interval_seconds(self, current_interval_seconds: float) -> float:
43
37
  return min(
@@ -73,7 +73,7 @@ from .stream_state import (
73
73
  _StreamOutputState,
74
74
  _TTLCache,
75
75
  )
76
- from .tool_orchestration import handle_a2a_call_tool, maybe_handle_tools, merge_streamed_tool_output
76
+ from .tool_orchestration import maybe_handle_tools, merge_streamed_tool_output
77
77
  from .upstream_error_translator import (
78
78
  _await_stream_terminal_signal,
79
79
  _extract_upstream_error_detail,
@@ -186,12 +186,6 @@ class OpencodeAgentExecutor(AgentExecutor):
186
186
  a2a_client_manager=self._a2a_client_manager,
187
187
  )
188
188
 
189
- async def _handle_a2a_call_tool(self, part: dict[str, Any]) -> dict[str, Any]:
190
- return await handle_a2a_call_tool(
191
- part,
192
- a2a_client_manager=self._a2a_client_manager,
193
- )
194
-
195
189
  @staticmethod
196
190
  def _merge_streamed_tool_output(current: str, incoming: str) -> str:
197
191
  return merge_streamed_tool_output(current, incoming)