Files
cleveragents-core/features/a2a_stdio_transport.feature
hurui200320 0127b6f745
CI / lint (pull_request) Successful in 1m7s
CI / typecheck (pull_request) Successful in 1m13s
CI / security (pull_request) Successful in 1m13s
CI / benchmark-publish (pull_request) Has been skipped
CI / push-validation (pull_request) Successful in 33s
CI / helm (pull_request) Successful in 35s
CI / build (pull_request) Successful in 51s
CI / quality (pull_request) Successful in 56s
CI / e2e_tests (pull_request) Successful in 4m33s
CI / integration_tests (pull_request) Successful in 5m4s
CI / unit_tests (pull_request) Successful in 6m24s
CI / docker (pull_request) Successful in 1m29s
CI / coverage (pull_request) Successful in 11m42s
CI / status-check (pull_request) Successful in 5s
CI / build (push) Successful in 50s
CI / helm (push) Successful in 30s
CI / push-validation (push) Successful in 28s
CI / lint (push) Successful in 1m6s
CI / quality (push) Successful in 1m10s
CI / typecheck (push) Successful in 1m33s
CI / security (push) Successful in 1m37s
CI / benchmark-publish (push) Failing after 48s
CI / e2e_tests (push) Successful in 3m54s
CI / integration_tests (push) Successful in 4m3s
CI / unit_tests (push) Successful in 6m6s
CI / docker (push) Successful in 1m32s
CI / coverage (push) Successful in 12m3s
CI / status-check (push) Successful in 3s
fix(reactive): synthesise execution route for type:llm actors in ReactiveConfigParser
When _build_from_v3() creates agents for type:llm or type:tool actors, and
when _build() processes the nested actors: map format (cleveragents version
3.0 YAML), no RouteConfig is produced. run_single_shot() then falls through
to the RxPY stream path which has no subscribers, causing the LLM to never
be invoked and the command to silently return empty output.

Fix A: after creating the agent in _build_from_v3() for type:llm/tool, call
_synthesise_single_node_route() to add a graph route with a message_router
node (catch-all rule), an actor node, and an edge to "end".

Fix B: after the agent loop in _build(), if rc.agents is non-empty and
rc.routes is empty, synthesise a default route using the cleveragents
default_actor (or the first agent).

Fix C: in _build(), the nested actors: map path now translates the v3
actor: "provider/model" key into separate provider and model keys in the
agent config dict. SimpleLLMAgent._resolve_llm() expects these keys; without
this translation, the LLM provider defaults to None (OpenAI) regardless of
the configured actor reference.

13 BDD scenarios in actor_v3_route_synthesis.feature:
- Flat v3 LLM/tool builds produce non-empty routes
- Route structure has router + actor nodes with edge to end
- Nested actors: map format produces routes, respects default_actor
- Explicit routes are not duplicated
- run_single_shot returns non-empty output with synthesised routes
- Graph actor regression guard
- Nested actors: map with actor key infers provider and model
- Nested actors: map with actor key without slash sets model only
- Nested actors: map with explicit provider/model keeps them unchanged

ISSUES CLOSED: #10807
2026-04-28 03:22:06 +00:00

120 lines
4.4 KiB
Gherkin

Feature: A2A stdio transport for local-mode communication
As a developer using local-mode agent communication
I want the A2aStdioTransport to handle subprocess communication correctly
So that JSON-RPC messages are sent and received reliably
@coverage
Scenario: Transport initializes with no process
Given a new A2aStdioTransport instance
Then the stdio transport should not be connected
And the stdio transport process should be None
@coverage
Scenario: Send raises when not connected
Given a new A2aStdioTransport instance
When I try to send a request without connecting
Then a RuntimeError should be raised about not connected
@coverage
Scenario: Send raises for non-A2aRequest input
Given a connected A2aStdioTransport with a mock process
When I try to send a non-A2aRequest object
Then a TypeError should be raised about A2aRequest
@coverage
Scenario: Send succeeds with valid request and mock response
Given a connected A2aStdioTransport with a mock process
And the mock process returns a valid JSON-RPC response
When I send a valid A2aRequest
Then I should receive an A2aResponse
@coverage
Scenario: Send raises on invalid JSON response
Given a connected A2aStdioTransport with a mock process
And the mock process returns invalid JSON
When I try to send a valid A2aRequest
Then a RuntimeError should be raised about invalid JSON
@coverage
Scenario: Send raises when subprocess closes unexpectedly
Given a connected A2aStdioTransport with a mock process
And the mock process returns empty response
When I try to send a valid A2aRequest
Then a RuntimeError should be raised about closed unexpectedly
@coverage
Scenario: Send raises when stdin is unavailable
Given a connected A2aStdioTransport with a mock process
And the mock process has no stdin
When I try to send a valid A2aRequest
Then a RuntimeError should be raised about stdin
@coverage
Scenario: Send raises when stdout is unavailable
Given a connected A2aStdioTransport with a mock process
And the mock process has no stdout but valid stdin
When I try to send a valid A2aRequest
Then a RuntimeError should be raised about stdout
@coverage
Scenario: Connect raises for empty agent path
Given a new A2aStdioTransport instance
When I try to connect with empty agent path
Then a ValueError should be raised about agent_path
@coverage
Scenario: Connect raises when already connected
Given a connected A2aStdioTransport with a mock process
When I try to connect again with a valid path
Then a RuntimeError should be raised about already connected
@coverage
Scenario: Disconnect is a no-op when not connected
Given a new A2aStdioTransport instance
When I call disconnect
Then no stdio transport error should be raised
@coverage
Scenario: Disconnect closes stdin and waits for process
Given a connected A2aStdioTransport with a mock process
When I call disconnect
Then the stdio transport should not be connected
And mock stdin close should have been called
And mock process wait should have been called
@coverage
Scenario: Disconnect terminates when wait times out
Given a connected A2aStdioTransport with a mock process
And the mock process times out on first wait
When I call disconnect
Then the stdio transport should not be connected
And mock process terminate should have been called
@coverage
Scenario: Connect with Python module path
Given a new A2aStdioTransport instance
And subprocess Popen is mocked to succeed
When I connect with agent path "cleveragents.a2a.agent"
Then the stdio transport should be connected
@coverage
Scenario: Connect with executable path
Given a new A2aStdioTransport instance
And subprocess Popen is mocked to succeed
When I connect with agent path "/usr/local/bin/agent"
Then the stdio transport should be connected
@coverage
Scenario: Connect with .py file path
Given a new A2aStdioTransport instance
And subprocess Popen is mocked to succeed
When I connect with agent path "agent.py"
Then the stdio transport should be connected
@coverage
Scenario: Connect raises for file not found
Given a new A2aStdioTransport instance
And subprocess Popen raises FileNotFoundError
When I try to connect with agent path "/nonexistent/agent"
Then a RuntimeError should be raised about agent not found