Files
agentic-mobile-control/openspec/changes/cloud-planner-proxy/tasks.md
T
q792602257 1107ace89c
Tests / Test passed: 626
Default-enable AI Planner in Host Agent; propose cloud-planner-proxy
- Host Agent now defaults AI_PLANNER_ENABLED=true (opt-out via env),
  scoped to apps/device-host-agent/host_agent/execution.py only; the
  shared runtime.planner_config default (disabled) is unchanged.
- Add openspec proposal for cloud-planner-proxy: centralize LLM
  provider config/credentials on the Cloud Control Plane and let the
  Host Agent proxy AI Planner decisions through it instead of holding
  provider API keys locally. Proposal only, no implementation yet.
2026-07-13 20:50:35 +08:00

4.8 KiB

1. Cloud API: planner configuration

  • 1.1 Add Cloud API-side planner configuration (provider, model, timeout, provider API keys) analogous to runtime/planner_config.py, loaded from the Cloud API's own process environment (e.g. AI_PLANNER_PROVIDER/AI_PLANNER_MODEL/AI_PLANNER_TIMEOUT_SECONDS, ANTHROPIC_API_KEY/OPENAI_API_KEY), living in packages/cloud-platform/cloud or apps/cloud-api.
  • 1.2 Add anthropic/openai as explicit dependencies of the package that hosts this configuration (confirm whether packages/cloud-platform or apps/cloud-api is the right home, matching where the new endpoint handler will live).

2. Cloud API: planner-decision internal endpoint

  • 2.1 Add request/response Pydantic models to cloud.internal_api.models for a planner-decision call: request carries system_prompt, user_prompt, optional base64 screenshot, tool specs, timeout; response carries resolved tool_name/arguments or a structured error.
  • 2.2 Add the internal route (e.g. POST /internal/v1/planner/decide) to the existing internal router, reusing the current host-scoped bearer auth dependency used by heartbeat/claim/renew/result -- no new scope.
  • 2.3 Implement the route handler by constructing runtime.tool_calling_client.AnthropicToolCallingClient or OpenAIToolCallingClient (per D1) from the Cloud API's own planner configuration, calling .decide(...), and translating ToolCallDecision/ToolCallUnavailable into the response model.
  • 2.4 Ensure the handler does not log or persist raw prompt text or screenshot bytes; only metadata (host id, resolved tool name, latency, error class) may be logged.

3. Host Agent: cloud-proxy transport

  • 3.1 Add AI_PLANNER_TRANSPORT (direct default | cloud) to apps/device-host-agent/host_agent/config.py.
  • 3.2 Add a request_planner_decision(...) method to host_agent/client.py::HostAgentClient that calls the new Cloud API endpoint using the existing authenticated httpx session, importing the new request/response models from cloud.internal_api.models.
  • 3.3 Add host_agent/cloud_planner_client.py::CloudProxyToolCallingClient implementing the runtime.tool_calling_client.ToolCallingClient Protocol structurally (no import of host_agent/cloud from runtime), wrapping HostAgentClient.request_planner_decision(...) and raising ToolCallUnavailable on any failure (network error, auth rejection, non-2xx, provider error, timeout) -- matching D7.

4. Host Agent: wiring

  • 4.1 Update apps/device-host-agent/host_agent/execution.py's _host_agent_planner_config()/create_task_runner() so that when AI_PLANNER_TRANSPORT=cloud, the constructed TaskRunner's AIPlanner is built with a CloudProxyToolCallingClient instead of the default local provider client, while leaving the existing default-enabled/direct-transport behavior unchanged when AI_PLANNER_TRANSPORT is unset or direct.
  • 4.2 Confirm apps/device-host-agent/tests/test_execution.py::test_runtime_owned_packages_do_not_import_host_or_cloud_concerns-style boundary checks still pass with the new module in place.

5. Tests

  • 5.1 Unit tests for Cloud API planner configuration loading (defaults, provider/model/timeout parsing) mirroring tests/test_planner_config.py.
  • 5.2 Unit tests for the planner-decision endpoint: authorized request resolves a decision, unauthenticated/foreign-host request is rejected, provider failure returns a structured error without crashing.
  • 5.3 Unit tests for CloudProxyToolCallingClient: successful decision round-trip, and each failure mode raises ToolCallUnavailable.
  • 5.4 Unit tests for Host Agent wiring: AI_PLANNER_TRANSPORT=cloud constructs an AIPlanner using CloudProxyToolCallingClient; AI_PLANNER_TRANSPORT unset or direct preserves existing direct-to-provider construction (no regression to the already-implemented default-enabled behavior).
  • 5.5 Full non-integration suite (uv run --all-packages pytest -m "not integration") passes with no regressions.

6. Documentation

  • 6.1 Update docs/CLOUD_DEPLOYMENT.md's Runtime AI Planner section with the cloud transport configuration path, its trade-offs (latency, cloud-availability coupling, expanded data path for screenshots/prompts), and the credential split (Cloud API holds provider keys for cloud transport; Host Agent holds them for direct transport).

7. Validation

  • 7.1 openspec validate --strict passes for this change.
  • 7.2 Ruff check/format and compileall pass for all touched packages.