opencode-a2a 0.6.0__tar.gz → 0.7.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 (186) hide show
  1. opencode_a2a-0.7.0/.github/workflows/publish.yml +160 -0
  2. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/CODE_OF_CONDUCT.md +2 -6
  3. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/CONTRIBUTING.md +26 -13
  4. {opencode_a2a-0.6.0/src/opencode_a2a.egg-info → opencode_a2a-0.7.0}/PKG-INFO +31 -53
  5. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/README.md +30 -51
  6. opencode_a2a-0.7.0/SECURITY.md +39 -0
  7. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/SUPPORT.md +2 -4
  8. opencode_a2a-0.7.0/docs/conformance-triage.md +89 -0
  9. opencode_a2a-0.7.0/docs/conformance.md +67 -0
  10. opencode_a2a-0.7.0/docs/extension-specifications.md +105 -0
  11. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/docs/guide.md +339 -400
  12. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/pyproject.toml +3 -1
  13. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/scripts/README.md +3 -2
  14. opencode_a2a-0.7.0/scripts/conformance.sh +248 -0
  15. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/scripts/smoke_test_built_cli.sh +13 -1
  16. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/__init__.py +3 -0
  17. opencode_a2a-0.7.0/src/opencode_a2a/auth.py +139 -0
  18. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/client/agent_card.py +4 -0
  19. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/client/client.py +18 -11
  20. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/client/config.py +23 -0
  21. opencode_a2a-0.7.0/src/opencode_a2a/client/request_context.py +80 -0
  22. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/config.py +142 -3
  23. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/contracts/extensions.py +346 -41
  24. opencode_a2a-0.7.0/src/opencode_a2a/execution/coordinator.py +499 -0
  25. opencode_a2a-0.7.0/src/opencode_a2a/execution/executor.py +579 -0
  26. opencode_a2a-0.7.0/src/opencode_a2a/execution/metrics.py +20 -0
  27. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/execution/stream_runtime.py +3 -0
  28. opencode_a2a-0.7.0/src/opencode_a2a/execution/tool_orchestration.py +153 -0
  29. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/jsonrpc/application.py +44 -13
  30. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/jsonrpc/dispatch.py +25 -21
  31. opencode_a2a-0.7.0/src/opencode_a2a/jsonrpc/error_responses.py +382 -0
  32. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/jsonrpc/handlers/common.py +22 -0
  33. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/jsonrpc/handlers/interrupt_callbacks.py +14 -0
  34. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/jsonrpc/handlers/session_control.py +20 -0
  35. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/jsonrpc/handlers/workspace_control.py +34 -9
  36. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/opencode_upstream_client.py +33 -4
  37. opencode_a2a-0.7.0/src/opencode_a2a/output_modes.py +29 -0
  38. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/profile/runtime.py +24 -0
  39. opencode_a2a-0.7.0/src/opencode_a2a/protocol_versions.py +103 -0
  40. opencode_a2a-0.7.0/src/opencode_a2a/py.typed +0 -0
  41. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/runtime_state.py +1 -0
  42. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/sandbox_policy.py +13 -0
  43. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/server/agent_card.py +116 -47
  44. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/server/application.py +127 -531
  45. opencode_a2a-0.7.0/src/opencode_a2a/server/client_manager.py +158 -0
  46. opencode_a2a-0.7.0/src/opencode_a2a/server/lifespan.py +43 -0
  47. opencode_a2a-0.7.0/src/opencode_a2a/server/middleware.py +583 -0
  48. opencode_a2a-0.7.0/src/opencode_a2a/server/migrations.py +240 -0
  49. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/server/openapi.py +106 -75
  50. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/server/request_parsing.py +41 -3
  51. opencode_a2a-0.7.0/src/opencode_a2a/server/rest_tasks.py +336 -0
  52. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/server/state_store.py +146 -90
  53. opencode_a2a-0.7.0/src/opencode_a2a/server/task_store.py +449 -0
  54. opencode_a2a-0.7.0/src/opencode_a2a/trace_context.py +125 -0
  55. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0/src/opencode_a2a.egg-info}/PKG-INFO +31 -53
  56. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a.egg-info/SOURCES.txt +20 -0
  57. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a.egg-info/requires.txt +0 -1
  58. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/client/test_client_config.py +8 -0
  59. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/client/test_client_facade.py +1 -2
  60. opencode_a2a-0.7.0/tests/client/test_request_context.py +123 -0
  61. opencode_a2a-0.7.0/tests/config/test_settings.py +345 -0
  62. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/contracts/test_extension_contract_consistency.py +40 -23
  63. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/execution/test_agent_errors.py +28 -1
  64. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/execution/test_directory_validation.py +1 -1
  65. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/execution/test_metrics.py +2 -2
  66. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/execution/test_multipart_input.py +1 -1
  67. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/execution/test_opencode_agent_session_binding.py +86 -2
  68. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/execution/test_session_ownership.py +2 -2
  69. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/execution/test_streaming_output_contract_blocks.py +39 -0
  70. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/execution/test_streaming_output_contract_logging.py +2 -2
  71. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/jsonrpc/test_dispatch_registry.py +48 -5
  72. opencode_a2a-0.7.0/tests/jsonrpc/test_error_responses.py +200 -0
  73. opencode_a2a-0.7.0/tests/jsonrpc/test_jsonrpc_unsupported_method.py +250 -0
  74. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/jsonrpc/test_opencode_session_extension_commands.py +255 -25
  75. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/jsonrpc/test_opencode_session_extension_interrupts.py +83 -19
  76. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/jsonrpc/test_opencode_session_extension_lifecycle.py +14 -14
  77. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/jsonrpc/test_opencode_session_extension_prompt_async.py +92 -21
  78. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/jsonrpc/test_opencode_session_extension_queries.py +46 -46
  79. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/jsonrpc/test_opencode_workspace_control_extension.py +116 -9
  80. opencode_a2a-0.7.0/tests/package/test_logging.py +9 -0
  81. opencode_a2a-0.7.0/tests/package/test_typing_contract.py +9 -0
  82. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/profile/test_profile_runtime.py +31 -4
  83. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/scripts/test_script_health_contract.py +17 -0
  84. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/server/test_a2a_client_manager.py +26 -12
  85. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/server/test_agent_card.py +297 -69
  86. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/server/test_app_behaviors.py +250 -18
  87. opencode_a2a-0.7.0/tests/server/test_auth.py +120 -0
  88. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/server/test_call_context_builder.py +26 -0
  89. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/server/test_database_app_persistence.py +5 -3
  90. opencode_a2a-0.7.0/tests/server/test_state_store.py +591 -0
  91. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/server/test_task_store_factory.py +165 -6
  92. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/server/test_transport_contract.py +655 -33
  93. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/support/helpers.py +81 -10
  94. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/support/streaming_output.py +1 -1
  95. opencode_a2a-0.7.0/tests/test_trace_context.py +53 -0
  96. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/upstream/test_opencode_upstream_client_params.py +121 -35
  97. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/uv.lock +0 -2
  98. opencode_a2a-0.6.0/.github/workflows/publish.yml +0 -90
  99. opencode_a2a-0.6.0/SECURITY.md +0 -58
  100. opencode_a2a-0.6.0/docs/extension-specifications.md +0 -122
  101. opencode_a2a-0.6.0/src/opencode_a2a/client/request_context.py +0 -97
  102. opencode_a2a-0.6.0/src/opencode_a2a/execution/executor.py +0 -1129
  103. opencode_a2a-0.6.0/src/opencode_a2a/jsonrpc/error_responses.py +0 -160
  104. opencode_a2a-0.6.0/src/opencode_a2a/server/task_store.py +0 -210
  105. opencode_a2a-0.6.0/tests/client/test_request_context.py +0 -79
  106. opencode_a2a-0.6.0/tests/config/test_settings.py +0 -135
  107. opencode_a2a-0.6.0/tests/jsonrpc/test_error_responses.py +0 -101
  108. opencode_a2a-0.6.0/tests/jsonrpc/test_jsonrpc_unsupported_method.py +0 -120
  109. opencode_a2a-0.6.0/tests/server/test_state_store.py +0 -225
  110. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/.github/workflows/ci.yml +0 -0
  111. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/.github/workflows/dependency-health.yml +0 -0
  112. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/.gitignore +0 -0
  113. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/.pre-commit-config.yaml +0 -0
  114. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/.secrets.baseline +0 -0
  115. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/AGENTS.md +0 -0
  116. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/LICENSE +0 -0
  117. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/scripts/check_coverage.py +0 -0
  118. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/scripts/dependency_health.sh +0 -0
  119. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/scripts/doctor.sh +0 -0
  120. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/scripts/health_common.sh +0 -0
  121. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/scripts/lint.sh +0 -0
  122. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/setup.cfg +0 -0
  123. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/cli.py +0 -0
  124. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/client/__init__.py +0 -0
  125. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/client/auth.py +0 -0
  126. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/client/error_mapping.py +0 -0
  127. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/client/errors.py +0 -0
  128. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/client/payload_text.py +0 -0
  129. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/client/polling.py +0 -0
  130. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/contracts/__init__.py +0 -0
  131. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/execution/__init__.py +0 -0
  132. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/execution/event_helpers.py +0 -0
  133. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/execution/request_context.py +0 -0
  134. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/execution/session_manager.py +0 -0
  135. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/execution/stream_events.py +0 -0
  136. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/execution/stream_state.py +0 -0
  137. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/execution/tool_error_mapping.py +0 -0
  138. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/execution/upstream_error_translator.py +0 -0
  139. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/invocation.py +0 -0
  140. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/jsonrpc/__init__.py +0 -0
  141. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/jsonrpc/handlers/__init__.py +0 -0
  142. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/jsonrpc/handlers/interrupt_queries.py +0 -0
  143. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/jsonrpc/handlers/provider_discovery.py +0 -0
  144. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/jsonrpc/handlers/session_lifecycle.py +0 -0
  145. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/jsonrpc/handlers/session_queries.py +0 -0
  146. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/jsonrpc/methods.py +0 -0
  147. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/jsonrpc/params.py +0 -0
  148. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/parts/__init__.py +0 -0
  149. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/parts/mapping.py +0 -0
  150. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/parts/text.py +0 -0
  151. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/profile/__init__.py +0 -0
  152. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/server/__init__.py +0 -0
  153. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/upstream_taxonomy.py +0 -0
  154. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a.egg-info/dependency_links.txt +0 -0
  155. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a.egg-info/entry_points.txt +0 -0
  156. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a.egg-info/top_level.txt +0 -0
  157. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/__init__.py +0 -0
  158. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/client/__init__.py +0 -0
  159. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/client/test_agent_card.py +0 -0
  160. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/client/test_error_mapping.py +0 -0
  161. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/client/test_payload_text.py +0 -0
  162. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/client/test_polling.py +0 -0
  163. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/config/__init__.py +0 -0
  164. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/conftest.py +0 -0
  165. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/contracts/__init__.py +0 -0
  166. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/execution/__init__.py +0 -0
  167. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/execution/test_agent_helpers.py +0 -0
  168. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/execution/test_cancellation.py +0 -0
  169. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/execution/test_session_lock_lifecycle.py +0 -0
  170. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/execution/test_streaming_output_contract_core.py +0 -0
  171. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/execution/test_streaming_output_contract_interrupts.py +0 -0
  172. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/jsonrpc/__init__.py +0 -0
  173. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/jsonrpc/test_jsonrpc_methods.py +0 -0
  174. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/jsonrpc/test_jsonrpc_params.py +0 -0
  175. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/package/__init__.py +0 -0
  176. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/package/test_version.py +0 -0
  177. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/parts/__init__.py +0 -0
  178. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/parts/test_parts_text.py +0 -0
  179. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/profile/__init__.py +0 -0
  180. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/scripts/__init__.py +0 -0
  181. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/server/__init__.py +0 -0
  182. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/server/test_cancel_contract.py +0 -0
  183. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/server/test_cli.py +0 -0
  184. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/support/__init__.py +0 -0
  185. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/support/session_extensions.py +0 -0
  186. {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/upstream/__init__.py +0 -0
@@ -0,0 +1,160 @@
1
+ name: Publish
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+ workflow_dispatch:
8
+ inputs:
9
+ release_tag:
10
+ description: Existing v* tag to publish or repair
11
+ required: true
12
+ type: string
13
+ publish_to_pypi:
14
+ description: Publish artifacts to PyPI before syncing the GitHub Release
15
+ required: true
16
+ default: false
17
+ type: boolean
18
+ sync_github_release:
19
+ description: Create or repair the GitHub Release and release assets
20
+ required: true
21
+ default: true
22
+ type: boolean
23
+
24
+ concurrency:
25
+ group: publish-${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref_name }}
26
+ cancel-in-progress: false
27
+
28
+ permissions:
29
+ contents: write
30
+ id-token: write
31
+
32
+ jobs:
33
+ publish:
34
+ runs-on: ubuntu-latest
35
+
36
+ steps:
37
+ - name: Checkout
38
+ uses: actions/checkout@v6
39
+ with:
40
+ fetch-depth: 0
41
+ ref: ${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref }}
42
+
43
+ - name: Setup Python
44
+ uses: actions/setup-python@v6
45
+ with:
46
+ python-version: "3.13"
47
+
48
+ - name: Setup uv
49
+ uses: astral-sh/setup-uv@v7
50
+ with:
51
+ enable-cache: false
52
+
53
+ - name: Run regression baseline
54
+ run: bash ./scripts/doctor.sh
55
+
56
+ - name: Export runtime requirements for vulnerability audit
57
+ run: >
58
+ uv export --format requirements.txt --no-dev --locked --no-emit-project
59
+ --output-file /tmp/runtime-requirements.txt >/dev/null
60
+
61
+ - name: Run runtime dependency vulnerability audit
62
+ run: uv run pip-audit --requirement /tmp/runtime-requirements.txt
63
+
64
+ - name: Clean previous build artifacts
65
+ run: rm -rf build dist
66
+
67
+ - name: Build package artifacts
68
+ run: uv build --no-sources
69
+
70
+ - name: Verify published version matches tag
71
+ env:
72
+ RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref_name }}
73
+ run: |
74
+ python - <<'PY'
75
+ import os
76
+ import pathlib
77
+
78
+ dist_dir = pathlib.Path("dist")
79
+ wheels = sorted(dist_dir.glob("opencode_a2a-*.whl"))
80
+ sdists = sorted(dist_dir.glob("opencode_a2a-*.tar.gz"))
81
+ if len(wheels) != 1:
82
+ raise SystemExit(f"Expected exactly one wheel in dist/, found {len(wheels)}")
83
+ if len(sdists) != 1:
84
+ raise SystemExit(f"Expected exactly one sdist in dist/, found {len(sdists)}")
85
+ wheel = wheels[0].name
86
+ sdist = sdists[0].name
87
+ version = wheel.removeprefix("opencode_a2a-").split("-py3", 1)[0]
88
+ sdist_version = sdist.removeprefix("opencode_a2a-").removesuffix(".tar.gz")
89
+ tag = os.environ["RELEASE_TAG"].removeprefix("v")
90
+ if version != tag:
91
+ raise SystemExit(f"Wheel version {version!r} does not match tag {tag!r}")
92
+ if sdist_version != tag:
93
+ raise SystemExit(f"sdist version {sdist_version!r} does not match tag {tag!r}")
94
+ print(f"Validated release version: {version}")
95
+ PY
96
+
97
+ - name: Smoke test wheel install
98
+ run: bash ./scripts/smoke_test_built_cli.sh dist/opencode_a2a-*.whl
99
+
100
+ - name: Smoke test sdist install
101
+ run: bash ./scripts/smoke_test_built_cli.sh dist/opencode_a2a-*.tar.gz
102
+
103
+ - name: Publish to PyPI
104
+ if: ${{ github.event_name != 'workflow_dispatch' || inputs.publish_to_pypi }}
105
+ uses: pypa/gh-action-pypi-publish@release/v1
106
+
107
+ - name: Sync GitHub Release
108
+ if: ${{ github.event_name != 'workflow_dispatch' || inputs.sync_github_release }}
109
+ env:
110
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
111
+ RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref_name }}
112
+ run: |
113
+ set -euo pipefail
114
+
115
+ retry() {
116
+ local attempts="$1"
117
+ local sleep_seconds="$2"
118
+ shift 2
119
+
120
+ local attempt=1
121
+ while true; do
122
+ if "$@"; then
123
+ return 0
124
+ fi
125
+
126
+ if [ "$attempt" -ge "$attempts" ]; then
127
+ echo "Command failed after ${attempts} attempts: $*" >&2
128
+ return 1
129
+ fi
130
+
131
+ echo "Retrying (${attempt}/${attempts}) after transient failure: $*" >&2
132
+ sleep "$sleep_seconds"
133
+ attempt=$((attempt + 1))
134
+ done
135
+ }
136
+
137
+ ensure_release() {
138
+ if retry 3 5 gh release view "$RELEASE_TAG" --json url >/dev/null; then
139
+ echo "Release ${RELEASE_TAG} already exists."
140
+ return 0
141
+ fi
142
+
143
+ retry 3 5 gh release create "$RELEASE_TAG" --verify-tag --generate-notes
144
+ }
145
+
146
+ ensure_release
147
+
148
+ mapfile -t existing_assets < <(
149
+ retry 3 5 gh release view "$RELEASE_TAG" --json assets --jq '.assets[].name'
150
+ )
151
+
152
+ for asset in dist/*.tar.gz dist/*.whl; do
153
+ asset_name="$(basename "$asset")"
154
+ if printf '%s\n' "${existing_assets[@]}" | grep -Fxq "$asset_name"; then
155
+ echo "Release asset already present: $asset_name"
156
+ continue
157
+ fi
158
+
159
+ retry 3 5 gh release upload "$RELEASE_TAG" "$asset"
160
+ done
@@ -18,12 +18,8 @@ This project expects respectful, technically focused collaboration.
18
18
 
19
19
  ## Reporting
20
20
 
21
- For normal collaboration problems, open an issue or discussion with enough
22
- context to review the situation. For security-sensitive or private concerns,
23
- follow the disclosure path in [SECURITY.md](SECURITY.md).
21
+ For normal collaboration problems, open an issue or discussion with enough context to review the situation. For security-sensitive or private concerns, follow the disclosure path in [SECURITY.md](SECURITY.md).
24
22
 
25
23
  ## Enforcement
26
24
 
27
- Repository maintainers may edit, hide, lock, or remove content that violates
28
- this policy, and may restrict participation when needed to keep collaboration
29
- safe and productive.
25
+ Repository maintainers may edit, hide, lock, or remove content that violates this policy, and may restrict participation when needed to keep collaboration safe and productive.
@@ -2,9 +2,7 @@
2
2
 
3
3
  Thanks for contributing to `opencode-a2a`.
4
4
 
5
- This repository maintains an OpenCode A2A runtime. Changes
6
- should keep runtime behavior, Agent Card declarations, OpenAPI examples, and
7
- machine-readable extension contracts aligned.
5
+ This repository maintains an OpenCode A2A runtime. Changes should keep runtime behavior, Agent Card declarations, OpenAPI examples, and machine-readable extension contracts aligned.
8
6
 
9
7
  ## Before You Start
10
8
 
@@ -35,7 +33,7 @@ opencode serve --hostname 127.0.0.1 --port 4096
35
33
  Then start the A2A runtime in another terminal:
36
34
 
37
35
  ```bash
38
- A2A_BEARER_TOKEN=dev-token \
36
+ A2A_STATIC_AUTH_CREDENTIALS='[{"scheme":"bearer","token":"dev-token","principal":"automation"}]' \
39
37
  OPENCODE_BASE_URL=http://127.0.0.1:4096 \
40
38
  OPENCODE_WORKSPACE_ROOT=/abs/path/to/workspace \
41
39
  uv run opencode-a2a serve
@@ -50,16 +48,22 @@ uv run pre-commit run --all-files
50
48
  uv run pytest
51
49
  ```
52
50
 
53
- If you change shell scripts, also run `bash -n` on each modified script, for
54
- example:
51
+ If you change shell scripts, also run `bash -n` on each modified script, for example:
55
52
 
56
53
  ```bash
57
54
  bash -n scripts/doctor.sh
58
55
  bash -n scripts/lint.sh
59
56
  ```
60
57
 
61
- If you change extension methods, extension metadata, or Agent Card/OpenAPI
62
- contract surfaces, also run:
58
+ External interoperability experiments stay outside the default regression baseline. When you need to reproduce current official-tool behavior, run:
59
+
60
+ ```bash
61
+ bash ./scripts/conformance.sh
62
+ ```
63
+
64
+ 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
+ If you change extension methods, extension metadata, or Agent Card/OpenAPI contract surfaces, also run:
63
67
 
64
68
  ```bash
65
69
  uv run pytest tests/contracts/test_extension_contract_consistency.py
@@ -82,6 +86,18 @@ uv run mypy src/opencode_a2a
82
86
  - Link the relevant issue in commits and PR descriptions when applicable.
83
87
  - Open PRs as Draft by default when the change still needs review or iteration.
84
88
 
89
+ ## Release Recovery
90
+
91
+ `Publish` is the release workflow for tagged versions. It now supports both the normal tag-push path and explicit maintainer recovery runs.
92
+
93
+ - Tag pushes still perform the full release flow: regression checks, artifact builds, PyPI publish, and GitHub Release sync.
94
+ - Manual `workflow_dispatch` runs require a `release_tag` input so the workflow checks out and rebuilds the exact tagged revision instead of the current branch tip.
95
+ - Manual `workflow_dispatch` runs default `publish_to_pypi=false` so the safest recovery path is to repair the GitHub Release without attempting a duplicate PyPI publish.
96
+ - Set `publish_to_pypi=true` only when a maintainer intentionally needs the manual dispatch to publish artifacts to PyPI before syncing the GitHub Release.
97
+ - GitHub Release sync is idempotent for the tagged release: it creates the release when missing and uploads only missing wheel/sdist assets.
98
+
99
+ If a release run publishes to PyPI successfully but fails while creating or uploading the GitHub Release, recover with a manual dispatch against the same tag and set `publish_to_pypi=false`.
100
+
85
101
  ## Documentation
86
102
 
87
103
  Update docs together with code whenever you change:
@@ -91,12 +107,9 @@ Update docs together with code whenever you change:
91
107
  - user-facing request or response shapes
92
108
  - operational scripts
93
109
 
94
- Keep compatibility guidance centralized in [docs/guide.md](docs/guide.md) unless a
95
- new standalone document is clearly necessary.
110
+ Keep compatibility guidance centralized in [docs/guide.md](docs/guide.md) unless a new standalone document is clearly necessary.
96
111
 
97
- When changing extension contracts, update
98
- [`src/opencode_a2a/contracts/extensions.py`](src/opencode_a2a/contracts/extensions.py)
99
- first and keep these generated/documented surfaces aligned:
112
+ 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:
100
113
 
101
114
  - Agent Card extension params
102
115
  - OpenAPI `POST /` extension metadata and examples
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: opencode-a2a
3
- Version: 0.6.0
3
+ Version: 0.7.0
4
4
  Summary: OpenCode A2A runtime
5
5
  Author: liujuanjuan1984@Intelligent-Internet
6
6
  License-Expression: Apache-2.0
@@ -25,7 +25,6 @@ Requires-Dist: fastapi<1.0,>=0.110
25
25
  Requires-Dist: httpx<1.0,>=0.27
26
26
  Requires-Dist: pydantic<3.0,>=2.6
27
27
  Requires-Dist: pydantic-settings<3.0,>=2.2
28
- Requires-Dist: requests<3.0,>=2.33.0
29
28
  Requires-Dist: sqlalchemy<3.0,>=2.0
30
29
  Requires-Dist: sse-starlette<4.0,>=2.1
31
30
  Requires-Dist: uvicorn<1.0,>=0.29
@@ -43,16 +42,12 @@ Dynamic: license-file
43
42
 
44
43
  > Expose OpenCode through A2A.
45
44
 
46
- `opencode-a2a` adds an A2A runtime layer to `opencode serve`, with
47
- auth, streaming, session continuity, interrupt handling, and a clear
48
- deployment boundary.
45
+ `opencode-a2a` adds an A2A runtime layer to `opencode serve`, with auth, streaming, session continuity, interrupt handling, and a clear deployment boundary.
49
46
 
50
47
  ## What This Is
51
48
 
52
- - An A2A adapter service built on `opencode serve`, with inbound runtime
53
- exposure plus outbound peer calling.
54
- - It supports both roles in one process: serving as an A2A Server and hosting an
55
- embedded A2A Client for `a2a_call`.
49
+ - An A2A adapter service built on `opencode serve`, with inbound runtime exposure plus outbound peer calling.
50
+ - It supports both roles in one process: serving as an A2A Server and hosting an embedded A2A Client for `a2a_call`.
56
51
 
57
52
  ## Architecture
58
53
 
@@ -95,8 +90,7 @@ Upgrade later with:
95
90
  uv tool upgrade opencode-a2a
96
91
  ```
97
92
 
98
- Make sure provider credentials and a default model are configured on the
99
- OpenCode side, then start OpenCode:
93
+ Make sure provider credentials and a default model are configured on the OpenCode side, then start OpenCode:
100
94
 
101
95
  ```bash
102
96
  opencode auth login
@@ -104,15 +98,13 @@ opencode models
104
98
  opencode serve --hostname 127.0.0.1 --port 4096
105
99
  ```
106
100
 
107
- Treat the deployed OpenCode user's HOME/XDG config directories as part of the
108
- runtime state. If a packaged or service-managed deployment appears to ignore
109
- fresh provider env vars, inspect that user's persisted OpenCode auth/config
110
- files before assuming the A2A adapter layer is overriding credentials.
101
+ Treat the deployed OpenCode user's HOME/XDG config directories as part of the runtime state. If a packaged or service-managed deployment appears to ignore fresh provider env vars, inspect that user's persisted OpenCode auth/config files before assuming the A2A adapter layer is overriding credentials.
111
102
 
112
103
  Then start `opencode-a2a` against that upstream:
113
104
 
114
105
  ```bash
115
- A2A_BEARER_TOKEN=dev-token \
106
+ DEMO_BEARER_TOKEN="$(python3 -c 'import secrets; print(secrets.token_hex(24))')"
107
+ A2A_STATIC_AUTH_CREDENTIALS='[{"scheme":"bearer","token":"'"${DEMO_BEARER_TOKEN}"'","principal":"automation"}]' \
116
108
  OPENCODE_BASE_URL=http://127.0.0.1:4096 \
117
109
  A2A_TASK_STORE_DATABASE_URL=sqlite+aiosqlite:///./opencode-a2a.db \
118
110
  A2A_HOST=127.0.0.1 \
@@ -130,11 +122,9 @@ curl http://127.0.0.1:8000/.well-known/agent-card.json
130
122
 
131
123
  ## Capabilities
132
124
 
133
- - A2A HTTP+JSON endpoints such as `/v1/message:send` and
134
- `/v1/message:stream`
125
+ - A2A HTTP+JSON endpoints such as `/v1/message:send` and `/v1/message:stream`
135
126
  - A2A JSON-RPC support on `POST /`
136
- - SDK-owned A2A task surfaces such as `GET /v1/tasks`, task push notification
137
- config routes, and JSON-RPC `agent/getAuthenticatedExtendedCard`
127
+ - SDK-owned A2A task surfaces such as `GET /v1/tasks`, task push notification config routes, and JSON-RPC `agent/getAuthenticatedExtendedCard`
138
128
  - Peering capabilities: can act as a client via `opencode-a2a call`
139
129
  - Autonomous tool execution: supports `a2a_call` tool for outbound agent-to-agent communication
140
130
  - SSE streaming with normalized `text`, `reasoning`, and `tool_call` blocks
@@ -142,6 +132,14 @@ curl http://127.0.0.1:8000/.well-known/agent-card.json
142
132
  - Request-scoped model selection through `metadata.shared.model`
143
133
  - OpenCode-oriented JSON-RPC extensions for session and model/provider queries
144
134
 
135
+ ## A2A Protocol Support
136
+
137
+ - Default protocol line: `0.3`
138
+ - Declared supported protocol lines: `0.3`, `1.0`
139
+ - `0.3` is the stable interoperability baseline for the current runtime surface.
140
+ - `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.
141
+ - The detailed compatibility matrix and machine-readable support boundary are documented in [`docs/guide.md`](docs/guide.md).
142
+
145
143
  ## Peering Node / Outbound Access
146
144
 
147
145
  `opencode-a2a` supports a "Peering Node" architecture where a single process handles both inbound (Server) and outbound (Client) A2A traffic.
@@ -163,21 +161,11 @@ opencode-a2a call http://other-agent:8000 "How are you?"
163
161
  ### Outbound Agent Calls (Tools)
164
162
  The server can autonomously execute `a2a_call(url, message)` tool calls emitted by the OpenCode runtime. Results are fetched via A2A and returned to the model as tool results, enabling multi-agent orchestration.
165
163
 
166
- When the target peer agent requires bearer auth, configure
167
- `A2A_CLIENT_BEARER_TOKEN` for server-side outbound calls. When the target peer
168
- agent requires Basic auth, use `A2A_CLIENT_BASIC_AUTH`.
169
- These outbound credentials apply to the peer specified by `opencode-a2a call`
170
- or `a2a_call(url, message)`, not to this service's inbound `A2A_BEARER_TOKEN`.
171
- The CLI intentionally reads outbound credentials from environment variables only,
172
- so secrets do not appear in shell history or process arguments.
164
+ When the target peer agent requires bearer auth, configure `A2A_CLIENT_BEARER_TOKEN` for server-side outbound calls. When the target peer agent requires Basic auth, use `A2A_CLIENT_BASIC_AUTH`. These outbound credentials apply to the peer specified by `opencode-a2a call` or `a2a_call(url, message)`, not to this service's inbound `A2A_STATIC_AUTH_CREDENTIALS`. The CLI intentionally reads outbound credentials from environment variables only, so secrets do not appear in shell history or process arguments.
173
165
 
174
- Server-side outbound client settings are fully wired through runtime config:
175
- `A2A_CLIENT_TIMEOUT_SECONDS`, `A2A_CLIENT_CARD_FETCH_TIMEOUT_SECONDS`,
176
- `A2A_CLIENT_USE_CLIENT_PREFERENCE`, `A2A_CLIENT_BEARER_TOKEN`, `A2A_CLIENT_BASIC_AUTH`, and
177
- `A2A_CLIENT_SUPPORTED_TRANSPORTS`.
166
+ Server-side outbound client settings are fully wired through runtime config: `A2A_CLIENT_TIMEOUT_SECONDS`, `A2A_CLIENT_CARD_FETCH_TIMEOUT_SECONDS`, `A2A_CLIENT_USE_CLIENT_PREFERENCE`, `A2A_CLIENT_BEARER_TOKEN`, `A2A_CLIENT_BASIC_AUTH`, and `A2A_CLIENT_SUPPORTED_TRANSPORTS`.
178
167
 
179
- Detailed protocol contracts, examples, and extension docs live in
180
- [`docs/guide.md`](docs/guide.md).
168
+ Detailed protocol contracts, examples, and extension docs live in [`docs/guide.md`](docs/guide.md).
181
169
 
182
170
  ## When To Use It
183
171
 
@@ -193,24 +181,17 @@ Look elsewhere if:
193
181
  - you want this project to manage your process supervisor or host bootstrap
194
182
  - you want a general client integration layer rather than a server wrapper
195
183
 
196
- For client-side integration, prefer
197
- [a2a-client-hub](https://github.com/liujuanjuan1984/a2a-client-hub).
184
+ For client-side integration, prefer [a2a-client-hub](https://github.com/liujuanjuan1984/a2a-client-hub).
198
185
 
199
186
  ## Deployment Boundary
200
187
 
201
- This repository improves the service boundary around OpenCode, but it does not
202
- turn OpenCode into a hardened multi-tenant platform.
188
+ This repository improves the service boundary around OpenCode, but it does not turn OpenCode into a hardened multi-tenant platform.
203
189
 
204
- - `A2A_BEARER_TOKEN` protects the A2A surface.
205
- - Provider auth and default model configuration remain on the OpenCode side; deployment-time
206
- precedence details and HOME/XDG state impact are documented in
207
- [docs/guide.md](docs/guide.md#troubleshooting-provider-auth-state).
208
- - Use `A2A_CLIENT_BEARER_TOKEN` for server-side outbound peer calls initiated by
209
- `a2a_call`.
210
- - Deployment supervision is intentionally BYO. Use `systemd`, Docker,
211
- Kubernetes, or another supervisor if you need long-running operation.
212
- - For mutually untrusted tenants, run separate instance pairs with isolated
213
- users, containers, workspaces, credentials, and ports.
190
+ - `A2A_STATIC_AUTH_CREDENTIALS` protects the A2A surface.
191
+ - Provider auth and default model configuration remain on the OpenCode side; deployment-time precedence details and HOME/XDG state impact are documented in [docs/guide.md](docs/guide.md#troubleshooting-provider-auth-state).
192
+ - Use `A2A_CLIENT_BEARER_TOKEN` for server-side outbound peer calls initiated by `a2a_call`.
193
+ - Deployment supervision is intentionally BYO. Use `systemd`, Docker, Kubernetes, or another supervisor if you need long-running operation.
194
+ - For mutually untrusted tenants, run separate instance pairs with isolated users, containers, workspaces, credentials, and ports.
214
195
 
215
196
  Read before deployment:
216
197
 
@@ -221,15 +202,12 @@ Read before deployment:
221
202
 
222
203
  ## Further Reading
223
204
 
224
- - [docs/guide.md](docs/guide.md)
225
- Usage guide, transport details, streaming behavior, extensions, and examples.
226
- - [SECURITY.md](SECURITY.md)
227
- Threat model, deployment caveats, and vulnerability disclosure guidance.
205
+ - [docs/guide.md](docs/guide.md) Usage guide, transport details, streaming behavior, extensions, and examples.
206
+ - [SECURITY.md](SECURITY.md) Threat model, deployment caveats, and vulnerability disclosure guidance.
228
207
 
229
208
  ## Development
230
209
 
231
- For contributor workflow, local validation, and helper scripts, see
232
- [CONTRIBUTING.md](CONTRIBUTING.md) and [scripts/README.md](scripts/README.md).
210
+ For contributor workflow, local validation, and helper scripts, see [CONTRIBUTING.md](CONTRIBUTING.md) and [scripts/README.md](scripts/README.md).
233
211
 
234
212
  ## License
235
213
 
@@ -2,16 +2,12 @@
2
2
 
3
3
  > Expose OpenCode through A2A.
4
4
 
5
- `opencode-a2a` adds an A2A runtime layer to `opencode serve`, with
6
- auth, streaming, session continuity, interrupt handling, and a clear
7
- deployment boundary.
5
+ `opencode-a2a` adds an A2A runtime layer to `opencode serve`, with auth, streaming, session continuity, interrupt handling, and a clear deployment boundary.
8
6
 
9
7
  ## What This Is
10
8
 
11
- - An A2A adapter service built on `opencode serve`, with inbound runtime
12
- exposure plus outbound peer calling.
13
- - It supports both roles in one process: serving as an A2A Server and hosting an
14
- embedded A2A Client for `a2a_call`.
9
+ - An A2A adapter service built on `opencode serve`, with inbound runtime exposure plus outbound peer calling.
10
+ - It supports both roles in one process: serving as an A2A Server and hosting an embedded A2A Client for `a2a_call`.
15
11
 
16
12
  ## Architecture
17
13
 
@@ -54,8 +50,7 @@ Upgrade later with:
54
50
  uv tool upgrade opencode-a2a
55
51
  ```
56
52
 
57
- Make sure provider credentials and a default model are configured on the
58
- OpenCode side, then start OpenCode:
53
+ Make sure provider credentials and a default model are configured on the OpenCode side, then start OpenCode:
59
54
 
60
55
  ```bash
61
56
  opencode auth login
@@ -63,15 +58,13 @@ opencode models
63
58
  opencode serve --hostname 127.0.0.1 --port 4096
64
59
  ```
65
60
 
66
- Treat the deployed OpenCode user's HOME/XDG config directories as part of the
67
- runtime state. If a packaged or service-managed deployment appears to ignore
68
- fresh provider env vars, inspect that user's persisted OpenCode auth/config
69
- files before assuming the A2A adapter layer is overriding credentials.
61
+ Treat the deployed OpenCode user's HOME/XDG config directories as part of the runtime state. If a packaged or service-managed deployment appears to ignore fresh provider env vars, inspect that user's persisted OpenCode auth/config files before assuming the A2A adapter layer is overriding credentials.
70
62
 
71
63
  Then start `opencode-a2a` against that upstream:
72
64
 
73
65
  ```bash
74
- A2A_BEARER_TOKEN=dev-token \
66
+ DEMO_BEARER_TOKEN="$(python3 -c 'import secrets; print(secrets.token_hex(24))')"
67
+ A2A_STATIC_AUTH_CREDENTIALS='[{"scheme":"bearer","token":"'"${DEMO_BEARER_TOKEN}"'","principal":"automation"}]' \
75
68
  OPENCODE_BASE_URL=http://127.0.0.1:4096 \
76
69
  A2A_TASK_STORE_DATABASE_URL=sqlite+aiosqlite:///./opencode-a2a.db \
77
70
  A2A_HOST=127.0.0.1 \
@@ -89,11 +82,9 @@ curl http://127.0.0.1:8000/.well-known/agent-card.json
89
82
 
90
83
  ## Capabilities
91
84
 
92
- - A2A HTTP+JSON endpoints such as `/v1/message:send` and
93
- `/v1/message:stream`
85
+ - A2A HTTP+JSON endpoints such as `/v1/message:send` and `/v1/message:stream`
94
86
  - A2A JSON-RPC support on `POST /`
95
- - SDK-owned A2A task surfaces such as `GET /v1/tasks`, task push notification
96
- config routes, and JSON-RPC `agent/getAuthenticatedExtendedCard`
87
+ - SDK-owned A2A task surfaces such as `GET /v1/tasks`, task push notification config routes, and JSON-RPC `agent/getAuthenticatedExtendedCard`
97
88
  - Peering capabilities: can act as a client via `opencode-a2a call`
98
89
  - Autonomous tool execution: supports `a2a_call` tool for outbound agent-to-agent communication
99
90
  - SSE streaming with normalized `text`, `reasoning`, and `tool_call` blocks
@@ -101,6 +92,14 @@ curl http://127.0.0.1:8000/.well-known/agent-card.json
101
92
  - Request-scoped model selection through `metadata.shared.model`
102
93
  - OpenCode-oriented JSON-RPC extensions for session and model/provider queries
103
94
 
95
+ ## A2A Protocol Support
96
+
97
+ - Default protocol line: `0.3`
98
+ - Declared supported protocol lines: `0.3`, `1.0`
99
+ - `0.3` is the stable interoperability baseline for the current runtime surface.
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).
102
+
104
103
  ## Peering Node / Outbound Access
105
104
 
106
105
  `opencode-a2a` supports a "Peering Node" architecture where a single process handles both inbound (Server) and outbound (Client) A2A traffic.
@@ -122,21 +121,11 @@ opencode-a2a call http://other-agent:8000 "How are you?"
122
121
  ### Outbound Agent Calls (Tools)
123
122
  The server can autonomously execute `a2a_call(url, message)` tool calls emitted by the OpenCode runtime. Results are fetched via A2A and returned to the model as tool results, enabling multi-agent orchestration.
124
123
 
125
- When the target peer agent requires bearer auth, configure
126
- `A2A_CLIENT_BEARER_TOKEN` for server-side outbound calls. When the target peer
127
- agent requires Basic auth, use `A2A_CLIENT_BASIC_AUTH`.
128
- These outbound credentials apply to the peer specified by `opencode-a2a call`
129
- or `a2a_call(url, message)`, not to this service's inbound `A2A_BEARER_TOKEN`.
130
- The CLI intentionally reads outbound credentials from environment variables only,
131
- so secrets do not appear in shell history or process arguments.
124
+ When the target peer agent requires bearer auth, configure `A2A_CLIENT_BEARER_TOKEN` for server-side outbound calls. When the target peer agent requires Basic auth, use `A2A_CLIENT_BASIC_AUTH`. These outbound credentials apply to the peer specified by `opencode-a2a call` or `a2a_call(url, message)`, not to this service's inbound `A2A_STATIC_AUTH_CREDENTIALS`. The CLI intentionally reads outbound credentials from environment variables only, so secrets do not appear in shell history or process arguments.
132
125
 
133
- Server-side outbound client settings are fully wired through runtime config:
134
- `A2A_CLIENT_TIMEOUT_SECONDS`, `A2A_CLIENT_CARD_FETCH_TIMEOUT_SECONDS`,
135
- `A2A_CLIENT_USE_CLIENT_PREFERENCE`, `A2A_CLIENT_BEARER_TOKEN`, `A2A_CLIENT_BASIC_AUTH`, and
136
- `A2A_CLIENT_SUPPORTED_TRANSPORTS`.
126
+ Server-side outbound client settings are fully wired through runtime config: `A2A_CLIENT_TIMEOUT_SECONDS`, `A2A_CLIENT_CARD_FETCH_TIMEOUT_SECONDS`, `A2A_CLIENT_USE_CLIENT_PREFERENCE`, `A2A_CLIENT_BEARER_TOKEN`, `A2A_CLIENT_BASIC_AUTH`, and `A2A_CLIENT_SUPPORTED_TRANSPORTS`.
137
127
 
138
- Detailed protocol contracts, examples, and extension docs live in
139
- [`docs/guide.md`](docs/guide.md).
128
+ Detailed protocol contracts, examples, and extension docs live in [`docs/guide.md`](docs/guide.md).
140
129
 
141
130
  ## When To Use It
142
131
 
@@ -152,24 +141,17 @@ Look elsewhere if:
152
141
  - you want this project to manage your process supervisor or host bootstrap
153
142
  - you want a general client integration layer rather than a server wrapper
154
143
 
155
- For client-side integration, prefer
156
- [a2a-client-hub](https://github.com/liujuanjuan1984/a2a-client-hub).
144
+ For client-side integration, prefer [a2a-client-hub](https://github.com/liujuanjuan1984/a2a-client-hub).
157
145
 
158
146
  ## Deployment Boundary
159
147
 
160
- This repository improves the service boundary around OpenCode, but it does not
161
- turn OpenCode into a hardened multi-tenant platform.
148
+ This repository improves the service boundary around OpenCode, but it does not turn OpenCode into a hardened multi-tenant platform.
162
149
 
163
- - `A2A_BEARER_TOKEN` protects the A2A surface.
164
- - Provider auth and default model configuration remain on the OpenCode side; deployment-time
165
- precedence details and HOME/XDG state impact are documented in
166
- [docs/guide.md](docs/guide.md#troubleshooting-provider-auth-state).
167
- - Use `A2A_CLIENT_BEARER_TOKEN` for server-side outbound peer calls initiated by
168
- `a2a_call`.
169
- - Deployment supervision is intentionally BYO. Use `systemd`, Docker,
170
- Kubernetes, or another supervisor if you need long-running operation.
171
- - For mutually untrusted tenants, run separate instance pairs with isolated
172
- users, containers, workspaces, credentials, and ports.
150
+ - `A2A_STATIC_AUTH_CREDENTIALS` protects the A2A surface.
151
+ - Provider auth and default model configuration remain on the OpenCode side; deployment-time precedence details and HOME/XDG state impact are documented in [docs/guide.md](docs/guide.md#troubleshooting-provider-auth-state).
152
+ - Use `A2A_CLIENT_BEARER_TOKEN` for server-side outbound peer calls initiated by `a2a_call`.
153
+ - Deployment supervision is intentionally BYO. Use `systemd`, Docker, Kubernetes, or another supervisor if you need long-running operation.
154
+ - For mutually untrusted tenants, run separate instance pairs with isolated users, containers, workspaces, credentials, and ports.
173
155
 
174
156
  Read before deployment:
175
157
 
@@ -180,15 +162,12 @@ Read before deployment:
180
162
 
181
163
  ## Further Reading
182
164
 
183
- - [docs/guide.md](docs/guide.md)
184
- Usage guide, transport details, streaming behavior, extensions, and examples.
185
- - [SECURITY.md](SECURITY.md)
186
- Threat model, deployment caveats, and vulnerability disclosure guidance.
165
+ - [docs/guide.md](docs/guide.md) Usage guide, transport details, streaming behavior, extensions, and examples.
166
+ - [SECURITY.md](SECURITY.md) Threat model, deployment caveats, and vulnerability disclosure guidance.
187
167
 
188
168
  ## Development
189
169
 
190
- For contributor workflow, local validation, and helper scripts, see
191
- [CONTRIBUTING.md](CONTRIBUTING.md) and [scripts/README.md](scripts/README.md).
170
+ For contributor workflow, local validation, and helper scripts, see [CONTRIBUTING.md](CONTRIBUTING.md) and [scripts/README.md](scripts/README.md).
192
171
 
193
172
  ## License
194
173
 
@@ -0,0 +1,39 @@
1
+ # Security Policy
2
+
3
+ ## Scope
4
+
5
+ This repository wraps OpenCode as an A2A runtime. It exposes A2A HTTP+JSON and JSON-RPC interfaces, and adds authentication, task/session contracts, streaming, interrupt handling, and runtime guidance. It does not fully isolate upstream model credentials from OpenCode runtime behavior.
6
+
7
+ ## Security Boundary
8
+
9
+ - `A2A_STATIC_AUTH_CREDENTIALS` protects access to the A2A surface, but it is not a tenant-isolation boundary inside one deployed instance.
10
+ - One `OpenCode + opencode-a2a` instance pair is treated as a single-tenant trust boundary by design.
11
+ - Tenant isolation across consumers is expected to come from parameterized self-deployment.
12
+ - For mutually untrusted tenants, use separate instance pairs with distinct Linux users, workspace roots, credentials, and runtime ports.
13
+ - Within one instance, consumers share the same underlying OpenCode workspace/environment by default.
14
+ - LLM provider keys are consumed by the `opencode` process. Prompt injection or indirect exfiltration attempts may still expose sensitive values.
15
+ - Payload logging is opt-in. When `A2A_LOG_PAYLOADS=true`, operators should treat logs as potentially sensitive operational data.
16
+ - This project does not ship host bootstrap or process-manager wrappers as an official product capability. Operators remain responsible for file permissions, secret storage, service users, and supervisor-specific hardening.
17
+
18
+ ## Threat Model
19
+
20
+ This project is currently best suited for trusted or internal environments. Important limits:
21
+
22
+ - no per-tenant workspace isolation inside one instance
23
+ - no hard guarantee that upstream provider keys are inaccessible to agent logic
24
+ - static credential auth only by default; stronger identity propagation is still a follow-up hardening area
25
+ - operators remain responsible for host hardening, secret rotation, process access controls, and reverse-proxy exposure strategy
26
+
27
+ ## Reporting a Vulnerability
28
+
29
+ Please avoid posting active secrets, bearer tokens, or reproduction payloads that contain private data in public issues.
30
+
31
+ Preferred disclosure order:
32
+
33
+ 1. Use GitHub private vulnerability reporting if it is available for this repository.
34
+ 2. If private reporting is unavailable, contact the repository maintainer directly through GitHub before opening a public issue.
35
+ 3. For low-risk hardening ideas that do not expose private data, a normal GitHub issue is acceptable.
36
+
37
+ ## Supported Branches
38
+
39
+ Security fixes are expected to land on the active `main` branch first.
@@ -17,10 +17,8 @@ Open a GitHub issue when you can provide:
17
17
 
18
18
  ## Security Concerns
19
19
 
20
- Do not post active secrets, bearer tokens, or sensitive workspace data in a
21
- public issue. Use the disclosure guidance in [SECURITY.md](SECURITY.md).
20
+ Do not post active secrets, bearer tokens, or sensitive workspace data in a public issue. Use the disclosure guidance in [SECURITY.md](SECURITY.md).
22
21
 
23
22
  ## Commercial Or SLA Support
24
23
 
25
- This repository does not currently advertise a separate SLA or managed support
26
- channel. GitHub issues are the default public support path.
24
+ This repository does not currently advertise a separate SLA or managed support channel. GitHub issues are the default public support path.