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
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
120 lines
4.4 KiB
Gherkin
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
|