androidctl 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- androidctl/__init__.py +5 -0
- androidctl/__main__.py +4 -0
- androidctl/_version.py +1 -0
- androidctl/app.py +73 -0
- androidctl/cli_options.py +27 -0
- androidctl/command_payloads.py +264 -0
- androidctl/command_views.py +157 -0
- androidctl/commands/__init__.py +1 -0
- androidctl/commands/actions.py +236 -0
- androidctl/commands/adb_wireless.py +157 -0
- androidctl/commands/close.py +30 -0
- androidctl/commands/connect.py +69 -0
- androidctl/commands/execute.py +179 -0
- androidctl/commands/list_apps.py +26 -0
- androidctl/commands/observe.py +26 -0
- androidctl/commands/open.py +41 -0
- androidctl/commands/plumbing.py +58 -0
- androidctl/commands/run_pipeline.py +307 -0
- androidctl/commands/screenshot.py +29 -0
- androidctl/commands/setup.py +301 -0
- androidctl/commands/wait.py +60 -0
- androidctl/daemon/__init__.py +1 -0
- androidctl/daemon/client.py +348 -0
- androidctl/daemon/discovery.py +190 -0
- androidctl/daemon/launcher.py +26 -0
- androidctl/daemon/owner.py +349 -0
- androidctl/errors/__init__.py +1 -0
- androidctl/errors/mapping.py +149 -0
- androidctl/errors/models.py +16 -0
- androidctl/exit_codes.py +8 -0
- androidctl/output.py +147 -0
- androidctl/parsing/__init__.py +1 -0
- androidctl/parsing/duration.py +17 -0
- androidctl/parsing/open_target.py +51 -0
- androidctl/parsing/refs.py +12 -0
- androidctl/parsing/screen_id.py +10 -0
- androidctl/parsing/wait.py +70 -0
- androidctl/renderers/__init__.py +110 -0
- androidctl/renderers/_paths.py +109 -0
- androidctl/renderers/xml.py +234 -0
- androidctl/renderers/xml_projection.py +732 -0
- androidctl/resources/__init__.py +1 -0
- androidctl/resources/androidctl-agent-0.1.0-release.apk +0 -0
- androidctl/setup/__init__.py +1 -0
- androidctl/setup/accessibility.py +159 -0
- androidctl/setup/adb.py +586 -0
- androidctl/setup/apk_resource.py +29 -0
- androidctl/setup/pairing.py +70 -0
- androidctl/setup/verify.py +175 -0
- androidctl/workspace/__init__.py +3 -0
- androidctl/workspace/resolve.py +27 -0
- androidctl-0.1.0.dist-info/METADATA +217 -0
- androidctl-0.1.0.dist-info/RECORD +187 -0
- androidctl-0.1.0.dist-info/WHEEL +5 -0
- androidctl-0.1.0.dist-info/entry_points.txt +3 -0
- androidctl-0.1.0.dist-info/licenses/LICENSE +674 -0
- androidctl-0.1.0.dist-info/top_level.txt +3 -0
- androidctl_contracts/__init__.py +55 -0
- androidctl_contracts/_version.py +1 -0
- androidctl_contracts/_wire_helpers.py +31 -0
- androidctl_contracts/base.py +142 -0
- androidctl_contracts/command_catalog.py +414 -0
- androidctl_contracts/command_results.py +630 -0
- androidctl_contracts/daemon_api.py +335 -0
- androidctl_contracts/errors.py +44 -0
- androidctl_contracts/paths.py +5 -0
- androidctl_contracts/public_screen.py +579 -0
- androidctl_contracts/user_state.py +23 -0
- androidctl_contracts/vocabulary.py +82 -0
- androidctld/__init__.py +5 -0
- androidctld/__main__.py +63 -0
- androidctld/_version.py +1 -0
- androidctld/actions/__init__.py +1 -0
- androidctld/actions/action_target.py +142 -0
- androidctld/actions/capabilities.py +539 -0
- androidctld/actions/executor.py +894 -0
- androidctld/actions/focus_confirmation.py +177 -0
- androidctld/actions/focused_input_admissibility.py +120 -0
- androidctld/actions/fresh_current.py +176 -0
- androidctld/actions/postconditions.py +473 -0
- androidctld/actions/repair.py +101 -0
- androidctld/actions/request_builder.py +204 -0
- androidctld/actions/settle.py +146 -0
- androidctld/actions/submit_confirmation.py +211 -0
- androidctld/actions/submit_routing.py +311 -0
- androidctld/actions/type_confirmation.py +257 -0
- androidctld/app_targets.py +71 -0
- androidctld/artifacts/__init__.py +1 -0
- androidctld/artifacts/models.py +26 -0
- androidctld/artifacts/screen_lookup.py +241 -0
- androidctld/artifacts/screen_payloads.py +109 -0
- androidctld/artifacts/writer.py +286 -0
- androidctld/auth/__init__.py +1 -0
- androidctld/auth/active_registry.py +266 -0
- androidctld/auth/secret_files.py +52 -0
- androidctld/auth/token_store.py +59 -0
- androidctld/commands/__init__.py +1 -0
- androidctld/commands/assembly.py +231 -0
- androidctld/commands/command_models.py +254 -0
- androidctld/commands/dispatch.py +99 -0
- androidctld/commands/executor.py +31 -0
- androidctld/commands/from_boundary.py +175 -0
- androidctld/commands/handlers/__init__.py +15 -0
- androidctld/commands/handlers/action.py +439 -0
- androidctld/commands/handlers/connect.py +94 -0
- androidctld/commands/handlers/list_apps.py +215 -0
- androidctld/commands/handlers/observe.py +121 -0
- androidctld/commands/handlers/screenshot.py +105 -0
- androidctld/commands/handlers/wait.py +286 -0
- androidctld/commands/models.py +65 -0
- androidctld/commands/open_targets.py +56 -0
- androidctld/commands/orchestration.py +353 -0
- androidctld/commands/registry.py +116 -0
- androidctld/commands/result_builders.py +40 -0
- androidctld/commands/result_models.py +555 -0
- androidctld/commands/results.py +108 -0
- androidctld/commands/semantic_command_names.py +17 -0
- androidctld/commands/semantic_error_mapping.py +93 -0
- androidctld/commands/semantic_truth.py +135 -0
- androidctld/commands/service.py +67 -0
- androidctld/config.py +75 -0
- androidctld/daemon/__init__.py +1 -0
- androidctld/daemon/active_slot.py +326 -0
- androidctld/daemon/envelope.py +30 -0
- androidctld/daemon/http_host.py +123 -0
- androidctld/daemon/ingress.py +112 -0
- androidctld/daemon/ownership_probe.py +204 -0
- androidctld/daemon/server.py +286 -0
- androidctld/daemon/service.py +99 -0
- androidctld/device/__init__.py +1 -0
- androidctld/device/action_models.py +154 -0
- androidctld/device/action_serialization.py +121 -0
- androidctld/device/adapters.py +220 -0
- androidctld/device/bootstrap.py +153 -0
- androidctld/device/connectors.py +231 -0
- androidctld/device/errors.py +100 -0
- androidctld/device/interfaces.py +58 -0
- androidctld/device/parsing.py +320 -0
- androidctld/device/rpc.py +483 -0
- androidctld/device/schema.py +114 -0
- androidctld/device/types.py +161 -0
- androidctld/errors/__init__.py +94 -0
- androidctld/logging/__init__.py +22 -0
- androidctld/observation.py +98 -0
- androidctld/protocol.py +53 -0
- androidctld/refs/__init__.py +1 -0
- androidctld/refs/models.py +54 -0
- androidctld/refs/repair.py +284 -0
- androidctld/refs/service.py +422 -0
- androidctld/rendering/__init__.py +1 -0
- androidctld/rendering/screen_xml.py +256 -0
- androidctld/runtime/__init__.py +21 -0
- androidctld/runtime/kernel.py +548 -0
- androidctld/runtime/lifecycle.py +19 -0
- androidctld/runtime/models.py +48 -0
- androidctld/runtime/screen_state.py +117 -0
- androidctld/runtime/state_repo.py +70 -0
- androidctld/runtime/store.py +76 -0
- androidctld/runtime_policy.py +127 -0
- androidctld/schema/__init__.py +5 -0
- androidctld/schema/base.py +132 -0
- androidctld/schema/core.py +35 -0
- androidctld/schema/daemon_api.py +108 -0
- androidctld/schema/persistence.py +161 -0
- androidctld/schema/persistence_io.py +41 -0
- androidctld/schema/validation_errors.py +309 -0
- androidctld/semantics/__init__.py +1 -0
- androidctld/semantics/compiler.py +610 -0
- androidctld/semantics/continuity.py +107 -0
- androidctld/semantics/labels.py +252 -0
- androidctld/semantics/models.py +25 -0
- androidctld/semantics/policy.py +23 -0
- androidctld/semantics/public_models.py +123 -0
- androidctld/semantics/registries.py +13 -0
- androidctld/semantics/submit_refs.py +417 -0
- androidctld/semantics/surface.py +254 -0
- androidctld/semantics/targets.py +167 -0
- androidctld/snapshots/__init__.py +1 -0
- androidctld/snapshots/models.py +219 -0
- androidctld/snapshots/refresh.py +273 -0
- androidctld/snapshots/schema.py +74 -0
- androidctld/snapshots/service.py +138 -0
- androidctld/text_equivalence.py +67 -0
- androidctld/waits/__init__.py +1 -0
- androidctld/waits/evaluators.py +216 -0
- androidctld/waits/loop.py +305 -0
- androidctld/waits/matcher.py +41 -0
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
"""Typed shared daemon API transport and runtime-route models."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Annotated, Any, Generic, Literal, TypeAlias, TypeVar
|
|
6
|
+
|
|
7
|
+
from pydantic import (
|
|
8
|
+
Field,
|
|
9
|
+
StringConstraints,
|
|
10
|
+
field_validator,
|
|
11
|
+
model_serializer,
|
|
12
|
+
model_validator,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
from ._wire_helpers import _drop_unset_keys, _validate_absolute_path
|
|
16
|
+
from .base import DaemonWireModel
|
|
17
|
+
from .errors import DaemonError
|
|
18
|
+
from .vocabulary import RuntimeStatus
|
|
19
|
+
|
|
20
|
+
TOKEN_HEADER_NAME = "X-Androidctld-Token"
|
|
21
|
+
OWNER_HEADER_NAME = "X-Androidctld-Owner"
|
|
22
|
+
|
|
23
|
+
ResultT = TypeVar("ResultT")
|
|
24
|
+
TrimmedString = Annotated[str, StringConstraints(strip_whitespace=True, min_length=1)]
|
|
25
|
+
PositiveInt = Annotated[int, Field(ge=1)]
|
|
26
|
+
NonNegativeInt = Annotated[int, Field(ge=0)]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _strip_optional_string(value: object) -> object:
|
|
30
|
+
if value is None:
|
|
31
|
+
return None
|
|
32
|
+
if isinstance(value, str):
|
|
33
|
+
normalized = value.strip()
|
|
34
|
+
if not normalized:
|
|
35
|
+
return None
|
|
36
|
+
return normalized
|
|
37
|
+
return value
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _normalize_discriminator_payload(
|
|
41
|
+
value: object,
|
|
42
|
+
*,
|
|
43
|
+
nested_field: str | None = None,
|
|
44
|
+
) -> object:
|
|
45
|
+
if not isinstance(value, dict):
|
|
46
|
+
return value
|
|
47
|
+
payload = dict(value)
|
|
48
|
+
kind = payload.get("kind")
|
|
49
|
+
if isinstance(kind, str):
|
|
50
|
+
payload["kind"] = kind.strip()
|
|
51
|
+
if nested_field is None:
|
|
52
|
+
return payload
|
|
53
|
+
nested_value = payload.get(nested_field)
|
|
54
|
+
if isinstance(nested_value, dict):
|
|
55
|
+
payload[nested_field] = _normalize_discriminator_payload(nested_value)
|
|
56
|
+
return payload
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class HealthResult(DaemonWireModel):
|
|
60
|
+
"""Typed health payload exposed by ``POST /health``."""
|
|
61
|
+
|
|
62
|
+
service: str
|
|
63
|
+
version: str
|
|
64
|
+
workspace_root: str
|
|
65
|
+
owner_id: str
|
|
66
|
+
|
|
67
|
+
_validate_workspace_root = field_validator("workspace_root")(
|
|
68
|
+
_validate_absolute_path
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class RuntimePayload(DaemonWireModel):
|
|
73
|
+
"""Stable runtime projection used by runtime endpoints."""
|
|
74
|
+
|
|
75
|
+
workspace_root: str
|
|
76
|
+
artifact_root: str
|
|
77
|
+
status: RuntimeStatus
|
|
78
|
+
current_screen_id: str | None = None
|
|
79
|
+
|
|
80
|
+
_validate_workspace_root = field_validator("workspace_root")(
|
|
81
|
+
_validate_absolute_path
|
|
82
|
+
)
|
|
83
|
+
_validate_artifact_root = field_validator("artifact_root")(_validate_absolute_path)
|
|
84
|
+
|
|
85
|
+
@model_serializer(mode="wrap")
|
|
86
|
+
def serialize_model(self, handler: Any) -> dict[str, Any]:
|
|
87
|
+
return _drop_unset_keys(
|
|
88
|
+
handler(self),
|
|
89
|
+
fields_set=self.model_fields_set,
|
|
90
|
+
optional_fields={"current_screen_id"},
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class DaemonSuccessEnvelope(DaemonWireModel, Generic[ResultT]):
|
|
95
|
+
"""Shared success envelope for daemon endpoints."""
|
|
96
|
+
|
|
97
|
+
ok: Literal[True] = True
|
|
98
|
+
result: ResultT
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class DaemonErrorEnvelope(DaemonWireModel):
|
|
102
|
+
"""Shared error envelope for daemon endpoints."""
|
|
103
|
+
|
|
104
|
+
ok: Literal[False] = False
|
|
105
|
+
error: DaemonError
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class RuntimeGetResult(DaemonWireModel):
|
|
109
|
+
"""Typed runtime/get result payload."""
|
|
110
|
+
|
|
111
|
+
runtime: RuntimePayload
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
class ConnectionPayload(DaemonWireModel):
|
|
115
|
+
"""Connection options for the retained ``connect`` daemon command."""
|
|
116
|
+
|
|
117
|
+
mode: Literal["adb", "lan"]
|
|
118
|
+
token: TrimmedString
|
|
119
|
+
serial: str | None = None
|
|
120
|
+
host: str | None = None
|
|
121
|
+
port: PositiveInt | None = None
|
|
122
|
+
|
|
123
|
+
@field_validator("serial", "host", mode="before")
|
|
124
|
+
@classmethod
|
|
125
|
+
def normalize_optional_strings(cls, value: object) -> object:
|
|
126
|
+
return _strip_optional_string(value)
|
|
127
|
+
|
|
128
|
+
@model_validator(mode="after")
|
|
129
|
+
def validate_shape(self) -> ConnectionPayload:
|
|
130
|
+
if self.mode == "adb":
|
|
131
|
+
if self.host is not None:
|
|
132
|
+
raise ValueError("host is only allowed for lan connect mode")
|
|
133
|
+
if self.port is not None:
|
|
134
|
+
raise ValueError("port is only allowed for lan connect mode")
|
|
135
|
+
return self
|
|
136
|
+
|
|
137
|
+
if self.host is None:
|
|
138
|
+
raise ValueError("host is required for lan connect mode")
|
|
139
|
+
if self.port is None:
|
|
140
|
+
raise ValueError("port is required for lan connect mode")
|
|
141
|
+
if self.serial is not None:
|
|
142
|
+
raise ValueError("serial is only allowed for adb connect mode")
|
|
143
|
+
return self
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class ConnectCommandPayload(DaemonWireModel):
|
|
147
|
+
kind: Literal["connect"]
|
|
148
|
+
connection: ConnectionPayload
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
class ObserveCommandPayload(DaemonWireModel):
|
|
152
|
+
kind: Literal["observe"]
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
class OpenAppTargetPayload(DaemonWireModel):
|
|
156
|
+
kind: Literal["app"]
|
|
157
|
+
value: TrimmedString
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
class OpenUrlTargetPayload(DaemonWireModel):
|
|
161
|
+
kind: Literal["url"]
|
|
162
|
+
value: TrimmedString
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
OpenTargetPayload: TypeAlias = Annotated[
|
|
166
|
+
OpenAppTargetPayload | OpenUrlTargetPayload,
|
|
167
|
+
Field(discriminator="kind"),
|
|
168
|
+
]
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
class OpenCommandPayload(DaemonWireModel):
|
|
172
|
+
kind: Literal["open"]
|
|
173
|
+
target: OpenTargetPayload
|
|
174
|
+
|
|
175
|
+
@model_validator(mode="before")
|
|
176
|
+
@classmethod
|
|
177
|
+
def normalize_target_discriminator(cls, value: object) -> object:
|
|
178
|
+
return _normalize_discriminator_payload(value, nested_field="target")
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
class RefActionCommandPayload(DaemonWireModel):
|
|
182
|
+
kind: Literal["tap", "longTap", "focus", "submit"]
|
|
183
|
+
ref: TrimmedString
|
|
184
|
+
source_screen_id: TrimmedString
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
class TypeCommandPayload(DaemonWireModel):
|
|
188
|
+
kind: Literal["type"]
|
|
189
|
+
ref: TrimmedString
|
|
190
|
+
source_screen_id: TrimmedString
|
|
191
|
+
text: str
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
class ScrollCommandPayload(DaemonWireModel):
|
|
195
|
+
kind: Literal["scroll"]
|
|
196
|
+
ref: TrimmedString
|
|
197
|
+
source_screen_id: TrimmedString
|
|
198
|
+
direction: Literal["up", "down", "left", "right", "backward"]
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
class GlobalActionCommandPayload(DaemonWireModel):
|
|
202
|
+
kind: Literal["back", "home", "recents", "notifications"]
|
|
203
|
+
source_screen_id: TrimmedString | None = None
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
class ScreenChangePredicatePayload(DaemonWireModel):
|
|
207
|
+
kind: Literal["screen-change"]
|
|
208
|
+
source_screen_id: TrimmedString
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
class TextPresentPredicatePayload(DaemonWireModel):
|
|
212
|
+
kind: Literal["text-present"]
|
|
213
|
+
text: TrimmedString
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
class GonePredicatePayload(DaemonWireModel):
|
|
217
|
+
kind: Literal["gone"]
|
|
218
|
+
source_screen_id: TrimmedString
|
|
219
|
+
ref: TrimmedString
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
class AppPredicatePayload(DaemonWireModel):
|
|
223
|
+
kind: Literal["app"]
|
|
224
|
+
package_name: TrimmedString
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
class IdlePredicatePayload(DaemonWireModel):
|
|
228
|
+
kind: Literal["idle"]
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
LiveScreenBoundCommandPayload: TypeAlias = (
|
|
232
|
+
RefActionCommandPayload
|
|
233
|
+
| TypeCommandPayload
|
|
234
|
+
| ScrollCommandPayload
|
|
235
|
+
| GlobalActionCommandPayload
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
ScreenRelativeWaitPredicatePayload: TypeAlias = (
|
|
240
|
+
ScreenChangePredicatePayload | GonePredicatePayload
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
WaitPredicatePayload: TypeAlias = Annotated[
|
|
245
|
+
(
|
|
246
|
+
ScreenChangePredicatePayload
|
|
247
|
+
| TextPresentPredicatePayload
|
|
248
|
+
| GonePredicatePayload
|
|
249
|
+
| AppPredicatePayload
|
|
250
|
+
| IdlePredicatePayload
|
|
251
|
+
),
|
|
252
|
+
Field(discriminator="kind"),
|
|
253
|
+
]
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
class WaitCommandPayload(DaemonWireModel):
|
|
257
|
+
kind: Literal["wait"]
|
|
258
|
+
predicate: WaitPredicatePayload
|
|
259
|
+
timeout_ms: NonNegativeInt | None = None
|
|
260
|
+
|
|
261
|
+
@model_validator(mode="before")
|
|
262
|
+
@classmethod
|
|
263
|
+
def normalize_predicate_discriminator(cls, value: object) -> object:
|
|
264
|
+
return _normalize_discriminator_payload(value, nested_field="predicate")
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
class ScreenshotCommandPayload(DaemonWireModel):
|
|
268
|
+
kind: Literal["screenshot"]
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
class ListAppsCommandPayload(DaemonWireModel):
|
|
272
|
+
kind: Literal["listApps"]
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
DaemonCommandPayload: TypeAlias = Annotated[
|
|
276
|
+
(
|
|
277
|
+
ConnectCommandPayload
|
|
278
|
+
| ObserveCommandPayload
|
|
279
|
+
| OpenCommandPayload
|
|
280
|
+
| RefActionCommandPayload
|
|
281
|
+
| TypeCommandPayload
|
|
282
|
+
| ScrollCommandPayload
|
|
283
|
+
| GlobalActionCommandPayload
|
|
284
|
+
| WaitCommandPayload
|
|
285
|
+
| ListAppsCommandPayload
|
|
286
|
+
| ScreenshotCommandPayload
|
|
287
|
+
),
|
|
288
|
+
Field(discriminator="kind"),
|
|
289
|
+
]
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
class CommandRunRequest(DaemonWireModel):
|
|
293
|
+
"""Typed ``POST /commands/run`` request."""
|
|
294
|
+
|
|
295
|
+
command: DaemonCommandPayload
|
|
296
|
+
|
|
297
|
+
@model_validator(mode="before")
|
|
298
|
+
@classmethod
|
|
299
|
+
def normalize_command_discriminator(cls, value: object) -> object:
|
|
300
|
+
return _normalize_discriminator_payload(value, nested_field="command")
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
__all__ = [
|
|
304
|
+
"OWNER_HEADER_NAME",
|
|
305
|
+
"TOKEN_HEADER_NAME",
|
|
306
|
+
"AppPredicatePayload",
|
|
307
|
+
"CommandRunRequest",
|
|
308
|
+
"ConnectCommandPayload",
|
|
309
|
+
"ConnectionPayload",
|
|
310
|
+
"DaemonCommandPayload",
|
|
311
|
+
"DaemonErrorEnvelope",
|
|
312
|
+
"DaemonSuccessEnvelope",
|
|
313
|
+
"GlobalActionCommandPayload",
|
|
314
|
+
"GonePredicatePayload",
|
|
315
|
+
"HealthResult",
|
|
316
|
+
"IdlePredicatePayload",
|
|
317
|
+
"ListAppsCommandPayload",
|
|
318
|
+
"LiveScreenBoundCommandPayload",
|
|
319
|
+
"ObserveCommandPayload",
|
|
320
|
+
"OpenAppTargetPayload",
|
|
321
|
+
"OpenCommandPayload",
|
|
322
|
+
"OpenTargetPayload",
|
|
323
|
+
"OpenUrlTargetPayload",
|
|
324
|
+
"RefActionCommandPayload",
|
|
325
|
+
"RuntimeGetResult",
|
|
326
|
+
"RuntimePayload",
|
|
327
|
+
"ScreenChangePredicatePayload",
|
|
328
|
+
"ScreenRelativeWaitPredicatePayload",
|
|
329
|
+
"ScreenshotCommandPayload",
|
|
330
|
+
"ScrollCommandPayload",
|
|
331
|
+
"TextPresentPredicatePayload",
|
|
332
|
+
"TypeCommandPayload",
|
|
333
|
+
"WaitCommandPayload",
|
|
334
|
+
"WaitPredicatePayload",
|
|
335
|
+
]
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""Stable daemon error contract models."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from enum import Enum
|
|
6
|
+
|
|
7
|
+
from pydantic import Field
|
|
8
|
+
|
|
9
|
+
from .base import DaemonWireModel
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class DaemonErrorCode(str, Enum):
|
|
13
|
+
"""Stable daemon error codes that cross the CLI and daemon boundary."""
|
|
14
|
+
|
|
15
|
+
DAEMON_BAD_REQUEST = "DAEMON_BAD_REQUEST"
|
|
16
|
+
DAEMON_UNAUTHORIZED = "DAEMON_UNAUTHORIZED"
|
|
17
|
+
WORKSPACE_BUSY = "WORKSPACE_BUSY"
|
|
18
|
+
RUNTIME_BUSY = "RUNTIME_BUSY"
|
|
19
|
+
RUNTIME_NOT_CONNECTED = "RUNTIME_NOT_CONNECTED"
|
|
20
|
+
SCREEN_NOT_READY = "SCREEN_NOT_READY"
|
|
21
|
+
COMMAND_NOT_FOUND = "COMMAND_NOT_FOUND"
|
|
22
|
+
COMMAND_CANCELLED = "COMMAND_CANCELLED"
|
|
23
|
+
REF_RESOLUTION_FAILED = "REF_RESOLUTION_FAILED"
|
|
24
|
+
DEVICE_RPC_FAILED = "DEVICE_RPC_FAILED"
|
|
25
|
+
DEVICE_DISCONNECTED = "DEVICE_DISCONNECTED"
|
|
26
|
+
DEVICE_AGENT_UNAVAILABLE = "DEVICE_AGENT_UNAVAILABLE"
|
|
27
|
+
DEVICE_AGENT_UNAUTHORIZED = "DEVICE_AGENT_UNAUTHORIZED"
|
|
28
|
+
DEVICE_AGENT_VERSION_MISMATCH = "DEVICE_AGENT_VERSION_MISMATCH"
|
|
29
|
+
DEVICE_AGENT_CAPABILITY_MISMATCH = "DEVICE_AGENT_CAPABILITY_MISMATCH"
|
|
30
|
+
ACCESSIBILITY_NOT_READY = "ACCESSIBILITY_NOT_READY"
|
|
31
|
+
DEVICE_RPC_TRANSPORT_RESET = "DEVICE_RPC_TRANSPORT_RESET"
|
|
32
|
+
INTERNAL_COMMAND_FAILURE = "INTERNAL_COMMAND_FAILURE"
|
|
33
|
+
WORKSPACE_UNAVAILABLE = "WORKSPACE_UNAVAILABLE"
|
|
34
|
+
ARTIFACT_ROOT_UNWRITABLE = "ARTIFACT_ROOT_UNWRITABLE"
|
|
35
|
+
ARTIFACT_WRITE_FAILED = "ARTIFACT_WRITE_FAILED"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class DaemonError(DaemonWireModel):
|
|
39
|
+
"""Typed daemon error payload for shared transport envelopes."""
|
|
40
|
+
|
|
41
|
+
code: DaemonErrorCode
|
|
42
|
+
message: str
|
|
43
|
+
retryable: bool
|
|
44
|
+
details: dict[str, object] = Field(default_factory=dict)
|