0e4a140f53
Replace the M3 echo-stub with real orchestrator-based LLM invocation via SessionWorkflow, wiring LangChainSessionCaller → ToolCallingRuntime.run_tool_loop(). Includes token tracking, cost estimation, streaming support, and A2A protocol compliance. ISSUES CLOSED: #5784
106 lines
5.5 KiB
Gherkin
106 lines
5.5 KiB
Gherkin
Feature: Session workflow coverage boost
|
|
Coverage boost for session_workflow.py helper functions (M1, n4).
|
|
|
|
Background:
|
|
Given the session workflow coverage environment is set up
|
|
|
|
# _extract_content
|
|
Scenario: _extract_content extracts text from content attribute
|
|
Given coverage boost a mock response with content "hello world"
|
|
When coverage boost _extract_content is called
|
|
Then coverage boost the extracted result should be "hello world"
|
|
|
|
Scenario: _extract_content falls back to text attribute
|
|
Given coverage boost a mock response with text "from text attr" and no content
|
|
When coverage boost _extract_content is called
|
|
Then coverage boost the extracted result should be "from text attr"
|
|
|
|
Scenario: _extract_content handles list content
|
|
Given coverage boost a mock response with list content containing text dicts and plain strings
|
|
When coverage boost _extract_content is called
|
|
Then coverage boost the result should contain the concatenated texts
|
|
|
|
Scenario: _extract_content falls back to str for unknown types
|
|
Given coverage boost a mock response with no content or text attribute
|
|
When coverage boost _extract_content is called
|
|
Then coverage boost the result should be a string
|
|
|
|
# _extract_token_usage
|
|
Scenario: _extract_token_usage reads from response_metadata.usage
|
|
Given coverage boost a mock response with response_metadata usage input_tokens=100 output_tokens=50
|
|
When coverage boost _extract_token_usage is called
|
|
Then coverage boost input tokens should be 100 and output tokens should be 50
|
|
|
|
Scenario: _extract_token_usage reads from response_metadata.token_usage
|
|
Given coverage boost a mock response with response_metadata token_usage input_tokens=200 output_tokens=100
|
|
When coverage boost _extract_token_usage is called
|
|
Then coverage boost input tokens should be 200 and output tokens should be 100
|
|
|
|
Scenario: _extract_token_usage reads prompt_tokens and completion_tokens
|
|
Given coverage boost a mock response with response_metadata usage prompt_tokens=300 completion_tokens=150
|
|
When coverage boost _extract_token_usage is called
|
|
Then coverage boost input tokens should be 300 and output tokens should be 150
|
|
|
|
Scenario: _extract_token_usage reads from usage_metadata
|
|
Given coverage boost a mock response with usage_metadata input_tokens=400 output_tokens=200
|
|
When coverage boost _extract_token_usage is called
|
|
Then coverage boost input tokens should be 400 and output tokens should be 200
|
|
|
|
Scenario: _extract_token_usage returns zeros for no metadata
|
|
Given coverage boost a mock response with no usage metadata
|
|
When coverage boost _extract_token_usage is called
|
|
Then coverage boost input tokens should be 0 and output tokens should be 0
|
|
|
|
# _estimate_cost
|
|
Scenario: _estimate_cost computes cost from token counts
|
|
Given coverage boost input tokens 1000 and output tokens 500
|
|
When coverage boost _estimate_cost is called
|
|
Then coverage boost the estimated cost should be positive
|
|
|
|
# _history_to_langchain_messages
|
|
Scenario: _history_to_langchain_messages converts all roles
|
|
Given coverage boost session messages with roles SYSTEM, USER, ASSISTANT, and TOOL
|
|
When coverage boost _history_to_langchain_messages is called
|
|
Then coverage boost the result should contain SystemMessage, HumanMessage, AIMessage, and ToolMessage
|
|
|
|
Scenario: _history_to_langchain_messages treats unknown role as human
|
|
Given coverage boost a session message with an unknown role
|
|
When coverage boost _history_to_langchain_messages is called
|
|
Then coverage boost the result should contain a HumanMessage
|
|
|
|
Scenario: _history_to_langchain_messages handles empty list
|
|
Given coverage boost an empty list of session messages
|
|
When coverage boost _history_to_langchain_messages is called
|
|
Then coverage boost the result should be an empty list
|
|
|
|
# LangChainSessionCaller.invoke() tool_results branch
|
|
Scenario: LangChainSessionCaller.invoke appends tool results
|
|
Given coverage boost a LangChainSessionCaller with a stub LLM and empty history
|
|
When coverage boost invoke is called with tool_results containing one success and one failure
|
|
Then coverage boost the accumulated messages should include tool result messages
|
|
|
|
# LangChainSessionCaller.invoke() with tool_calls in response
|
|
Scenario: LangChainSessionCaller.invoke extracts tool calls from response
|
|
Given coverage boost a LangChainSessionCaller with a stub LLM that returns tool calls
|
|
When coverage boost invoke is called for the first time
|
|
Then coverage boost the LLMResponse should contain the extracted tool calls
|
|
|
|
# _build_lc_messages_from_history
|
|
Scenario: _build_lc_messages_from_history adds system prompt when absent
|
|
Given coverage boost a SessionWorkflow with a stub service and no registry
|
|
And coverage boost session history without a system message
|
|
When coverage boost _build_lc_messages_from_history is called with a prompt
|
|
Then coverage boost the first message should be a SystemMessage with the session system prompt
|
|
|
|
# _MinimalStubLLM
|
|
Scenario: _MinimalStubLLM.invoke returns stub response
|
|
Given coverage boost a _MinimalStubLLM instance
|
|
When coverage boost invoke on the stub is called
|
|
Then coverage boost the stub response content should be "(no LLM configured)"
|
|
And coverage boost the stub response should have empty tool_calls
|
|
|
|
Scenario: _MinimalStubLLM.stream yields stub chunk
|
|
Given coverage boost a _MinimalStubLLM instance
|
|
When coverage boost stream on the stub is called
|
|
Then coverage boost it should yield a chunk with content "(no LLM configured)"
|