9c6d69153e
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 18s
CI / lint (pull_request) Failing after 18s
CI / helm (pull_request) Successful in 23s
CI / security (pull_request) Failing after 52s
CI / typecheck (pull_request) Failing after 54s
CI / coverage (pull_request) Has been skipped
CI / benchmark-regression (pull_request) Has been skipped
CI / unit_tests (pull_request) Failing after 1m47s
CI / docker (pull_request) Has been skipped
CI / quality (pull_request) Successful in 3m42s
CI / e2e_tests (pull_request) Failing after 14m21s
CI / integration_tests (pull_request) Failing after 20m58s
CI / status-check (pull_request) Failing after 1s
Rewrites the A2aRequest and A2aResponse Pydantic models to use the field names mandated by the JSON-RPC 2.0 specification, fixing a fundamental protocol compliance issue that prevented external A2A-compliant clients from communicating with the server. Changes: - A2aRequest: a2a_version→jsonrpc (fixed '2.0'), request_id→id, operation→method; auth field removed (not in JSON-RPC 2.0) - A2aResponse: a2a_version→jsonrpc, request_id→id, status+data→result (success path), timing_ms removed; added _result_xor_error validator enforcing mutual exclusion of result and error fields - A2aLocalFacade.dispatch(): updated to use request.method, request.id, result=data, error=A2aErrorDetail(...) - A2aHttpTransport.send(): updated to use request.method - CLI call sites (session.py, plan.py): updated A2aRequest(method=...) and response.result / response.error field access - All existing A2A Behave step files updated to new field names - New 35-scenario Behave feature (a2a_jsonrpc_wire_format.feature) covering serialisation, deserialisation, validation, and facade dispatch - New 7-test Robot Framework suite (a2a_jsonrpc_wire_format.robot) for end-to-end wire format verification ISSUES CLOSED: #1501
114 lines
4.0 KiB
Python
114 lines
4.0 KiB
Python
"""Step definitions for a2a_extension_methods.feature.
|
|
|
|
Tests the _cleveragents/ extension method routing in the A2A local
|
|
facade, verifying spec-aligned operation names are supported and
|
|
produce valid responses.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
from typing import Any
|
|
|
|
from behave import given, then, when
|
|
|
|
try:
|
|
from cleveragents.a2a.facade import A2aLocalFacade
|
|
from cleveragents.a2a.models import A2aRequest
|
|
except ImportError:
|
|
A2aLocalFacade = None # type: ignore[assignment,misc]
|
|
A2aRequest = None # type: ignore[assignment,misc]
|
|
|
|
|
|
@given("a facade instance for extension method testing")
|
|
def step_create_extension_facade(context: Any) -> None:
|
|
"""Create a facade with no services (all handlers return stubs)."""
|
|
context.facade = A2aLocalFacade()
|
|
|
|
|
|
@when('I dispatch "{operation}" with params {params_json}')
|
|
def step_dispatch_operation(context: Any, operation: str, params_json: str) -> None:
|
|
params = json.loads(params_json)
|
|
request = A2aRequest(method=operation, params=params)
|
|
context.response = context.facade.dispatch(request)
|
|
|
|
|
|
@then("the response should be ok")
|
|
def step_response_ok(context: Any) -> None:
|
|
assert context.response.error is None, (
|
|
f"Expected no error, got error: {context.response.error}"
|
|
)
|
|
|
|
|
|
@then('the response data should contain key "{key}"')
|
|
def step_response_has_key(context: Any, key: str) -> None:
|
|
assert key in context.response.result, (
|
|
f"Expected key '{key}' in response data, got: {list(context.response.result.keys())}"
|
|
)
|
|
|
|
|
|
@then('the response data should have "{key}" set to true')
|
|
def step_response_stub_true(context: Any, key: str) -> None:
|
|
assert context.response.result.get(key) is True, (
|
|
f"Expected data['{key}'] to be True, got: {context.response.result.get(key)}"
|
|
)
|
|
|
|
|
|
@then("the facade should support _cleveragents/plan/ methods")
|
|
def step_check_plan_methods(context: Any) -> None:
|
|
ops = context.facade.list_operations()
|
|
plan_ops = [o for o in ops if o.startswith("_cleveragents/plan/")]
|
|
assert len(plan_ops) >= 13, (
|
|
f"Expected >=13 plan extension methods, got {len(plan_ops)}: {plan_ops}"
|
|
)
|
|
|
|
|
|
@then("the facade should support _cleveragents/registry/ methods")
|
|
def step_check_registry_methods(context: Any) -> None:
|
|
ops = context.facade.list_operations()
|
|
reg_ops = [o for o in ops if o.startswith("_cleveragents/registry/")]
|
|
assert len(reg_ops) >= 6, (
|
|
f"Expected >=6 registry extension methods, got {len(reg_ops)}: {reg_ops}"
|
|
)
|
|
|
|
|
|
@then("the facade should support _cleveragents/context/ methods")
|
|
def step_check_context_methods(context: Any) -> None:
|
|
ops = context.facade.list_operations()
|
|
ctx_ops = [o for o in ops if o.startswith("_cleveragents/context/")]
|
|
assert len(ctx_ops) >= 4, (
|
|
f"Expected >=4 context extension methods, got {len(ctx_ops)}: {ctx_ops}"
|
|
)
|
|
|
|
|
|
@then("the facade should support _cleveragents/health/ methods")
|
|
def step_check_health_methods(context: Any) -> None:
|
|
ops = context.facade.list_operations()
|
|
health_ops = [
|
|
o
|
|
for o in ops
|
|
if o.startswith("_cleveragents/health/")
|
|
or o.startswith("_cleveragents/diagnostics/")
|
|
]
|
|
assert len(health_ops) >= 2, (
|
|
f"Expected >=2 health/diagnostics methods, got {len(health_ops)}: {health_ops}"
|
|
)
|
|
|
|
|
|
@then("the facade should support _cleveragents/sync/ methods")
|
|
def step_check_sync_methods(context: Any) -> None:
|
|
ops = context.facade.list_operations()
|
|
sync_ops = [o for o in ops if o.startswith("_cleveragents/sync/")]
|
|
assert len(sync_ops) >= 3, (
|
|
f"Expected >=3 sync extension methods, got {len(sync_ops)}: {sync_ops}"
|
|
)
|
|
|
|
|
|
@then("the facade should support _cleveragents/namespace/ methods")
|
|
def step_check_namespace_methods(context: Any) -> None:
|
|
ops = context.facade.list_operations()
|
|
ns_ops = [o for o in ops if o.startswith("_cleveragents/namespace/")]
|
|
assert len(ns_ops) >= 3, (
|
|
f"Expected >=3 namespace extension methods, got {len(ns_ops)}: {ns_ops}"
|
|
)
|