123 lines
5.5 KiB
Markdown
123 lines
5.5 KiB
Markdown
# Artemis Thin Client Design
|
|
|
|
This document describes the remote SDK, not the web console's visual design.
|
|
The shared runtime and UI boundaries are documented in the repository's
|
|
[DESIGN.md](../../DESIGN.md). Current behavior below includes the 2.0 exploration
|
|
adapter; versioned remote endpoints remain a protocol evolution proposal.
|
|
|
|
## Goals
|
|
|
|
Developer machines install only a small remote SDK, while the host connected to
|
|
Android devices runs the full Artemis stack. The SDK must:
|
|
|
|
- have no dependency on ADB, device drivers, agents, LLMs, web services, or image libraries;
|
|
- never attempt to start a local Artemis daemon;
|
|
- remain compatible with the existing server API;
|
|
- allow the server to add agent and device capabilities independently; and
|
|
- provide explicit capability negotiation and errors as the protocol evolves.
|
|
|
|
## Boundary
|
|
|
|
The client owns request modeling, HTTP communication, status polling, error
|
|
normalization, and result models. Device discovery, task scheduling, concurrency
|
|
control, model selection, execution, logs, videos, and artifact generation all
|
|
belong to the server.
|
|
|
|
The distribution is named `artemis-client`, while the Python import is
|
|
`artemis_client`. This prevents it from shadowing the full runtime's top-level
|
|
`artemis` package. The full runtime can depend on this package later and
|
|
re-export the client from `artemis` for compatibility.
|
|
|
|
## Phase 1: Compatibility Adapter
|
|
|
|
The first release calls the current `/api/*` administration endpoints directly.
|
|
The client generates a task ID and maps it to the server's existing `session_id`
|
|
to make retries idempotent. While a task is queued but not yet visible in the
|
|
session database, the client reconstructs its state from `queue` and
|
|
`active_tasks` in `/api/status`.
|
|
|
|
Experimental parameters live in `options`. Older servers ignore unknown fields,
|
|
while newer servers can consume them without requiring an immediate SDK release.
|
|
|
|
### Guided exploration in 2.0
|
|
|
|
`ArtemisClient.exploration()` uses the existing `/api/explorations` API shared
|
|
with the web workspace and MCP. It supports read-only list/get/case queries,
|
|
session lifecycle and messages, manual demonstrations, immutable case versions,
|
|
generation, reruns, and batch-draft creation. It adds no scheduler or local agent.
|
|
|
|
Mutations require a stable `request_id`, except pause/stop. Reusing a request ID
|
|
must not repeat the business operation. Read operations reject mutation fields;
|
|
creating a batch draft does not start it. Case generation returns a job whose
|
|
state is read from the exploration session, rather than blocking the client for
|
|
the entire model call.
|
|
|
|
Execution status, test verdict, case generation, and rerun results are separate.
|
|
`TaskResult.succeeded` currently reflects execution status only; it does not
|
|
prove that the test passed. Consumers must inspect the server's effective test
|
|
result and evidence, including `runs[].test_result` for exploration, and retain
|
|
unknown response fields through `raw`. A client polling timeout does not cancel
|
|
the server task; stopping it is a separate explicit operation.
|
|
|
|
The host owns source metadata, demonstration recording scope, execution budgets,
|
|
model retries, final acceptance, and artifact persistence. The client passes the
|
|
requested settings through the shared API and never reconstructs missing PC
|
|
evidence from Android screenshots or restarts a case after a request failure.
|
|
|
|
## Phase 2: Proposed stable remote API
|
|
|
|
The following endpoints are an evolution proposal, not the current submission
|
|
API. Do not replace the working compatibility adapter with these routes until
|
|
the host implements and advertises them:
|
|
|
|
```text
|
|
POST /api/v1/tasks
|
|
GET /api/v1/tasks/{task_id}
|
|
DELETE /api/v1/tasks/{task_id}
|
|
GET /api/v1/tasks/{task_id}/events
|
|
GET /api/v1/tasks/{task_id}/artifacts
|
|
GET /api/v1/devices
|
|
GET /api/v1/capabilities
|
|
```
|
|
|
|
A future remote surface can separate administration access from task access
|
|
while delegating to the same backend services and scheduler. The proposed error
|
|
envelope is:
|
|
|
|
```json
|
|
{
|
|
"error": {
|
|
"code": "DEVICE_OFFLINE",
|
|
"message": "The selected device is offline",
|
|
"retryable": false
|
|
}
|
|
}
|
|
```
|
|
|
|
## Compatibility Rules
|
|
|
|
1. `/api/v1` may add optional request and response fields, but must not change existing field semantics.
|
|
2. The client ignores unknown response fields and preserves the original response in each model's `raw` attribute.
|
|
3. Every new request field must have a server-side default.
|
|
4. `capabilities()` probes `/api/v1/capabilities` and falls back to the known baseline on 404; future feature gating must not pretend that this fallback advertises new host features.
|
|
5. Breaking changes ship under `/api/v2`; they are never applied in place.
|
|
6. The SDK and server follow semantic versioning independently.
|
|
|
|
## Security
|
|
|
|
The current daemon exposes administration and credential-related endpoints and
|
|
must not listen on a public interface without protection. Use an SSH or VPN tunnel
|
|
in the short term. In production, place a reverse proxy in front of the daemon,
|
|
expose only the remote API, and enforce HTTPS, bearer-token authentication,
|
|
request-size limits, rate limits, and audit logging. Tokens are accepted only
|
|
through arguments or environment variables and are never persisted by the SDK.
|
|
|
|
## Future Work
|
|
|
|
- SSE event subscriptions with reconnection support;
|
|
- artifact manifests and streaming downloads;
|
|
- batch task submission;
|
|
- server and API version constraints;
|
|
- retries limited to network failures and idempotent requests; and
|
|
- OpenAPI contract tests to prevent server and SDK drift.
|