feat(planner): persist reusable action semantics
Tests / Test passed: 879

This commit is contained in:
2026-07-15 18:14:28 +08:00
parent 361dada276
commit d69be48f96
41 changed files with 733 additions and 116 deletions
@@ -23,6 +23,10 @@ The system SHALL provide a Planner implementation that, given a goal, the curren
- **WHEN** the LLM response contains only a tool call with no preceding text block
- **THEN** `PlannedStep.rationale` is `None` and the step is returned normally
#### Scenario: Device action includes reusable purpose and expected outcome
- **WHEN** the AI Planner selects a device action (`tap`, `swipe`, `input_text`, `launch_app`, or `terminate_app`)
- **THEN** its tool call requires non-empty `purpose` and `expected_outcome` values, and the returned `PlannedStep` carries both separately from the executable action arguments
### Requirement: Pluggable dual-provider tool-calling abstraction
The system SHALL support at least two interchangeable LLM providers (Anthropic native tool use and OpenAI function calling) for the AI Planner's decision calls, selectable via configuration, with both providers constrained to return exactly one tool call per request. The Anthropic client SHALL additionally support optional extended thinking via a configurable `thinking_budget_tokens` value. The OpenAI client SHALL capture `reasoning_content` from responses when present. Independently of provider selection, the system SHALL support at least two transports for making that decision call — direct-to-provider and cloud-proxy — selectable via configuration without requiring any change to `AIPlanner`'s own decision logic.
@@ -50,6 +54,6 @@ The system SHALL support at least two interchangeable LLM providers (Anthropic n
- **WHEN** the Host Agent is configured with the cloud-proxy transport
- **THEN** its tool-calling client sends the decision request to the Cloud Control Plane's planner-decision endpoint instead of constructing a local Anthropic or OpenAI SDK client
#### Scenario: Cloud-proxy transport returns None for thinking and text_output
- **WHEN** the Host Agent uses cloud-proxy transport
- **THEN** `ToolCallDecision.thinking` and `ToolCallDecision.text_output` are `None` because the proxy surface does not expose them
#### Scenario: Cloud-proxy transport returns planner metadata
- **WHEN** the Host Agent uses cloud-proxy transport and the Cloud Planner returns a decision
- **THEN** the proxy returns its rationale, thinking, purpose, and expected outcome alongside the tool name and executable arguments