feat: checkpoint device agent runtime milestones

This commit is contained in:
2026-07-06 17:24:03 +08:00
parent 2d4251e98e
commit 5658735bca
153 changed files with 8060 additions and 65 deletions
@@ -0,0 +1,45 @@
## ADDED Requirements
### Requirement: Register a device
The system SHALL expose `POST /console/devices` accepting `driver_type`, `connection_info`, and an optional `name`, persist the configuration, and register the device with the running `DeviceManager`. Unsupported `driver_type` values SHALL be rejected.
#### Scenario: Register a supported device
- **WHEN** an operator posts `{"driver_type": "wda", "connection_info": {"server_url": "http://127.0.0.1:4723", "udid": "abc123"}}` to `POST /console/devices`
- **THEN** the response is a `201` with the new device's id and status `idle`, the device appears in `GET /console/devices`, and its configuration is persisted
#### Scenario: Reject unsupported driver type
- **WHEN** an operator posts a device with `driver_type` not in the supported set (currently `wda`)
- **THEN** the response is a `400` and no device is registered or persisted
### Requirement: Unregister a device
The system SHALL expose `DELETE /console/devices/{device_id}` that disconnects and removes the device from `DeviceManager` and deletes its persisted configuration, or returns a `404` if the device is unknown.
#### Scenario: Unregister a known device
- **WHEN** an operator calls `DELETE /console/devices/{device_id}` for a registered device
- **THEN** the response is a `204`, the device no longer appears in `GET /console/devices`, and its persisted configuration is removed
#### Scenario: Unregister an unknown device
- **WHEN** an operator calls `DELETE /console/devices/{device_id}` for a device id that is not registered
- **THEN** the response is a `404`
### Requirement: Persisted devices reload on startup
The system SHALL re-register every persisted device configuration with `DeviceManager` automatically when the application starts, without requiring manual re-registration.
#### Scenario: Restart with previously registered devices
- **WHEN** the application starts and one or more device configurations exist in the persisted device config store
- **THEN** each persisted device appears in `GET /console/devices` immediately after startup, without any additional operator action
### Requirement: View and update runtime parameters
The system SHALL expose `GET /console/config` returning current adjustable runtime parameters (currently the task runner's `max_steps`) and `PUT /console/config` to update them, applying the change to the running task runner immediately and persisting it across restarts.
#### Scenario: View current runtime parameters
- **WHEN** an operator calls `GET /console/config`
- **THEN** the response is a `200` including the current `max_steps` value
#### Scenario: Update max_steps
- **WHEN** an operator calls `PUT /console/config` with `{"max_steps": 30}`
- **THEN** the response is a `200` with the updated value, subsequently started tasks (and the next iteration of any in-flight task) use the new `max_steps`, and the value is persisted so it survives a restart
#### Scenario: Reject invalid runtime parameter value
- **WHEN** an operator calls `PUT /console/config` with a non-positive `max_steps` (e.g. `0` or `-1`)
- **THEN** the response is a `400` and the previous value remains in effect
@@ -0,0 +1,49 @@
## ADDED Requirements
### Requirement: List device status
The system SHALL expose `GET /console/devices` returning every registered device's id, name, status (`idle`/`busy`/`offline`/`error`), and driver type, reusing `DeviceManager.list_devices()`.
#### Scenario: Devices are registered
- **WHEN** an operator calls `GET /console/devices` while one or more devices are registered
- **THEN** the response is a `200` with a JSON array containing one entry per device with its current `status`
#### Scenario: No devices registered
- **WHEN** an operator calls `GET /console/devices` while no devices are registered
- **THEN** the response is a `200` with an empty JSON array
### Requirement: List tasks
The system SHALL expose `GET /console/tasks` returning all tasks known to `TaskMetadataStore`, most recently created first, with optional `device_id` and `status` query filters.
#### Scenario: List all tasks
- **WHEN** an operator calls `GET /console/tasks` with no query parameters
- **THEN** the response is a `200` with a JSON array of tasks ordered by `created_at` descending
#### Scenario: Filter by device
- **WHEN** an operator calls `GET /console/tasks?device_id=<id>`
- **THEN** the response contains only tasks whose `device_id` matches `<id>`
#### Scenario: Filter by status
- **WHEN** an operator calls `GET /console/tasks?status=running`
- **THEN** the response contains only tasks whose `status` equals `running`
### Requirement: Task detail
The system SHALL expose `GET /console/tasks/{task_id}` returning the full task record, or a `404` if the task does not exist.
#### Scenario: Task exists
- **WHEN** an operator calls `GET /console/tasks/{task_id}` for a known task id
- **THEN** the response is a `200` with the task's goal, device_id, status, timestamps, and failure_reason (if any)
#### Scenario: Task does not exist
- **WHEN** an operator calls `GET /console/tasks/{task_id}` for an unknown task id
- **THEN** the response is a `404`
### Requirement: Task timeline replay
The system SHALL expose `GET /console/tasks/{task_id}/timeline` returning the ordered list of execution steps recorded for the task, each including its scene, prompt, tool call, result, timestamp, and a base64-encoded screenshot when one was captured for that step.
#### Scenario: Task has recorded steps
- **WHEN** an operator calls `GET /console/tasks/{task_id}/timeline` for a task that executed at least one step
- **THEN** the response is a `200` with a JSON array ordered by step `index` ascending, each entry including `image_base64` when a screenshot was captured for that step
#### Scenario: Task has no recorded steps
- **WHEN** an operator calls `GET /console/tasks/{task_id}/timeline` for a task with no timeline history (e.g. it failed before its first step)
- **THEN** the response is a `200` with an empty JSON array
@@ -0,0 +1,45 @@
## ADDED Requirements
### Requirement: Device status dashboard
The web console SHALL display a list of registered devices with their current status, fetched from `console-status-api`, and SHALL show an explicit empty state when no devices are registered.
#### Scenario: Devices registered
- **WHEN** an operator opens the dashboard while devices are registered
- **THEN** each device is shown with its name/id and current status, refreshed without a full page reload
#### Scenario: No devices registered
- **WHEN** an operator opens the dashboard while no devices are registered
- **THEN** an empty-state message is shown inviting the operator to add a device
### Requirement: Task list and timeline replay
The web console SHALL let an operator browse the task list, open a task's detail view, and step through its recorded timeline including screenshots.
#### Scenario: Browse tasks
- **WHEN** an operator opens the task list view
- **THEN** tasks are shown most-recent-first with their goal, device, and status, and can be filtered by device or status
#### Scenario: Replay a task's timeline
- **WHEN** an operator opens a completed or failed task's detail view
- **THEN** the console renders each recorded step in order, showing its tool call, result, and screenshot (when available)
### Requirement: Device configuration
The web console SHALL let an operator register a new device (choosing a supported driver type and entering its connection info) and remove an existing device, surfacing any validation error returned by `console-config-api`.
#### Scenario: Add a device successfully
- **WHEN** an operator submits the add-device form with valid driver type and connection info
- **THEN** the new device appears in the dashboard without a page reload
#### Scenario: Add a device with invalid input
- **WHEN** an operator submits the add-device form with an unsupported driver type
- **THEN** the console displays the error returned by the API and does not add the device to the list
#### Scenario: Remove a device
- **WHEN** an operator confirms removal of a registered device
- **THEN** the device disappears from the dashboard without a page reload
### Requirement: Runtime parameter configuration
The web console SHALL let an operator view and edit adjustable runtime parameters (currently `max_steps`) through a settings form.
#### Scenario: Update a runtime parameter
- **WHEN** an operator changes `max_steps` in the settings form and saves
- **THEN** the console shows the updated value on success, or the validation error if the API rejects it