mirror of
https://github.com/callstack/agent-device.git
synced 2026-09-14 20:06:34 +08:00
refactor: consolidate architecture ownership and client results (#1210)
* refactor: consolidate architecture ownership and client results Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * fix: keep selector parse chunk grouping current Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * fix: update moved architecture breadcrumbs Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * fix: enforce moved selector architecture Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * fix: keep selector guarantee ownership current Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * docs: update selector ownership references Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --------- Co-authored-by: Michał Pierzchała <thymikee@gmail.com> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
c93dcdbc90
commit
0a8ea3a57b
@@ -72,6 +72,11 @@ Command identity, routing, capability, and request-policy traits are *derived* a
|
||||
- command names: `src/command-catalog.ts`; never re-create command string sets in handlers
|
||||
Keep `src/daemon.ts` a thin router and `src/daemon/request-router.ts` orchestration-only. New daemon handler-family commands update the daemon command registry; its tests guard the traits.
|
||||
|
||||
Shared selector parsing, matching, resolution, and evaluation live in `src/selectors`; request
|
||||
cancellation/progress primitives live in `src/request`; cross-layer platform and command data
|
||||
contracts live in `src/contracts`. CLI grammar owns flag declarations under
|
||||
`src/commands/cli-grammar`, while cross-surface CLI schema composition lives in `src/cli-schema`.
|
||||
|
||||
## Toolchain Snapshot
|
||||
- Package manager: `pnpm` only. Do not add or restore `package-lock.json`.
|
||||
- Daemon state: packaged installs use `~/.agent-device`; source checkouts use worktree-scoped dirs under `~/.agent-device/dev/<basename-slug>-<hash>`. Use `pnpm daemon:state-dir` to inspect it, `--state-dir`/`AGENT_DEVICE_STATE_DIR` to override it, and `pnpm clean:daemon --prune-dev` to prune stale dev dirs. Daemons are isolated by worktree, but devices are not; target different devices/simulators for concurrent worktrees.
|
||||
@@ -92,7 +97,9 @@ Keep `src/daemon.ts` a thin router and `src/daemon/request-router.ts` orchestrat
|
||||
- read `.oxlintrc.json` before treating lint output as source-level bugs
|
||||
- For files over 500 LOC, search for the relevant type/function/section first, then read a bounded range.
|
||||
- Do not run integration tests by default.
|
||||
- Keep long help prose in `src/cli/parser/cli-help.ts`, flag definitions in `src/cli/parser/cli-flags.ts`, and command-specific usage/flag metadata with the command family metadata that owns the command.
|
||||
- Keep long help prose in `src/cli/parser/cli-help.ts`, flag definitions in
|
||||
`src/commands/cli-grammar/flag-definitions-*.ts`, and command-specific usage/flag metadata with
|
||||
the command family metadata that owns the command.
|
||||
- If build/type errors mention declaration generation, inspect `tsconfig.lib.json` before reading platform code.
|
||||
- If lint failures appear after toolchain edits, check whether the rule is from `eslint/*`, `typescript/*`, `import/*`, or `node/*` in `.oxlintrc.json` before assuming source bugs.
|
||||
|
||||
@@ -105,7 +112,13 @@ Keep `src/daemon.ts` a thin router and `src/daemon/request-router.ts` orchestrat
|
||||
|
||||
A new snapshot/command flag touches only the layers that need to understand it. Follow this checklist in order:
|
||||
|
||||
1. `src/cli/parser/cli-flags.ts`: add to `CliFlags`, `FLAG_DEFINITIONS`, and the relevant exported flag group (e.g. `SNAPSHOT_FLAGS`). Then update the command family metadata/schema that exposes the flag; find the owner with `rg -n "<command>|supportedFlags|allowedFlags" src/commands src/cli/parser`. For schema-only CLI commands (`cdp`, `auth`, `connect`, `proxy`, `react-devtools`, `web`), the flag schema owner is `src/utils/cli-command-overrides.ts` (`SCHEMA_ONLY_CLI_COMMAND_SCHEMAS`).
|
||||
1. `src/contracts/cli-flags.ts`: add to `CliFlags`; add the definition to the matching
|
||||
`src/commands/cli-grammar/flag-definitions-*.ts` owner and the relevant group in
|
||||
`flag-groups.ts` (for example, `SNAPSHOT_FLAGS`). Then update the command family metadata/schema
|
||||
that exposes the flag; find the owner with
|
||||
`rg -n "<command>|supportedFlags|allowedFlags" src/commands src/cli-schema src/cli/parser`. For
|
||||
schema-only CLI commands (`cdp`, `auth`, `connect`, `proxy`, `react-devtools`, `web`), the owner
|
||||
is `src/cli-schema/command-overrides.ts` (`SCHEMA_ONLY_CLI_COMMAND_SCHEMAS`).
|
||||
2. `src/commands/cli-grammar/*`: read the CLI flag into command input when the CLI accepts it.
|
||||
3. `src/commands/command-projection.ts` and command-family projection helpers: write the input into the daemon request only if the flag affects daemon execution.
|
||||
4. `src/commands/*-command-contracts.ts`: add or update the command input schema only if the option should be available through Node.js or MCP as structured input.
|
||||
@@ -140,8 +153,9 @@ This repo encodes invariants as self-declaring gates. The correct response to a
|
||||
- Apple-family target changes must keep `src/kernel/device.ts`, `src/core/capabilities.ts`, `src/core/dispatch-resolve.ts`, `src/platforms/apple/core/devices.ts`, and `src/platforms/apple/core/runner/runner-xctestrun.ts` in sync.
|
||||
- iOS simulator-set scoping is iOS-specific: do not let `iosSimulatorDeviceSet` hide the host macOS desktop target when `--platform macos` or `--target desktop` is requested.
|
||||
- If Swift runner code changes, run `pnpm build:xcuitest`.
|
||||
- Use `inferFillText` and `uniqueStrings` from `src/daemon/action-utils.ts`.
|
||||
- Use `evaluateIsPredicate` from `src/daemon/is-predicates.ts` for assertion logic.
|
||||
- Use `inferFillText` from `src/daemon/action-utils.ts` and `uniqueStrings` from
|
||||
`src/kernel/collections.ts`.
|
||||
- Use `evaluateIsPredicate` from `src/selectors/predicates.ts` for assertion logic.
|
||||
|
||||
## Logs Contract
|
||||
- Logs backend/source of truth is `src/daemon/app-log.ts`.
|
||||
@@ -190,10 +204,10 @@ This repo encodes invariants as self-declaring gates. The correct response to a
|
||||
## Selector System Rules
|
||||
- Interaction commands (`click`, `fill`, `get`, `is`) and `wait` accept selectors and `@ref`.
|
||||
- Pipeline: **parse -> resolve -> act -> record selectorChain -> heal on replay**.
|
||||
- Keep selector parsing/matching in `src/daemon/selectors.ts`.
|
||||
- Keep selector parsing, matching, and resolution in `src/selectors/`.
|
||||
- Call `buildSelectorChainForNode` after resolving target nodes.
|
||||
- New element-targeting interactions must support selector + `@ref`, record `selectorChain`, and hook replay healing (`healReplayAction` in `session.ts` + selector helpers in `session-replay-heal.ts`).
|
||||
- New selector keys remain centralized in `selectors.ts`.
|
||||
- New selector keys remain centralized in `src/selectors/parse.ts`.
|
||||
- New `is` predicates belong in `evaluateIsPredicate`.
|
||||
- On macOS, snapshot rects are absolute in window space. Point-based runner interactions must translate through the interaction root frame; do not assume app-origin `(0,0)` coordinates.
|
||||
- Prefer selector or `@ref` interactions over raw x/y commands in tests and docs, especially on macOS where window position can vary across runs.
|
||||
@@ -206,7 +220,8 @@ This repo encodes invariants as self-declaring gates. The correct response to a
|
||||
## Testing Matrix
|
||||
- For code changes, run `pnpm check:affected --base origin/main --run` by default (`--json` for a machine-readable plan without execution). It delegates affected Vitest selection to `vitest related` and derives the remaining gates from repository sources of truth; GitHub CI stays authoritative. See `docs/agents/testing.md`.
|
||||
- Docs/skills only: no tests required unless a more specific rule below applies.
|
||||
- CLI help/guidance changes in `src/cli/parser/cli-help.ts`, `src/utils/cli-command-overrides.ts`, or `src/utils/command-schema.ts`: run `pnpm exec vitest run src/cli/parser/__tests__ src/utils/__tests__/command-schema-guards.test.ts`.
|
||||
- CLI help/guidance changes in `src/cli/parser/cli-help.ts` or `src/cli-schema/`: run
|
||||
`pnpm exec vitest run src/cli/parser/__tests__ src/cli-schema/command-schema-guards.test.ts`.
|
||||
- SkillGym prompt/assertion changes: run `pnpm test:skillgym:case <case-id>`; the script builds local CLI help first. For broad validation, use `pnpm test:skillgym`; append `-- --tag fixture-smoke` or `-- --tag skill-guidance` when validating one suite group.
|
||||
- Non-TS, no behavior impact: no tests unless requested.
|
||||
- Keep tests behavioral; do not assert shapes or cases TypeScript already proves.
|
||||
@@ -251,8 +266,13 @@ This repo encodes invariants as self-declaring gates. The correct response to a
|
||||
- Changing `tsconfig.lib.json`/build tooling without running `pnpm check:tooling`; declaration generation is stricter than a plain typecheck.
|
||||
|
||||
## Docs & Skills
|
||||
- Versioned CLI help is the agent-facing source of truth. Put workflow guidance/help topics in `src/cli/parser/cli-help.ts`, flags in `src/cli/parser/cli-flags.ts`, command-specific schema/help metadata with the owning command family, and assertions near the focused CLI parser/help tests.
|
||||
- Keep parser schema and help rendering separate: parser/help rendering lives in `src/cli/parser/`, while command schema metadata is derived from command metadata, command family declarations, and the schema-only merge path in `src/utils/cli-command-overrides.ts`.
|
||||
- Versioned CLI help is the agent-facing source of truth. Put workflow guidance/help topics in
|
||||
`src/cli/parser/cli-help.ts`, shared flag contracts in `src/contracts/cli-flags.ts`, flag
|
||||
definitions in `src/commands/cli-grammar/`, command-specific schema/help metadata with the owning
|
||||
command family, and assertions near the focused CLI parser/help tests.
|
||||
- Keep parser schema and help rendering separate: parser/help rendering lives in `src/cli/parser/`,
|
||||
while command schema metadata is derived from command metadata, command family declarations, and
|
||||
the schema-only merge path in `src/cli-schema/command-overrides.ts`.
|
||||
- Before planning device automation commands, read `agent-device help workflow`; then read topic help such as `debugging`, `react-native`, `react-devtools`, `physical-device`, `macos`, or `dogfood` when relevant. This is required even when local agent skills are unavailable.
|
||||
- Skills are thin routers. Keep `skills/**/SKILL.md` focused on when to use the skill, version gating, which `agent-device help <topic>` page to read, and a short default loop. Do not duplicate full CLI manuals in skills.
|
||||
- For behavior/CLI surface changes, update help/metadata, README or `website/docs/**` when user-facing, and a SkillGym case in `test/skillgym/suites/agent-device-smoke-suite.ts` when command-planning guidance changes.
|
||||
@@ -273,7 +293,11 @@ This repo encodes invariants as self-declaring gates. The correct response to a
|
||||
- Command identity and projection: search command descriptors and command contracts first with `rg -n "<command>|CommandDescriptor|defineCommand" src/core/command-descriptor src/command-catalog.ts src/commands`.
|
||||
- Daemon routing and policy: start with `src/daemon/daemon-command-registry.ts`, then trace to the named handler/request module with `rg -n "<command>|route|policy" src/daemon`.
|
||||
- Platform behavior and capabilities: start with `src/core/capabilities.ts` and the relevant platform under `src/platforms/`; use `rg`, not broad directory reads.
|
||||
- CLI help and command-planning guidance: start with `src/cli/parser/cli-help.ts` and `src/cli/parser/cli-flags.ts`; for command-specific schema, search `rg -n "helpDescription|summary|supportedFlags|allowedFlags" src/commands src/cli/parser src/utils/cli-command-overrides.ts`, and check `SCHEMA_ONLY_CLI_COMMAND_SCHEMAS` for schema-only CLI commands (`cdp`, `auth`, `connect`, `proxy`, `react-devtools`, `web`).
|
||||
- CLI help and command-planning guidance: start with `src/cli/parser/cli-help.ts` and
|
||||
`src/commands/cli-grammar/`; for command-specific schema, search
|
||||
`rg -n "helpDescription|summary|supportedFlags|allowedFlags" src/commands src/cli/parser src/cli-schema`,
|
||||
and check `SCHEMA_ONLY_CLI_COMMAND_SCHEMAS` in `src/cli-schema/command-overrides.ts` for
|
||||
schema-only CLI commands (`cdp`, `auth`, `connect`, `proxy`, `react-devtools`, `web`).
|
||||
|
||||
## Pull Requests
|
||||
- Before opening PR: ensure no conflict markers/unmerged paths.
|
||||
|
||||
+8
-9
@@ -76,9 +76,10 @@ The perfect-shape refactor is complete and merged. Its end-state:
|
||||
traits, and platform dispatch command set are _derived_ by parity-tested projection. Command
|
||||
families still own surface metadata/CLI schema in `src/commands/**`, but descriptor/catalog
|
||||
coherence guards prevent surface names from drifting; system command facets now project their
|
||||
simple Node client command methods. Public Node-client result narrowing remains a deferred typed
|
||||
contract target ([#1153](https://github.com/callstack/agent-device/issues/1153)), separate from
|
||||
the completed descriptor registry migration. One
|
||||
simple Node client command methods. Closed public Node-client result contracts are narrowed
|
||||
through `CommandResultMap`; action/backend-dependent methods remain explicitly broad until their
|
||||
public response projections are reconciled. See
|
||||
[Node client result types](docs/node-client-result-types.md). One
|
||||
`PlatformPlugin` per platform family (`src/core/platform-plugin/`) stops core/daemon from branching
|
||||
on platform, with the Apple plugin the first instance. See
|
||||
[ADR 0008](docs/adr/0008-command-descriptor-registry.md).
|
||||
@@ -100,15 +101,13 @@ The perfect-shape refactor is complete and merged. Its end-state:
|
||||
- Agent-cost. Responses carry a cost block and MCP `outputSchema`, rendered through a leveled
|
||||
`ResponseView`.
|
||||
|
||||
### Deferred / next-minor
|
||||
### Deferred
|
||||
|
||||
The refactor is substantively done; these follow-ups are intentionally deferred, not lost:
|
||||
|
||||
- Phase 2c — narrow the ~15 remaining `Record`-typed client methods in
|
||||
`src/client/client-types.ts` to their existing typed contracts (a semver-relevant public-API
|
||||
narrowing; not yet done).
|
||||
- Strict DAG back-edge inversion — the layering lint prevents target-spine back-edge growth, but
|
||||
the full zero-back-edge DAG (e.g. `commands` → `cli`/`client`) is not done.
|
||||
- Dynamic Node-client results — interactions, observability, alert, React Native overlay, and
|
||||
settings remain broad until their action/backend-specific payloads have accurate public
|
||||
projections. See [Node client result types](docs/node-client-result-types.md).
|
||||
- Legacy alias drops — ~175 LOC of legacy aliases/barrels remain, gated to the next major.
|
||||
|
||||
## Selector Capture Reliability Contract
|
||||
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
import XCTest
|
||||
|
||||
// Swift port of buildScrollGesturePlan from src/core/scroll-gesture.ts.
|
||||
// Swift port of buildScrollGesturePlan from src/contracts/scroll-gesture.ts.
|
||||
//
|
||||
// This is a deliberate two-place invariant: the daemon keeps the TS implementation (for Android,
|
||||
// recording, and reported-pixels), and the runner places the gesture with this Swift copy. The
|
||||
// parity test vectors at the bottom of this file mirror src/core/__tests__/scroll-gesture.test.ts —
|
||||
// parity test vectors at the bottom of this file mirror src/contracts/scroll-gesture.test.ts —
|
||||
// if you change the math in either language, update the other and both vector sets.
|
||||
//
|
||||
// All inputs here are positive (reference dims, travel, center), so Swift's `.rounded()`
|
||||
@@ -64,7 +64,7 @@ func runnerScrollGesturePlan(
|
||||
|
||||
#if AGENT_DEVICE_RUNNER_UNIT_TESTS
|
||||
extension RunnerTests {
|
||||
// Cross-language parity vectors mirroring src/core/__tests__/scroll-gesture.test.ts. Keep these
|
||||
// Cross-language parity vectors mirroring src/contracts/scroll-gesture.test.ts. Keep these
|
||||
// in sync with the vitest vectors so the two buildScrollGesturePlan implementations cannot drift.
|
||||
|
||||
func testRunnerScrollGesturePlanMapsRelativeAmount() throws {
|
||||
|
||||
@@ -30,7 +30,7 @@ agent failures (selector/ref misses), and consumers that drop fields (MCP tool e
|
||||
default from `defaultHintForCode` would mislead; it is omitted where the default suffices —
|
||||
mass-adding boilerplate hints is worse than the default. Shared failure modes get shared hint
|
||||
constants next to the code that detects them (`selectorFailureHint`, `STALE_REF_HINT` in
|
||||
`src/daemon/selectors-resolve.ts`; `resolveIosDevicectlHint`; `bootFailureHint`), not copy-pasted
|
||||
`src/selectors/resolve.ts`; `resolveIosDevicectlHint`; `bootFailureHint`), not copy-pasted
|
||||
strings. Re-wraps preserve an existing hint rather than clobbering it.
|
||||
4. **Wrapping external tool failures.** Prefer `exec.ts` errors as-is. A hand-rolled wrap of an
|
||||
`allowFailure` result must carry `{ stdout, stderr, exitCode, processExitError: true }` so
|
||||
|
||||
@@ -19,8 +19,8 @@ or hand-written, and executed step-by-step by `runReplayScriptFile`
|
||||
`emitReplayTestActionProgress`, `session-replay-runtime.ts:243-260`).
|
||||
|
||||
Recovery is opt-in `--update`/`-u` healing (`replayUpdate` flag,
|
||||
`src/cli/parser/cli-flags.ts:1041-1047`). It only fires after a step has already returned a hard
|
||||
failure (`session-replay-runtime.ts:118-149`: `if (!shouldUpdate) return failure; ...
|
||||
`src/commands/cli-grammar/flag-definitions-workflow.ts`). It only fires after a step has already
|
||||
returned a hard failure (`session-replay-runtime.ts:118-149`: `if (!shouldUpdate) return failure; ...
|
||||
healReplayAction(...)`), and it only retries the SAME recorded selector material —
|
||||
`collectReplaySelectorCandidates` (`session-replay-heal.ts:39-81`) gathers the step's originally
|
||||
recorded `selectorChain`/positionals, then `resolveSelectorChain` re-resolves those exact candidate
|
||||
@@ -56,7 +56,7 @@ zero on the happy path and paying only where reality diverged from the recording
|
||||
live and replay alike. `resolveSelectorInteractionTarget` calls `resolveSelectorChain(..., {
|
||||
disambiguateAmbiguous: true })` on every press/click/fill (`resolution.ts:170-183`); when a selector
|
||||
matches N>1 nodes, `accumulateDisambiguationCandidate`/`compareDisambiguationCandidates`
|
||||
(`src/daemon/selectors-resolve.ts:153-204`) silently pick a winner — visible candidates over
|
||||
(`src/selectors/resolve.ts:181-285`) silently pick a winner — visible candidates over
|
||||
off-screen ones, then deepest node, then smallest on-screen area, only an exact tie failing.
|
||||
`describeResolvedInteractionNode` (`resolution.ts:227-249`), the response's entire identity payload,
|
||||
carries `node`/`selectorChain`/`refLabel`/`targetHittable`/`hint` — no match count, no signal a
|
||||
@@ -129,7 +129,7 @@ both `.ad` and Maestro paths) grounds the same conclusions from the caller's sea
|
||||
(`session-replay-runtime.ts:349-369`) puts only `replayPath` + `step` in the error details.
|
||||
- **The same failure class reports differently per format.** An `.ad` selector miss is
|
||||
`COMMAND_FAILED` with the targeted hint "Run snapshot -i ... or use find ..."
|
||||
(`selectorFailureHint`, `src/daemon/selectors-resolve.ts:84-97`, thrown at `resolution.ts:199-203`);
|
||||
(`selectorFailureHint`, `src/selectors/resolve.ts:110-113`, thrown at `resolution.ts:213-217`);
|
||||
the equivalent Maestro miss is `ELEMENT_NOT_FOUND` constructed with no hint
|
||||
(`src/compat/maestro/runtime-interactions.ts:644-652`), falling through to the generic default
|
||||
"Retry with --debug and inspect diagnostics log for details." (`defaultHintForCode`,
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
# Node client result types
|
||||
|
||||
The `0.20` minor line intentionally narrows public TypeScript return types when a command has an
|
||||
accurate, closed daemon result contract. Runtime payloads are unchanged. This is source-compatible
|
||||
for callers that only read real response fields, but TypeScript code that indexed arbitrary keys
|
||||
from the former `Record<string, unknown>` result must switch to the declared fields or explicitly
|
||||
narrow an external payload at its own trust boundary.
|
||||
|
||||
The closed-result batch covers:
|
||||
|
||||
- `command.doctor`
|
||||
- `capture.diff` (`kind: 'snapshot'`)
|
||||
- `replay.run`
|
||||
- `replay.test`
|
||||
- `recording.record`
|
||||
- `recording.trace`
|
||||
|
||||
Their canonical result types live in `src/contracts`, feed `CommandResultMap`, and have matching MCP
|
||||
output schemas.
|
||||
|
||||
The remaining broad methods are deliberate:
|
||||
|
||||
- `command.alert` and `command.reactNative` spread platform/interaction-specific data.
|
||||
- The interaction family (`click` through `find`) needs one public response projection reconciled
|
||||
with settle/evidence and fast-path additions before its existing runtime contracts are safe as
|
||||
public return types.
|
||||
- Observability (`perf`, `logs`, `events`, `network`, `audio`) is action- and backend-dependent.
|
||||
- `settings.update` spreads backend-specific setting data.
|
||||
|
||||
Those methods remain `CommandRequestResult` until their producers expose accurate closed public
|
||||
contracts. Do not narrow them with casts, compatibility aliases, or invented partial shapes.
|
||||
@@ -16,6 +16,9 @@
|
||||
"type_only_dependencies": [],
|
||||
"test_only_dependencies": [],
|
||||
"boundary_violations": [],
|
||||
"boundary_coverage_violations": [],
|
||||
"boundary_call_violations": [],
|
||||
"policy_violations": [],
|
||||
"stale_suppressions": [],
|
||||
"unused_catalog_entries": [],
|
||||
"empty_catalog_groups": [],
|
||||
|
||||
@@ -18,6 +18,14 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/cli-schema/option-schema.ts": {
|
||||
"complexity_moderate": {
|
||||
"count": 1
|
||||
},
|
||||
"crap_moderate": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/cli.ts": {
|
||||
"complexity_critical": {
|
||||
"count": 1
|
||||
@@ -76,7 +84,7 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/client/client-shared.ts": {
|
||||
"src/contracts/result-serialization.ts": {
|
||||
"crap_moderate": {
|
||||
"count": 1
|
||||
}
|
||||
@@ -133,10 +141,10 @@
|
||||
}
|
||||
},
|
||||
"src/daemon/device-ready.ts": {
|
||||
"complexity_critical": {
|
||||
"complexity_high": {
|
||||
"count": 1
|
||||
},
|
||||
"crap_critical": {
|
||||
"crap_high": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
@@ -202,11 +210,6 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/daemon/handlers/interaction-common.ts": {
|
||||
"crap_high": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/daemon/handlers/interaction-touch-reference-frame.ts": {
|
||||
"crap_moderate": {
|
||||
"count": 1
|
||||
@@ -301,16 +304,6 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/daemon/selectors-match.ts": {
|
||||
"crap_high": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/daemon/selectors-resolve.ts": {
|
||||
"crap_moderate": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/daemon/server/http-server.ts": {
|
||||
"complexity_critical": {
|
||||
"count": 1
|
||||
@@ -333,19 +326,17 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/kernel/contracts.ts": {
|
||||
"crap_moderate": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/kernel/device.ts": {
|
||||
"complexity_moderate": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/metro/client-metro.ts": {
|
||||
"crap_high": {
|
||||
"count": 1
|
||||
},
|
||||
"crap_moderate": {
|
||||
"count": 3
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"src/platforms/android/app-parsers.ts": {
|
||||
@@ -396,11 +387,6 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/platforms/apple/core/runner/runner-xctestrun.ts": {
|
||||
"complexity_moderate": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/platforms/apple/core/screenshot-status-bar.ts": {
|
||||
"complexity_moderate": {
|
||||
"count": 1
|
||||
@@ -414,11 +400,6 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/platforms/apple/core/simulator.ts": {
|
||||
"crap_moderate": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/platforms/apple/os/macos/helper.ts": {
|
||||
"crap_high": {
|
||||
"count": 1
|
||||
@@ -475,19 +456,34 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/snapshot/mobile-snapshot-semantics.ts": {
|
||||
"crap_moderate": {
|
||||
"count": 2
|
||||
"src/selectors/build.ts": {
|
||||
"complexity_high": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/snapshot/snapshot-diff.ts": {
|
||||
"src/selectors/match.ts": {
|
||||
"crap_high": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/selectors/parse.ts": {
|
||||
"complexity_moderate": {
|
||||
"count": 1
|
||||
},
|
||||
"crap_moderate": {
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"src/selectors/predicates.ts": {
|
||||
"crap_moderate": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/snapshot/mobile-snapshot-semantics.ts": {
|
||||
"crap_moderate": {
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"src/snapshot/snapshot-lines.ts": {
|
||||
"crap_moderate": {
|
||||
"count": 1
|
||||
@@ -498,14 +494,6 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/utils/cli-option-schema.ts": {
|
||||
"complexity_moderate": {
|
||||
"count": 1
|
||||
},
|
||||
"crap_moderate": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/utils/exec.ts": {
|
||||
"complexity_moderate": {
|
||||
"count": 1
|
||||
@@ -526,24 +514,6 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/utils/selector-build.ts": {
|
||||
"complexity_high": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/utils/selector-is-predicates.ts": {
|
||||
"crap_moderate": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/utils/selectors-parse.ts": {
|
||||
"complexity_moderate": {
|
||||
"count": 1
|
||||
},
|
||||
"crap_moderate": {
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"src/utils/source-value.ts": {
|
||||
"complexity_high": {
|
||||
"count": 1
|
||||
@@ -610,63 +580,65 @@
|
||||
"runtime_coverage_findings": [],
|
||||
"target_keys": [
|
||||
"src/daemon/client/daemon-client.ts:high impact",
|
||||
"src/replay/script.ts:complexity",
|
||||
"src/daemon/handlers/session-replay-runtime.ts:high impact",
|
||||
"src/cli/parser/args.ts:high impact",
|
||||
"src/daemon/lease-context.ts:high impact",
|
||||
"src/daemon/context.ts:high impact",
|
||||
"src/daemon/handlers/session-replay-heal.ts:high impact",
|
||||
"src/utils/output.ts:high impact",
|
||||
"src/daemon/android-snapshot-freshness.ts:high impact",
|
||||
"src/daemon/handlers/session-replay-heal.ts:complexity",
|
||||
"src/platforms/web/agent-browser-provider.ts:high impact",
|
||||
"src/compat/maestro/support.ts:high impact",
|
||||
"src/daemon/context.ts:high impact",
|
||||
"src/daemon/handlers/session.ts:complexity",
|
||||
"src/replay/script-utils.ts:high impact",
|
||||
"src/selectors/predicates.ts:high impact",
|
||||
"src/daemon/android-snapshot-freshness.ts:high impact",
|
||||
"src/platforms/boot-diagnostics.ts:complexity",
|
||||
"src/utils/selector-is-predicates.ts:high impact",
|
||||
"src/snapshot/snapshot-processing.ts:high impact",
|
||||
"src/compat/maestro/support.ts:high impact",
|
||||
"src/daemon/session-routing.ts:high impact",
|
||||
"src/daemon/handlers/session-state.ts:complexity",
|
||||
"src/commands/cli-grammar/common.ts:high impact",
|
||||
"src/utils/success-text.ts:high impact",
|
||||
"src/snapshot/snapshot-processing.ts:high impact",
|
||||
"src/daemon/network-log.ts:high impact",
|
||||
"src/commands/cli-grammar/common.ts:high impact",
|
||||
"src/daemon/snapshot-presentation/tree.ts:high impact",
|
||||
"src/utils/success-text.ts:high impact",
|
||||
"src/cli.ts:complexity",
|
||||
"src/utils/timeouts.ts:high impact",
|
||||
"src/client/client-shared.ts:high impact",
|
||||
"src/replay/script-utils.ts:high impact",
|
||||
"src/commands/interaction/output.ts:high impact",
|
||||
"src/snapshot/snapshot-lines.ts:high impact",
|
||||
"src/contracts/result-serialization.ts:high impact",
|
||||
"src/utils/rect-center.ts:high impact",
|
||||
"src/platforms/apple/core/app-launch.ts:complexity",
|
||||
"src/utils/parsing.ts:high impact",
|
||||
"src/cli/parser/args.ts:high impact",
|
||||
"src/daemon/snapshot-presentation/tree.ts:high impact",
|
||||
"src/platforms/apple/core/perf-xml.ts:high impact",
|
||||
"src/platforms/web/json-utils.ts:high impact",
|
||||
"src/utils/rect-center.ts:high impact",
|
||||
"src/daemon/handlers/session-doctor-output.ts:high impact",
|
||||
"src/daemon/app-log-process.ts:high impact",
|
||||
"src/daemon/handlers/session-test-sharding.ts:high impact",
|
||||
"src/platforms/apple/core/debug-symbols/utils.ts:high impact",
|
||||
"src/daemon/request-cancel.ts:high impact",
|
||||
"src/core/interaction-targeting.ts:high impact",
|
||||
"src/platforms/linux/snapshot.ts:high impact",
|
||||
"src/snapshot/snapshot-lines.ts:high impact",
|
||||
"src/cli.ts:complexity",
|
||||
"src/utils/selector-build.ts:high impact",
|
||||
"src/utils/source-value.ts:high impact",
|
||||
"src/utils/text-surface.ts:high impact",
|
||||
"src/daemon/daemon-command-registry.ts:high impact",
|
||||
"src/replay/script.ts:complexity",
|
||||
"src/daemon/handlers/session-doctor-output.ts:high impact",
|
||||
"src/platforms/apple/core/perf-xml.ts:high impact",
|
||||
"src/daemon/daemon-process.ts:high impact",
|
||||
"src/utils/screenshot-result.ts:high impact",
|
||||
"src/platforms/web/json-utils.ts:high impact",
|
||||
"src/platforms/android/settings.ts:complexity",
|
||||
"src/utils/text-surface.ts:high impact",
|
||||
"src/daemon/handlers/session-test-sharding.ts:high impact",
|
||||
"src/daemon/handlers/session-replay-runtime.ts:complexity",
|
||||
"src/platforms/apple/core/debug-symbols/utils.ts:high impact",
|
||||
"src/platforms/linux/snapshot.ts:high impact",
|
||||
"src/core/interaction-targeting.ts:high impact",
|
||||
"src/compat/maestro/runtime-targets.ts:high impact",
|
||||
"src/utils/source-value.ts:high impact",
|
||||
"src/request/cancel.ts:high impact",
|
||||
"src/commands/interaction/selectors.ts:untested risk",
|
||||
"src/selectors/build.ts:high impact",
|
||||
"src/kernel/redaction.ts:high impact",
|
||||
"src/utils/rect-visibility.ts:high impact",
|
||||
"src/cloud-webdriver/webdriver-utils.ts:high impact",
|
||||
"src/utils/keyed-lock.ts:high impact",
|
||||
"src/utils/screenshot-result.ts:high impact",
|
||||
"src/cloud-webdriver/webdriver-source.ts:high impact",
|
||||
"src/daemon/request-progress-protocol.ts:high impact",
|
||||
"src/replay/test/reporters/format.ts:high impact",
|
||||
"src/daemon/handlers/session-test-infrastructure.ts:high impact",
|
||||
"src/daemon/request-progress-protocol.ts:high impact",
|
||||
"src/platforms/android/ui-hierarchy.ts:high impact",
|
||||
"src/utils/rect-visibility.ts:high impact",
|
||||
"src/daemon/handlers/session-test-artifacts.ts:high impact",
|
||||
"src/platforms/android/app-parsers.ts:high impact",
|
||||
"src/daemon/server/http-server.ts:complexity",
|
||||
"src/platforms/android/ui-hierarchy.ts:high impact",
|
||||
"src/platforms/android/sdk.ts:high impact",
|
||||
"src/daemon/client/daemon-client-lifecycle.ts:complexity",
|
||||
"src/client/client-companion-tunnel-worker.ts:complexity"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ function ids(changedFiles: string[]): CheckId[] {
|
||||
}
|
||||
|
||||
test('production source selects static/build gates and delegates tests to Vitest', () => {
|
||||
const result = plan(['src/daemon/selectors.ts']);
|
||||
const result = plan(['src/selectors/index.ts']);
|
||||
assert.equal(result.failOpen, false);
|
||||
for (const id of [
|
||||
'format',
|
||||
@@ -139,7 +139,7 @@ test('workflow/tooling and selector-owning changes fail open', () => {
|
||||
});
|
||||
|
||||
test('a fail-open path in a mixed changeset forces the full set', () => {
|
||||
const result = plan(['src/daemon/selectors.ts', 'bin/agent-device.mjs']);
|
||||
const result = plan(['src/selectors/index.ts', 'bin/agent-device.mjs']);
|
||||
assert.equal(result.failOpen, true);
|
||||
assert.deepEqual(result.checks, [...ALL_CHECKS]);
|
||||
});
|
||||
|
||||
@@ -112,7 +112,7 @@ test('runChecks runs local checks in order and stops on the first failure', asyn
|
||||
return command.includes('lint') ? 1 : 0;
|
||||
};
|
||||
const plan = selectChecks({
|
||||
changedFiles: ['src/daemon/selectors.ts'],
|
||||
changedFiles: ['src/selectors/index.ts'],
|
||||
packageEntryFiles: [],
|
||||
});
|
||||
const code = await runChecks(plan, { scripts: ALL_SCRIPTS }, ARGS, { execute, cwd: '.' });
|
||||
@@ -130,7 +130,7 @@ test('runChecks passes the selector change set to Vitest related', async () => {
|
||||
executed.push(command);
|
||||
return 0;
|
||||
};
|
||||
const changedFiles = ['src/daemon/selectors.ts', 'src/daemon/selectors.test.ts'];
|
||||
const changedFiles = ['src/selectors/index.ts', 'src/selectors/index.test.ts'];
|
||||
const plan = selectChecks({ changedFiles, packageEntryFiles: [] });
|
||||
const code = await runChecks(plan, { scripts: ALL_SCRIPTS }, ARGS, {
|
||||
execute,
|
||||
|
||||
@@ -2,7 +2,7 @@ import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { PUBLIC_COMMANDS } from '../src/command-catalog.ts';
|
||||
import { listCommandMetadata } from '../src/commands/command-metadata.ts';
|
||||
import { getFlagDefinitions } from '../src/cli/parser/cli-flags.ts';
|
||||
import { getFlagDefinitions } from '../src/commands/cli-grammar/flag-registry.ts';
|
||||
|
||||
const EMPTY_COVERAGE_METRIC = { pct: 0 };
|
||||
const EMPTY_STATEMENT_COVERAGE = { covered: 0, pct: 0, total: 0 };
|
||||
|
||||
@@ -1,50 +1 @@
|
||||
{
|
||||
"client -> daemon-client": [
|
||||
"src/client/client.ts -> src/daemon/client/daemon-client.ts"
|
||||
],
|
||||
"commands -> cli": [
|
||||
"src/commands/capture/diff.ts -> src/cli/parser/cli-flags.ts",
|
||||
"src/commands/capture/snapshot.ts -> src/cli/parser/cli-flags.ts",
|
||||
"src/commands/capture/wait.ts -> src/cli/parser/cli-flags.ts",
|
||||
"src/commands/command-flags.ts -> src/cli/parser/cli-flags.ts",
|
||||
"src/commands/interaction/index.ts -> src/cli/parser/cli-flags.ts",
|
||||
"src/commands/metro/index.ts -> src/cli/parser/cli-flags.ts",
|
||||
"src/commands/replay/index.ts -> src/cli/parser/cli-flags.ts"
|
||||
],
|
||||
"commands -> client": [
|
||||
"src/commands/capture/output.ts -> src/client/client-shared.ts",
|
||||
"src/commands/command-flags.ts -> src/client/client-normalizers.ts",
|
||||
"src/commands/management/output.ts -> src/client/client-shared.ts"
|
||||
],
|
||||
"commands -> daemon-server": [
|
||||
"src/commands/interaction/runtime/resolution.ts -> src/daemon/selectors.ts",
|
||||
"src/commands/interaction/runtime/selector-read.ts -> src/daemon/selectors.ts"
|
||||
],
|
||||
"platforms -> core": [
|
||||
"src/platforms/android/app-lifecycle.ts -> src/core/open-target.ts",
|
||||
"src/platforms/android/device-input-state.ts -> src/core/android-input-ownership.ts",
|
||||
"src/platforms/android/fill-verification.ts -> src/core/android-input-ownership.ts",
|
||||
"src/platforms/android/input-actions.ts -> src/core/scroll-gesture.ts",
|
||||
"src/platforms/android/input-actions.ts -> src/core/tv-remote.ts",
|
||||
"src/platforms/android/snapshot-content-recovery.ts -> src/core/android-input-ownership.ts",
|
||||
"src/platforms/apple/core/app-launch.ts -> src/core/launch-console.ts",
|
||||
"src/platforms/apple/core/app-launch.ts -> src/core/open-target.ts",
|
||||
"src/platforms/apple/core/app-settings.ts -> src/core/settings-contract.ts",
|
||||
"src/platforms/apple/core/scroll.ts -> src/core/scroll-gesture.ts",
|
||||
"src/platforms/apple/interactions.ts -> src/core/scroll-command.ts",
|
||||
"src/platforms/apple/interactions.ts -> src/core/scroll-gesture.ts",
|
||||
"src/platforms/apple/interactor.ts -> src/core/tv-remote.ts",
|
||||
"src/platforms/apple/os/macos/apps.ts -> src/core/open-target.ts",
|
||||
"src/platforms/apple/plugin.ts -> src/core/platform-inventory.ts",
|
||||
"src/platforms/apple/plugin.ts -> src/core/platform-plugin/apple-os-capabilities.ts"
|
||||
],
|
||||
"platforms -> daemon-server": [
|
||||
"src/platforms/apple/core/perf-xctrace.ts -> src/daemon/action-utils.ts",
|
||||
"src/platforms/apple/core/perf.ts -> src/daemon/action-utils.ts",
|
||||
"src/platforms/apple/core/runner/runner-artifact.ts -> src/daemon/request-progress.ts",
|
||||
"src/platforms/apple/core/runner/runner-contract.ts -> src/daemon/request-cancel.ts",
|
||||
"src/platforms/apple/core/runner/runner-lifecycle.ts -> src/daemon/request-cancel.ts",
|
||||
"src/platforms/apple/core/runner/runner-session.ts -> src/daemon/request-progress.ts",
|
||||
"src/platforms/apple/core/runner/runner-transport.ts -> src/daemon/request-cancel.ts"
|
||||
]
|
||||
}
|
||||
{}
|
||||
|
||||
@@ -103,6 +103,28 @@ test('back-edge counts follow the documented target spine and drift in either di
|
||||
);
|
||||
});
|
||||
|
||||
test('neutral ownership zones reject value imports into higher layers', () => {
|
||||
const edges = resolveImportEdges(
|
||||
new Map([
|
||||
['src/contracts/result.ts', "import '../core/result.ts';"],
|
||||
['src/core/result.ts', 'export const result = true;'],
|
||||
['src/request/cancel.ts', "import '../commands/cancel.ts';"],
|
||||
['src/commands/cancel.ts', 'export const cancel = true;'],
|
||||
['src/selectors/parse.ts', "import '../client/client.ts';"],
|
||||
['src/client/client.ts', 'export const client = true;'],
|
||||
['src/cli-schema/schema.ts', "import '../cli/parser.ts';"],
|
||||
['src/cli/parser.ts', 'export const parser = true;'],
|
||||
]),
|
||||
);
|
||||
|
||||
assert.deepEqual(collectBackEdges(edges), {
|
||||
'cli-schema -> cli': ['src/cli-schema/schema.ts -> src/cli/parser.ts'],
|
||||
'contracts -> core': ['src/contracts/result.ts -> src/core/result.ts'],
|
||||
'request -> commands': ['src/request/cancel.ts -> src/commands/cancel.ts'],
|
||||
'selectors -> client': ['src/selectors/parse.ts -> src/client/client.ts'],
|
||||
});
|
||||
});
|
||||
|
||||
test('exact back-edge identities reject same-count replacements', () => {
|
||||
const baseline = {
|
||||
'commands -> cli': ['src/commands/a.ts -> src/cli/a.ts'],
|
||||
|
||||
@@ -24,9 +24,13 @@ export type BackEdgeDrift = {
|
||||
|
||||
const TARGET_DAG_RANK = new Map([
|
||||
['kernel', 0],
|
||||
['contracts', 1],
|
||||
['request', 1],
|
||||
['selectors', 1],
|
||||
['platforms', 1],
|
||||
['core', 2],
|
||||
['commands', 3],
|
||||
['cli-schema', 3],
|
||||
['client', 4],
|
||||
['daemon-server', 4],
|
||||
['daemon-client', 5],
|
||||
|
||||
@@ -12,7 +12,7 @@ import type {
|
||||
AppOpenOptions,
|
||||
MetroPrepareOptions,
|
||||
MetroReloadOptions,
|
||||
} from '../client/client.ts';
|
||||
} from '../agent-device-client.ts';
|
||||
import type { SettingsUpdateOptions } from '../client/client-types.ts';
|
||||
import { AppError } from '../kernel/errors.ts';
|
||||
import { resolveCliOptions } from '../utils/cli-options.ts';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { test } from 'vitest';
|
||||
import assert from 'node:assert/strict';
|
||||
import { readInputFromCli } from '../commands/cli-grammar.ts';
|
||||
import type { CliFlags } from '../cli/parser/cli-flags.ts';
|
||||
import type { CliFlags } from '../commands/cli-grammar/flag-types.ts';
|
||||
|
||||
const BASE_FLAGS: CliFlags = {
|
||||
json: false,
|
||||
|
||||
@@ -10,7 +10,7 @@ import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import { prepareMetroRuntime, reloadMetro } from '../metro/client-metro.ts';
|
||||
import { resolveMetroReloadEndpoints } from '../metro/metro-reload-endpoints.ts';
|
||||
import { createAgentDeviceClient } from '../client/client.ts';
|
||||
import { createAgentDeviceClient } from '../agent-device-client.ts';
|
||||
import { readMetroSessionHints } from '../metro/metro-session-hints.ts';
|
||||
import { resolveDaemonPaths } from '../daemon/config.ts';
|
||||
import { AppError } from '../kernel/errors.ts';
|
||||
|
||||
@@ -7,11 +7,17 @@ import {
|
||||
createAgentDeviceClient,
|
||||
type AgentDeviceClient,
|
||||
type AgentDeviceClientConfig,
|
||||
type DiffSnapshotCommandResult,
|
||||
type DoctorCommandResult,
|
||||
type PrepareCommandResult,
|
||||
type PushCommandResult,
|
||||
type RecordingCommandResult,
|
||||
type ReplayCommandResult,
|
||||
type ReplaySuiteResult,
|
||||
type TraceCommandResult,
|
||||
type TriggerAppEventCommandResult,
|
||||
type WaitCommandResult,
|
||||
} from '../client/client.ts';
|
||||
} from '../agent-device-client.ts';
|
||||
import { runCommand } from '../commands/command-surface.ts';
|
||||
import type { CommandResult } from '../core/command-descriptor/command-result.ts';
|
||||
import type { DaemonRequest, DaemonResponse, DaemonResponseData } from '../kernel/contracts.ts';
|
||||
@@ -113,10 +119,46 @@ test('client exposes narrowed result types for closed daemon projections', async
|
||||
Awaited<ReturnType<AgentDeviceClient['command']['wait']>>,
|
||||
CommandResult<'wait'>
|
||||
> = true;
|
||||
const doctorType: Equal<
|
||||
Awaited<ReturnType<AgentDeviceClient['command']['doctor']>>,
|
||||
DoctorCommandResult
|
||||
> = true;
|
||||
const diffType: Equal<
|
||||
Awaited<ReturnType<AgentDeviceClient['capture']['diff']>>,
|
||||
DiffSnapshotCommandResult
|
||||
> = true;
|
||||
const replayType: Equal<
|
||||
Awaited<ReturnType<AgentDeviceClient['replay']['run']>>,
|
||||
ReplayCommandResult
|
||||
> = true;
|
||||
const replayTestType: Equal<
|
||||
Awaited<ReturnType<AgentDeviceClient['replay']['test']>>,
|
||||
ReplaySuiteResult
|
||||
> = true;
|
||||
const recordType: Equal<
|
||||
Awaited<ReturnType<AgentDeviceClient['recording']['record']>>,
|
||||
RecordingCommandResult
|
||||
> = true;
|
||||
const traceType: Equal<
|
||||
Awaited<ReturnType<AgentDeviceClient['recording']['trace']>>,
|
||||
TraceCommandResult
|
||||
> = true;
|
||||
|
||||
assert.deepEqual(
|
||||
[waitType, prepareType, pushType, triggerType, clientWaitType],
|
||||
[true, true, true, true, true],
|
||||
[
|
||||
waitType,
|
||||
prepareType,
|
||||
pushType,
|
||||
triggerType,
|
||||
clientWaitType,
|
||||
doctorType,
|
||||
diffType,
|
||||
replayType,
|
||||
replayTestType,
|
||||
recordType,
|
||||
traceType,
|
||||
],
|
||||
[true, true, true, true, true, true, true, true, true, true, true],
|
||||
);
|
||||
assert.deepEqual(waitResult, { waitedMs: 25, text: 'Ready' });
|
||||
assert.equal(prepareResult.timing.additiveParts.connectAfterBuildMs, 10);
|
||||
|
||||
@@ -6,7 +6,7 @@ import path from 'node:path';
|
||||
import { connectCommand } from '../cli/commands/connection.ts';
|
||||
import { resolveCloudAccessForConnect } from '../cli/auth-session.ts';
|
||||
import { readActiveConnectionState } from '../remote/remote-connection-state.ts';
|
||||
import type { AgentDeviceClient } from '../client/client.ts';
|
||||
import type { AgentDeviceClient } from '../agent-device-client.ts';
|
||||
|
||||
afterEach(() => {
|
||||
vi.unstubAllEnvs();
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
readActiveConnectionState,
|
||||
type RemoteConnectionState,
|
||||
} from '../remote/remote-connection-state.ts';
|
||||
import type { AgentDeviceClient } from '../client/client.ts';
|
||||
import type { AgentDeviceClient } from '../agent-device-client.ts';
|
||||
|
||||
vi.mock('../cli/auth-session.ts', () => ({
|
||||
resolveCloudAccessForConnect: vi.fn(),
|
||||
|
||||
@@ -3,7 +3,7 @@ import { EventEmitter } from 'node:events';
|
||||
import type { Socket } from 'node:net';
|
||||
import { test } from 'vitest';
|
||||
import type { DaemonRequest, DaemonResponse } from '../daemon/types.ts';
|
||||
import type { RequestProgressEvent } from '../daemon/request-progress.ts';
|
||||
import type { RequestProgressEvent } from '../request/progress.ts';
|
||||
import { readDaemonSocketProgressResponse } from '../daemon/client/daemon-client-progress.ts';
|
||||
import { AppError } from '../kernel/errors.ts';
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ import {
|
||||
readRemoteConnectionState,
|
||||
writeRemoteConnectionState,
|
||||
} from '../remote/remote-connection-state.ts';
|
||||
import type { AgentDeviceClient } from '../client/client.ts';
|
||||
import type { AgentDeviceClient } from '../agent-device-client.ts';
|
||||
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
import { sendToDaemon } from '../daemon/client/daemon-client.ts';
|
||||
import { prepareMetroRuntime, reloadMetro } from '../metro/client-metro.ts';
|
||||
import { sendToDaemon } from './daemon/client/daemon-client.ts';
|
||||
import { prepareMetroRuntime, reloadMetro } from './metro/client-metro.ts';
|
||||
import {
|
||||
clearMetroSessionHints,
|
||||
readMetroSessionHints,
|
||||
writeMetroSessionHints,
|
||||
type MetroSessionHints,
|
||||
} from '../metro/metro-session-hints.ts';
|
||||
import { resolveDaemonPaths } from '../daemon/config.ts';
|
||||
import { INTERNAL_COMMANDS } from '../command-catalog.ts';
|
||||
} from './metro/metro-session-hints.ts';
|
||||
import { resolveDaemonPaths } from './daemon/config.ts';
|
||||
import { INTERNAL_COMMANDS } from './command-catalog.ts';
|
||||
import {
|
||||
prepareDaemonCommandRequest,
|
||||
type DaemonCommandName,
|
||||
} from '../commands/command-projection.ts';
|
||||
import { systemCommandFamily } from '../commands/system/index.ts';
|
||||
import { buildRequestFlags } from '../commands/command-flags.ts';
|
||||
import { throwDaemonError } from '../daemon-error.ts';
|
||||
} from './commands/command-projection.ts';
|
||||
import { systemCommandFamily } from './commands/system/index.ts';
|
||||
import { buildRequestFlags } from './commands/command-flags.ts';
|
||||
import { throwDaemonError } from './daemon-error.ts';
|
||||
import {
|
||||
buildMeta,
|
||||
normalizeDeployResult,
|
||||
@@ -30,9 +30,9 @@ import {
|
||||
readRequiredString,
|
||||
readSnapshotNodes,
|
||||
resolveSessionName,
|
||||
} from './client-normalizers.ts';
|
||||
import { readScreenshotResultData } from '../utils/screenshot-result.ts';
|
||||
import { isRecord } from '../utils/parsing.ts';
|
||||
} from './client/client-normalizers.ts';
|
||||
import { readScreenshotResultData } from './utils/screenshot-result.ts';
|
||||
import { isRecord } from './utils/parsing.ts';
|
||||
import type {
|
||||
AgentDeviceCommandClient,
|
||||
AgentDeviceClient,
|
||||
@@ -53,17 +53,17 @@ import type {
|
||||
MaterializationReleaseOptions,
|
||||
MetroPrepareOptions,
|
||||
MetroPrepareResult,
|
||||
} from './client-types.ts';
|
||||
import type { CommandResult } from '../core/command-descriptor/command-result.ts';
|
||||
} from './client/client-types.ts';
|
||||
import type { CommandResult } from './core/command-descriptor/command-result.ts';
|
||||
import {
|
||||
isNonDefaultResponseLevel,
|
||||
type ResponseLevel,
|
||||
type SessionRuntimeHints,
|
||||
} from '../kernel/contracts.ts';
|
||||
import { readSerializedSnapshotCaptureAnnotations } from '../snapshot-capture-annotations.ts';
|
||||
import { readSnapshotDiagnosticsSummary } from '../snapshot-diagnostics.ts';
|
||||
import type { CommandFlags } from '../core/dispatch-context.ts';
|
||||
import type { AgentArtifactsResult } from '../cloud-artifacts.ts';
|
||||
} from './kernel/contracts.ts';
|
||||
import { readSerializedSnapshotCaptureAnnotations } from './snapshot-capture-annotations.ts';
|
||||
import { readSnapshotDiagnosticsSummary } from './snapshot-diagnostics.ts';
|
||||
import type { CommandFlags } from './core/dispatch-context.ts';
|
||||
import type { AgentArtifactsResult } from './cloud-artifacts.ts';
|
||||
|
||||
type ProjectedSystemCommandClient = Pick<
|
||||
AgentDeviceCommandClient,
|
||||
@@ -132,7 +132,8 @@ export function createAgentDeviceClient(
|
||||
alert: async (options = {}) => await executeCommand('alert', options),
|
||||
...projectedSystemCommands,
|
||||
reactNative: async (options) => await executeCommand('react-native', options),
|
||||
doctor: async (options = {}) => await executeCommand('doctor', options),
|
||||
doctor: async (options = {}) =>
|
||||
await executeCommand<CommandResult<'doctor'>>('doctor', options),
|
||||
prepare: async (options) =>
|
||||
await executeCommand<CommandResult<'prepare'>>('prepare', options),
|
||||
viewport: async (options) =>
|
||||
@@ -345,7 +346,7 @@ export function createAgentDeviceClient(
|
||||
identifiers: { session },
|
||||
};
|
||||
},
|
||||
diff: async (options) => await executeCommand('diff', options),
|
||||
diff: async (options) => await executeCommand<CommandResult<'diff'>>('diff', options),
|
||||
},
|
||||
interactions: {
|
||||
click: async (options) => await executeCommand('click', options),
|
||||
@@ -367,8 +368,8 @@ export function createAgentDeviceClient(
|
||||
find: async (options) => await executeCommand('find', options),
|
||||
},
|
||||
replay: {
|
||||
run: async (options) => await executeCommand('replay', options),
|
||||
test: async (options) => await executeCommand('test', options),
|
||||
run: async (options) => await executeCommand<CommandResult<'replay'>>('replay', options),
|
||||
test: async (options) => await executeCommand<CommandResult<'test'>>('test', options),
|
||||
},
|
||||
batch: {
|
||||
run: async (options) => await executeCommand('batch', options),
|
||||
@@ -383,13 +384,13 @@ export function createAgentDeviceClient(
|
||||
debug: {
|
||||
symbols: async (options) => {
|
||||
const { symbolicateCrashArtifact } =
|
||||
await import('../platforms/apple/core/debug-symbols.ts');
|
||||
await import('./platforms/apple/core/debug-symbols.ts');
|
||||
return symbolicateCrashArtifact({ cwd: options.cwd ?? config.cwd, ...options });
|
||||
},
|
||||
},
|
||||
recording: {
|
||||
record: async (options) => await executeCommand('record', options),
|
||||
trace: async (options) => await executeCommand('trace', options),
|
||||
record: async (options) => await executeCommand<CommandResult<'record'>>('record', options),
|
||||
trace: async (options) => await executeCommand<CommandResult<'trace'>>('trace', options),
|
||||
},
|
||||
settings: {
|
||||
update: async (options) => await executeCommand('settings', options),
|
||||
@@ -567,4 +568,4 @@ function normalizeLease(data: Record<string, unknown>): Lease {
|
||||
};
|
||||
}
|
||||
|
||||
export type * from './client-types.ts';
|
||||
export type * from './client/client-types.ts';
|
||||
+5
-5
@@ -4,13 +4,13 @@ import type { JsonObject } from './contracts/json.ts';
|
||||
import type { Point, SnapshotNode, SnapshotOptions, SnapshotState } from './kernel/snapshot.ts';
|
||||
import type { NetworkIncludeMode } from './kernel/contracts.ts';
|
||||
import type { DeviceTarget, Platform, PlatformSelector, PublicPlatform } from './kernel/device.ts';
|
||||
import type { BackMode } from './core/back-mode.ts';
|
||||
import type { BackMode } from './contracts/back-mode.ts';
|
||||
import type { RepeatedInput } from './commands/command-input.ts';
|
||||
import type { ClickButton } from './core/click-button.ts';
|
||||
import type { DeviceRotation } from './core/device-rotation.ts';
|
||||
import type { ScrollDirection } from './core/scroll-gesture.ts';
|
||||
import type { SessionSurface } from './core/session-surface.ts';
|
||||
import type { TvRemoteButton } from './core/tv-remote.ts';
|
||||
import type { DeviceRotation } from './contracts/device-rotation.ts';
|
||||
import type { ScrollDirection } from './contracts/scroll-gesture.ts';
|
||||
import type { SessionSurface } from './contracts/session-surface.ts';
|
||||
import type { TvRemoteButton } from './contracts/tv-remote.ts';
|
||||
import type { RecordingExportQuality } from './core/recording-export-quality.ts';
|
||||
import type { SnapshotDiagnosticsSummary } from './snapshot-diagnostics.ts';
|
||||
import type {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { CliFlags } from './cli/parser/cli-flags.ts';
|
||||
import type { CliFlags } from './commands/cli-grammar/flag-types.ts';
|
||||
|
||||
type BooleanCliFlagKey = {
|
||||
[Key in keyof CliFlags]-?: Exclude<CliFlags[Key], undefined> extends boolean ? Key : never;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import type { CommandName } from '../commands/command-metadata.ts';
|
||||
import { listCommandFamilyCliSchemas } from '../commands/family/registry.ts';
|
||||
import type { LocalCliCommandName } from '../command-catalog.ts';
|
||||
import type { CommandSchema, CommandSchemaOverride } from './cli-command-schema-types.ts';
|
||||
import type { CommandSchema, CommandSchemaOverride } from './types.ts';
|
||||
import {
|
||||
COMMON_COMMAND_SUPPORTED_FLAG_KEYS,
|
||||
METRO_PREPARE_FLAGS,
|
||||
} from '../cli/parser/cli-flags.ts';
|
||||
} from '../commands/cli-grammar/flag-groups.ts';
|
||||
|
||||
type SchemaOnlyCliCommandName = Exclude<LocalCliCommandName, CommandName>;
|
||||
|
||||
+5
-5
@@ -4,15 +4,15 @@ import fs from 'node:fs';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { parseSync } from 'oxc-parser';
|
||||
import type { BinaryExpression, Expression, PrivateIdentifier } from 'oxc-parser';
|
||||
import { listCapabilityCommands } from '../../core/capabilities.ts';
|
||||
import { listCapabilityCommands } from '../core/capabilities.ts';
|
||||
import {
|
||||
INTERNAL_COMMANDS,
|
||||
isKnownCliCommandName,
|
||||
listCliCommandNames,
|
||||
SPECIAL_CLI_COMMANDS,
|
||||
} from '../../command-catalog.ts';
|
||||
import { listCapabilityCheckedCommandNames } from '../../core/command-descriptor/registry.ts';
|
||||
import { getCliCommandSchema } from '../command-schema.ts';
|
||||
} from '../command-catalog.ts';
|
||||
import { listCapabilityCheckedCommandNames } from '../core/command-descriptor/registry.ts';
|
||||
import { getCliCommandSchema } from './command-schema.ts';
|
||||
|
||||
test('every public capability command has a parser schema entry', () => {
|
||||
const schemaCommands = new Set<string>(listCliCommandNames());
|
||||
@@ -75,7 +75,7 @@ const INTERNAL_GESTURE_CAPABILITY_COMMANDS = new Set([
|
||||
]);
|
||||
|
||||
function collectCliDispatchCommandLiterals(): Set<string> {
|
||||
const cliPath = fileURLToPath(new URL('../../cli.ts', import.meta.url));
|
||||
const cliPath = fileURLToPath(new URL('../cli.ts', import.meta.url));
|
||||
const sourceText = fs.readFileSync(cliPath, 'utf8');
|
||||
const parsed = parseSync(cliPath, sourceText);
|
||||
const commands = new Set<string>();
|
||||
@@ -1,17 +1,18 @@
|
||||
import type { CliCommandName } from '../command-catalog.ts';
|
||||
import { listCommandMetadata } from '../commands/command-metadata.ts';
|
||||
import type { CommandSchema, CommandSchemaOverride } from './cli-command-schema-types.ts';
|
||||
import { getCliCommandOverride, getSchemaOnlyCliCommandSchema } from './cli-command-overrides.ts';
|
||||
import type { CommandSchema, CommandSchemaOverride } from './types.ts';
|
||||
import { getCliCommandOverride, getSchemaOnlyCliCommandSchema } from './command-overrides.ts';
|
||||
import { getFlagDefinition, getFlagDefinitions } from '../commands/cli-grammar/flag-registry.ts';
|
||||
import {
|
||||
getFlagDefinition,
|
||||
getFlagDefinitions,
|
||||
COMMON_COMMAND_SUPPORTED_FLAG_KEYS,
|
||||
GLOBAL_FLAG_KEYS,
|
||||
} from '../commands/cli-grammar/flag-groups.ts';
|
||||
import {
|
||||
type CliFlags,
|
||||
type DaemonExcludedCliFlag,
|
||||
type FlagDefinition,
|
||||
type FlagKey,
|
||||
} from '../cli/parser/cli-flags.ts';
|
||||
} from '../commands/cli-grammar/flag-types.ts';
|
||||
|
||||
export type { CliFlags, DaemonExcludedCliFlag, FlagDefinition, FlagKey };
|
||||
export type { CommandSchema, CommandSchemaOverride };
|
||||
+3
-3
@@ -6,12 +6,12 @@ import {
|
||||
isFlagSupportedForCommand,
|
||||
parseOptionValueFromSource,
|
||||
resolveSourceValueDefinition,
|
||||
} from '../cli-option-schema.ts';
|
||||
import { AppError } from '../../kernel/errors.ts';
|
||||
} from './option-schema.ts';
|
||||
import { AppError } from '../kernel/errors.ts';
|
||||
import {
|
||||
REMOTE_CONFIG_FIELD_SPECS,
|
||||
getRemoteConfigEnvNames,
|
||||
} from '../../remote/remote-config-schema.ts';
|
||||
} from '../remote/remote-config-schema.ts';
|
||||
|
||||
test('option schema exposes config/env metadata for global options', () => {
|
||||
const spec = getOptionSpec('platform');
|
||||
@@ -1,4 +1,4 @@
|
||||
import { buildPrimaryEnvVarName, parseSourceValue } from './source-value.ts';
|
||||
import { buildPrimaryEnvVarName, parseSourceValue } from '../utils/source-value.ts';
|
||||
import { listCliCommandNames } from '../command-catalog.ts';
|
||||
import {
|
||||
getCliCommandSchema,
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { CliFlags, FlagKey } from '../cli/parser/cli-flags.ts';
|
||||
import type { CliFlags, FlagKey } from '../commands/cli-grammar/flag-types.ts';
|
||||
|
||||
export type CommandSchema = {
|
||||
helpDescription: string;
|
||||
+2
-2
@@ -12,7 +12,7 @@ import {
|
||||
createAgentDeviceClient,
|
||||
type AgentDeviceClientConfig,
|
||||
type AgentDeviceDaemonTransport,
|
||||
} from './client/client.ts';
|
||||
} from './agent-device-client.ts';
|
||||
import { materializeRemoteConnectionForCommand } from './cli/commands/connection-runtime.ts';
|
||||
import { tryRunClientBackedCommand } from './cli/commands/router.ts';
|
||||
import { runAgentCdpCommand } from './cli/commands/agent-cdp.ts';
|
||||
@@ -35,7 +35,7 @@ import {
|
||||
type RemoteConnectionRequestMetadata,
|
||||
} from './remote/remote-connection-state.ts';
|
||||
import { resolveRemoteAuthForCli } from './cli/auth-session.ts';
|
||||
import type { CliFlags, FlagKey } from './cli/parser/cli-flags.ts';
|
||||
import type { CliFlags, FlagKey } from './commands/cli-grammar/flag-types.ts';
|
||||
import type { SessionRuntimeHints } from './kernel/contracts.ts';
|
||||
import { isKnownCliCommandName } from './command-catalog.ts';
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { runCmd } from '../utils/exec.ts';
|
||||
import { AppError } from '../kernel/errors.ts';
|
||||
import type { CliFlags } from './parser/cli-flags.ts';
|
||||
import type { CliFlags } from '../commands/cli-grammar/flag-types.ts';
|
||||
import type { EnvMap } from '../utils/env-map.ts';
|
||||
import { readCloudJsonResponse } from './cloud-response.ts';
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { type SessionRuntimeHints } from '../kernel/contracts.ts';
|
||||
import { parseBatchStepRuntime } from '../batch-contract.ts';
|
||||
import { readInputFromCli } from '../commands/cli-grammar.ts';
|
||||
import { isCommandName, type CommandName } from '../commands/command-metadata.ts';
|
||||
import type { CliFlags } from './parser/cli-flags.ts';
|
||||
import type { CliFlags } from '../commands/cli-grammar/flag-types.ts';
|
||||
import { AppError } from '../kernel/errors.ts';
|
||||
import { isRecord } from '../utils/parsing.ts';
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { test } from 'vitest';
|
||||
import assert from 'node:assert/strict';
|
||||
import { createAgentDeviceClient } from '../../../client/client.ts';
|
||||
import { createAgentDeviceClient } from '../../../agent-device-client.ts';
|
||||
import type { DaemonResponse } from '../../../kernel/contracts.ts';
|
||||
import type { CliFlags } from '../../parser/cli-flags.ts';
|
||||
import type { CliFlags } from '../../../commands/cli-grammar/flag-types.ts';
|
||||
import type { ClientBackedCliCommandName } from '../client-backed.ts';
|
||||
import { runGenericClientBackedCommand } from '../generic.ts';
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { test } from 'vitest';
|
||||
import assert from 'node:assert/strict';
|
||||
import { createAgentDeviceClient } from '../../../client/client.ts';
|
||||
import { createAgentDeviceClient } from '../../../agent-device-client.ts';
|
||||
import type { DaemonResponse } from '../../../kernel/contracts.ts';
|
||||
import type { CliFlags } from '../../parser/cli-flags.ts';
|
||||
import type { CliFlags } from '../../../commands/cli-grammar/flag-types.ts';
|
||||
import { screenshotCommand } from '../screenshot.ts';
|
||||
|
||||
async function captureStdout(fn: () => Promise<unknown>): Promise<string> {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { runCmdStreaming } from '../../utils/exec.ts';
|
||||
import { AppError } from '../../kernel/errors.ts';
|
||||
import { isRemoteBridgeBackend } from './remote-bridge.ts';
|
||||
import type { SessionRuntimeHints } from '../../kernel/contracts.ts';
|
||||
import type { CliFlags } from '../parser/cli-flags.ts';
|
||||
import type { CliFlags } from '../../commands/cli-grammar/flag-types.ts';
|
||||
|
||||
const AGENT_CDP_VERSION = '1.6.1';
|
||||
export const AGENT_CDP_PACKAGE = `agent-cdp@${AGENT_CDP_VERSION}`;
|
||||
|
||||
@@ -24,8 +24,8 @@ import { profileToCliFlags } from '../../utils/remote-config.ts';
|
||||
import type { BatchStep } from '../../client/client-types.ts';
|
||||
import { AppError } from '../../kernel/errors.ts';
|
||||
import type { LeaseBackend, SessionRuntimeHints } from '../../kernel/contracts.ts';
|
||||
import type { CliFlags } from '../parser/cli-flags.ts';
|
||||
import type { AgentDeviceClient, Lease } from '../../client/client.ts';
|
||||
import type { CliFlags } from '../../commands/cli-grammar/flag-types.ts';
|
||||
import type { AgentDeviceClient, Lease } from '../../agent-device-client.ts';
|
||||
import type { CloudProviderSessionResult } from '../../cloud-artifacts.ts';
|
||||
import { INTERNAL_COMMANDS, PUBLIC_COMMANDS } from '../../command-catalog.ts';
|
||||
import { readMetroPrepareKind } from '../../commands/metro/prepare-kind.ts';
|
||||
|
||||
@@ -35,7 +35,7 @@ import {
|
||||
} from './connection-runtime.ts';
|
||||
import { writeCommandOutput } from './shared.ts';
|
||||
import type { LeaseBackend } from '../../kernel/contracts.ts';
|
||||
import type { CliFlags } from '../parser/cli-flags.ts';
|
||||
import type { CliFlags } from '../../commands/cli-grammar/flag-types.ts';
|
||||
import type { ClientCommandHandler } from './router-types.ts';
|
||||
|
||||
export const connectCommand: ClientCommandHandler = async ({ positionals, flags, client }) => {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { CommandRequestResult } from '../../client/client.ts';
|
||||
import type { CommandRequestResult } from '../../agent-device-client.ts';
|
||||
import { runCliCommandWithOutput } from '../../commands/cli-runner.ts';
|
||||
import type { CommandName } from '../../commands/command-metadata.ts';
|
||||
import type { CliOutput } from '../../commands/command-contract.ts';
|
||||
import type { ReplaySuiteResult } from '../../daemon/types.ts';
|
||||
import type { CliFlags } from '../parser/cli-flags.ts';
|
||||
import type { CliFlags } from '../../commands/cli-grammar/flag-types.ts';
|
||||
import { readCommandMessage } from '../../utils/success-text.ts';
|
||||
import { isNonDefaultResponseLevel } from '../../kernel/contracts.ts';
|
||||
import { writeCommandOutput } from './shared.ts';
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
} from '../../daemon/client/daemon-client-lifecycle.ts';
|
||||
import { AppError } from '../../kernel/errors.ts';
|
||||
import { colorize, supportsColor } from '../../utils/output.ts';
|
||||
import type { CliFlags } from '../parser/cli-flags.ts';
|
||||
import type { CliFlags } from '../../commands/cli-grammar/flag-types.ts';
|
||||
import { writeCommandOutput } from './shared.ts';
|
||||
import type { ClientCommandHandler } from './router-types.ts';
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
} from '../../client/client-react-devtools-companion.ts';
|
||||
import { AppError } from '../../kernel/errors.ts';
|
||||
import { isRemoteBridgeBackend } from './remote-bridge.ts';
|
||||
import type { CliFlags } from '../parser/cli-flags.ts';
|
||||
import type { CliFlags } from '../../commands/cli-grammar/flag-types.ts';
|
||||
|
||||
const AGENT_REACT_DEVTOOLS_VERSION = '0.4.0';
|
||||
export const AGENT_REACT_DEVTOOLS_PACKAGE = `agent-react-devtools@${AGENT_REACT_DEVTOOLS_VERSION}`;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { CliFlags } from '../parser/cli-flags.ts';
|
||||
import type { CliFlags } from '../../commands/cli-grammar/flag-types.ts';
|
||||
|
||||
export function isRemoteBridgeBackend(leaseBackend: CliFlags['leaseBackend']): boolean {
|
||||
return leaseBackend === 'android-instance' || leaseBackend === 'ios-instance';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { CliFlags } from '../parser/cli-flags.ts';
|
||||
import type { AgentDeviceClient } from '../../client/client.ts';
|
||||
import type { CliFlags } from '../../commands/cli-grammar/flag-types.ts';
|
||||
import type { AgentDeviceClient } from '../../agent-device-client.ts';
|
||||
import type { CliCommandName } from '../../command-catalog.ts';
|
||||
import type { ReplayTestReporterRuntime } from '../../replay/test/reporting.ts';
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { CliFlags } from '../parser/cli-flags.ts';
|
||||
import type { AgentDeviceClient } from '../../client/client.ts';
|
||||
import type { CliFlags } from '../../commands/cli-grammar/flag-types.ts';
|
||||
import type { AgentDeviceClient } from '../../agent-device-client.ts';
|
||||
import { isClientBackedCliCommandName, type ClientBackedCliCommandName } from './client-backed.ts';
|
||||
import { connectCommand, connectionCommand, disconnectCommand } from './connection.ts';
|
||||
import { authCommand } from './auth.ts';
|
||||
|
||||
@@ -3,10 +3,10 @@ import { AppError } from '../../kernel/errors.ts';
|
||||
import { isNonDefaultResponseLevel } from '../../kernel/contracts.ts';
|
||||
import { resolveUserPath } from '../../utils/path-resolution.ts';
|
||||
import type { AgentDeviceBackend } from '../../backend.ts';
|
||||
import type { AgentDeviceClient, CaptureScreenshotResult } from '../../client/client.ts';
|
||||
import type { AgentDeviceClient, CaptureScreenshotResult } from '../../agent-device-client.ts';
|
||||
import { runCliCommand } from '../../commands/cli-runner.ts';
|
||||
import { pickScreenshotResultData } from '../../utils/screenshot-result.ts';
|
||||
import type { CliFlags } from '../parser/cli-flags.ts';
|
||||
import type { CliFlags } from '../../commands/cli-grammar/flag-types.ts';
|
||||
import { writeCommandOutput } from './shared.ts';
|
||||
import type { ClientCommandHandler } from './router-types.ts';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { CliFlags } from '../parser/cli-flags.ts';
|
||||
import type { CliFlags } from '../../commands/cli-grammar/flag-types.ts';
|
||||
import { printJson } from '../../utils/output.ts';
|
||||
|
||||
export function writeCommandOutput(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { AgentBrowserToolStatus } from '../../platforms/web/agent-browser-tool.ts';
|
||||
import { AppError } from '../../kernel/errors.ts';
|
||||
import type { CliFlags } from '../parser/cli-flags.ts';
|
||||
import type { CliFlags } from '../../commands/cli-grammar/flag-types.ts';
|
||||
import { printJson } from '../../utils/output.ts';
|
||||
|
||||
type PublicAgentBrowserToolStatus = Omit<AgentBrowserToolStatus, 'socketDir'>;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import crypto from 'node:crypto';
|
||||
import type { RemoteConfigProfile } from '../../remote/remote-config-schema.ts';
|
||||
import { AppError } from '../../kernel/errors.ts';
|
||||
import type { CliFlags } from '../parser/cli-flags.ts';
|
||||
import type { CliFlags } from '../../commands/cli-grammar/flag-types.ts';
|
||||
import type { EnvMap } from '../../utils/env-map.ts';
|
||||
import { resolveCloudAccessForConnect } from '../auth-session.ts';
|
||||
import { readCloudJsonResponse } from '../cloud-response.ts';
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { CloudWebDriverKnownProviderName } from '../../cloud-webdriver/prov
|
||||
import type { RemoteConfigProfile } from '../../remote/remote-config-schema.ts';
|
||||
import { AppError } from '../../kernel/errors.ts';
|
||||
import type { PlatformSelector } from '../../kernel/device.ts';
|
||||
import type { CliFlags } from '../parser/cli-flags.ts';
|
||||
import type { CliFlags } from '../../commands/cli-grammar/flag-types.ts';
|
||||
import type { EnvMap } from '../../utils/env-map.ts';
|
||||
import { readMetroProfileFields } from './profile-fields.ts';
|
||||
import { persistAndResolveGeneratedProfile } from './generated-config.ts';
|
||||
|
||||
@@ -8,7 +8,7 @@ import type {
|
||||
} from '../../remote/remote-config-schema.ts';
|
||||
import { AppError, asAppError } from '../../kernel/errors.ts';
|
||||
import type { EnvMap } from '../../utils/env-map.ts';
|
||||
import type { CliFlags } from '../parser/cli-flags.ts';
|
||||
import type { CliFlags } from '../../commands/cli-grammar/flag-types.ts';
|
||||
import { profileToCliFlags } from '../../utils/remote-config.ts';
|
||||
|
||||
const GENERATED_REMOTE_CONFIG_SECRET_KEYS = new Set(['daemonAuthToken', 'metroBearerToken']);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { RemoteConfigMetroOptions } from '../../remote/remote-config-schema.ts';
|
||||
import type { CliFlags } from '../parser/cli-flags.ts';
|
||||
import type { CliFlags } from '../../commands/cli-grammar/flag-types.ts';
|
||||
|
||||
export function readMetroProfileFields(flags: CliFlags): RemoteConfigMetroOptions {
|
||||
return {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import crypto from 'node:crypto';
|
||||
import type { RemoteConfigProfile } from '../../remote/remote-config-schema.ts';
|
||||
import { AppError } from '../../kernel/errors.ts';
|
||||
import type { CliFlags } from '../parser/cli-flags.ts';
|
||||
import type { CliFlags } from '../../commands/cli-grammar/flag-types.ts';
|
||||
import type { EnvMap } from '../../utils/env-map.ts';
|
||||
import { readMetroProfileFields } from './profile-fields.ts';
|
||||
import { persistAndResolveGeneratedProfile } from './generated-config.ts';
|
||||
|
||||
@@ -528,7 +528,7 @@ test('parseArgs accepts metro prepare arguments', () => {
|
||||
'--kind',
|
||||
'repack',
|
||||
'--runtime-file',
|
||||
'./.agent-device/metro-runtime.json',
|
||||
'.agent-device/metro-runtime.json',
|
||||
'--no-reuse-existing',
|
||||
'--no-install-deps',
|
||||
],
|
||||
@@ -543,7 +543,7 @@ test('parseArgs accepts metro prepare arguments', () => {
|
||||
assert.equal(parsed.flags.metroBearerToken, 'secret');
|
||||
assert.equal(parsed.flags.metroPreparePort, 9090);
|
||||
assert.equal(parsed.flags.kind, 'repack');
|
||||
assert.equal(parsed.flags.metroRuntimeFile, './.agent-device/metro-runtime.json');
|
||||
assert.equal(parsed.flags.metroRuntimeFile, '.agent-device/metro-runtime.json');
|
||||
assert.equal(parsed.flags.metroNoReuseExisting, true);
|
||||
assert.equal(parsed.flags.metroNoInstallDeps, true);
|
||||
});
|
||||
|
||||
@@ -4,7 +4,7 @@ import { isKnownCliCommandName } from '../../../command-catalog.ts';
|
||||
import { keyboardCliReader } from '../../../commands/system/index.ts';
|
||||
import { AppError } from '../../../kernel/errors.ts';
|
||||
import { parseArgs } from '../args.ts';
|
||||
import type { CliFlags } from '../cli-flags.ts';
|
||||
import type { CliFlags } from '../../../commands/cli-grammar/flag-types.ts';
|
||||
import { listCommandAliasSuggestionEntries, suggestCommandFor } from '../command-suggestions.ts';
|
||||
|
||||
// Guards against the curated alias map drifting to a command that no longer
|
||||
|
||||
@@ -8,8 +8,8 @@ import {
|
||||
type CliFlags,
|
||||
type FlagDefinition,
|
||||
type FlagKey,
|
||||
} from '../../utils/command-schema.ts';
|
||||
import { isFlagSupportedForCommand } from '../../utils/cli-option-schema.ts';
|
||||
} from '../../cli-schema/command-schema.ts';
|
||||
import { isFlagSupportedForCommand } from '../../cli-schema/option-schema.ts';
|
||||
import { isKnownCliCommandName } from '../../command-catalog.ts';
|
||||
import { cliCommandAlias, normalizeCliCommandAlias } from '../../cli-command-aliases.ts';
|
||||
import { formatUnknownFlagMessage, suggestCommandFor } from './command-suggestions.ts';
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,8 +7,8 @@ import {
|
||||
type CommandSchema,
|
||||
type FlagDefinition,
|
||||
type FlagKey,
|
||||
} from '../../utils/command-schema.ts';
|
||||
import { buildCommandUsage } from '../../utils/cli-usage.ts';
|
||||
} from '../../cli-schema/command-schema.ts';
|
||||
import { buildCommandUsage } from '../../cli-schema/usage.ts';
|
||||
|
||||
const AGENT_WORKFLOWS = [
|
||||
{
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
import type { CommandFlags } from '../core/dispatch.ts';
|
||||
import { screenshotFlagsFromOptions } from '../contracts/screenshot.ts';
|
||||
import type { DaemonRequest, SessionRuntimeHints } from '../daemon/types.ts';
|
||||
import { AppError, type NormalizedError } from '../kernel/errors.ts';
|
||||
import type { SnapshotNode } from '../kernel/snapshot.ts';
|
||||
import { buildAppIdentifiers, buildDeviceIdentifiers } from './client-shared.ts';
|
||||
import { buildAppIdentifiers, buildDeviceIdentifiers } from '../contracts/result-serialization.ts';
|
||||
import { isAppleOs, isApplePlatform, isPublicPlatform, type AppleOS } from '../kernel/device.ts';
|
||||
import {
|
||||
leaseScopeFromOptions,
|
||||
leaseScopeToCommandFlags,
|
||||
leaseScopeToRequestMeta,
|
||||
} from '../core/lease-scope.ts';
|
||||
import { leaseScopeFromOptions, leaseScopeToRequestMeta } from '../core/lease-scope.ts';
|
||||
import type {
|
||||
AgentDeviceDevice,
|
||||
AgentDeviceSession,
|
||||
@@ -275,104 +269,6 @@ export function readSnapshotNodes(value: unknown): SnapshotNode[] {
|
||||
return Array.isArray(value) ? (value as SnapshotNode[]) : [];
|
||||
}
|
||||
|
||||
export function buildFlags(options: InternalRequestOptions): CommandFlags {
|
||||
const leaseScope = leaseScopeFromOptions(options);
|
||||
return stripUndefined({
|
||||
stateDir: options.stateDir,
|
||||
daemonBaseUrl: options.daemonBaseUrl,
|
||||
daemonAuthToken: options.daemonAuthToken,
|
||||
daemonTransport: options.daemonTransport,
|
||||
daemonServerMode: options.daemonServerMode,
|
||||
...leaseScopeToCommandFlags(leaseScope),
|
||||
provider: options.provider,
|
||||
providerSessionId: options.providerSessionId,
|
||||
providerApp: options.providerApp,
|
||||
providerOsVersion: options.providerOsVersion,
|
||||
providerProject: options.providerProject,
|
||||
providerBuild: options.providerBuild,
|
||||
providerSessionName: options.providerSessionName,
|
||||
awsProjectArn: options.awsProjectArn,
|
||||
awsDeviceArn: options.awsDeviceArn,
|
||||
awsAppArn: options.awsAppArn,
|
||||
awsRegion: options.awsRegion,
|
||||
awsInteractionMode: options.awsInteractionMode,
|
||||
sessionIsolation: options.sessionIsolation,
|
||||
platform: options.platform,
|
||||
target: options.target,
|
||||
device: options.device,
|
||||
udid: options.udid,
|
||||
serial: options.serial,
|
||||
iosSimulatorDeviceSet: options.iosSimulatorDeviceSet,
|
||||
iosXctestrunFile: options.iosXctestrunFile,
|
||||
iosXctestDerivedDataPath: options.iosXctestDerivedDataPath,
|
||||
iosXctestEnvDir: options.iosXctestEnvDir,
|
||||
androidDeviceAllowlist: options.androidDeviceAllowlist,
|
||||
surface: options.surface,
|
||||
activity: options.activity,
|
||||
launchConsole: options.launchConsole,
|
||||
launchArgs: options.launchArgs,
|
||||
relaunch: options.relaunch,
|
||||
shutdown: options.shutdown,
|
||||
saveScript: options.saveScript,
|
||||
deviceHub: options.deviceHub,
|
||||
testIme: options.testIme,
|
||||
noRecord: options.noRecord,
|
||||
backMode: options.backMode,
|
||||
metroHost: options.metroHost,
|
||||
metroPort: options.metroPort,
|
||||
bundleUrl: options.bundleUrl,
|
||||
launchUrl: options.launchUrl,
|
||||
snapshotInteractiveOnly: options.interactiveOnly,
|
||||
snapshotDepth: options.depth,
|
||||
snapshotScope: options.scope,
|
||||
snapshotRaw: options.raw,
|
||||
snapshotForceFull: options.forceFull,
|
||||
...screenshotFlagsFromOptions(options),
|
||||
appsFilter: options.appsFilter,
|
||||
kind: options.kind,
|
||||
out: options.out,
|
||||
count: options.count,
|
||||
fps: options.fps,
|
||||
screenshotMaxSize: options.maxSize,
|
||||
quality: options.quality,
|
||||
hideTouches: options.hideTouches,
|
||||
recordingScope: options.recordingScope,
|
||||
intervalMs: options.intervalMs,
|
||||
delayMs: options.delayMs,
|
||||
durationMs: options.durationMs,
|
||||
holdMs: options.holdMs,
|
||||
jitterPx: options.jitterPx,
|
||||
pixels: options.pixels,
|
||||
doubleTap: options.doubleTap,
|
||||
verify: options.verify,
|
||||
settle: options.settle,
|
||||
settleQuietMs: options.settleQuietMs,
|
||||
clickButton: options.clickButton,
|
||||
pauseMs: options.pauseMs,
|
||||
pattern: options.pattern,
|
||||
headless: options.headless,
|
||||
restart: options.restart,
|
||||
replayUpdate: options.replayUpdate,
|
||||
replayBackend: options.replayBackend,
|
||||
replayEnv: options.replayEnv,
|
||||
replayShellEnv: options.replayShellEnv,
|
||||
failFast: options.failFast,
|
||||
timeoutMs: options.timeoutMs,
|
||||
retries: options.retries,
|
||||
recordVideo: options.recordVideo,
|
||||
artifactsDir: options.artifactsDir,
|
||||
shardAll: options.shardAll,
|
||||
shardSplit: options.shardSplit,
|
||||
findFirst: options.findFirst,
|
||||
findLast: options.findLast,
|
||||
networkInclude: options.networkInclude,
|
||||
batchOnError: options.batchOnError,
|
||||
batchMaxSteps: options.batchMaxSteps,
|
||||
batchSteps: options.batchSteps,
|
||||
verbose: options.debug,
|
||||
}) as CommandFlags;
|
||||
}
|
||||
|
||||
export function buildMeta(options: InternalRequestOptions): DaemonRequest['meta'] {
|
||||
const leaseScope = leaseScopeFromOptions(options);
|
||||
return stripUndefined({
|
||||
|
||||
+27
-14
@@ -19,22 +19,22 @@ import type {
|
||||
PublicPlatform,
|
||||
PlatformSelector,
|
||||
} from '../kernel/device.ts';
|
||||
import type { BackMode } from '../core/back-mode.ts';
|
||||
import type { BackMode } from '../contracts/back-mode.ts';
|
||||
import type { ClickButton } from '../core/click-button.ts';
|
||||
import type { RecordingExportQuality } from '../core/recording-export-quality.ts';
|
||||
import type { RecordingScope } from '../core/recording-scope.ts';
|
||||
import type { DeviceRotation } from '../core/device-rotation.ts';
|
||||
import type { TvRemoteButton } from '../core/tv-remote.ts';
|
||||
import type { RecordingScope } from '../contracts/recording-scope.ts';
|
||||
import type { DeviceRotation } from '../contracts/device-rotation.ts';
|
||||
import type { TvRemoteButton } from '../contracts/tv-remote.ts';
|
||||
import type {
|
||||
ScrollDirection,
|
||||
SwipePattern,
|
||||
SwipePreset,
|
||||
TransformGestureParams,
|
||||
} from '../core/scroll-gesture.ts';
|
||||
} from '../contracts/scroll-gesture.ts';
|
||||
import type { ScrollInputDirection } from '../commands/interaction/runtime/gestures.ts';
|
||||
import type { LogAction } from '../contracts/logs.ts';
|
||||
import type { SessionSurface } from '../core/session-surface.ts';
|
||||
import type { FindLocator } from '../utils/finders.ts';
|
||||
import type { SessionSurface } from '../contracts/session-surface.ts';
|
||||
import type { FindLocator } from '../selectors/find.ts';
|
||||
import type { SnapshotNode, SnapshotUnchanged, SnapshotVisibility } from '../kernel/snapshot.ts';
|
||||
import type { ScreenshotResultData } from '../utils/screenshot-result.ts';
|
||||
import type {
|
||||
@@ -60,7 +60,7 @@ import type {
|
||||
import type { CommandResult } from '../core/command-descriptor/command-result.ts';
|
||||
import type { AgentArtifactsResult, CloudProviderSessionResult } from '../cloud-artifacts.ts';
|
||||
|
||||
export type { FindLocator } from '../utils/finders.ts';
|
||||
export type { FindLocator } from '../selectors/find.ts';
|
||||
export type { CompanionTunnelScope, MetroBridgeScope } from './client-companion-tunnel-contract.ts';
|
||||
export type { AppsFilter } from '../contracts/app-inventory.ts';
|
||||
export type { AlertAction, AlertInfo, AlertPlatform, AlertSource } from '../alert-contract.ts';
|
||||
@@ -82,6 +82,19 @@ export type { WaitCommandResult } from '../contracts/wait.ts';
|
||||
export type { PrepareCommandResult } from '../contracts/prepare.ts';
|
||||
export type { PushCommandResult } from '../contracts/push.ts';
|
||||
export type { TriggerAppEventCommandResult } from '../contracts/app-events.ts';
|
||||
export type { DoctorCommandResult } from '../contracts/doctor.ts';
|
||||
export type { DiffSnapshotCommandResult } from '../contracts/diff.ts';
|
||||
export type {
|
||||
RecordingCommandResult,
|
||||
RecordingStartCommandResult,
|
||||
RecordingStopCommandResult,
|
||||
TraceCommandResult,
|
||||
} from '../contracts/recording.ts';
|
||||
export type {
|
||||
ReplayCommandResult,
|
||||
ReplaySuiteResult,
|
||||
ReplaySuiteTestResult,
|
||||
} from '../contracts/replay.ts';
|
||||
export type { JsonObject, JsonPrimitive, JsonValue } from '../contracts/json.ts';
|
||||
|
||||
export type AgentDeviceDaemonTransport = (
|
||||
@@ -582,7 +595,7 @@ export type AgentDeviceCommandClient = {
|
||||
clipboard: (options: ClipboardCommandOptions) => Promise<CommandResult<'clipboard'>>;
|
||||
tvRemote: (options: TvRemoteCommandOptions) => Promise<CommandResult<'tv-remote'>>;
|
||||
reactNative: (options: ReactNativeCommandOptions) => Promise<CommandRequestResult>;
|
||||
doctor: (options?: DoctorCommandOptions) => Promise<CommandRequestResult>;
|
||||
doctor: (options?: DoctorCommandOptions) => Promise<CommandResult<'doctor'>>;
|
||||
/**
|
||||
* JSON prepare results include timing.additiveParts for additive wall-clock phases.
|
||||
* Top-level buildMs/connectMs/healthCheckMs are diagnostics and may overlap.
|
||||
@@ -1085,7 +1098,7 @@ export type AgentDeviceClient = {
|
||||
capture: {
|
||||
snapshot: (options?: CaptureSnapshotOptions) => Promise<CaptureSnapshotResult>;
|
||||
screenshot: (options?: CaptureScreenshotOptions) => Promise<CaptureScreenshotResult>;
|
||||
diff: (options: CaptureDiffOptions) => Promise<CommandRequestResult>;
|
||||
diff: (options: CaptureDiffOptions) => Promise<CommandResult<'diff'>>;
|
||||
};
|
||||
interactions: {
|
||||
click: (options: ClickOptions) => Promise<CommandRequestResult>;
|
||||
@@ -1107,8 +1120,8 @@ export type AgentDeviceClient = {
|
||||
find: (options: FindOptions) => Promise<CommandRequestResult>;
|
||||
};
|
||||
replay: {
|
||||
run: (options: ReplayRunOptions) => Promise<CommandRequestResult>;
|
||||
test: (options: ReplayTestOptions) => Promise<CommandRequestResult>;
|
||||
run: (options: ReplayRunOptions) => Promise<CommandResult<'replay'>>;
|
||||
test: (options: ReplayTestOptions) => Promise<CommandResult<'test'>>;
|
||||
};
|
||||
batch: {
|
||||
run: (options: BatchRunOptions) => Promise<BatchRunResult>;
|
||||
@@ -1124,8 +1137,8 @@ export type AgentDeviceClient = {
|
||||
symbols: (options: DebugSymbolsOptions) => Promise<DebugSymbolsResult>;
|
||||
};
|
||||
recording: {
|
||||
record: (options: RecordOptions) => Promise<CommandRequestResult>;
|
||||
trace: (options: TraceOptions) => Promise<CommandRequestResult>;
|
||||
record: (options: RecordOptions) => Promise<CommandResult<'record'>>;
|
||||
trace: (options: TraceOptions) => Promise<CommandResult<'trace'>>;
|
||||
};
|
||||
settings: {
|
||||
update: (options: SettingsUpdateOptions) => Promise<CommandRequestResult>;
|
||||
|
||||
@@ -4,13 +4,13 @@ import type {
|
||||
SnapshotOptions,
|
||||
SnapshotResult,
|
||||
} from '../core/interactor-types.ts';
|
||||
import type { BackMode } from '../core/back-mode.ts';
|
||||
import type { DeviceRotation } from '../core/device-rotation.ts';
|
||||
import type { ScrollDirection, TransformGestureParams } from '../core/scroll-gesture.ts';
|
||||
import type { TvRemoteButton } from '../core/tv-remote.ts';
|
||||
import type { BackMode } from '../contracts/back-mode.ts';
|
||||
import type { DeviceRotation } from '../contracts/device-rotation.ts';
|
||||
import type { ScrollDirection, TransformGestureParams } from '../contracts/scroll-gesture.ts';
|
||||
import type { TvRemoteButton } from '../contracts/tv-remote.ts';
|
||||
import type { SettingOptions } from '../platforms/permission-utils.ts';
|
||||
import { AppError } from '../kernel/errors.ts';
|
||||
import { buildScrollGesturePlan } from '../core/scroll-gesture.ts';
|
||||
import { buildScrollGesturePlan } from '../contracts/scroll-gesture.ts';
|
||||
import {
|
||||
capabilitySupported,
|
||||
unsupportedCapabilityMessage,
|
||||
|
||||
@@ -89,7 +89,7 @@ describe('explainCommand', () => {
|
||||
cli: { usage: 'web setup | web doctor' },
|
||||
files: expect.arrayContaining([
|
||||
'src/core/command-descriptor/registry.ts',
|
||||
'src/utils/cli-command-overrides.ts',
|
||||
'src/cli-schema/command-overrides.ts',
|
||||
'src/cli/commands/web.ts',
|
||||
]),
|
||||
},
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
listCommandResponseDataTransforms,
|
||||
listMcpExposedCommandNames,
|
||||
} from '../../core/command-descriptor/registry.ts';
|
||||
import { getSchemaOnlyCliCommandSchema } from '../../utils/cli-command-overrides.ts';
|
||||
import { getSchemaOnlyCliCommandSchema } from '../../cli-schema/command-overrides.ts';
|
||||
import {
|
||||
listCommandMetadata,
|
||||
listCommandMetadataNames,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { BatchRunOptions } from '../../client/client-types.ts';
|
||||
import type { CommandSchemaOverride } from '../../utils/cli-command-schema-types.ts';
|
||||
import type { CommandSchemaOverride } from '../../cli-schema/types.ts';
|
||||
import { commonInputFromFlags } from '../cli-grammar/common.ts';
|
||||
import type { CliReader } from '../cli-grammar/types.ts';
|
||||
import { defineCommandFacet, defineCommandFamilyFromFacets } from '../family/types.ts';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { PUBLIC_COMMANDS } from '../../command-catalog.ts';
|
||||
import { SNAPSHOT_FLAGS } from '../../cli/parser/cli-flags.ts';
|
||||
import { SNAPSHOT_FLAGS } from '../cli-grammar/flag-groups.ts';
|
||||
import { AppError } from '../../kernel/errors.ts';
|
||||
import {
|
||||
booleanField,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, test } from 'vitest';
|
||||
import type { CliFlags } from '../../cli/parser/cli-flags.ts';
|
||||
import type { CliFlags } from '../cli-grammar/flag-types.ts';
|
||||
import { alertCliReader, alertDaemonWriter } from './alert.ts';
|
||||
import { diffCliReader } from './diff.ts';
|
||||
import { snapshotCliOutput } from './output.ts';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { serializeSnapshotResult } from '../../client/client-shared.ts';
|
||||
import { serializeSnapshotResult } from '../../contracts/result-serialization.ts';
|
||||
import type { CaptureSnapshotResult } from '../../client/client-types.ts';
|
||||
import { dedupeInheritedSnapshotLabels } from '../../snapshot/snapshot-label-dedup.ts';
|
||||
import { formatSnapshotText } from '../../utils/output.ts';
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
compareScreenshots,
|
||||
type ScreenshotDiffResult,
|
||||
} from '../../../screenshot-diff/screenshot-diff.ts';
|
||||
import type { DiffScreenshotCommandResult } from '../../../contracts/diff.ts';
|
||||
import { attachCurrentOverlayMatches } from '../../../screenshot-diff/screenshot-diff-overlay-matches.ts';
|
||||
import type { RuntimeCommand } from '../../runtime-types.ts';
|
||||
import {
|
||||
@@ -37,9 +38,7 @@ export type DiffScreenshotCommandOptions = CommandContext & {
|
||||
surface?: BackendScreenshotOptions['surface'];
|
||||
};
|
||||
|
||||
export type DiffScreenshotCommandResult = ScreenshotDiffResult & {
|
||||
artifacts?: ArtifactDescriptor[];
|
||||
};
|
||||
export type { DiffScreenshotCommandResult } from '../../../contracts/diff.ts';
|
||||
|
||||
const DEFAULT_SCREENSHOT_DIFF_THRESHOLD = 0.1;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { BackendSnapshotResult } from '../../../backend.ts';
|
||||
import type { DiffSnapshotCommandResult } from '../../../contracts/diff.ts';
|
||||
import type { SnapshotDiagnosticsSummary } from '../../../snapshot-diagnostics.ts';
|
||||
import type { AgentDeviceRuntime, CommandSessionRecord } from '../../../runtime-contract.ts';
|
||||
import {
|
||||
@@ -13,7 +14,6 @@ import {
|
||||
buildSnapshotDiff,
|
||||
countSnapshotComparableLines,
|
||||
} from '../../../snapshot/snapshot-diff.ts';
|
||||
import type { SnapshotDiffLine, SnapshotDiffSummary } from '../../../snapshot/snapshot-diff.ts';
|
||||
import type {
|
||||
SnapshotNode,
|
||||
SnapshotState,
|
||||
@@ -45,13 +45,7 @@ export type SnapshotCommandResult = {
|
||||
snapshotDiagnostics?: SnapshotDiagnosticsSummary;
|
||||
} & PublicSnapshotCaptureAnnotations;
|
||||
|
||||
export type DiffSnapshotCommandResult = {
|
||||
mode: 'snapshot';
|
||||
baselineInitialized: boolean;
|
||||
summary: SnapshotDiffSummary;
|
||||
lines: SnapshotDiffLine[];
|
||||
warnings?: string[];
|
||||
};
|
||||
export type { DiffSnapshotCommandResult } from '../../../contracts/diff.ts';
|
||||
|
||||
type SnapshotCapture = {
|
||||
snapshot: SnapshotState;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { PUBLIC_COMMANDS } from '../../command-catalog.ts';
|
||||
import type { CaptureScreenshotOptions } from '../../client/client-types.ts';
|
||||
import { SESSION_SURFACES } from '../../core/session-surface.ts';
|
||||
import { SESSION_SURFACES } from '../../contracts/session-surface.ts';
|
||||
import {
|
||||
SCREENSHOT_COMMAND_FLAG_KEYS,
|
||||
screenshotFlagsFromOptions,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { PUBLIC_COMMANDS } from '../../command-catalog.ts';
|
||||
import type { SettingsUpdateOptions } from '../../client/client-types.ts';
|
||||
import { SETTINGS_USAGE_OVERRIDE } from '../../core/settings-contract.ts';
|
||||
import type { CommandSchemaOverride } from '../../utils/cli-command-schema-types.ts';
|
||||
import type { CliFlags } from '../../cli/parser/cli-flags.ts';
|
||||
import { SETTINGS_USAGE_OVERRIDE } from '../../contracts/settings-contract.ts';
|
||||
import type { CommandSchemaOverride } from '../../cli-schema/types.ts';
|
||||
import type { CliFlags } from '../cli-grammar/flag-types.ts';
|
||||
import { AppError } from '../../kernel/errors.ts';
|
||||
import { readLocationCoordinate } from '../../utils/location-coordinates.ts';
|
||||
import { defineExecutableCommand } from '../command-contract.ts';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { PUBLIC_COMMANDS } from '../../command-catalog.ts';
|
||||
import { SNAPSHOT_FLAGS } from '../../cli/parser/cli-flags.ts';
|
||||
import { SNAPSHOT_FLAGS } from '../cli-grammar/flag-groups.ts';
|
||||
import { booleanField, integerField, stringField } from '../command-input.ts';
|
||||
import { defineExecutableCommand } from '../command-contract.ts';
|
||||
import { commonInputFromFlags, direct } from '../cli-grammar/common.ts';
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { PUBLIC_COMMANDS } from '../../command-catalog.ts';
|
||||
import type { WaitCommandOptions } from '../../client/client-types.ts';
|
||||
import { parseWaitPositionals } from '../../core/wait-positionals.ts';
|
||||
import { SELECTOR_SNAPSHOT_FLAGS, type CliFlags } from '../../cli/parser/cli-flags.ts';
|
||||
import { SELECTOR_SNAPSHOT_FLAGS } from '../cli-grammar/flag-groups.ts';
|
||||
import { type CliFlags } from '../cli-grammar/flag-types.ts';
|
||||
import { AppError } from '../../kernel/errors.ts';
|
||||
import { tryParseSelectorChain } from '../../utils/selectors-parse.ts';
|
||||
import { tryParseSelectorChain } from '../../selectors/parse.ts';
|
||||
import {
|
||||
booleanField,
|
||||
enumField,
|
||||
|
||||
@@ -3,8 +3,8 @@ import type {
|
||||
InteractionTarget,
|
||||
InternalRequestOptions,
|
||||
} from '../../client/client-types.ts';
|
||||
import { splitSelectorFromArgs } from '../../utils/selectors-parse.ts';
|
||||
import type { CliFlags } from '../../cli/parser/cli-flags.ts';
|
||||
import { splitSelectorFromArgs } from '../../selectors/parse.ts';
|
||||
import type { CliFlags } from './flag-types.ts';
|
||||
import { AppError } from '../../kernel/errors.ts';
|
||||
import { compactRecord, type SelectorSnapshotInput } from '../command-input.ts';
|
||||
import type {
|
||||
|
||||
@@ -0,0 +1,288 @@
|
||||
import { RESPONSE_LEVELS } from '../../kernel/contracts.ts';
|
||||
import { RECORDING_SCOPE_VALUES } from '../../contracts/recording-scope.ts';
|
||||
import type { FlagDefinition } from './flag-types.ts';
|
||||
|
||||
export const ACTION_FLAG_DEFINITIONS: readonly FlagDefinition[] = [
|
||||
{
|
||||
key: 'count',
|
||||
names: ['--count'],
|
||||
type: 'int',
|
||||
min: 1,
|
||||
max: 200,
|
||||
usageLabel: '--count <n>',
|
||||
usageDescription: 'Repeat count for press/swipe series',
|
||||
},
|
||||
{
|
||||
key: 'fps',
|
||||
names: ['--fps'],
|
||||
type: 'int',
|
||||
min: 1,
|
||||
max: 120,
|
||||
usageLabel: '--fps <n>',
|
||||
usageDescription: 'Record: target frames per second (iOS physical device runner)',
|
||||
},
|
||||
{
|
||||
key: 'quality',
|
||||
names: ['--quality'],
|
||||
type: 'string',
|
||||
usageLabel: '--quality <medium|high>',
|
||||
usageDescription:
|
||||
'Record: output quality preset; Android maps this to screenrecord bitrate, Apple targets use it for export/encoding. Legacy numeric values 5-7 map to medium; 8-10 map to high',
|
||||
},
|
||||
{
|
||||
key: 'hideTouches',
|
||||
names: ['--hide-touches'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--hide-touches',
|
||||
usageDescription: 'Record: skip touch-overlay post-processing for faster raw benchmark videos',
|
||||
},
|
||||
{
|
||||
key: 'recordingScope',
|
||||
names: ['--scope'],
|
||||
type: 'enum',
|
||||
enumValues: RECORDING_SCOPE_VALUES,
|
||||
usageLabel: '--scope <app|device|system>',
|
||||
usageDescription:
|
||||
'Record: app requires an active app session; device/system records the whole screen',
|
||||
},
|
||||
{
|
||||
key: 'intervalMs',
|
||||
names: ['--interval-ms'],
|
||||
type: 'int',
|
||||
min: 0,
|
||||
max: 10_000,
|
||||
usageLabel: '--interval-ms <ms>',
|
||||
usageDescription: 'Delay between press iterations',
|
||||
},
|
||||
{
|
||||
key: 'delayMs',
|
||||
names: ['--delay-ms'],
|
||||
type: 'int',
|
||||
min: 0,
|
||||
max: 10_000,
|
||||
usageLabel: '--delay-ms <ms>',
|
||||
usageDescription: 'Delay between typed characters',
|
||||
},
|
||||
{
|
||||
key: 'durationMs',
|
||||
names: ['--duration-ms'],
|
||||
type: 'int',
|
||||
min: 0,
|
||||
max: 10_000,
|
||||
usageLabel: '--duration-ms <ms>',
|
||||
usageDescription: 'Scroll: pace the gesture over this duration when supported',
|
||||
},
|
||||
{
|
||||
key: 'holdMs',
|
||||
names: ['--hold-ms'],
|
||||
type: 'int',
|
||||
min: 0,
|
||||
max: 10_000,
|
||||
usageLabel: '--hold-ms <ms>',
|
||||
usageDescription: 'Press hold duration for each iteration',
|
||||
},
|
||||
{
|
||||
key: 'jitterPx',
|
||||
names: ['--jitter-px'],
|
||||
type: 'int',
|
||||
min: 0,
|
||||
max: 100,
|
||||
usageLabel: '--jitter-px <n>',
|
||||
usageDescription: 'Deterministic coordinate jitter radius for press',
|
||||
},
|
||||
{
|
||||
key: 'pixels',
|
||||
names: ['--pixels'],
|
||||
type: 'int',
|
||||
min: 1,
|
||||
max: 100_000,
|
||||
usageLabel: '--pixels <n>',
|
||||
usageDescription: 'Scroll: explicit gesture distance in pixels',
|
||||
},
|
||||
{
|
||||
key: 'doubleTap',
|
||||
names: ['--double-tap'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--double-tap',
|
||||
usageDescription: 'Use double-tap gesture per press iteration',
|
||||
},
|
||||
{
|
||||
key: 'verify',
|
||||
names: ['--verify'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--verify',
|
||||
usageDescription:
|
||||
'Capture cheap post-action evidence (AX digest, node counts, changedFromBefore) instead of a follow-up snapshot',
|
||||
},
|
||||
{
|
||||
key: 'settle',
|
||||
names: ['--settle'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--settle',
|
||||
usageDescription:
|
||||
'After the action, wait for the UI to go quiet and return the settled diff vs the pre-action tree in the same response (best-effort; never fails the action)',
|
||||
},
|
||||
{
|
||||
key: 'settleQuietMs',
|
||||
names: ['--settle-quiet'],
|
||||
type: 'int',
|
||||
min: 0,
|
||||
usageLabel: '--settle-quiet <ms>',
|
||||
usageDescription: 'Settle: quiet window the UI must hold to count as settled (default 500ms)',
|
||||
},
|
||||
{
|
||||
key: 'clickButton',
|
||||
names: ['--button'],
|
||||
type: 'enum',
|
||||
enumValues: ['primary', 'secondary', 'middle'],
|
||||
usageLabel: '--button primary|secondary|middle',
|
||||
usageDescription: 'Click: choose mouse button (middle reserved for future macOS support)',
|
||||
},
|
||||
// These aliases encode the value directly in the flag name so `back` reads naturally as
|
||||
// `back --in-app` or `back --system` without introducing a separate `--back-mode` flag.
|
||||
{
|
||||
key: 'backMode',
|
||||
names: ['--in-app'],
|
||||
type: 'enum',
|
||||
enumValues: ['in-app', 'system'],
|
||||
setValue: 'in-app',
|
||||
usageLabel: '--in-app',
|
||||
usageDescription: 'Back: use app-provided back UI when available',
|
||||
},
|
||||
{
|
||||
key: 'backMode',
|
||||
names: ['--system'],
|
||||
type: 'enum',
|
||||
enumValues: ['in-app', 'system'],
|
||||
setValue: 'system',
|
||||
usageLabel: '--system',
|
||||
usageDescription: 'Back: use system back input or gesture when available',
|
||||
},
|
||||
{
|
||||
key: 'pauseMs',
|
||||
names: ['--pause-ms'],
|
||||
type: 'int',
|
||||
min: 0,
|
||||
max: 10_000,
|
||||
usageLabel: '--pause-ms <ms>',
|
||||
usageDescription: 'Delay between swipe iterations',
|
||||
},
|
||||
{
|
||||
key: 'pattern',
|
||||
names: ['--pattern'],
|
||||
type: 'enum',
|
||||
enumValues: ['one-way', 'ping-pong'],
|
||||
usageLabel: '--pattern one-way|ping-pong',
|
||||
usageDescription: 'Swipe repeat pattern',
|
||||
},
|
||||
{
|
||||
key: 'verbose',
|
||||
names: ['--debug', '--verbose', '-v'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--debug, --verbose, -v',
|
||||
usageDescription:
|
||||
'Enable debug diagnostics; test --verbose prints per-test step timings without debug logs',
|
||||
},
|
||||
{
|
||||
key: 'cost',
|
||||
names: ['--cost'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--cost',
|
||||
usageDescription: 'Include per-command wall-clock latency (cost.wallClockMs) in the response',
|
||||
},
|
||||
{
|
||||
key: 'responseLevel',
|
||||
names: ['--level'],
|
||||
type: 'enum',
|
||||
enumValues: RESPONSE_LEVELS,
|
||||
usageLabel: '--level digest|default|full',
|
||||
usageDescription:
|
||||
'Response detail level: digest (token-cheap), default (today), or full. Default keeps the wire shape unchanged.',
|
||||
},
|
||||
{
|
||||
key: 'json',
|
||||
names: ['--json'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--json',
|
||||
usageDescription: 'JSON output',
|
||||
},
|
||||
{
|
||||
key: 'help',
|
||||
names: ['--help', '-h'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--help, -h',
|
||||
usageDescription: 'Print help and exit',
|
||||
},
|
||||
{
|
||||
key: 'version',
|
||||
names: ['--version', '-V'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--version, -V',
|
||||
usageDescription: 'Print version and exit',
|
||||
},
|
||||
{
|
||||
key: 'snapshotDiff',
|
||||
names: ['--diff'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--diff',
|
||||
usageDescription: 'Snapshot: show structural diff against the previous session baseline',
|
||||
},
|
||||
{
|
||||
key: 'saveScript',
|
||||
names: ['--save-script'],
|
||||
type: 'booleanOrString',
|
||||
usageLabel: '--save-script [path]',
|
||||
usageDescription: 'Save session script (.ad) on close; optional custom output path',
|
||||
},
|
||||
{
|
||||
key: 'networkInclude',
|
||||
names: ['--include'],
|
||||
type: 'enum',
|
||||
enumValues: ['summary', 'headers', 'body', 'all'],
|
||||
usageLabel: '--include summary|headers|body|all',
|
||||
usageDescription: 'Network: include headers, bodies, or both in output',
|
||||
},
|
||||
{
|
||||
key: 'shutdown',
|
||||
names: ['--shutdown'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--shutdown',
|
||||
usageDescription: 'close: shutdown associated simulator/emulator after ending session',
|
||||
},
|
||||
{
|
||||
key: 'relaunch',
|
||||
names: ['--relaunch'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--relaunch',
|
||||
usageDescription: 'open: terminate app process before launching it',
|
||||
},
|
||||
{
|
||||
key: 'restart',
|
||||
names: ['--restart'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--restart',
|
||||
usageDescription: 'logs clear: stop active stream, clear logs, then start streaming again',
|
||||
},
|
||||
{
|
||||
key: 'retainPaths',
|
||||
names: ['--retain-paths'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--retain-paths',
|
||||
usageDescription: 'install-from-source: keep materialized artifact paths after install',
|
||||
},
|
||||
{
|
||||
key: 'retentionMs',
|
||||
names: ['--retention-ms'],
|
||||
type: 'int',
|
||||
min: 1,
|
||||
usageLabel: '--retention-ms <ms>',
|
||||
usageDescription: 'install-from-source: retention TTL for materialized artifact paths',
|
||||
},
|
||||
{
|
||||
key: 'noRecord',
|
||||
names: ['--no-record'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--no-record',
|
||||
usageDescription: 'Do not record this action',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,234 @@
|
||||
import type { FlagDefinition } from './flag-types.ts';
|
||||
|
||||
export const CONNECTION_FLAG_DEFINITIONS: readonly FlagDefinition[] = [
|
||||
{
|
||||
key: 'config',
|
||||
names: ['--config'],
|
||||
type: 'string',
|
||||
usageLabel: '--config <path>',
|
||||
usageDescription: 'Load CLI defaults from a specific config file',
|
||||
},
|
||||
{
|
||||
key: 'remoteConfig',
|
||||
names: ['--remote-config'],
|
||||
type: 'string',
|
||||
usageLabel: '--remote-config <path>',
|
||||
usageDescription: 'Load remote host + Metro workflow settings from a specific profile file',
|
||||
},
|
||||
{
|
||||
key: 'stateDir',
|
||||
names: ['--state-dir'],
|
||||
type: 'string',
|
||||
usageLabel: '--state-dir <path>',
|
||||
usageDescription:
|
||||
'Daemon state directory (defaults to ~/.agent-device for packages, or a worktree-scoped dev dir from source)',
|
||||
},
|
||||
{
|
||||
key: 'daemonBaseUrl',
|
||||
names: ['--daemon-base-url'],
|
||||
type: 'string',
|
||||
usageLabel: '--daemon-base-url <url>',
|
||||
usageDescription: 'Explicit remote HTTP daemon base URL (skip local daemon discovery/startup)',
|
||||
},
|
||||
{
|
||||
key: 'daemonAuthToken',
|
||||
names: ['--daemon-auth-token'],
|
||||
type: 'string',
|
||||
usageLabel: '--daemon-auth-token <token>',
|
||||
usageDescription:
|
||||
'Remote HTTP daemon or proxy auth token (sent as request token and bearer header)',
|
||||
},
|
||||
{
|
||||
key: 'daemonTransport',
|
||||
names: ['--daemon-transport'],
|
||||
type: 'enum',
|
||||
enumValues: ['auto', 'socket', 'http'],
|
||||
usageLabel: '--daemon-transport auto|socket|http',
|
||||
usageDescription: 'Daemon client transport preference',
|
||||
},
|
||||
{
|
||||
key: 'daemonServerMode',
|
||||
names: ['--daemon-server-mode'],
|
||||
type: 'enum',
|
||||
enumValues: ['socket', 'http', 'dual'],
|
||||
usageLabel: '--daemon-server-mode socket|http|dual',
|
||||
usageDescription: 'Daemon server mode used when spawning daemon',
|
||||
},
|
||||
{
|
||||
key: 'proxyHost',
|
||||
names: ['--host'],
|
||||
type: 'string',
|
||||
usageLabel: '--host <host>',
|
||||
usageDescription: 'Proxy: host interface to bind (default: 127.0.0.1)',
|
||||
},
|
||||
{
|
||||
key: 'proxyPort',
|
||||
names: ['--port'],
|
||||
type: 'int',
|
||||
min: 1,
|
||||
max: 65535,
|
||||
usageLabel: '--port <port>',
|
||||
usageDescription: 'Proxy: TCP port to bind (default: 0, choose a free port)',
|
||||
},
|
||||
{
|
||||
key: 'tenant',
|
||||
names: ['--tenant'],
|
||||
type: 'string',
|
||||
usageLabel: '--tenant <id>',
|
||||
usageDescription: 'Tenant scope identifier for isolated daemon sessions',
|
||||
},
|
||||
{
|
||||
key: 'sessionIsolation',
|
||||
names: ['--session-isolation'],
|
||||
type: 'enum',
|
||||
enumValues: ['none', 'tenant'],
|
||||
usageLabel: '--session-isolation none|tenant',
|
||||
usageDescription: 'Session isolation strategy (tenant prefixes session namespace)',
|
||||
},
|
||||
{
|
||||
key: 'runId',
|
||||
names: ['--run-id'],
|
||||
type: 'string',
|
||||
usageLabel: '--run-id <id>',
|
||||
usageDescription: 'Run identifier used for tenant lease admission checks',
|
||||
},
|
||||
{
|
||||
key: 'leaseId',
|
||||
names: ['--lease-id'],
|
||||
type: 'string',
|
||||
usageLabel: '--lease-id <id>',
|
||||
usageDescription: 'Lease identifier bound to tenant/run admission scope',
|
||||
},
|
||||
{
|
||||
key: 'leaseBackend',
|
||||
names: ['--lease-backend'],
|
||||
type: 'enum',
|
||||
enumValues: ['ios-simulator', 'ios-instance', 'android-instance'],
|
||||
usageLabel: '--lease-backend ios-simulator|ios-instance|android-instance',
|
||||
usageDescription: 'Lease backend for remote tenant connection admission',
|
||||
},
|
||||
{
|
||||
key: 'provider',
|
||||
names: ['--provider'],
|
||||
type: 'string',
|
||||
usageLabel: '--provider <name>',
|
||||
usageDescription: 'Cloud provider name for provider-scoped commands',
|
||||
},
|
||||
{
|
||||
key: 'providerSessionId',
|
||||
names: ['--provider-session'],
|
||||
type: 'string',
|
||||
usageLabel: '--provider-session <id>',
|
||||
usageDescription: 'Cloud provider session id or ARN',
|
||||
},
|
||||
{
|
||||
key: 'providerApp',
|
||||
names: ['--provider-app'],
|
||||
type: 'string',
|
||||
usageLabel: '--provider-app <ref-or-path>',
|
||||
usageDescription:
|
||||
'Cloud provider app reference or local app path used when creating hosted WebDriver sessions',
|
||||
},
|
||||
{
|
||||
key: 'providerOsVersion',
|
||||
names: ['--provider-os-version', '--os-version'],
|
||||
type: 'string',
|
||||
usageLabel: '--provider-os-version <version>',
|
||||
usageDescription: 'Hosted cloud provider OS version, for example 17 or 14.0',
|
||||
},
|
||||
{
|
||||
key: 'providerProject',
|
||||
names: ['--provider-project'],
|
||||
type: 'string',
|
||||
usageLabel: '--provider-project <name>',
|
||||
usageDescription: 'Hosted cloud provider project label',
|
||||
},
|
||||
{
|
||||
key: 'providerBuild',
|
||||
names: ['--provider-build'],
|
||||
type: 'string',
|
||||
usageLabel: '--provider-build <name>',
|
||||
usageDescription: 'Hosted cloud provider build label',
|
||||
},
|
||||
{
|
||||
key: 'providerSessionName',
|
||||
names: ['--provider-session-name'],
|
||||
type: 'string',
|
||||
usageLabel: '--provider-session-name <name>',
|
||||
usageDescription: 'Hosted cloud provider session label',
|
||||
},
|
||||
{
|
||||
key: 'awsProjectArn',
|
||||
names: ['--aws-project-arn'],
|
||||
type: 'string',
|
||||
usageLabel: '--aws-project-arn <arn>',
|
||||
usageDescription: 'AWS Device Farm project ARN for hosted WebDriver sessions',
|
||||
},
|
||||
{
|
||||
key: 'awsDeviceArn',
|
||||
names: ['--aws-device-arn'],
|
||||
type: 'string',
|
||||
usageLabel: '--aws-device-arn <arn>',
|
||||
usageDescription: 'AWS Device Farm device ARN for hosted WebDriver sessions',
|
||||
},
|
||||
{
|
||||
key: 'awsAppArn',
|
||||
names: ['--aws-app-arn'],
|
||||
type: 'string',
|
||||
usageLabel: '--aws-app-arn <arn>',
|
||||
usageDescription: 'AWS Device Farm app ARN attached to hosted remote access sessions',
|
||||
},
|
||||
{
|
||||
key: 'awsRegion',
|
||||
names: ['--aws-region'],
|
||||
type: 'string',
|
||||
usageLabel: '--aws-region <region>',
|
||||
usageDescription: 'AWS region for Device Farm API calls',
|
||||
},
|
||||
{
|
||||
key: 'awsInteractionMode',
|
||||
names: ['--aws-interaction-mode'],
|
||||
type: 'enum',
|
||||
enumValues: ['INTERACTIVE', 'NO_VIDEO', 'VIDEO_ONLY'],
|
||||
usageLabel: '--aws-interaction-mode INTERACTIVE|NO_VIDEO|VIDEO_ONLY',
|
||||
usageDescription: 'AWS Device Farm remote access interaction mode',
|
||||
},
|
||||
{
|
||||
key: 'force',
|
||||
names: ['--force'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--force',
|
||||
usageDescription: 'Force connection state replacement when reconnecting',
|
||||
},
|
||||
{
|
||||
key: 'noLogin',
|
||||
names: ['--no-login'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--no-login',
|
||||
usageDescription: 'Connect: fail instead of starting implicit cloud login',
|
||||
},
|
||||
{
|
||||
key: 'sessionLock',
|
||||
names: ['--session-lock'],
|
||||
type: 'enum',
|
||||
enumValues: ['reject', 'strip'],
|
||||
usageLabel: '--session-lock reject|strip',
|
||||
usageDescription:
|
||||
'Lock bound-session device routing for this CLI invocation and nested batch steps',
|
||||
},
|
||||
{
|
||||
key: 'sessionLocked',
|
||||
names: ['--session-locked'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--session-locked',
|
||||
usageDescription: 'Deprecated alias for --session-lock reject',
|
||||
},
|
||||
{
|
||||
key: 'sessionLockConflicts',
|
||||
names: ['--session-lock-conflicts'],
|
||||
type: 'enum',
|
||||
enumValues: ['reject', 'strip'],
|
||||
usageLabel: '--session-lock-conflicts reject|strip',
|
||||
usageDescription: 'Deprecated alias for --session-lock',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,327 @@
|
||||
import { SESSION_SURFACES } from '../../contracts/session-surface.ts';
|
||||
import { PLATFORM_SELECTORS } from '../../kernel/device.ts';
|
||||
import { PERF_KIND_VALUES } from '../../contracts/perf.ts';
|
||||
import type { FlagDefinition } from './flag-types.ts';
|
||||
|
||||
export const TARGET_FLAG_DEFINITIONS: readonly FlagDefinition[] = [
|
||||
{
|
||||
key: 'platform',
|
||||
names: ['--platform'],
|
||||
type: 'enum',
|
||||
enumValues: PLATFORM_SELECTORS,
|
||||
usageLabel: `--platform ${PLATFORM_SELECTORS.join('|')}`,
|
||||
usageDescription: 'Platform to target (`apple` aliases the Apple automation backend)',
|
||||
},
|
||||
{
|
||||
key: 'target',
|
||||
names: ['--target'],
|
||||
type: 'enum',
|
||||
enumValues: ['mobile', 'tv', 'desktop'],
|
||||
usageLabel: '--target mobile|tv|desktop',
|
||||
usageDescription: 'Device target class to match',
|
||||
},
|
||||
{
|
||||
key: 'device',
|
||||
names: ['--device'],
|
||||
type: 'string',
|
||||
usageLabel: '--device <name>',
|
||||
usageDescription: 'Device name to target',
|
||||
},
|
||||
{
|
||||
key: 'udid',
|
||||
names: ['--udid'],
|
||||
type: 'string',
|
||||
usageLabel: '--udid <udid>',
|
||||
usageDescription: 'iOS device UDID',
|
||||
},
|
||||
{
|
||||
key: 'serial',
|
||||
names: ['--serial'],
|
||||
type: 'string',
|
||||
usageLabel: '--serial <serial>',
|
||||
usageDescription: 'Android device serial',
|
||||
},
|
||||
{
|
||||
key: 'surface',
|
||||
names: ['--surface'],
|
||||
type: 'enum',
|
||||
enumValues: SESSION_SURFACES,
|
||||
usageLabel: '--surface app|frontmost-app|desktop|menubar',
|
||||
usageDescription: 'macOS session surface for open (defaults to app)',
|
||||
},
|
||||
{
|
||||
key: 'headless',
|
||||
names: ['--headless'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--headless',
|
||||
usageDescription: 'Boot: launch Android emulator without a GUI window',
|
||||
},
|
||||
{
|
||||
key: 'targetApp',
|
||||
names: ['--app', '--target-app'],
|
||||
type: 'string',
|
||||
usageLabel: '--app <id-or-name>',
|
||||
usageDescription: 'Doctor: verify an installed target app without opening a session',
|
||||
},
|
||||
{
|
||||
key: 'metroHost',
|
||||
names: ['--metro-host'],
|
||||
type: 'string',
|
||||
usageLabel: '--metro-host <host>',
|
||||
usageDescription: 'Session-scoped Metro/debug host hint',
|
||||
},
|
||||
{
|
||||
key: 'metroPort',
|
||||
names: ['--metro-port'],
|
||||
type: 'int',
|
||||
min: 1,
|
||||
max: 65535,
|
||||
usageLabel: '--metro-port <port>',
|
||||
usageDescription: 'Session-scoped Metro/debug port hint',
|
||||
},
|
||||
{
|
||||
key: 'metroProjectRoot',
|
||||
names: ['--project-root'],
|
||||
type: 'string',
|
||||
usageLabel: '--project-root <path>',
|
||||
usageDescription: 'metro prepare: React Native project root (default: cwd)',
|
||||
},
|
||||
{
|
||||
key: 'kind',
|
||||
names: ['--kind'],
|
||||
type: 'enum',
|
||||
enumValues: ['auto', 'react-native', 'expo', 'repack', ...PERF_KIND_VALUES],
|
||||
usageLabel: '--kind <kind>',
|
||||
usageDescription:
|
||||
'Kind selector for commands that support it, such as metro prepare or perf artifact collectors',
|
||||
},
|
||||
{
|
||||
key: 'perfTemplate',
|
||||
names: ['--template'],
|
||||
type: 'string',
|
||||
usageLabel: '--template <name>',
|
||||
usageDescription: 'Perf xctrace template name, for example Time Profiler',
|
||||
},
|
||||
{
|
||||
key: 'metroKind',
|
||||
names: ['--metro-kind'],
|
||||
type: 'enum',
|
||||
enumValues: ['auto', 'react-native', 'expo', 'repack'],
|
||||
usageLabel: '--metro-kind auto|react-native|expo|repack',
|
||||
usageDescription: 'metro prepare: detect or force the React Native dev-server launcher kind',
|
||||
},
|
||||
{
|
||||
key: 'metroPublicBaseUrl',
|
||||
names: ['--public-base-url'],
|
||||
type: 'string',
|
||||
usageLabel: '--public-base-url <url>',
|
||||
usageDescription: 'metro prepare: public base URL used for direct dev-server bundle hints',
|
||||
},
|
||||
{
|
||||
key: 'metroProxyBaseUrl',
|
||||
names: ['--proxy-base-url'],
|
||||
type: 'string',
|
||||
usageLabel: '--proxy-base-url <url>',
|
||||
usageDescription: 'metro prepare: optional bridge origin for remote dev-server access',
|
||||
},
|
||||
{
|
||||
key: 'metroBearerToken',
|
||||
names: ['--bearer-token'],
|
||||
type: 'string',
|
||||
usageLabel: '--bearer-token <token>',
|
||||
usageDescription:
|
||||
'metro prepare: host bridge bearer token (or AGENT_DEVICE_METRO_BEARER_TOKEN; falls back to AGENT_DEVICE_DAEMON_AUTH_TOKEN)',
|
||||
},
|
||||
{
|
||||
key: 'metroPreparePort',
|
||||
names: ['--port'],
|
||||
type: 'int',
|
||||
min: 1,
|
||||
max: 65535,
|
||||
usageLabel: '--port <port>',
|
||||
usageDescription: 'metro prepare: local dev-server port (default: 8081)',
|
||||
},
|
||||
{
|
||||
key: 'metroListenHost',
|
||||
names: ['--listen-host'],
|
||||
type: 'string',
|
||||
usageLabel: '--listen-host <host>',
|
||||
usageDescription: 'metro prepare: host dev server listens on (default: 0.0.0.0)',
|
||||
},
|
||||
{
|
||||
key: 'metroStatusHost',
|
||||
names: ['--status-host'],
|
||||
type: 'string',
|
||||
usageLabel: '--status-host <host>',
|
||||
usageDescription:
|
||||
'metro prepare: host used for local dev-server /status polling (default: 127.0.0.1)',
|
||||
},
|
||||
{
|
||||
key: 'metroStartupTimeoutMs',
|
||||
names: ['--startup-timeout-ms'],
|
||||
type: 'int',
|
||||
min: 1,
|
||||
usageLabel: '--startup-timeout-ms <ms>',
|
||||
usageDescription: 'metro prepare: timeout while waiting for the dev server to become ready',
|
||||
},
|
||||
{
|
||||
key: 'metroProbeTimeoutMs',
|
||||
names: ['--probe-timeout-ms'],
|
||||
type: 'int',
|
||||
min: 1,
|
||||
usageLabel: '--probe-timeout-ms <ms>',
|
||||
usageDescription: 'metro prepare: timeout for /status and proxy bridge calls',
|
||||
},
|
||||
{
|
||||
key: 'metroRuntimeFile',
|
||||
names: ['--runtime-file'],
|
||||
type: 'string',
|
||||
usageLabel: '--runtime-file <path>',
|
||||
usageDescription: 'metro prepare: optional file path to persist the JSON result',
|
||||
},
|
||||
{
|
||||
key: 'metroNoReuseExisting',
|
||||
names: ['--no-reuse-existing'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--no-reuse-existing',
|
||||
usageDescription: 'metro prepare: always start a fresh Metro process',
|
||||
},
|
||||
{
|
||||
key: 'metroNoInstallDeps',
|
||||
names: ['--no-install-deps'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--no-install-deps',
|
||||
usageDescription: 'metro prepare: skip package-manager install when node_modules is missing',
|
||||
},
|
||||
{
|
||||
key: 'bundleUrl',
|
||||
names: ['--bundle-url'],
|
||||
type: 'string',
|
||||
usageLabel: '--bundle-url <url>',
|
||||
usageDescription: 'Session-scoped bundle URL hint',
|
||||
},
|
||||
{
|
||||
key: 'launchUrl',
|
||||
names: ['--launch-url'],
|
||||
type: 'string',
|
||||
usageLabel: '--launch-url <url>',
|
||||
usageDescription: 'Session-scoped deep link / launch URL hint',
|
||||
},
|
||||
{
|
||||
key: 'iosSimulatorDeviceSet',
|
||||
names: ['--ios-simulator-device-set'],
|
||||
type: 'string',
|
||||
usageLabel: '--ios-simulator-device-set <path>',
|
||||
usageDescription: 'Scope iOS simulator discovery/commands to this simulator device set',
|
||||
},
|
||||
{
|
||||
key: 'iosXctestrunFile',
|
||||
names: ['--ios-xctestrun-file'],
|
||||
type: 'string',
|
||||
usageLabel: '--ios-xctestrun-file <path>',
|
||||
usageDescription: 'Use an externally built iOS XCTest runner .xctestrun artifact',
|
||||
},
|
||||
{
|
||||
key: 'iosXctestDerivedDataPath',
|
||||
names: ['--ios-xctest-derived-data-path'],
|
||||
type: 'string',
|
||||
usageLabel: '--ios-xctest-derived-data-path <path>',
|
||||
usageDescription: 'Derived data path for external iOS XCTest runner execution',
|
||||
},
|
||||
{
|
||||
key: 'iosXctestEnvDir',
|
||||
names: ['--ios-xctest-env-dir'],
|
||||
type: 'string',
|
||||
usageLabel: '--ios-xctest-env-dir <path>',
|
||||
usageDescription: 'Writable directory for per-session iOS XCTest runner env overlays',
|
||||
},
|
||||
{
|
||||
key: 'deviceHub',
|
||||
names: ['--device-hub'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--device-hub',
|
||||
usageDescription: 'open: use Xcode Device Hub when surfacing Apple simulators',
|
||||
},
|
||||
{
|
||||
key: 'testIme',
|
||||
names: ['--test-ime'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--test-ime',
|
||||
usageDescription:
|
||||
'open: activate the headless Android test IME for deterministic Unicode text entry (default on for emulators; opt-in on real devices)',
|
||||
},
|
||||
{
|
||||
key: 'testIme',
|
||||
names: ['--no-test-ime'],
|
||||
type: 'boolean',
|
||||
setValue: false,
|
||||
usageLabel: '--no-test-ime',
|
||||
usageDescription:
|
||||
'open: keep the real Android keyboard even on emulators (opt out of the headless test IME)',
|
||||
},
|
||||
{
|
||||
key: 'androidDeviceAllowlist',
|
||||
names: ['--android-device-allowlist'],
|
||||
type: 'string',
|
||||
usageLabel: '--android-device-allowlist <serials>',
|
||||
usageDescription: 'Comma/space separated Android serial allowlist for discovery/selection',
|
||||
},
|
||||
{
|
||||
key: 'remote',
|
||||
names: ['--remote'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--remote',
|
||||
usageDescription: 'Doctor: check remote connection setup instead of local device inventory',
|
||||
},
|
||||
{
|
||||
key: 'activity',
|
||||
names: ['--activity'],
|
||||
type: 'string',
|
||||
usageLabel: '--activity <component>',
|
||||
usageDescription: 'Android app launch activity (package/Activity); not for URL opens',
|
||||
},
|
||||
{
|
||||
key: 'launchConsole',
|
||||
names: ['--launch-console'],
|
||||
type: 'string',
|
||||
usageLabel: '--launch-console <path>',
|
||||
usageDescription: 'open: capture the initial iOS simulator launch console window to a file',
|
||||
},
|
||||
{
|
||||
key: 'launchArgs',
|
||||
names: ['--launch-args'],
|
||||
type: 'string',
|
||||
multiple: true,
|
||||
usageLabel: '--launch-args <arg>',
|
||||
usageDescription:
|
||||
'open: repeatable launch argument forwarded verbatim to the platform launch command (iOS app process args; Android adb shell am start args). Linux and macOS reject the flag.',
|
||||
},
|
||||
{
|
||||
key: 'header',
|
||||
names: ['--header'],
|
||||
type: 'string',
|
||||
multiple: true,
|
||||
usageLabel: '--header <name:value>',
|
||||
usageDescription: 'install-from-source: repeatable HTTP header for URL downloads',
|
||||
},
|
||||
{
|
||||
key: 'githubActionsArtifact',
|
||||
names: ['--github-actions-artifact'],
|
||||
type: 'string',
|
||||
usageLabel: '--github-actions-artifact <owner/repo:artifact>',
|
||||
usageDescription: 'install-from-source: GitHub Actions artifact resolved by a remote daemon',
|
||||
},
|
||||
{
|
||||
key: 'installSource',
|
||||
// Config-only virtual option; parsed explicitly from JSON before generic string options.
|
||||
names: [],
|
||||
type: 'string',
|
||||
},
|
||||
{
|
||||
key: 'session',
|
||||
names: ['--session'],
|
||||
type: 'string',
|
||||
usageLabel: '--session <name>',
|
||||
usageDescription: 'Named session',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,257 @@
|
||||
import { SCREENSHOT_SPECIFIC_FLAG_DEFINITIONS } from '../../contracts/screenshot.ts';
|
||||
import {
|
||||
MAESTRO_COMPAT_TRACKER_URL,
|
||||
formatMaestroSupportedSubsetForCli,
|
||||
} from '../../compat/maestro/support-matrix.ts';
|
||||
import type { FlagDefinition } from './flag-types.ts';
|
||||
|
||||
export const WORKFLOW_FLAG_DEFINITIONS: readonly FlagDefinition[] = [
|
||||
{
|
||||
key: 'replayUpdate',
|
||||
names: ['--update', '-u'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--update, -u',
|
||||
usageDescription: 'Replay: update selectors and rewrite replay file in place',
|
||||
},
|
||||
{
|
||||
key: 'replayMaestro',
|
||||
names: ['--maestro'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--maestro',
|
||||
usageDescription:
|
||||
`Replay: treat input as a Maestro YAML compatibility flow. ${formatMaestroSupportedSubsetForCli()} ` +
|
||||
`Unsupported syntax fails loudly with a link to ${MAESTRO_COMPAT_TRACKER_URL}`,
|
||||
},
|
||||
{
|
||||
key: 'replayExportFormat',
|
||||
names: ['--format'],
|
||||
type: 'enum',
|
||||
enumValues: ['maestro'],
|
||||
usageLabel: '--format maestro',
|
||||
usageDescription: 'Replay export: output format',
|
||||
},
|
||||
{
|
||||
key: 'replayEnv',
|
||||
names: ['-e', '--env'],
|
||||
type: 'string',
|
||||
multiple: true,
|
||||
usageLabel: '-e KEY=VALUE, --env KEY=VALUE',
|
||||
usageDescription:
|
||||
'Replay/Test: inject or override a ${KEY} variable for the script (repeatable)',
|
||||
},
|
||||
{
|
||||
key: 'failFast',
|
||||
names: ['--fail-fast'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--fail-fast',
|
||||
usageDescription:
|
||||
'Test: stop the suite after the first failing script; with sharding, each shard stops independently',
|
||||
},
|
||||
{
|
||||
key: 'timeoutMs',
|
||||
names: ['--timeout'],
|
||||
type: 'int',
|
||||
min: 1,
|
||||
usageLabel: '--timeout <ms>',
|
||||
usageDescription:
|
||||
'Prepare/Replay/Snapshot/Test: maximum wall-clock time for the command or attempt. With --settle: the settle-wait deadline (default 10s)',
|
||||
},
|
||||
{
|
||||
key: 'retries',
|
||||
names: ['--retries'],
|
||||
type: 'int',
|
||||
min: 0,
|
||||
max: 3,
|
||||
usageLabel: '--retries <n>',
|
||||
usageDescription: 'Test: retry each failed script up to n additional times',
|
||||
},
|
||||
{
|
||||
key: 'recordVideo',
|
||||
names: ['--record-video'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--record-video',
|
||||
usageDescription: 'Test: record each replay attempt to recording.mp4 in its attempt artifacts',
|
||||
},
|
||||
{
|
||||
key: 'artifactsDir',
|
||||
names: ['--artifacts-dir'],
|
||||
type: 'string',
|
||||
usageLabel: '--artifacts-dir <path>',
|
||||
usageDescription: 'Test: root directory for suite artifacts',
|
||||
},
|
||||
{
|
||||
key: 'reporter',
|
||||
names: ['--reporter'],
|
||||
type: 'string',
|
||||
multiple: true,
|
||||
usageLabel: '--reporter <name-or-path>',
|
||||
usageDescription:
|
||||
'Test: add a replay suite reporter; use default, junit:<path>, or a custom reporter path (repeatable)',
|
||||
},
|
||||
{
|
||||
key: 'reportJunit',
|
||||
names: ['--report-junit'],
|
||||
type: 'string',
|
||||
usageLabel: '--report-junit <path>',
|
||||
usageDescription: 'Test: compatibility alias for --reporter junit:<path>',
|
||||
},
|
||||
{
|
||||
key: 'shardAll',
|
||||
names: ['--shard-all'],
|
||||
type: 'int',
|
||||
min: 1,
|
||||
usageLabel: '--shard-all <n>',
|
||||
usageDescription:
|
||||
'Test: run the full suite on each of n devices; combine with --device id1,id2 for explicit connected devices; AD_SHARD_INDEX is zero-based',
|
||||
},
|
||||
{
|
||||
key: 'shardSplit',
|
||||
names: ['--shard-split'],
|
||||
type: 'int',
|
||||
min: 1,
|
||||
usageLabel: '--shard-split <n>',
|
||||
usageDescription:
|
||||
'Test: split runnable suite entries across n devices; AD_SHARD_INDEX is zero-based',
|
||||
},
|
||||
{
|
||||
key: 'steps',
|
||||
names: ['--steps'],
|
||||
type: 'string',
|
||||
usageLabel: '--steps <json>',
|
||||
usageDescription: 'Batch: JSON array of steps',
|
||||
},
|
||||
{
|
||||
key: 'stepsFile',
|
||||
names: ['--steps-file'],
|
||||
type: 'string',
|
||||
usageLabel: '--steps-file <path>',
|
||||
usageDescription: 'Batch: read steps JSON from file',
|
||||
},
|
||||
{
|
||||
key: 'batchOnError',
|
||||
names: ['--on-error'],
|
||||
type: 'enum',
|
||||
enumValues: ['stop'],
|
||||
usageLabel: '--on-error stop',
|
||||
usageDescription: 'Batch: stop when a step fails',
|
||||
},
|
||||
{
|
||||
key: 'batchMaxSteps',
|
||||
names: ['--max-steps'],
|
||||
type: 'int',
|
||||
min: 1,
|
||||
max: 1000,
|
||||
usageLabel: '--max-steps <n>',
|
||||
usageDescription: 'Batch: maximum number of allowed steps',
|
||||
},
|
||||
{
|
||||
key: 'appsFilter',
|
||||
names: ['--all'],
|
||||
type: 'enum',
|
||||
enumValues: ['user-installed', 'all'],
|
||||
setValue: 'all',
|
||||
usageLabel: '--all',
|
||||
usageDescription: 'Apps: include system/OEM apps',
|
||||
},
|
||||
{
|
||||
key: 'snapshotInteractiveOnly',
|
||||
names: ['-i'],
|
||||
type: 'boolean',
|
||||
usageLabel: '-i',
|
||||
usageDescription: 'Snapshot: interactive elements only',
|
||||
},
|
||||
{
|
||||
key: 'snapshotDepth',
|
||||
names: ['--depth', '-d'],
|
||||
type: 'int',
|
||||
min: 0,
|
||||
usageLabel: '--depth, -d <depth>',
|
||||
usageDescription: 'Snapshot: limit snapshot depth',
|
||||
},
|
||||
{
|
||||
key: 'snapshotScope',
|
||||
names: ['--scope', '-s'],
|
||||
type: 'string',
|
||||
usageLabel: '--scope, -s <scope>',
|
||||
usageDescription: 'Snapshot: scope snapshot to label/identifier',
|
||||
},
|
||||
{
|
||||
key: 'snapshotRaw',
|
||||
names: ['--raw'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--raw',
|
||||
usageDescription: 'Snapshot: raw node output',
|
||||
},
|
||||
{
|
||||
key: 'snapshotForceFull',
|
||||
names: ['--force-full'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--force-full',
|
||||
usageDescription: 'Snapshot: re-emit the full tree even when unchanged',
|
||||
},
|
||||
{
|
||||
key: 'findFirst',
|
||||
names: ['--first'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--first',
|
||||
usageDescription: 'Find: pick the first match when ambiguous',
|
||||
},
|
||||
{
|
||||
key: 'findLast',
|
||||
names: ['--last'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--last',
|
||||
usageDescription: 'Find: pick the last match when ambiguous',
|
||||
},
|
||||
{
|
||||
key: 'out',
|
||||
names: ['--out'],
|
||||
type: 'string',
|
||||
usageLabel: '--out <path>',
|
||||
usageDescription: 'Output path',
|
||||
},
|
||||
{
|
||||
key: 'artifact',
|
||||
names: ['--artifact'],
|
||||
type: 'string',
|
||||
usageLabel: '--artifact <path>',
|
||||
usageDescription: 'Debug symbols: Apple crash artifact path (.ips, .crash, or .log)',
|
||||
},
|
||||
{
|
||||
key: 'dsym',
|
||||
names: ['--dsym'],
|
||||
type: 'string',
|
||||
usageLabel: '--dsym <path>',
|
||||
usageDescription: 'Debug symbols: matching .dSYM bundle path',
|
||||
},
|
||||
{
|
||||
key: 'searchPath',
|
||||
names: ['--search-path'],
|
||||
type: 'string',
|
||||
usageLabel: '--search-path <dir>',
|
||||
usageDescription: 'Debug symbols: directory to scan for matching .dSYM bundles',
|
||||
},
|
||||
{
|
||||
key: 'overlayRefs',
|
||||
names: ['--overlay-refs'],
|
||||
type: 'boolean',
|
||||
usageLabel: '--overlay-refs',
|
||||
usageDescription:
|
||||
'Screenshot: draw current snapshot refs and target rectangles onto the saved PNG; diff screenshot: also write a separate current-screen overlay guide',
|
||||
},
|
||||
...SCREENSHOT_SPECIFIC_FLAG_DEFINITIONS,
|
||||
{
|
||||
key: 'baseline',
|
||||
names: ['--baseline', '-b'],
|
||||
type: 'string',
|
||||
usageLabel: '--baseline, -b <path>',
|
||||
usageDescription: 'Diff screenshot: path to baseline image file',
|
||||
},
|
||||
{
|
||||
key: 'threshold',
|
||||
names: ['--threshold'],
|
||||
type: 'string',
|
||||
usageLabel: '--threshold <0-1>',
|
||||
usageDescription: 'Diff screenshot: color distance threshold (default 0.1)',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,95 @@
|
||||
import type { FlagKey } from './flag-types.ts';
|
||||
|
||||
function flagKeys<const TKeys extends readonly FlagKey[]>(...keys: TKeys): TKeys {
|
||||
return keys;
|
||||
}
|
||||
|
||||
export const SNAPSHOT_FLAGS = flagKeys(
|
||||
'snapshotInteractiveOnly',
|
||||
'snapshotDepth',
|
||||
'snapshotScope',
|
||||
'snapshotRaw',
|
||||
);
|
||||
|
||||
export const SELECTOR_SNAPSHOT_FLAGS = flagKeys('snapshotDepth', 'snapshotScope', 'snapshotRaw');
|
||||
|
||||
export const METRO_PREPARE_FLAGS = flagKeys(
|
||||
'metroProjectRoot',
|
||||
'kind',
|
||||
'metroKind',
|
||||
'metroPublicBaseUrl',
|
||||
'metroProxyBaseUrl',
|
||||
'metroBearerToken',
|
||||
'metroPreparePort',
|
||||
'metroListenHost',
|
||||
'metroStatusHost',
|
||||
'metroStartupTimeoutMs',
|
||||
'metroProbeTimeoutMs',
|
||||
'metroRuntimeFile',
|
||||
'metroNoReuseExisting',
|
||||
'metroNoInstallDeps',
|
||||
);
|
||||
|
||||
export const METRO_RELOAD_FLAGS = flagKeys('metroHost', 'metroPort', 'bundleUrl');
|
||||
export const REPEATED_TOUCH_FLAGS = flagKeys(
|
||||
'count',
|
||||
'intervalMs',
|
||||
'holdMs',
|
||||
'jitterPx',
|
||||
'doubleTap',
|
||||
);
|
||||
// Interaction commands with the descriptor post-action observation trait use
|
||||
// these flags for `--settle` (#1101). --timeout doubles as the settle deadline
|
||||
// (flag-sourced budget on the interaction descriptors, mirroring wait's
|
||||
// positional budget).
|
||||
export const SETTLE_FLAGS = flagKeys('settle', 'settleQuietMs', 'timeoutMs');
|
||||
export const REPLAY_FLAGS = flagKeys('replayUpdate', 'replayEnv');
|
||||
|
||||
export const COMMON_COMMAND_SUPPORTED_FLAG_KEYS = flagKeys(
|
||||
'remoteConfig',
|
||||
'stateDir',
|
||||
'daemonBaseUrl',
|
||||
'daemonAuthToken',
|
||||
'daemonTransport',
|
||||
'daemonServerMode',
|
||||
'tenant',
|
||||
'sessionIsolation',
|
||||
'runId',
|
||||
'leaseId',
|
||||
'leaseBackend',
|
||||
'sessionLock',
|
||||
'sessionLocked',
|
||||
'sessionLockConflicts',
|
||||
'platform',
|
||||
'target',
|
||||
'device',
|
||||
'providerApp',
|
||||
'providerOsVersion',
|
||||
'providerProject',
|
||||
'providerBuild',
|
||||
'providerSessionName',
|
||||
'awsProjectArn',
|
||||
'awsDeviceArn',
|
||||
'awsAppArn',
|
||||
'awsRegion',
|
||||
'awsInteractionMode',
|
||||
'udid',
|
||||
'serial',
|
||||
'iosSimulatorDeviceSet',
|
||||
'iosXctestrunFile',
|
||||
'iosXctestDerivedDataPath',
|
||||
'iosXctestEnvDir',
|
||||
'androidDeviceAllowlist',
|
||||
'session',
|
||||
'noRecord',
|
||||
);
|
||||
|
||||
export const GLOBAL_FLAG_KEYS = new Set<FlagKey>([
|
||||
'json',
|
||||
'config',
|
||||
'help',
|
||||
'version',
|
||||
'verbose',
|
||||
'cost',
|
||||
'responseLevel',
|
||||
]);
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { test } from 'vitest';
|
||||
import assert from 'node:assert/strict';
|
||||
import { getFlagDefinition } from '../../cli/parser/cli-flags.ts';
|
||||
import { getFlagDefinition } from './flag-registry.ts';
|
||||
import { PLATFORM_SELECTORS } from '../../kernel/device.ts';
|
||||
|
||||
test('--platform enumValues are derived from the canonical PLATFORM_SELECTORS tuple', () => {
|
||||
@@ -0,0 +1,25 @@
|
||||
import { ACTION_FLAG_DEFINITIONS } from './flag-definitions-action.ts';
|
||||
import { CONNECTION_FLAG_DEFINITIONS } from './flag-definitions-connection.ts';
|
||||
import { TARGET_FLAG_DEFINITIONS } from './flag-definitions-target.ts';
|
||||
import { WORKFLOW_FLAG_DEFINITIONS } from './flag-definitions-workflow.ts';
|
||||
import type { FlagDefinition } from './flag-types.ts';
|
||||
|
||||
const FLAG_DEFINITIONS: readonly FlagDefinition[] = [
|
||||
...CONNECTION_FLAG_DEFINITIONS,
|
||||
...TARGET_FLAG_DEFINITIONS,
|
||||
...ACTION_FLAG_DEFINITIONS,
|
||||
...WORKFLOW_FLAG_DEFINITIONS,
|
||||
];
|
||||
|
||||
const flagDefinitionByName = new Map<string, FlagDefinition>();
|
||||
for (const definition of FLAG_DEFINITIONS) {
|
||||
for (const name of definition.names) flagDefinitionByName.set(name, definition);
|
||||
}
|
||||
|
||||
export function getFlagDefinition(token: string): FlagDefinition | undefined {
|
||||
return flagDefinitionByName.get(token);
|
||||
}
|
||||
|
||||
export function getFlagDefinitions(): readonly FlagDefinition[] {
|
||||
return FLAG_DEFINITIONS;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import type { CliFlags } from '../../contracts/cli-flags.ts';
|
||||
|
||||
export type { CliFlags, DaemonExcludedCliFlag } from '../../contracts/cli-flags.ts';
|
||||
|
||||
export type FlagKey = keyof CliFlags;
|
||||
type FlagType = 'boolean' | 'int' | 'enum' | 'string' | 'booleanOrString';
|
||||
|
||||
export type FlagDefinition = {
|
||||
key: FlagKey;
|
||||
names: readonly string[];
|
||||
type: FlagType;
|
||||
multiple?: boolean;
|
||||
enumValues?: readonly string[];
|
||||
min?: number;
|
||||
max?: number;
|
||||
setValue?: CliFlags[FlagKey];
|
||||
usageLabel?: string;
|
||||
usageDescription?: string;
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { CliFlags } from '../../cli/parser/cli-flags.ts';
|
||||
import type { CliFlags } from './flag-types.ts';
|
||||
import type { CommandName } from '../command-metadata.ts';
|
||||
import { listCommandFamilyCliReaders } from '../family/registry.ts';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { InteractionTarget, InternalRequestOptions } from '../../client/client-types.ts';
|
||||
import type { CommandFlags } from '../../core/dispatch-context.ts';
|
||||
import type { CliFlags } from '../../cli/parser/cli-flags.ts';
|
||||
import type { CliFlags } from './flag-types.ts';
|
||||
import type { ClickButton } from '../../core/click-button.ts';
|
||||
import type { DecodedFillTarget } from '../../core/interaction-positionals.ts';
|
||||
import type { WaitParsed } from '../../core/wait-positionals.ts';
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { AgentDeviceClient, CommandRequestResult } from '../client/client.ts';
|
||||
import type { AgentDeviceClient, CommandRequestResult } from '../agent-device-client.ts';
|
||||
import { formatCliOutput } from './cli-output.ts';
|
||||
import { readInputFromCli } from './cli-grammar.ts';
|
||||
import { runCommand, type CommandName } from './command-surface.ts';
|
||||
import type { CliOutput } from './command-contract.ts';
|
||||
import type { CliFlags } from '../cli/parser/cli-flags.ts';
|
||||
import type { CliFlags } from './cli-grammar/flag-types.ts';
|
||||
|
||||
type CliRunOptions = {
|
||||
client: AgentDeviceClient;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { listCliCommandNames } from '../command-catalog.ts';
|
||||
import { cliAliasesForCommand, normalizeCliCommandAlias } from '../cli-command-aliases.ts';
|
||||
import { buildCommandUsage } from '../utils/cli-usage.ts';
|
||||
import { buildCommandUsage } from '../cli-schema/usage.ts';
|
||||
import type { DaemonCommandRoute } from '../daemon/daemon-command-registry.ts';
|
||||
import { commandDescriptors, type Command } from '../core/command-descriptor/registry.ts';
|
||||
import { ownerFilesForCommand } from '../core/command-descriptor/owner-files.ts';
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
type CommandSchema,
|
||||
type FlagDefinition,
|
||||
type FlagKey,
|
||||
} from '../utils/command-schema.ts';
|
||||
} from '../cli-schema/command-schema.ts';
|
||||
import { commandFamilies, type CommandFamilyMetadata } from './family/registry.ts';
|
||||
|
||||
export type CommandFlagExplanation = {
|
||||
@@ -329,7 +329,7 @@ function commandFiles(
|
||||
`src/commands/${family}/index.test.ts`,
|
||||
);
|
||||
} else if (cliCommandNames.has(command)) {
|
||||
derived.push('src/utils/cli-command-overrides.ts');
|
||||
derived.push('src/cli-schema/command-overrides.ts');
|
||||
}
|
||||
if (daemonRoute) derived.push(daemonRouteOwnerFiles[daemonRoute]);
|
||||
if (hasDispatch) derived.push('src/core/dispatch.ts');
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { buildFlags } from '../client/client-normalizers.ts';
|
||||
import { screenshotFlagsFromOptions } from '../contracts/screenshot.ts';
|
||||
import type { CommandFlags } from '../core/dispatch-context.ts';
|
||||
import { getFlagDefinitions } from '../cli/parser/cli-flags.ts';
|
||||
import { leaseScopeFromOptions, leaseScopeToCommandFlags } from '../core/lease-scope.ts';
|
||||
import { stripUndefined } from '../utils/parsing.ts';
|
||||
import { getFlagDefinitions } from './cli-grammar/flag-registry.ts';
|
||||
import type { InternalRequestOptions } from '../client/client-types.ts';
|
||||
import type { CommandMetadata } from './command-contract.ts';
|
||||
|
||||
@@ -8,6 +10,104 @@ const CLI_FLAG_KEYS: ReadonlySet<string> = new Set(
|
||||
getFlagDefinitions().map((definition) => definition.key),
|
||||
);
|
||||
|
||||
function buildFlags(options: InternalRequestOptions): CommandFlags {
|
||||
const leaseScope = leaseScopeFromOptions(options);
|
||||
return stripUndefined({
|
||||
stateDir: options.stateDir,
|
||||
daemonBaseUrl: options.daemonBaseUrl,
|
||||
daemonAuthToken: options.daemonAuthToken,
|
||||
daemonTransport: options.daemonTransport,
|
||||
daemonServerMode: options.daemonServerMode,
|
||||
...leaseScopeToCommandFlags(leaseScope),
|
||||
provider: options.provider,
|
||||
providerSessionId: options.providerSessionId,
|
||||
providerApp: options.providerApp,
|
||||
providerOsVersion: options.providerOsVersion,
|
||||
providerProject: options.providerProject,
|
||||
providerBuild: options.providerBuild,
|
||||
providerSessionName: options.providerSessionName,
|
||||
awsProjectArn: options.awsProjectArn,
|
||||
awsDeviceArn: options.awsDeviceArn,
|
||||
awsAppArn: options.awsAppArn,
|
||||
awsRegion: options.awsRegion,
|
||||
awsInteractionMode: options.awsInteractionMode,
|
||||
sessionIsolation: options.sessionIsolation,
|
||||
platform: options.platform,
|
||||
target: options.target,
|
||||
device: options.device,
|
||||
udid: options.udid,
|
||||
serial: options.serial,
|
||||
iosSimulatorDeviceSet: options.iosSimulatorDeviceSet,
|
||||
iosXctestrunFile: options.iosXctestrunFile,
|
||||
iosXctestDerivedDataPath: options.iosXctestDerivedDataPath,
|
||||
iosXctestEnvDir: options.iosXctestEnvDir,
|
||||
androidDeviceAllowlist: options.androidDeviceAllowlist,
|
||||
surface: options.surface,
|
||||
activity: options.activity,
|
||||
launchConsole: options.launchConsole,
|
||||
launchArgs: options.launchArgs,
|
||||
relaunch: options.relaunch,
|
||||
shutdown: options.shutdown,
|
||||
saveScript: options.saveScript,
|
||||
deviceHub: options.deviceHub,
|
||||
testIme: options.testIme,
|
||||
noRecord: options.noRecord,
|
||||
backMode: options.backMode,
|
||||
metroHost: options.metroHost,
|
||||
metroPort: options.metroPort,
|
||||
bundleUrl: options.bundleUrl,
|
||||
launchUrl: options.launchUrl,
|
||||
snapshotInteractiveOnly: options.interactiveOnly,
|
||||
snapshotDepth: options.depth,
|
||||
snapshotScope: options.scope,
|
||||
snapshotRaw: options.raw,
|
||||
snapshotForceFull: options.forceFull,
|
||||
...screenshotFlagsFromOptions(options),
|
||||
appsFilter: options.appsFilter,
|
||||
kind: options.kind,
|
||||
out: options.out,
|
||||
count: options.count,
|
||||
fps: options.fps,
|
||||
screenshotMaxSize: options.maxSize,
|
||||
quality: options.quality,
|
||||
hideTouches: options.hideTouches,
|
||||
recordingScope: options.recordingScope,
|
||||
intervalMs: options.intervalMs,
|
||||
delayMs: options.delayMs,
|
||||
durationMs: options.durationMs,
|
||||
holdMs: options.holdMs,
|
||||
jitterPx: options.jitterPx,
|
||||
pixels: options.pixels,
|
||||
doubleTap: options.doubleTap,
|
||||
verify: options.verify,
|
||||
settle: options.settle,
|
||||
settleQuietMs: options.settleQuietMs,
|
||||
clickButton: options.clickButton,
|
||||
pauseMs: options.pauseMs,
|
||||
pattern: options.pattern,
|
||||
headless: options.headless,
|
||||
restart: options.restart,
|
||||
replayUpdate: options.replayUpdate,
|
||||
replayBackend: options.replayBackend,
|
||||
replayEnv: options.replayEnv,
|
||||
replayShellEnv: options.replayShellEnv,
|
||||
failFast: options.failFast,
|
||||
timeoutMs: options.timeoutMs,
|
||||
retries: options.retries,
|
||||
recordVideo: options.recordVideo,
|
||||
artifactsDir: options.artifactsDir,
|
||||
shardAll: options.shardAll,
|
||||
shardSplit: options.shardSplit,
|
||||
findFirst: options.findFirst,
|
||||
findLast: options.findLast,
|
||||
networkInclude: options.networkInclude,
|
||||
batchOnError: options.batchOnError,
|
||||
batchMaxSteps: options.batchMaxSteps,
|
||||
batchSteps: options.batchSteps,
|
||||
verbose: options.debug,
|
||||
}) as CommandFlags;
|
||||
}
|
||||
|
||||
export function buildRequestFlags(
|
||||
options: InternalRequestOptions,
|
||||
metadataFlags: Partial<CommandFlags> | undefined,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, test } from 'vitest';
|
||||
import type { CliFlags } from '../../cli/parser/cli-flags.ts';
|
||||
import type { CliFlags } from '../cli-grammar/flag-types.ts';
|
||||
import { debugCliReader, debugCommandDefinition, debugCommandMetadata } from './index.ts';
|
||||
|
||||
describe('debugging command interface', () => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { AppError } from '../../kernel/errors.ts';
|
||||
import type { CommandSchemaOverride } from '../../utils/cli-command-schema-types.ts';
|
||||
import type { CommandSchemaOverride } from '../../cli-schema/types.ts';
|
||||
import { enumField, requiredField, stringField } from '../command-input.ts';
|
||||
import { defineCommandFacet, defineCommandFamilyFromFacets } from '../family/types.ts';
|
||||
import { defineExecutableCommand } from '../command-contract.ts';
|
||||
|
||||
@@ -12,7 +12,7 @@ import { reactNativeCommandFamily } from '../react-native/index.ts';
|
||||
import { recordingCommandFamily } from '../recording/index.ts';
|
||||
import { replayCommandFamily } from '../replay/index.ts';
|
||||
import { systemCommandFamily } from '../system/index.ts';
|
||||
import type { CommandSchemaOverride } from '../../utils/cli-command-schema-types.ts';
|
||||
import type { CommandSchemaOverride } from '../../cli-schema/types.ts';
|
||||
import { type CommandFamilyFacet } from './types.ts';
|
||||
|
||||
type CommandFamilyRecordMap = {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { AgentDeviceClient } from '../../client/client-types.ts';
|
||||
import type { CommandSchemaOverride } from '../../utils/cli-command-schema-types.ts';
|
||||
import type { CommandSchemaOverride } from '../../cli-schema/types.ts';
|
||||
import type { CliReader, DaemonWriter } from '../cli-grammar/types.ts';
|
||||
import type { CommandMetadata, JsonSchema } from '../command-contract.ts';
|
||||
import type { CliOutputFormatter } from '../output-common.ts';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, test } from 'vitest';
|
||||
import type { CliFlags } from '../../cli/parser/cli-flags.ts';
|
||||
import type { CliFlags } from '../cli-grammar/flag-types.ts';
|
||||
import type { CommandInput } from '../cli-grammar/types.ts';
|
||||
import { gestureCliReaders, gestureDaemonWriters } from './gesture.ts';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { PUBLIC_COMMANDS } from '../../command-catalog.ts';
|
||||
import type { FlingOptions, RotateGestureOptions } from '../../client/client-types.ts';
|
||||
import type { CliFlags } from '../../cli/parser/cli-flags.ts';
|
||||
import type { CliFlags } from '../cli-grammar/flag-types.ts';
|
||||
import { AppError } from '../../kernel/errors.ts';
|
||||
import {
|
||||
commonInputFromFlags,
|
||||
|
||||
@@ -17,13 +17,13 @@ import type {
|
||||
TransformGestureOptions,
|
||||
TypeTextOptions,
|
||||
} from '../../client/client-types.ts';
|
||||
import type { CommandSchemaOverride } from '../../utils/cli-command-schema-types.ts';
|
||||
import type { CommandSchemaOverride } from '../../cli-schema/types.ts';
|
||||
import {
|
||||
REPEATED_TOUCH_FLAGS,
|
||||
SELECTOR_SNAPSHOT_FLAGS,
|
||||
SETTLE_FLAGS,
|
||||
type FlagKey,
|
||||
} from '../../cli/parser/cli-flags.ts';
|
||||
} from '../cli-grammar/flag-groups.ts';
|
||||
import { type FlagKey } from '../cli-grammar/flag-types.ts';
|
||||
import {
|
||||
commandSupportsSettleObservation,
|
||||
commandSupportsVerifyEvidence,
|
||||
|
||||
@@ -27,16 +27,16 @@ import {
|
||||
} from '../command-input.ts';
|
||||
import { defineFieldCommandMetadata } from '../field-command-contract.ts';
|
||||
import { CLICK_BUTTONS } from '../../core/click-button.ts';
|
||||
import { SCROLL_DURATION_MAX_MS } from '../../core/scroll-command.ts';
|
||||
import { SCROLL_DURATION_MAX_MS } from '../../contracts/scroll-command.ts';
|
||||
import {
|
||||
SCROLL_DIRECTIONS,
|
||||
SWIPE_PATTERNS,
|
||||
SWIPE_PRESETS,
|
||||
type ScrollDirection,
|
||||
type SwipePreset,
|
||||
} from '../../core/scroll-gesture.ts';
|
||||
} from '../../contracts/scroll-gesture.ts';
|
||||
import { SCROLL_INPUT_DIRECTIONS } from './runtime/gestures.ts';
|
||||
import { FIND_LOCATORS } from '../../utils/finders.ts';
|
||||
import { FIND_LOCATORS } from '../../selectors/find.ts';
|
||||
import {
|
||||
commandSupportsSettleObservation,
|
||||
commandSupportsVerifyEvidence,
|
||||
|
||||
@@ -7,12 +7,12 @@ import {
|
||||
type GestureReferenceFrame,
|
||||
type ScrollDirection,
|
||||
type SwipePreset,
|
||||
} from '../../../core/scroll-gesture.ts';
|
||||
} from '../../../contracts/scroll-gesture.ts';
|
||||
import {
|
||||
assertExclusiveScrollDistanceInputs,
|
||||
honoredScrollDurationMs,
|
||||
normalizeScrollDurationMs,
|
||||
} from '../../../core/scroll-command.ts';
|
||||
} from '../../../contracts/scroll-command.ts';
|
||||
import type { AgentDeviceRuntime, CommandContext } from '../../../runtime-contract.ts';
|
||||
import { requireIntInRange } from '../../../utils/validation.ts';
|
||||
import { successText } from '../../../utils/success-text.ts';
|
||||
|
||||
@@ -3,15 +3,15 @@ import type { Point, SnapshotNode, SnapshotState } from '../../../kernel/snapsho
|
||||
import { findNodeByRef, normalizeRef } from '../../../kernel/snapshot.ts';
|
||||
import { resolveRectCenter } from '../../../utils/rect-center.ts';
|
||||
import type { AgentDeviceRuntime, CommandContext } from '../../../runtime-contract.ts';
|
||||
import { parseSelectorChain } from '../../../utils/selectors-parse.ts';
|
||||
import { parseSelectorChain } from '../../../selectors/parse.ts';
|
||||
import {
|
||||
formatSelectorFailure,
|
||||
resolveSelectorChain,
|
||||
selectorFailureHint,
|
||||
STALE_REF_HINT,
|
||||
type SelectorResolution,
|
||||
} from '../../../daemon/selectors.ts';
|
||||
import { buildSelectorChainForNode } from '../../../utils/selector-build.ts';
|
||||
} from '../../../selectors/index.ts';
|
||||
import { buildSelectorChainForNode } from '../../../selectors/build.ts';
|
||||
import {
|
||||
findNodeByLabel,
|
||||
normalizeType,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { test } from 'vitest';
|
||||
import { parseSelectorChain } from '../../../utils/selectors-parse.ts';
|
||||
import { parseSelectorChain } from '../../../selectors/parse.ts';
|
||||
import { deriveSelectorCapturePolicy } from './selector-capture-policy.ts';
|
||||
|
||||
test('selector capture policy reads full snapshots for focused predicates', () => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { IsPredicate } from '../../../utils/selector-is-predicates.ts';
|
||||
import type { SelectorChain } from '../../../utils/selectors-parse.ts';
|
||||
import type { IsPredicate } from '../../../selectors/predicates.ts';
|
||||
import type { SelectorChain } from '../../../selectors/parse.ts';
|
||||
|
||||
export type SelectorCapturePolicyInput = {
|
||||
predicate?: IsPredicate;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user