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.
- opencode_a2a-0.7.0/.github/workflows/publish.yml +160 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/CODE_OF_CONDUCT.md +2 -6
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/CONTRIBUTING.md +26 -13
- {opencode_a2a-0.6.0/src/opencode_a2a.egg-info → opencode_a2a-0.7.0}/PKG-INFO +31 -53
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/README.md +30 -51
- opencode_a2a-0.7.0/SECURITY.md +39 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/SUPPORT.md +2 -4
- opencode_a2a-0.7.0/docs/conformance-triage.md +89 -0
- opencode_a2a-0.7.0/docs/conformance.md +67 -0
- opencode_a2a-0.7.0/docs/extension-specifications.md +105 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/docs/guide.md +339 -400
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/pyproject.toml +3 -1
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/scripts/README.md +3 -2
- opencode_a2a-0.7.0/scripts/conformance.sh +248 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/scripts/smoke_test_built_cli.sh +13 -1
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/__init__.py +3 -0
- opencode_a2a-0.7.0/src/opencode_a2a/auth.py +139 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/client/agent_card.py +4 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/client/client.py +18 -11
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/client/config.py +23 -0
- opencode_a2a-0.7.0/src/opencode_a2a/client/request_context.py +80 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/config.py +142 -3
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/contracts/extensions.py +346 -41
- opencode_a2a-0.7.0/src/opencode_a2a/execution/coordinator.py +499 -0
- opencode_a2a-0.7.0/src/opencode_a2a/execution/executor.py +579 -0
- opencode_a2a-0.7.0/src/opencode_a2a/execution/metrics.py +20 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/execution/stream_runtime.py +3 -0
- opencode_a2a-0.7.0/src/opencode_a2a/execution/tool_orchestration.py +153 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/jsonrpc/application.py +44 -13
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/jsonrpc/dispatch.py +25 -21
- opencode_a2a-0.7.0/src/opencode_a2a/jsonrpc/error_responses.py +382 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/jsonrpc/handlers/common.py +22 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/jsonrpc/handlers/interrupt_callbacks.py +14 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/jsonrpc/handlers/session_control.py +20 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/jsonrpc/handlers/workspace_control.py +34 -9
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/opencode_upstream_client.py +33 -4
- opencode_a2a-0.7.0/src/opencode_a2a/output_modes.py +29 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/profile/runtime.py +24 -0
- opencode_a2a-0.7.0/src/opencode_a2a/protocol_versions.py +103 -0
- opencode_a2a-0.7.0/src/opencode_a2a/py.typed +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/runtime_state.py +1 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/sandbox_policy.py +13 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/server/agent_card.py +116 -47
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/server/application.py +127 -531
- opencode_a2a-0.7.0/src/opencode_a2a/server/client_manager.py +158 -0
- opencode_a2a-0.7.0/src/opencode_a2a/server/lifespan.py +43 -0
- opencode_a2a-0.7.0/src/opencode_a2a/server/middleware.py +583 -0
- opencode_a2a-0.7.0/src/opencode_a2a/server/migrations.py +240 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/server/openapi.py +106 -75
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/server/request_parsing.py +41 -3
- opencode_a2a-0.7.0/src/opencode_a2a/server/rest_tasks.py +336 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/server/state_store.py +146 -90
- opencode_a2a-0.7.0/src/opencode_a2a/server/task_store.py +449 -0
- opencode_a2a-0.7.0/src/opencode_a2a/trace_context.py +125 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0/src/opencode_a2a.egg-info}/PKG-INFO +31 -53
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a.egg-info/SOURCES.txt +20 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a.egg-info/requires.txt +0 -1
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/client/test_client_config.py +8 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/client/test_client_facade.py +1 -2
- opencode_a2a-0.7.0/tests/client/test_request_context.py +123 -0
- opencode_a2a-0.7.0/tests/config/test_settings.py +345 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/contracts/test_extension_contract_consistency.py +40 -23
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/execution/test_agent_errors.py +28 -1
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/execution/test_directory_validation.py +1 -1
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/execution/test_metrics.py +2 -2
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/execution/test_multipart_input.py +1 -1
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/execution/test_opencode_agent_session_binding.py +86 -2
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/execution/test_session_ownership.py +2 -2
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/execution/test_streaming_output_contract_blocks.py +39 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/execution/test_streaming_output_contract_logging.py +2 -2
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/jsonrpc/test_dispatch_registry.py +48 -5
- opencode_a2a-0.7.0/tests/jsonrpc/test_error_responses.py +200 -0
- opencode_a2a-0.7.0/tests/jsonrpc/test_jsonrpc_unsupported_method.py +250 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/jsonrpc/test_opencode_session_extension_commands.py +255 -25
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/jsonrpc/test_opencode_session_extension_interrupts.py +83 -19
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/jsonrpc/test_opencode_session_extension_lifecycle.py +14 -14
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/jsonrpc/test_opencode_session_extension_prompt_async.py +92 -21
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/jsonrpc/test_opencode_session_extension_queries.py +46 -46
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/jsonrpc/test_opencode_workspace_control_extension.py +116 -9
- opencode_a2a-0.7.0/tests/package/test_logging.py +9 -0
- opencode_a2a-0.7.0/tests/package/test_typing_contract.py +9 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/profile/test_profile_runtime.py +31 -4
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/scripts/test_script_health_contract.py +17 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/server/test_a2a_client_manager.py +26 -12
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/server/test_agent_card.py +297 -69
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/server/test_app_behaviors.py +250 -18
- opencode_a2a-0.7.0/tests/server/test_auth.py +120 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/server/test_call_context_builder.py +26 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/server/test_database_app_persistence.py +5 -3
- opencode_a2a-0.7.0/tests/server/test_state_store.py +591 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/server/test_task_store_factory.py +165 -6
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/server/test_transport_contract.py +655 -33
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/support/helpers.py +81 -10
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/support/streaming_output.py +1 -1
- opencode_a2a-0.7.0/tests/test_trace_context.py +53 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/upstream/test_opencode_upstream_client_params.py +121 -35
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/uv.lock +0 -2
- opencode_a2a-0.6.0/.github/workflows/publish.yml +0 -90
- opencode_a2a-0.6.0/SECURITY.md +0 -58
- opencode_a2a-0.6.0/docs/extension-specifications.md +0 -122
- opencode_a2a-0.6.0/src/opencode_a2a/client/request_context.py +0 -97
- opencode_a2a-0.6.0/src/opencode_a2a/execution/executor.py +0 -1129
- opencode_a2a-0.6.0/src/opencode_a2a/jsonrpc/error_responses.py +0 -160
- opencode_a2a-0.6.0/src/opencode_a2a/server/task_store.py +0 -210
- opencode_a2a-0.6.0/tests/client/test_request_context.py +0 -79
- opencode_a2a-0.6.0/tests/config/test_settings.py +0 -135
- opencode_a2a-0.6.0/tests/jsonrpc/test_error_responses.py +0 -101
- opencode_a2a-0.6.0/tests/jsonrpc/test_jsonrpc_unsupported_method.py +0 -120
- opencode_a2a-0.6.0/tests/server/test_state_store.py +0 -225
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/.github/workflows/ci.yml +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/.github/workflows/dependency-health.yml +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/.gitignore +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/.pre-commit-config.yaml +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/.secrets.baseline +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/AGENTS.md +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/LICENSE +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/scripts/check_coverage.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/scripts/dependency_health.sh +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/scripts/doctor.sh +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/scripts/health_common.sh +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/scripts/lint.sh +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/setup.cfg +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/cli.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/client/__init__.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/client/auth.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/client/error_mapping.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/client/errors.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/client/payload_text.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/client/polling.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/contracts/__init__.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/execution/__init__.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/execution/event_helpers.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/execution/request_context.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/execution/session_manager.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/execution/stream_events.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/execution/stream_state.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/execution/tool_error_mapping.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/execution/upstream_error_translator.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/invocation.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/jsonrpc/__init__.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/jsonrpc/handlers/__init__.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/jsonrpc/handlers/interrupt_queries.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/jsonrpc/handlers/provider_discovery.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/jsonrpc/handlers/session_lifecycle.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/jsonrpc/handlers/session_queries.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/jsonrpc/methods.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/jsonrpc/params.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/parts/__init__.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/parts/mapping.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/parts/text.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/profile/__init__.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/server/__init__.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a/upstream_taxonomy.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a.egg-info/dependency_links.txt +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a.egg-info/entry_points.txt +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/src/opencode_a2a.egg-info/top_level.txt +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/__init__.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/client/__init__.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/client/test_agent_card.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/client/test_error_mapping.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/client/test_payload_text.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/client/test_polling.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/config/__init__.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/conftest.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/contracts/__init__.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/execution/__init__.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/execution/test_agent_helpers.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/execution/test_cancellation.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/execution/test_session_lock_lifecycle.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/execution/test_streaming_output_contract_core.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/execution/test_streaming_output_contract_interrupts.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/jsonrpc/__init__.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/jsonrpc/test_jsonrpc_methods.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/jsonrpc/test_jsonrpc_params.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/package/__init__.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/package/test_version.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/parts/__init__.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/parts/test_parts_text.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/profile/__init__.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/scripts/__init__.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/server/__init__.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/server/test_cancel_contract.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/server/test_cli.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/support/__init__.py +0 -0
- {opencode_a2a-0.6.0 → opencode_a2a-0.7.0}/tests/support/session_extensions.py +0 -0
- {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
|
-
|
|
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
|
-
|
|
62
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
- `
|
|
205
|
-
- Provider auth and default model configuration remain on the OpenCode side; deployment-time
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
- `
|
|
164
|
-
- Provider auth and default model configuration remain on the OpenCode side; deployment-time
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
-
|
|
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
|
-
|
|
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.
|