diff --git a/.github/workflows/package-smoke.yml b/.github/workflows/package-smoke.yml index f0a83cab6b..295792e5bf 100644 --- a/.github/workflows/package-smoke.yml +++ b/.github/workflows/package-smoke.yml @@ -5,6 +5,8 @@ on: paths: - 'package.json' - 'pnpm-lock.yaml' + - 'pnpm-workspace.yaml' + - 'packages/**' - 'tsdown.config.ts' - 'scripts/build-android-helper.sh' - 'scripts/build-xcuitest-apple.sh' @@ -25,6 +27,8 @@ on: paths: - 'package.json' - 'pnpm-lock.yaml' + - 'pnpm-workspace.yaml' + - 'packages/**' - 'tsdown.config.ts' - 'scripts/build-android-helper.sh' - 'scripts/build-xcuitest-apple.sh' diff --git a/AGENTS.md b/AGENTS.md index 064ed253fd..9f02cd039a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -25,7 +25,7 @@ prose in this repo, including this file. ## Principles (expensive lessons — each cost an incident) - Guarantees erode at path boundaries. Any new dispatch path or fast path classifies its cells in - `src/contracts/interaction-guarantees.ts` first; the typechecker forces completeness, you supply + `packages/contracts/src/interaction-guarantees.ts` first; the typechecker forces completeness, you supply honesty. ADR 0011. - A registry claim is not a semantic check: never mark a cell `runner` without reading whether the Swift code implements the guarantee's *definition*, not just a similar-sounding behavior. @@ -54,7 +54,7 @@ declaration site rather than any map someone wrote down: capabilities, MCP/CLI projection, batch policy, timeout policy — ADR 0008) - daemon route ownership + request-policy traits: `src/daemon/daemon-command-registry.ts` (parity-tested) -- interaction dispatch paths × guarantees: `src/contracts/interaction-guarantees.ts` (ADR 0011) +- interaction dispatch paths × guarantees: `packages/contracts/src/interaction-guarantees.ts` (ADR 0011) - command names: `src/command-catalog.ts` — never re-create command string sets in handlers - capabilities: `src/core/capabilities.ts` is the only home for command/device support checks @@ -72,10 +72,10 @@ Invariants here are self-declaring gates. The correct response to a failure is t the new thing — never to suppress or allowlist it. - public CLI flags must be classified: `scripts/integration-progress-model.ts` -- guarantee matrix completeness + honesty: `src/contracts/__tests__/interaction-guarantees.test.ts` +- guarantee matrix completeness + honesty: `src/__tests__/contracts/interaction-guarantees.test.ts` (gap waivers need a `trackingIssue`; the pin list changes only in reviewed diffs) - every enforced/delegated matrix cell needs a contract scenario: - `src/contracts/__tests__/interaction-contract-coverage.test.ts` + `test/integration/interaction-contract/` + `src/__tests__/contracts/interaction-contract-coverage.test.ts` + `test/integration/interaction-contract/` - interaction responses build only through `buildInteractionResponseData` (construction-guard test) - every command declares a timeout policy on its descriptor (timeout-policy completeness test) - TS/Swift rule parity: golden tables under `contracts/fixtures/`, consumed by vitest and the gated diff --git a/CONTEXT.md b/CONTEXT.md index 2b06b63031..e4e6ea5603 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -72,7 +72,7 @@ task touches: center coordinate when a frame is available. This keeps target selection semantic while avoiding `XCUIElement.tap()` post-action element re-resolution after normal navigation. tvOS remains focus/remote-driven. -- Guarantee cell: one (dispatch path, guarantee) entry in `src/contracts/interaction-guarantees.ts`, +- Guarantee cell: one (dispatch path, guarantee) entry in `packages/contracts/src/interaction-guarantees.ts`, classified as runtime/runner/delegated/inapplicable/waived. Completeness is a compile error; honesty is gate-tested. - Owned waiver: a `gap:`-prefixed waived cell carrying a `trackingIssue` URL. Waivers are diffable @@ -227,7 +227,7 @@ task touches: ADR 0011 (interaction guarantee contract) is the interaction-semantics counterpart of ADR 0008's registry thesis: the dispatch-path × guarantee matrix is declared once in -`src/contracts/interaction-guarantees.ts`, completeness is type-enforced, honesty and coverage are +`packages/contracts/src/interaction-guarantees.ts`, completeness is type-enforced, honesty and coverage are gate-enforced, and cross-language rules are pinned by golden parity tables. New dispatch paths and guarantees are whole-matrix decisions, not local edits. @@ -311,7 +311,7 @@ The perfect-shape refactor is complete and merged. Its end-state: theirs. - Type-cycle growth (R9). R4 keeps the VALUE import graph acyclic, so every remaining cycle is created by type-only imports — free at runtime, invisible to R5/R6, and the largest single - obstacle to reading a subsystem in isolation: inside a strongly-connected component of 102 files, + obstacle to reading a subsystem in isolation: inside a strongly-connected component of 76 files, no file has a self-contained slice. `TYPE_CYCLE_BASELINE`, derived from the zone ceilings in `scripts/layering/daemon-modularity.ts`, ratchets it for **growth only**, deliberately unlike R6: reducing it is a real refactor rather than a file move, so a hard equality would turn every unrelated @@ -319,8 +319,8 @@ The perfect-shape refactor is complete and merged. Its end-state: failing. Hubs by in-component dependents: `runtime-contract.ts` (25), `commands/runtime-types.ts` (21), `backend.ts` (15), `commands/runtime-common.ts` (12). - Daemon modularity migration (R10). The same tooling-only declaration records R7 at 30 - writer-owned fields / 42 owner-file claims, R9's 102 members by zone (`commands` 33, - `daemon-server` 30, `platforms` 19, `core` 12, root 5, `contracts` 2, `client` 1), and the four + writer-owned fields / 42 owner-file claims, R9's 76 members by zone (`commands` 33, + `daemon-server` 20, `core` 10, `platforms` 7, root 5, `client` 1), and the four production importers of `daemon/types.ts` from outside daemon. R7 counts and external importers may only shrink; no zone may grow inside R9, and replay/Maestro/replay-test engine files remain outside it. This per-zone migration ratchet is intentionally stricter than R9's ordinary total-growth diff --git a/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift b/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift index 2724d96d67..5612a21e8c 100644 --- a/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift +++ b/apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+ScrollGesture.swift @@ -1,10 +1,11 @@ import XCTest -// Swift port of buildScrollGesturePlan from src/contracts/scroll-gesture.ts. +// Swift port of buildScrollGesturePlan from packages/contracts/src/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/contracts/scroll-gesture.test.ts — +// parity test vectors at the bottom of this file mirror +// packages/contracts/src/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 +65,7 @@ func runnerScrollGesturePlan( #if AGENT_DEVICE_RUNNER_UNIT_TESTS extension RunnerTests { - // Cross-language parity vectors mirroring src/contracts/scroll-gesture.test.ts. Keep these + // Cross-language parity vectors mirroring packages/contracts/src/scroll-gesture.test.ts. Keep these // in sync with the vitest vectors so the two buildScrollGesturePlan implementations cannot drift. func testRunnerScrollGesturePlanMapsRelativeAmount() throws { diff --git a/docs/adr/0011-interaction-guarantee-contract.md b/docs/adr/0011-interaction-guarantee-contract.md index 80c3fbed87..8d8e5baf86 100644 --- a/docs/adr/0011-interaction-guarantee-contract.md +++ b/docs/adr/0011-interaction-guarantee-contract.md @@ -58,7 +58,7 @@ parity only starts once the fixture tables (Layer 2) and contract scenarios unwatched cell becomes impossible; an unproven cell is at least a visible, owned claim. -`src/contracts/interaction-guarantees.ts` declares both axes and requires +`packages/contracts/src/interaction-guarantees.ts` declares both axes and requires every cell to be classified: ```ts diff --git a/docs/adr/0012-interactive-replay.md b/docs/adr/0012-interactive-replay.md index 05f91a601f..3d6452e326 100644 --- a/docs/adr/0012-interactive-replay.md +++ b/docs/adr/0012-interactive-replay.md @@ -20,7 +20,7 @@ Normative summary, one entry per decision. The binding contracts, amendments, an `ref`/`exact` or `ref`/`label-fallback`, `direct-ios`/`not-observed`; coordinate dispatches and executed maestro-fallbacks carry none. Disclosed alternatives are pre-action diagnostics, never issued refs. Enforced as ADR 0011's `resolutionDisclosure` guarantee row - (`src/contracts/interaction-guarantees.ts`). + (`packages/contracts/src/interaction-guarantees.ts`). 3. **Recording writes `target-v1` identity evidence; replay verifies it before acting.** One versioned JSON comment per element-targeting action carries identity (unique id, else role+label, plus a leaf-anchored ancestry prefix), disambiguation signals (`sibling`, @@ -1216,7 +1216,7 @@ zero on the happy path and paying only where reality diverged from the recording a hint beats silently guessing" (`src/cli/parser/command-suggestions.ts:16-17`). Selector resolution took the opposite default, and ADR 0011's own registry records that choice precisely: the `disambiguation` cell for `runtime-selector` is classified `{ kind: 'runtime', via: - '...selectors-resolve.ts#resolveSelectorChain' }` (`src/contracts/interaction-guarantees.ts:176-179`) + '...selectors-resolve.ts#resolveSelectorChain' }` (`packages/contracts/src/interaction-guarantees.ts:176-179`) — proving the heuristic runs consistently across paths, not that the caller is told it ran. That default is not being revisited here; see the rejected hard-reject alternative below for why. - **(f) Issue #1037 / PR #1040 is the direct, partial precedent.** A UNIQUE-but-wrong match (Apple diff --git a/docs/adr/0013-unified-gesture-plans.md b/docs/adr/0013-unified-gesture-plans.md index fe23a00e1f..cce2d70868 100644 --- a/docs/adr/0013-unified-gesture-plans.md +++ b/docs/adr/0013-unified-gesture-plans.md @@ -21,7 +21,7 @@ the Android planned-touch executor. ## Decision -Public gesture inputs normalize once in `src/contracts/gesture-normalization.ts`. This is the +Public gesture inputs normalize once in `packages/contracts/src/gesture-normalization.ts`. This is the explicit public compatibility boundary: canonical semantic intent is produced before entering the runtime. Deprecated arguments that have been removed (timed `swipe`, timed `gesture fling`, `gesture rotate` `velocity`) are rejected with actionable `INVALID_ARGS` messages rather than @@ -30,7 +30,7 @@ that do not appear on public surfaces; Maestro timed swipes use `internal.gestureExecutionProfile: 'endpoint-hold'` to preserve iOS fast-swipe-then-hold behavior while still routing through the canonical `pan` input. -The runtime plans canonical intent in `src/contracts/gesture-plan.ts`. Contact topology is separate +The runtime plans canonical intent in `packages/contracts/src/gesture-plan.ts`. Contact topology is separate from motion: - one contact: pan or fling with a complete pointer trajectory and an explicit execution profile; diff --git a/docs/adr/0018-unified-event-journal.md b/docs/adr/0018-unified-event-journal.md index 34f2233d8c..50e48c99a2 100644 --- a/docs/adr/0018-unified-event-journal.md +++ b/docs/adr/0018-unified-event-journal.md @@ -14,7 +14,7 @@ intentional compatibility change rather than hidden under a byte-compatibility c Normative summary of the proposal; contracts and rationale below. -- One **event catalog** (`src/contracts/events.ts`) is the single declaration site for every +- One **event catalog** (`packages/contracts/src/events.ts`) is the single declaration site for every diagnostic/telemetry event kind: key, subsystem, default level, and derivation traits. Emitting a kind not in the catalog is a compile error; consumers derive kind sets from traits, never from parsing kind names. @@ -100,7 +100,7 @@ genuinely telemetry. Progress is not one of them (decision 3). ### 1. Event catalog: kinds are declared data -`src/contracts/events.ts` exports one `EVENT_CATALOG` — a const object with one entry per event +`packages/contracts/src/events.ts` exports one `EVENT_CATALOG` — a const object with one entry per event kind, keyed by today's diagnostics phase strings (no renames in this ADR): ```ts diff --git a/docs/agents/cli-flags.md b/docs/agents/cli-flags.md index 7a4245fb80..5457900588 100644 --- a/docs/agents/cli-flags.md +++ b/docs/agents/cli-flags.md @@ -3,7 +3,7 @@ A new flag touches only the layers that need to understand it. Stop at the layer where it stops mattering — threading it further is the common failure, not stopping too early. -1. `src/contracts/cli-flags.ts`: add to `CliFlags`; add the definition to the matching +1. `packages/contracts/src/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 @@ -26,7 +26,7 @@ mattering — threading it further is the common failure, not stopping too early 9. `scripts/integration-progress-model.ts`: classify the flag (device-observable vs intentionally-outside). The architecture-progress gate fails CI on unclassified public flags. 10. If the flag changes interaction semantics, revisit the affected cells in - `src/contracts/interaction-guarantees.ts` (scope with `appliesTo` when the flag exists only on + `packages/contracts/src/interaction-guarantees.ts` (scope with `appliesTo` when the flag exists only on some commands). Command-only flags (like `find --first`) that never reach the platform layer usually stop at diff --git a/docs/agents/contract-projection-output-economy-spike.md b/docs/agents/contract-projection-output-economy-spike.md index 89daecfe14..0fd9a4754a 100644 --- a/docs/agents/contract-projection-output-economy-spike.md +++ b/docs/agents/contract-projection-output-economy-spike.md @@ -18,7 +18,7 @@ Selected commands: - `app-switcher` - `tv-remote` -These commands already have closed neutral results in `src/contracts/navigation.ts`, typed +These commands already have closed neutral results in `packages/contracts/src/navigation.ts`, typed `CommandResultMap` entries, executable definitions, Node client methods, and MCP output schemas. They do not overlap the broad-return client methods narrowed under #1183 (since closed). diff --git a/docs/agents/testing.md b/docs/agents/testing.md index ec10868877..9c4e24b5ec 100644 --- a/docs/agents/testing.md +++ b/docs/agents/testing.md @@ -156,7 +156,7 @@ The output tells you which gates to run and which live scenarios claim the behav are loaded through `import()`. - **live scenario owners** — the iOS simulator coverage manifest's owning scenario for each of those commands, when that manifest is in the tree. -- **guarantee-matrix rows** — the ADR 0011 cells (`src/contracts/interaction-guarantees.ts`) whose +- **guarantee-matrix rows** — the ADR 0011 cells (`packages/contracts/src/interaction-guarantees.ts`) whose `via` names the file, i.e. the guarantees your edit is the implementation of. Lists are bounded (`--limit`, default 10) and always disclose what they hid; `--json` is diff --git a/fallow-baselines/health.json b/fallow-baselines/health.json index c7619889c1..489d56421f 100644 --- a/fallow-baselines/health.json +++ b/fallow-baselines/health.json @@ -89,7 +89,7 @@ "count": 1 } }, - "src/contracts/result-serialization.ts": { + "src/utils/result-serialization.ts": { "crap_moderate": { "count": 1 } @@ -597,7 +597,7 @@ "src/utils/timeouts.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/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", @@ -636,4 +636,4 @@ "src/daemon/client/daemon-client-lifecycle.ts:complexity", "src/client/client-companion-tunnel-worker.ts:complexity" ] -} \ No newline at end of file +} diff --git a/package.json b/package.json index bd4664003a..1bbf8c36e8 100644 --- a/package.json +++ b/package.json @@ -145,7 +145,7 @@ "check:unit": "pnpm check:contention-retry && pnpm test:unit && pnpm test:smoke", "check": "pnpm check:tooling && pnpm check:fallow && pnpm check:unit", "prepack": "pnpm check:mcp-metadata && pnpm package:npm", - "typecheck": "tsc -b packages/kernel && tsc -p tsconfig.json && tsc -p examples/sdk/tsconfig.json", + "typecheck": "tsc -b packages/kernel packages/contracts && tsc -p tsconfig.json && tsc -p examples/sdk/tsconfig.json", "test-app:install": "pnpm install --dir examples/test-app", "test-app:start": "pnpm --dir examples/test-app start", "test-app:ios": "pnpm --dir examples/test-app ios", @@ -245,6 +245,7 @@ "yaml": "^2.9.0" }, "devDependencies": { + "@agent-device/contracts": "workspace:*", "@agent-device/kernel": "workspace:*", "@chenglou/freerange": "^0.0.1", "@stryker-mutator/core": "9.6.1", diff --git a/packages/contracts/package.json b/packages/contracts/package.json new file mode 100644 index 0000000000..9032f1ee18 --- /dev/null +++ b/packages/contracts/package.json @@ -0,0 +1,60 @@ +{ + "name": "@agent-device/contracts", + "version": "0.0.0", + "private": true, + "type": "module", + "description": "Shared agent-device command, snapshot, provider, and platform vocabulary. Internal workspace package bundled into the published agent-device artifact.", + "dependencies": { + "@agent-device/kernel": "workspace:*" + }, + "exports": { + "./client": { + "types": "./src/facades/client.ts", + "default": "./src/facades/client.ts" + }, + "./command": { + "types": "./src/facades/command.ts", + "default": "./src/facades/command.ts" + }, + "./device": { + "types": "./src/facades/device.ts", + "default": "./src/facades/device.ts" + }, + "./interaction": { + "types": "./src/facades/interaction.ts", + "default": "./src/facades/interaction.ts" + }, + "./capture": { + "types": "./src/facades/capture.ts", + "default": "./src/facades/capture.ts" + }, + "./platform": { + "types": "./src/facades/platform.ts", + "default": "./src/facades/platform.ts" + }, + "./settings": { + "types": "./src/settings.ts", + "default": "./src/settings.ts" + }, + "./session": { + "types": "./src/facades/session.ts", + "default": "./src/facades/session.ts" + }, + "./recording": { + "types": "./src/facades/recording.ts", + "default": "./src/facades/recording.ts" + }, + "./observability": { + "types": "./src/facades/observability.ts", + "default": "./src/facades/observability.ts" + }, + "./remote": { + "types": "./src/facades/remote.ts", + "default": "./src/facades/remote.ts" + }, + "./replay": { + "types": "./src/facades/replay.ts", + "default": "./src/facades/replay.ts" + } + } +} diff --git a/src/contracts/alert-contract.ts b/packages/contracts/src/alert-contract.ts similarity index 100% rename from src/contracts/alert-contract.ts rename to packages/contracts/src/alert-contract.ts diff --git a/src/contracts/android-input-ownership.ts b/packages/contracts/src/android-input-ownership.ts similarity index 100% rename from src/contracts/android-input-ownership.ts rename to packages/contracts/src/android-input-ownership.ts diff --git a/src/contracts/android-system-chrome.ts b/packages/contracts/src/android-system-chrome.ts similarity index 100% rename from src/contracts/android-system-chrome.ts rename to packages/contracts/src/android-system-chrome.ts diff --git a/src/contracts/app-events.ts b/packages/contracts/src/app-events.ts similarity index 100% rename from src/contracts/app-events.ts rename to packages/contracts/src/app-events.ts diff --git a/src/contracts/app-inventory.ts b/packages/contracts/src/app-inventory.ts similarity index 100% rename from src/contracts/app-inventory.ts rename to packages/contracts/src/app-inventory.ts diff --git a/src/contracts/app-state.ts b/packages/contracts/src/app-state.ts similarity index 100% rename from src/contracts/app-state.ts rename to packages/contracts/src/app-state.ts diff --git a/src/contracts/apple-multitouch-support.ts b/packages/contracts/src/apple-multitouch-support.ts similarity index 100% rename from src/contracts/apple-multitouch-support.ts rename to packages/contracts/src/apple-multitouch-support.ts diff --git a/src/contracts/audio-probe-result.ts b/packages/contracts/src/audio-probe-result.ts similarity index 100% rename from src/contracts/audio-probe-result.ts rename to packages/contracts/src/audio-probe-result.ts diff --git a/src/contracts/audio-probe-support.ts b/packages/contracts/src/audio-probe-support.ts similarity index 100% rename from src/contracts/audio-probe-support.ts rename to packages/contracts/src/audio-probe-support.ts diff --git a/src/contracts/back-mode.ts b/packages/contracts/src/back-mode.ts similarity index 100% rename from src/contracts/back-mode.ts rename to packages/contracts/src/back-mode.ts diff --git a/src/contracts/batch-contract.ts b/packages/contracts/src/batch-contract.ts similarity index 96% rename from src/contracts/batch-contract.ts rename to packages/contracts/src/batch-contract.ts index 9466aff176..5653a1fd6c 100644 --- a/src/contracts/batch-contract.ts +++ b/packages/contracts/src/batch-contract.ts @@ -1,6 +1,6 @@ import { daemonRuntimeSchema, type SessionRuntimeHints } from '@agent-device/kernel/contracts'; import { AppError } from '@agent-device/kernel/errors'; -import { isRecord } from '../utils/parsing.ts'; +import { isRecord } from './json.ts'; export const DEFAULT_BATCH_MAX_STEPS = 100; diff --git a/src/contracts/batch-step.ts b/packages/contracts/src/batch-step.ts similarity index 100% rename from src/contracts/batch-step.ts rename to packages/contracts/src/batch-step.ts diff --git a/src/contracts/cli-flags.ts b/packages/contracts/src/cli-flags.ts similarity index 100% rename from src/contracts/cli-flags.ts rename to packages/contracts/src/cli-flags.ts diff --git a/src/contracts/click-button.ts b/packages/contracts/src/click-button.ts similarity index 100% rename from src/contracts/click-button.ts rename to packages/contracts/src/click-button.ts diff --git a/src/contracts/client-app.ts b/packages/contracts/src/client-app.ts similarity index 100% rename from src/contracts/client-app.ts rename to packages/contracts/src/client-app.ts diff --git a/src/contracts/client-capture.ts b/packages/contracts/src/client-capture.ts similarity index 97% rename from src/contracts/client-capture.ts rename to packages/contracts/src/client-capture.ts index e7de8dc804..848ac098ad 100644 --- a/src/contracts/client-capture.ts +++ b/packages/contracts/src/client-capture.ts @@ -8,7 +8,7 @@ import type { SnapshotUnchanged, SnapshotVisibility, } from '@agent-device/kernel/snapshot'; -import type { ScreenshotResultData } from '../utils/screenshot-result.ts'; +import type { ScreenshotResultData } from './snapshot-types.ts'; import type { AgentDeviceIdentifiers, AgentDeviceRequestOverrides, diff --git a/src/contracts/client-connection.ts b/packages/contracts/src/client-connection.ts similarity index 100% rename from src/contracts/client-connection.ts rename to packages/contracts/src/client-connection.ts diff --git a/src/contracts/client-device-view.ts b/packages/contracts/src/client-device-view.ts similarity index 100% rename from src/contracts/client-device-view.ts rename to packages/contracts/src/client-device-view.ts diff --git a/src/contracts/client-gesture.ts b/packages/contracts/src/client-gesture.ts similarity index 100% rename from src/contracts/client-gesture.ts rename to packages/contracts/src/client-gesture.ts diff --git a/src/contracts/client-lease.ts b/packages/contracts/src/client-lease.ts similarity index 100% rename from src/contracts/client-lease.ts rename to packages/contracts/src/client-lease.ts diff --git a/src/contracts/client-observability.ts b/packages/contracts/src/client-observability.ts similarity index 100% rename from src/contracts/client-observability.ts rename to packages/contracts/src/client-observability.ts diff --git a/src/contracts/client-replay.ts b/packages/contracts/src/client-replay.ts similarity index 100% rename from src/contracts/client-replay.ts rename to packages/contracts/src/client-replay.ts diff --git a/src/contracts/client-request.ts b/packages/contracts/src/client-request.ts similarity index 100% rename from src/contracts/client-request.ts rename to packages/contracts/src/client-request.ts diff --git a/src/contracts/client-selector-read.ts b/packages/contracts/src/client-selector-read.ts similarity index 97% rename from src/contracts/client-selector-read.ts rename to packages/contracts/src/client-selector-read.ts index 8af0cbb03b..9dabc6a0a3 100644 --- a/src/contracts/client-selector-read.ts +++ b/packages/contracts/src/client-selector-read.ts @@ -1,6 +1,6 @@ // The public API vocabulary for the read commands that resolve a selector (get / is / find). -import type { FindLocator } from '../selectors/find.ts'; +import type { FindLocator } from './snapshot-types.ts'; import type { FindSnapshotCommandOptions, SelectorSnapshotCommandOptions, diff --git a/src/contracts/client-session.ts b/packages/contracts/src/client-session.ts similarity index 100% rename from src/contracts/client-session.ts rename to packages/contracts/src/client-session.ts diff --git a/src/contracts/client-settings.ts b/packages/contracts/src/client-settings.ts similarity index 100% rename from src/contracts/client-settings.ts rename to packages/contracts/src/client-settings.ts diff --git a/src/contracts/client-system.ts b/packages/contracts/src/client-system.ts similarity index 100% rename from src/contracts/client-system.ts rename to packages/contracts/src/client-system.ts diff --git a/src/contracts/client-target.ts b/packages/contracts/src/client-target.ts similarity index 100% rename from src/contracts/client-target.ts rename to packages/contracts/src/client-target.ts diff --git a/src/contracts/clipboard.ts b/packages/contracts/src/clipboard.ts similarity index 100% rename from src/contracts/clipboard.ts rename to packages/contracts/src/clipboard.ts diff --git a/src/contracts/cloud-artifacts.ts b/packages/contracts/src/cloud-artifacts.ts similarity index 100% rename from src/contracts/cloud-artifacts.ts rename to packages/contracts/src/cloud-artifacts.ts diff --git a/src/contracts/command-flags.ts b/packages/contracts/src/command-flags.ts similarity index 100% rename from src/contracts/command-flags.ts rename to packages/contracts/src/command-flags.ts diff --git a/src/contracts/companion-tunnel-scope.ts b/packages/contracts/src/companion-tunnel-scope.ts similarity index 100% rename from src/contracts/companion-tunnel-scope.ts rename to packages/contracts/src/companion-tunnel-scope.ts diff --git a/src/contracts/debug-symbols.ts b/packages/contracts/src/debug-symbols.ts similarity index 100% rename from src/contracts/debug-symbols.ts rename to packages/contracts/src/debug-symbols.ts diff --git a/src/contracts/device-inventory.test.ts b/packages/contracts/src/device-inventory.test.ts similarity index 100% rename from src/contracts/device-inventory.test.ts rename to packages/contracts/src/device-inventory.test.ts diff --git a/src/contracts/device-inventory.ts b/packages/contracts/src/device-inventory.ts similarity index 100% rename from src/contracts/device-inventory.ts rename to packages/contracts/src/device-inventory.ts diff --git a/src/contracts/device-provider.ts b/packages/contracts/src/device-provider.ts similarity index 91% rename from src/contracts/device-provider.ts rename to packages/contracts/src/device-provider.ts index 51894623ec..8d9f4bd6cb 100644 --- a/src/contracts/device-provider.ts +++ b/packages/contracts/src/device-provider.ts @@ -6,7 +6,7 @@ // inside the daemon module that happens to consume them first. import type { DeviceInfo } from '@agent-device/kernel/device'; -import type { DaemonRequest, LeaseBackend } from '@agent-device/kernel/contracts'; +import type { LeaseBackend } from '@agent-device/kernel/contracts'; import type { DeviceInventoryRequest } from './device-inventory.ts'; export type DeviceLease = { @@ -23,7 +23,8 @@ export type DeviceLease = { }; export type LeaseLifecycleContext = { - req: DaemonRequest; + flags?: Readonly>; + cwd?: string; }; export type LeaseLifecycleProvider = { diff --git a/src/contracts/device-rotation.test.ts b/packages/contracts/src/device-rotation.test.ts similarity index 100% rename from src/contracts/device-rotation.test.ts rename to packages/contracts/src/device-rotation.test.ts diff --git a/src/contracts/device-rotation.ts b/packages/contracts/src/device-rotation.ts similarity index 100% rename from src/contracts/device-rotation.ts rename to packages/contracts/src/device-rotation.ts diff --git a/src/contracts/device.ts b/packages/contracts/src/device.ts similarity index 100% rename from src/contracts/device.ts rename to packages/contracts/src/device.ts diff --git a/packages/contracts/src/diff.ts b/packages/contracts/src/diff.ts new file mode 100644 index 0000000000..bd437b9a8a --- /dev/null +++ b/packages/contracts/src/diff.ts @@ -0,0 +1,22 @@ +export type SnapshotDiffLine = { + kind: 'added' | 'removed' | 'unchanged'; + text: string; + /** + * Plain ref body (`e12`) of the current-tree node behind an added line. + * Only populated with `withRefs`; removed and unchanged lines never carry it. + */ + ref?: string; +}; +export type SnapshotDiffSummary = { + additions: number; + removals: number; + unchanged: number; +}; + +export type DiffSnapshotCommandResult = { + mode: 'snapshot'; + baselineInitialized: boolean; + summary: SnapshotDiffSummary; + lines: SnapshotDiffLine[]; + warnings?: string[]; +}; diff --git a/src/contracts/dispatched-command.ts b/packages/contracts/src/dispatched-command.ts similarity index 100% rename from src/contracts/dispatched-command.ts rename to packages/contracts/src/dispatched-command.ts diff --git a/src/contracts/doctor.ts b/packages/contracts/src/doctor.ts similarity index 100% rename from src/contracts/doctor.ts rename to packages/contracts/src/doctor.ts diff --git a/packages/contracts/src/facades/capture.ts b/packages/contracts/src/facades/capture.ts new file mode 100644 index 0000000000..7cf30e8e31 --- /dev/null +++ b/packages/contracts/src/facades/capture.ts @@ -0,0 +1,6 @@ +export * from '../diff.ts'; +export * from '../screenshot.ts'; +export * from '../snapshot-capture-annotations.ts'; +export * from '../snapshot-diagnostics.ts'; +export * from '../snapshot-types.ts'; +export * from '../viewport.ts'; diff --git a/packages/contracts/src/facades/client.ts b/packages/contracts/src/facades/client.ts new file mode 100644 index 0000000000..332625a750 --- /dev/null +++ b/packages/contracts/src/facades/client.ts @@ -0,0 +1,15 @@ +export * from '../client-app.ts'; +export * from '../client-capture.ts'; +export * from '../client-connection.ts'; +export * from '../client-device-view.ts'; +export * from '../client-gesture.ts'; +export * from '../client-lease.ts'; +export * from '../client-observability.ts'; +export * from '../client-replay.ts'; +export * from '../client-request.ts'; +export * from '../client-selector-read.ts'; +export * from '../client-session.ts'; +export * from '../client-settings.ts'; +export * from '../client-system.ts'; +export * from '../client-target.ts'; +export * from '../json.ts'; diff --git a/packages/contracts/src/facades/command.ts b/packages/contracts/src/facades/command.ts new file mode 100644 index 0000000000..5404c2a2b1 --- /dev/null +++ b/packages/contracts/src/facades/command.ts @@ -0,0 +1,9 @@ +export * from '../batch-contract.ts'; +export * from '../batch-step.ts'; +export * from '../cli-flags.ts'; +export * from '../command-flags.ts'; +export * from '../dispatched-command.ts'; +export * from '../input-validation.ts'; +export * from '../open-target.ts'; +export * from '../prepare.ts'; +export * from '../push.ts'; diff --git a/packages/contracts/src/facades/device.ts b/packages/contracts/src/facades/device.ts new file mode 100644 index 0000000000..f0d0299012 --- /dev/null +++ b/packages/contracts/src/facades/device.ts @@ -0,0 +1,9 @@ +export * from '../app-events.ts'; +export * from '../app-inventory.ts'; +export * from '../app-state.ts'; +export * from '../device-inventory.ts'; +export * from '../device-provider.ts'; +export * from '../device-rotation.ts'; +export * from '../device.ts'; +export * from '../provider-device-runtime.ts'; +export * from '../target-shutdown-contract.ts'; diff --git a/packages/contracts/src/facades/interaction.ts b/packages/contracts/src/facades/interaction.ts new file mode 100644 index 0000000000..f5a33c3aca --- /dev/null +++ b/packages/contracts/src/facades/interaction.ts @@ -0,0 +1,17 @@ +export * from '../alert-contract.ts'; +export * from '../back-mode.ts'; +export * from '../click-button.ts'; +export * from '../clipboard.ts'; +export * from '../gesture-input.ts'; +export * from '../gesture-normalization.ts'; +export * from '../gesture-plan.ts'; +export * from '../gesture-plan-types.ts'; +export * from '../interaction.ts'; +export * from '../interaction-guarantees.ts'; +export * from '../interactor-types.ts'; +export * from '../keyboard.ts'; +export * from '../navigation.ts'; +export * from '../scroll-command.ts'; +export * from '../scroll-gesture.ts'; +export * from '../tv-remote.ts'; +export * from '../wait.ts'; diff --git a/packages/contracts/src/facades/observability.ts b/packages/contracts/src/facades/observability.ts new file mode 100644 index 0000000000..fc3f6a2f43 --- /dev/null +++ b/packages/contracts/src/facades/observability.ts @@ -0,0 +1,7 @@ +export * from '../cloud-artifacts.ts'; +export * from '../debug-symbols.ts'; +export * from '../doctor.ts'; +export * from '../launch-console.ts'; +export * from '../logs.ts'; +export * from '../network-log.ts'; +export * from '../perf.ts'; diff --git a/packages/contracts/src/facades/platform.ts b/packages/contracts/src/facades/platform.ts new file mode 100644 index 0000000000..fc22f780f5 --- /dev/null +++ b/packages/contracts/src/facades/platform.ts @@ -0,0 +1,8 @@ +export * from '../android-input-ownership.ts'; +export * from '../android-system-chrome.ts'; +export * from '../apple-multitouch-support.ts'; +export * from '../audio-probe-result.ts'; +export * from '../audio-probe-support.ts'; +export * from '../platform-plugin.ts'; +export * from '../platform-providers.ts'; +export * from '../runner-lease-context.ts'; diff --git a/packages/contracts/src/facades/recording.ts b/packages/contracts/src/facades/recording.ts new file mode 100644 index 0000000000..39aeac1eae --- /dev/null +++ b/packages/contracts/src/facades/recording.ts @@ -0,0 +1,3 @@ +export * from '../recording.ts'; +export * from '../recording-export-quality.ts'; +export * from '../recording-scope.ts'; diff --git a/packages/contracts/src/facades/remote.ts b/packages/contracts/src/facades/remote.ts new file mode 100644 index 0000000000..9b1a0d638a --- /dev/null +++ b/packages/contracts/src/facades/remote.ts @@ -0,0 +1,3 @@ +export * from '../companion-tunnel-scope.ts'; +export * from '../metro.ts'; +export * from '../remote-config-fields.ts'; diff --git a/packages/contracts/src/facades/replay.ts b/packages/contracts/src/facades/replay.ts new file mode 100644 index 0000000000..ccef875760 --- /dev/null +++ b/packages/contracts/src/facades/replay.ts @@ -0,0 +1,3 @@ +export * from '../ref-frame-effect.ts'; +export * from '../replay.ts'; +export * from '../target-annotation.ts'; diff --git a/packages/contracts/src/facades/session.ts b/packages/contracts/src/facades/session.ts new file mode 100644 index 0000000000..d10bb8d713 --- /dev/null +++ b/packages/contracts/src/facades/session.ts @@ -0,0 +1,2 @@ +export * from '../session-action.ts'; +export * from '../session-surface.ts'; diff --git a/src/contracts/gesture-input.test.ts b/packages/contracts/src/gesture-input.test.ts similarity index 100% rename from src/contracts/gesture-input.test.ts rename to packages/contracts/src/gesture-input.test.ts diff --git a/src/contracts/gesture-input.ts b/packages/contracts/src/gesture-input.ts similarity index 100% rename from src/contracts/gesture-input.ts rename to packages/contracts/src/gesture-input.ts diff --git a/src/contracts/gesture-normalization.test.ts b/packages/contracts/src/gesture-normalization.test.ts similarity index 100% rename from src/contracts/gesture-normalization.test.ts rename to packages/contracts/src/gesture-normalization.test.ts diff --git a/src/contracts/gesture-normalization.ts b/packages/contracts/src/gesture-normalization.ts similarity index 100% rename from src/contracts/gesture-normalization.ts rename to packages/contracts/src/gesture-normalization.ts diff --git a/src/contracts/gesture-plan-types.ts b/packages/contracts/src/gesture-plan-types.ts similarity index 100% rename from src/contracts/gesture-plan-types.ts rename to packages/contracts/src/gesture-plan-types.ts diff --git a/src/contracts/gesture-plan.ts b/packages/contracts/src/gesture-plan.ts similarity index 100% rename from src/contracts/gesture-plan.ts rename to packages/contracts/src/gesture-plan.ts diff --git a/src/contracts/input-validation.ts b/packages/contracts/src/input-validation.ts similarity index 100% rename from src/contracts/input-validation.ts rename to packages/contracts/src/input-validation.ts diff --git a/src/contracts/interaction-guarantees.ts b/packages/contracts/src/interaction-guarantees.ts similarity index 100% rename from src/contracts/interaction-guarantees.ts rename to packages/contracts/src/interaction-guarantees.ts diff --git a/src/contracts/interaction.ts b/packages/contracts/src/interaction.ts similarity index 100% rename from src/contracts/interaction.ts rename to packages/contracts/src/interaction.ts diff --git a/src/contracts/interactor-types.ts b/packages/contracts/src/interactor-types.ts similarity index 97% rename from src/contracts/interactor-types.ts rename to packages/contracts/src/interactor-types.ts index 4de12184c0..6b9707ff50 100644 --- a/src/contracts/interactor-types.ts +++ b/packages/contracts/src/interactor-types.ts @@ -3,9 +3,9 @@ import type { DeviceRotation } from './device-rotation.ts'; import type { ScrollDirection } from './scroll-gesture.ts'; import type { TvRemoteButton } from './tv-remote.ts'; import type { GesturePlan } from './gesture-plan-types.ts'; -import type { SettingOptions } from '../platforms/permission-utils.ts'; +import type { SettingOptions } from './settings.ts'; import type { SessionSurface } from './session-surface.ts'; -import type { BackendSnapshotResult } from '../backend.ts'; +import type { BackendSnapshotResult } from './snapshot-types.ts'; import type { RunnerLogicalLeaseContext } from './runner-lease-context.ts'; import type { RawSnapshotNode, diff --git a/src/contracts/json.ts b/packages/contracts/src/json.ts similarity index 53% rename from src/contracts/json.ts rename to packages/contracts/src/json.ts index 210e9d5917..00740a156a 100644 --- a/src/contracts/json.ts +++ b/packages/contracts/src/json.ts @@ -1,3 +1,7 @@ export type JsonPrimitive = string | number | boolean | null; export type JsonValue = JsonPrimitive | JsonObject | JsonValue[]; export type JsonObject = { [key: string]: JsonValue }; + +export function isRecord(value: unknown): value is Record { + return typeof value === 'object' && value !== null && !Array.isArray(value); +} diff --git a/src/contracts/keyboard.ts b/packages/contracts/src/keyboard.ts similarity index 100% rename from src/contracts/keyboard.ts rename to packages/contracts/src/keyboard.ts diff --git a/src/contracts/launch-console.ts b/packages/contracts/src/launch-console.ts similarity index 100% rename from src/contracts/launch-console.ts rename to packages/contracts/src/launch-console.ts diff --git a/src/contracts/logs.ts b/packages/contracts/src/logs.ts similarity index 100% rename from src/contracts/logs.ts rename to packages/contracts/src/logs.ts diff --git a/src/contracts/metro.ts b/packages/contracts/src/metro.ts similarity index 100% rename from src/contracts/metro.ts rename to packages/contracts/src/metro.ts diff --git a/src/contracts/navigation.ts b/packages/contracts/src/navigation.ts similarity index 100% rename from src/contracts/navigation.ts rename to packages/contracts/src/navigation.ts diff --git a/src/contracts/network-log.ts b/packages/contracts/src/network-log.ts similarity index 100% rename from src/contracts/network-log.ts rename to packages/contracts/src/network-log.ts diff --git a/src/contracts/open-target.test.ts b/packages/contracts/src/open-target.test.ts similarity index 100% rename from src/contracts/open-target.test.ts rename to packages/contracts/src/open-target.test.ts diff --git a/src/contracts/open-target.ts b/packages/contracts/src/open-target.ts similarity index 100% rename from src/contracts/open-target.ts rename to packages/contracts/src/open-target.ts diff --git a/src/contracts/perf.ts b/packages/contracts/src/perf.ts similarity index 97% rename from src/contracts/perf.ts rename to packages/contracts/src/perf.ts index 9b19773d0f..6ee718c9cb 100644 --- a/src/contracts/perf.ts +++ b/packages/contracts/src/perf.ts @@ -1,4 +1,4 @@ -import { defineStringEnum } from '../utils/string-enum.ts'; +import { defineStringEnum } from './string-enum.ts'; export const PERF_AREA_VALUES = ['metrics', 'frames', 'memory', 'cpu', 'trace'] as const; export const PERF_ACTION_VALUES = ['sample', 'snapshot', 'start', 'stop', 'report'] as const; diff --git a/src/contracts/platform-plugin.ts b/packages/contracts/src/platform-plugin.ts similarity index 82% rename from src/contracts/platform-plugin.ts rename to packages/contracts/src/platform-plugin.ts index 981f371aee..6e5d3c1e15 100644 --- a/src/contracts/platform-plugin.ts +++ b/packages/contracts/src/platform-plugin.ts @@ -1,4 +1,3 @@ -import { AppError } from '@agent-device/kernel/errors'; import type { DeviceInfo, Platform, PlatformSelector } from '@agent-device/kernel/device'; import type { LogBackend } from './logs.ts'; import type { RecordingBackendTag } from './recording.ts'; @@ -64,8 +63,8 @@ export type PlatformPlugin = { * command-descriptor facet (ADR-0009: relocate, never * flatten). They are keyed by command name and owned by the family that owns the * device's platform; `isCommandSupportedOnDevice` / `unsupportedHintForDevice` - * consult the map for `getPlugin(device.platform)`, so a family with no entry for a - * command (the key is absent) admits it unchanged. Only the Apple family carries + * consult the root platform-plugin registry, so a family with no entry for a command + * (the key is absent) admits it unchanged. Only the Apple family carries * entries today — every relocated closure is a no-op (returns `true` / `undefined`) * on non-Apple devices, proven byte-for-byte by the parity gate before the * command-facet closures were deleted. @@ -147,48 +146,3 @@ export type PlatformPlugin = { readonly platformGatedResolvers: readonly PlatformGatedProviderResolverKey[]; }; }; - -// The single registry instance: leaf platform -> owning plugin. A family plugin -// is registered once per leaf platform it owns, so `getPlugin('apple')` and -// `getPlugin('apple')` resolve to the SAME Apple plugin object. -const registry = new Map(); - -/** - * Registers `plugin` for each leaf platform it owns. Throws on a duplicate - * registration so a double-owned platform is a hard error, not a silent - * last-writer-wins. - */ -export function registerPlatformPlugin(plugin: PlatformPlugin): void { - for (const platform of plugin.platforms) { - if (registry.has(platform)) { - throw new Error(`PlatformPlugin already registered for platform "${platform}"`); - } - registry.set(platform, plugin); - } -} - -/** - * Returns the plugin for `platform`, throwing the SAME `UNSUPPORTED_PLATFORM` - * AppError (identical code + message) that the hand-authored `getInteractor` - * switch default threw, so routing through it is byte-identical. - */ -export function getPlugin(platform: Platform): PlatformPlugin { - const plugin = registry.get(platform); - if (!plugin) { - throw new AppError('UNSUPPORTED_PLATFORM', `Unsupported platform: ${platform}`); - } - return plugin; -} - -/** Non-throwing lookup, for call-sites that branch on plugin presence. */ -export function tryGetPlugin(platform: Platform): PlatformPlugin | undefined { - return registry.get(platform); -} - -/** - * @internal The leaf platforms that currently carry a plugin, in registration order. - * Exposed for parity tests. - */ -export function registeredPlatforms(): Platform[] { - return [...registry.keys()]; -} diff --git a/src/contracts/platform-providers.ts b/packages/contracts/src/platform-providers.ts similarity index 100% rename from src/contracts/platform-providers.ts rename to packages/contracts/src/platform-providers.ts diff --git a/src/contracts/prepare.ts b/packages/contracts/src/prepare.ts similarity index 100% rename from src/contracts/prepare.ts rename to packages/contracts/src/prepare.ts diff --git a/packages/contracts/src/provider-device-runtime.ts b/packages/contracts/src/provider-device-runtime.ts new file mode 100644 index 0000000000..755110272c --- /dev/null +++ b/packages/contracts/src/provider-device-runtime.ts @@ -0,0 +1,57 @@ +import type { DeviceInfo } from '@agent-device/kernel/device'; +import type { CloudArtifactProvider } from './cloud-artifacts.ts'; +import type { + DeviceInventoryProvider, + DeviceLease, + LeaseLifecycleProvider, +} from './device-provider.ts'; +import type { Interactor, RunnerContext } from './interactor-types.ts'; + +export type ProviderDeviceInstallResult = { + bundleId?: string; + packageName?: string; + appName?: string; + launchTarget?: string; +}; + +export type ProviderDeviceInstallOptions = { + relaunch?: boolean; + appIdentifierHint?: string; + packageNameHint?: string; +}; + +export type ProviderPortReverseOptions = { + leaseId: string; + provider?: string; + devicePort: number; + hostPort: number; + name: string; +}; + +export type ProviderExpiredLeaseRecovery = (lease: DeviceLease) => Promise; + +/** Provider adapter contract; root owns active-runtime and request composition. */ +export type ProviderDeviceRuntime = { + provider: string; + leaseLifecycle: LeaseLifecycleProvider; + recoverExpiredLease?: ProviderExpiredLeaseRecovery; + cloudArtifacts?: CloudArtifactProvider; + deviceInventoryProvider: DeviceInventoryProvider; + ownsDevice(device: DeviceInfo): boolean; + getInteractor(device: DeviceInfo, runnerContext?: RunnerContext): Interactor | undefined; + installApp?( + device: DeviceInfo, + app: string, + appPath: string, + options?: ProviderDeviceInstallOptions, + ): Promise; + installInstallablePath?( + device: DeviceInfo, + installablePath: string, + options?: ProviderDeviceInstallOptions, + ): Promise; + configurePortReverse?( + options: ProviderPortReverseOptions, + ): Promise | undefined>; + shutdown(): Promise; +}; diff --git a/src/contracts/push.ts b/packages/contracts/src/push.ts similarity index 100% rename from src/contracts/push.ts rename to packages/contracts/src/push.ts diff --git a/src/contracts/__tests__/recording-export-quality.test.ts b/packages/contracts/src/recording-export-quality.test.ts similarity index 91% rename from src/contracts/__tests__/recording-export-quality.test.ts rename to packages/contracts/src/recording-export-quality.test.ts index d3e254d6ce..1368a1c99e 100644 --- a/src/contracts/__tests__/recording-export-quality.test.ts +++ b/packages/contracts/src/recording-export-quality.test.ts @@ -4,9 +4,9 @@ import { RECORDING_EXPORT_QUALITIES, isRecordingExportQuality, recordingQualityInputToExportQuality, -} from '../../contracts/recording-export-quality.ts'; +} from './facades/recording.ts'; -describe('recording export quality', () => { +describe('recording facade export quality', () => { test('defaults to the fast medium export to preserve existing behavior', () => { expect(DEFAULT_RECORDING_EXPORT_QUALITY).toBe('medium'); expect(RECORDING_EXPORT_QUALITIES).toEqual(['medium', 'high']); diff --git a/src/contracts/recording-export-quality.ts b/packages/contracts/src/recording-export-quality.ts similarity index 100% rename from src/contracts/recording-export-quality.ts rename to packages/contracts/src/recording-export-quality.ts diff --git a/src/contracts/recording-scope.ts b/packages/contracts/src/recording-scope.ts similarity index 100% rename from src/contracts/recording-scope.ts rename to packages/contracts/src/recording-scope.ts diff --git a/src/contracts/recording.ts b/packages/contracts/src/recording.ts similarity index 100% rename from src/contracts/recording.ts rename to packages/contracts/src/recording.ts diff --git a/src/contracts/ref-frame-effect.ts b/packages/contracts/src/ref-frame-effect.ts similarity index 100% rename from src/contracts/ref-frame-effect.ts rename to packages/contracts/src/ref-frame-effect.ts diff --git a/src/contracts/remote-config-fields.ts b/packages/contracts/src/remote-config-fields.ts similarity index 100% rename from src/contracts/remote-config-fields.ts rename to packages/contracts/src/remote-config-fields.ts diff --git a/src/contracts/replay.ts b/packages/contracts/src/replay.ts similarity index 100% rename from src/contracts/replay.ts rename to packages/contracts/src/replay.ts diff --git a/src/contracts/runner-lease-context.ts b/packages/contracts/src/runner-lease-context.ts similarity index 100% rename from src/contracts/runner-lease-context.ts rename to packages/contracts/src/runner-lease-context.ts diff --git a/src/contracts/screenshot.ts b/packages/contracts/src/screenshot.ts similarity index 100% rename from src/contracts/screenshot.ts rename to packages/contracts/src/screenshot.ts diff --git a/src/contracts/scroll-command.ts b/packages/contracts/src/scroll-command.ts similarity index 100% rename from src/contracts/scroll-command.ts rename to packages/contracts/src/scroll-command.ts diff --git a/src/contracts/scroll-gesture.test.ts b/packages/contracts/src/scroll-gesture.test.ts similarity index 100% rename from src/contracts/scroll-gesture.test.ts rename to packages/contracts/src/scroll-gesture.test.ts diff --git a/src/contracts/scroll-gesture.ts b/packages/contracts/src/scroll-gesture.ts similarity index 99% rename from src/contracts/scroll-gesture.ts rename to packages/contracts/src/scroll-gesture.ts index b774f135b8..35ef996bc4 100644 --- a/src/contracts/scroll-gesture.ts +++ b/packages/contracts/src/scroll-gesture.ts @@ -1,5 +1,5 @@ import { AppError } from '@agent-device/kernel/errors'; -import { defineStringEnum } from '../utils/string-enum.ts'; +import { defineStringEnum } from './string-enum.ts'; import type { Rect, SnapshotNode } from '@agent-device/kernel/snapshot'; // What a caller may ASK for, as opposed to `ScrollDirection` (what the gesture resolves to): diff --git a/src/contracts/session-action.ts b/packages/contracts/src/session-action.ts similarity index 100% rename from src/contracts/session-action.ts rename to packages/contracts/src/session-action.ts diff --git a/src/contracts/session-surface.ts b/packages/contracts/src/session-surface.ts similarity index 89% rename from src/contracts/session-surface.ts rename to packages/contracts/src/session-surface.ts index b6efd61e5a..d5728edb62 100644 --- a/src/contracts/session-surface.ts +++ b/packages/contracts/src/session-surface.ts @@ -1,4 +1,4 @@ -import { defineStringEnum } from '../utils/string-enum.ts'; +import { defineStringEnum } from './string-enum.ts'; export const SESSION_SURFACES = ['app', 'frontmost-app', 'desktop', 'menubar'] as const; export type SessionSurface = (typeof SESSION_SURFACES)[number]; diff --git a/src/contracts/settings-contract.ts b/packages/contracts/src/settings.ts similarity index 55% rename from src/contracts/settings-contract.ts rename to packages/contracts/src/settings.ts index f6ec74a0bc..5f54ac9823 100644 --- a/src/contracts/settings-contract.ts +++ b/packages/contracts/src/settings.ts @@ -1,3 +1,42 @@ +import { AppError } from '@agent-device/kernel/errors'; + +export type PermissionAction = 'grant' | 'deny' | 'reset'; +export type PermissionTarget = + | 'camera' + | 'microphone' + | 'photos' + | 'contacts' + | 'contacts-limited' + | 'notifications' + | 'calendar' + | 'location' + | 'location-always' + | 'media-library' + | 'motion' + | 'reminders' + | 'siri'; +export type SettingOptions = { + permissionTarget?: string; + permissionMode?: string; + latitude?: number; + longitude?: number; +}; +const PERMISSION_TARGETS: readonly PermissionTarget[] = [ + 'camera', + 'microphone', + 'photos', + 'contacts', + 'contacts-limited', + 'notifications', + 'calendar', + 'location', + 'location-always', + 'media-library', + 'motion', + 'reminders', + 'siri', +]; + const SETTINGS_WIFI_USAGE = ' '; const SETTINGS_LOCATION_SET_USAGE = 'location set '; const SETTINGS_ANIMATIONS_USAGE = 'animations '; @@ -35,3 +74,36 @@ export function isMacOsSettingSupported(setting: string): boolean { export function getUnsupportedMacOsSettingMessage(setting: string): string { return `Unsupported macOS setting: ${setting}. ${SETTINGS_MACOS_SUPPORTED_MESSAGE}`; } + +export function parsePermissionAction(action: string): PermissionAction { + const normalized = action.trim().toLowerCase(); + if (normalized === 'grant') return 'grant'; + if (normalized === 'deny') return 'deny'; + if (normalized === 'reset') return 'reset'; + throw new AppError('INVALID_ARGS', `Invalid permission action: ${action}. Use grant|deny|reset.`); +} + +export function parsePermissionTarget(value: string | undefined): PermissionTarget { + const normalized = value?.trim().toLowerCase(); + if ( + normalized === 'camera' || + normalized === 'microphone' || + normalized === 'photos' || + normalized === 'contacts' || + normalized === 'contacts-limited' || + normalized === 'notifications' || + normalized === 'calendar' || + normalized === 'location' || + normalized === 'location-always' || + normalized === 'media-library' || + normalized === 'motion' || + normalized === 'reminders' || + normalized === 'siri' + ) { + return normalized; + } + throw new AppError( + 'INVALID_ARGS', + `permission setting requires a target: ${PERMISSION_TARGETS.join('|')}`, + ); +} diff --git a/src/contracts/snapshot-capture-annotations.ts b/packages/contracts/src/snapshot-capture-annotations.ts similarity index 83% rename from src/contracts/snapshot-capture-annotations.ts rename to packages/contracts/src/snapshot-capture-annotations.ts index ffa837746a..4aebaf6787 100644 --- a/src/contracts/snapshot-capture-annotations.ts +++ b/packages/contracts/src/snapshot-capture-annotations.ts @@ -1,8 +1,5 @@ -import type { AndroidSnapshotBackendMetadata } from '../platforms/android/snapshot-types.ts'; -import { - readSnapshotQualityVerdict, - type SnapshotQualityVerdict, -} from '../snapshot/snapshot-quality.ts'; +import type { SnapshotQualityVerdict } from '@agent-device/kernel/snapshot'; +import type { AndroidSnapshotBackendMetadata } from './snapshot-types.ts'; export type SnapshotCaptureAnalysis = { rawNodeCount: number; @@ -73,6 +70,14 @@ export function readSerializedSnapshotCaptureAnnotations( }); } +function readSnapshotQualityVerdict(value: unknown): SnapshotQualityVerdict | undefined { + if (!value || typeof value !== 'object') return undefined; + const raw = value as Record; + return typeof raw.state === 'string' && typeof raw.backend === 'string' + ? (raw as SnapshotQualityVerdict) + : undefined; +} + function readObject(value: unknown): Record | undefined { return typeof value === 'object' && value !== null ? (value as Record) diff --git a/src/contracts/snapshot-diagnostics.ts b/packages/contracts/src/snapshot-diagnostics.ts similarity index 99% rename from src/contracts/snapshot-diagnostics.ts rename to packages/contracts/src/snapshot-diagnostics.ts index 1679dde1c5..a109b63783 100644 --- a/src/contracts/snapshot-diagnostics.ts +++ b/packages/contracts/src/snapshot-diagnostics.ts @@ -1,6 +1,6 @@ import type { SnapshotBackend } from '@agent-device/kernel/snapshot'; import type { PublicPlatform } from '@agent-device/kernel/device'; -import { isRecord } from '../utils/parsing.ts'; +import { isRecord } from './json.ts'; const SLOW_SNAPSHOT_P95_WARNING_MS = 1_500; diff --git a/packages/contracts/src/snapshot-types.ts b/packages/contracts/src/snapshot-types.ts new file mode 100644 index 0000000000..02b6309c6b --- /dev/null +++ b/packages/contracts/src/snapshot-types.ts @@ -0,0 +1,63 @@ +import type { + SnapshotNode, + SnapshotState, + SnapshotOptions, + SnapshotQualityVerdict, + ScreenshotOverlayRef, +} from '@agent-device/kernel/snapshot'; +import type { SnapshotDiagnosticsSummary } from './snapshot-diagnostics.ts'; + +export type ScreenshotResultData = { + path?: string; + width?: number; + height?: number; + logicalWidth?: number; + logicalHeight?: number; + pixelDensity?: number; + overlayRefs?: ScreenshotOverlayRef[]; +}; +export type BackendSnapshotResult = { + nodes?: SnapshotNode[]; + truncated?: boolean; + backend?: string; + snapshot?: SnapshotState; + appName?: string; + appBundleId?: string; + snapshotDiagnostics?: SnapshotDiagnosticsSummary; + analysis?: { rawNodeCount: number; maxDepth: number }; + androidSnapshot?: AndroidSnapshotBackendMetadata; + freshness?: { + action: string; + retryCount: number; + staleAfterRetries: boolean; + reason?: 'empty-interactive' | 'sharp-drop' | 'stuck-route'; + }; + quality?: SnapshotQualityVerdict; + warnings?: string[]; +}; +export type BackendSnapshotOptions = SnapshotOptions & { + includeRects?: boolean; + includeHiddenContentHints?: boolean; + outPath?: string; +}; +export type AndroidSnapshotBackendMetadata = { + backend: 'android-helper'; + helperVersion?: string; + helperApiVersion?: string; + helperTransport?: string; + helperSessionReused?: boolean; + installReason?: string; + waitForIdleTimeoutMs?: number; + waitForIdleQuietMs?: number; + timeoutMs?: number; + maxDepth?: number; + maxNodes?: number; + rootPresent?: boolean; + captureMode?: string; + systemSurfaceOnly?: boolean; + windowCount?: number; + nodeCount?: number; + helperTruncated?: boolean; + elapsedMs?: number; +}; +export type FindLocator = 'any' | 'text' | 'label' | 'value' | 'role' | 'id'; diff --git a/packages/contracts/src/string-enum.ts b/packages/contracts/src/string-enum.ts new file mode 100644 index 0000000000..47869e5983 --- /dev/null +++ b/packages/contracts/src/string-enum.ts @@ -0,0 +1,21 @@ +import { AppError } from '@agent-device/kernel/errors'; + +export function defineStringEnum( + values: T, + options: { + normalize?: (value: string) => string; + message: (value: string) => string; + } = { message: (value) => `Invalid value: ${value}` }, +) { + type Value = T[number]; + const allowed = new Set(values); + const normalize = options.normalize ?? ((value: string) => value); + return { + is: (value: unknown): value is Value => typeof value === 'string' && allowed.has(value), + parse: (value: string | undefined): Value => { + const normalized = normalize(value ?? ''); + if (allowed.has(normalized)) return normalized as Value; + throw new AppError('INVALID_ARGS', options.message(value ?? '')); + }, + }; +} diff --git a/src/contracts/target-annotation.ts b/packages/contracts/src/target-annotation.ts similarity index 100% rename from src/contracts/target-annotation.ts rename to packages/contracts/src/target-annotation.ts diff --git a/src/contracts/target-shutdown-contract.ts b/packages/contracts/src/target-shutdown-contract.ts similarity index 100% rename from src/contracts/target-shutdown-contract.ts rename to packages/contracts/src/target-shutdown-contract.ts diff --git a/src/contracts/tv-remote.test.ts b/packages/contracts/src/tv-remote.test.ts similarity index 100% rename from src/contracts/tv-remote.test.ts rename to packages/contracts/src/tv-remote.test.ts diff --git a/src/contracts/tv-remote.ts b/packages/contracts/src/tv-remote.ts similarity index 100% rename from src/contracts/tv-remote.ts rename to packages/contracts/src/tv-remote.ts diff --git a/src/contracts/viewport.ts b/packages/contracts/src/viewport.ts similarity index 100% rename from src/contracts/viewport.ts rename to packages/contracts/src/viewport.ts diff --git a/src/contracts/wait.ts b/packages/contracts/src/wait.ts similarity index 100% rename from src/contracts/wait.ts rename to packages/contracts/src/wait.ts diff --git a/packages/contracts/tsconfig.json b/packages/contracts/tsconfig.json new file mode 100644 index 0000000000..935c871a4d --- /dev/null +++ b/packages/contracts/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "composite": true, + "noEmit": false, + "emitDeclarationOnly": true, + "declaration": true, + "declarationDir": "./dist-types", + "rootDir": "./src" + }, + "include": ["src"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6ba2e7a1a2..aa63e04142 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -24,6 +24,9 @@ importers: specifier: ^2.9.0 version: 2.9.0 devDependencies: + '@agent-device/contracts': + specifier: workspace:* + version: link:packages/contracts '@agent-device/kernel': specifier: workspace:* version: link:packages/kernel @@ -73,6 +76,12 @@ importers: specifier: ^4.1.8 version: 4.1.8(@types/node@22.19.21)(@vitest/coverage-v8@4.1.8)(vite@8.0.16(@types/node@22.19.21)(yaml@2.9.0)) + packages/contracts: + dependencies: + '@agent-device/kernel': + specifier: workspace:* + version: link:../kernel + packages/kernel: {} website: diff --git a/scripts/check-affected/model.test.ts b/scripts/check-affected/model.test.ts index 7563c8854b..da4c957245 100644 --- a/scripts/check-affected/model.test.ts +++ b/scripts/check-affected/model.test.ts @@ -141,17 +141,22 @@ test('skills guidance change is docs-only', () => { }); test('workspace package source selects static gates, layering, and the build', () => { - const result = plan(['packages/kernel/src/errors.ts']); - assert.equal(result.failOpen, false); - for (const id of [ - 'format', - 'lint', - 'typecheck', - 'layering', - 'build', - 'vitest-related', - ] as const) { - assert.ok(result.checks.includes(id), `expected ${id}`); + for (const file of [ + 'packages/kernel/src/errors.ts', + 'packages/contracts/src/facades/device.ts', + ]) { + const result = plan([file]); + assert.equal(result.failOpen, false, file); + for (const id of [ + 'format', + 'lint', + 'typecheck', + 'layering', + 'build', + 'vitest-related', + ] as const) { + assert.ok(result.checks.includes(id), `expected ${id} for ${file}`); + } } }); diff --git a/scripts/depgraph/affected-run.ts b/scripts/depgraph/affected-run.ts index ad316dcbed..6536e9eec3 100644 --- a/scripts/depgraph/affected-run.ts +++ b/scripts/depgraph/affected-run.ts @@ -22,7 +22,7 @@ import { PUBLIC_COMMANDS } from '../../src/command-catalog.ts'; import { INTERACTION_DISPATCH_PATHS, type InteractionPathId, -} from '../../src/contracts/interaction-guarantees.ts'; +} from '@agent-device/contracts/interaction'; import { DAEMON_COMMAND_DESCRIPTORS } from '../../src/daemon/daemon-command-registry.ts'; import { parseArgs } from 'node:util'; import { selectChecks, type CheckPlan } from '../check-affected/model.ts'; diff --git a/scripts/layering/daemon-modularity.test.ts b/scripts/layering/daemon-modularity.test.ts index 636f1d11be..981eed9f57 100644 --- a/scripts/layering/daemon-modularity.test.ts +++ b/scripts/layering/daemon-modularity.test.ts @@ -36,8 +36,8 @@ test('daemon modularity baseline records the measured R7 ownership pressure', () Object.values(SESSION_STATE_FIELD_OWNERS).reduce((sum, owners) => sum + owners.length, 0), DAEMON_MODULARITY_BASELINE.sessionState.ownerFileClaims, ); - assert.equal(TYPE_CYCLE_BASELINE, 102); - assert.equal(DAEMON_MODULARITY_BASELINE.largestTypeCycle.zoneMembers['daemon-server'], 30); + assert.equal(TYPE_CYCLE_BASELINE, 76); + assert.equal(DAEMON_MODULARITY_BASELINE.largestTypeCycle.zoneMembers['daemon-server'], 20); assert.equal('daemon' in DAEMON_MODULARITY_BASELINE.largestTypeCycle.zoneMembers, false); }); diff --git a/scripts/layering/daemon-modularity.ts b/scripts/layering/daemon-modularity.ts index 047a460970..27e21a73fc 100644 --- a/scripts/layering/daemon-modularity.ts +++ b/scripts/layering/daemon-modularity.ts @@ -6,10 +6,9 @@ const LARGEST_TYPE_CYCLE_ZONE_CEILINGS: Readonly> = { '(root)': 5, client: 1, commands: 33, - contracts: 2, - core: 12, - 'daemon-server': 30, - platforms: 19, + core: 10, + 'daemon-server': 20, + platforms: 7, }; export const DAEMON_MODULARITY_BASELINE = { diff --git a/scripts/layering/model.test.ts b/scripts/layering/model.test.ts index 5afdc11236..9ff82f788c 100644 --- a/scripts/layering/model.test.ts +++ b/scripts/layering/model.test.ts @@ -625,7 +625,7 @@ test('largestTypeCycleSize counts type-only cycles and ignores dynamic ones', () const acyclic = resolveImportEdges( new Map( Object.entries({ - 'src/core/a.ts': "import type { B } from '../contracts/b.ts';", + 'src/core/a.ts': "import type { B } from '@agent-device/contracts/b';", 'src/contracts/b.ts': 'export type B = 1;', }), ), diff --git a/scripts/layering/package-boundaries.test.ts b/scripts/layering/package-boundaries.test.ts index 92b9e8fd22..23fb6eed62 100644 --- a/scripts/layering/package-boundaries.test.ts +++ b/scripts/layering/package-boundaries.test.ts @@ -29,12 +29,26 @@ const contracts: WorkspacePackage = { dir: 'packages/contracts', name: '@agent-device/contracts', exportTargets: new Map([ - ['@agent-device/contracts/gesture', 'packages/contracts/src/gesture.ts'], + ['@agent-device/contracts/interaction', 'packages/contracts/src/facades/interaction.ts'], ]), workspaceDependencies: new Set(['@agent-device/kernel']), }; const ALL = [kernel, contracts]; +const CONTRACT_EXPORTS = [ + '@agent-device/contracts/capture', + '@agent-device/contracts/client', + '@agent-device/contracts/command', + '@agent-device/contracts/device', + '@agent-device/contracts/interaction', + '@agent-device/contracts/observability', + '@agent-device/contracts/platform', + '@agent-device/contracts/recording', + '@agent-device/contracts/remote', + '@agent-device/contracts/replay', + '@agent-device/contracts/session', + '@agent-device/contracts/settings', +] as const; function rules(violations: { rule: string }[]): string[] { return violations.map((violation) => violation.rule); @@ -107,7 +121,7 @@ test('a cross-package import needs a workspace:* declaration and an exported sub const undeclared = specifierSites( 'packages/kernel/src/errors.ts', - "import { g } from '@agent-device/contracts/gesture';", + "import { g } from '@agent-device/contracts/interaction';", ); assert.equal(checkPackageInternalSites(kernel, undeclared, ALL).length, 1); @@ -175,10 +189,18 @@ test('the real tree parses, declares, and passes R11', () => { const kernelPackage = packages.find((pkg) => pkg.name === '@agent-device/kernel'); assert.ok(kernelPackage, 'kernel package must exist'); assert.ok(kernelPackage.exportTargets.size >= 8, 'kernel exports its vocabulary subpaths'); + const contractsPackage = packages.find((pkg) => pkg.name === '@agent-device/contracts'); + assert.ok(contractsPackage, 'contracts package must exist'); + assert.deepEqual([...contractsPackage.exportTargets.keys()].sort(), [...CONTRACT_EXPORTS].sort()); + assert.deepEqual([...contractsPackage.workspaceDependencies], ['@agent-device/kernel']); assert.ok( rootWorkspaceDependencyNames(repoRoot).has('@agent-device/kernel'), 'root must declare the kernel workspace dependency', ); + assert.ok( + rootWorkspaceDependencyNames(repoRoot).has('@agent-device/contracts'), + 'root must declare the contracts workspace dependency', + ); assert.deepEqual(checkPackageBoundaries(repoRoot, new Set()), []); }); @@ -192,6 +214,9 @@ test('Node resolution enforces the exports map at runtime', () => { '@agent-device/kernel/src/errors.ts', '@agent-device/kernel/internal-not-exported', '@agent-device/kernel', + '@agent-device/contracts/gesture-plan', + '@agent-device/contracts/src/gesture-plan.ts', + '@agent-device/contracts', ]) { assert.throws( () => import.meta.resolve(deep), @@ -199,4 +224,10 @@ test('Node resolution enforces the exports map at runtime', () => { `${deep} must not resolve`, ); } + + const contractsResolved = import.meta.resolve('@agent-device/contracts/interaction'); + assert.ok( + contractsResolved.endsWith('packages/contracts/src/facades/interaction.ts'), + contractsResolved, + ); }); diff --git a/src/__tests__/cli-client-commands.test.ts b/src/__tests__/cli-client-commands.test.ts index ec98ea3fcf..9cddcb2113 100644 --- a/src/__tests__/cli-client-commands.test.ts +++ b/src/__tests__/cli-client-commands.test.ts @@ -13,7 +13,7 @@ import type { MetroPrepareOptions, MetroReloadOptions, } from '../agent-device-client.ts'; -import type { SettingsUpdateOptions } from '../contracts/client-settings.ts'; +import type { SettingsUpdateOptions } from '@agent-device/contracts/client'; import { AppError } from '@agent-device/kernel/errors'; import { resolveCliOptions } from '../cli/resolve-cli-options.ts'; diff --git a/src/__tests__/cli-grammar.test.ts b/src/__tests__/cli-grammar.test.ts index 05b13a99de..4f88198863 100644 --- a/src/__tests__/cli-grammar.test.ts +++ b/src/__tests__/cli-grammar.test.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 '../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; const BASE_FLAGS: CliFlags = { json: false, diff --git a/src/__tests__/client.test.ts b/src/__tests__/client.test.ts index 1c654889ba..7f3ba0a3f2 100644 --- a/src/__tests__/client.test.ts +++ b/src/__tests__/client.test.ts @@ -9,7 +9,7 @@ import type { FindCommandResponseData, LongPressCommandResponseData, PressCommandResponseData, -} from '../contracts/interaction.ts'; +} from '@agent-device/contracts/interaction'; import { createAgentDeviceClient, type AgentDeviceClient, diff --git a/src/__tests__/contracts-schema-public.test.ts b/src/__tests__/contracts-schema-public.test.ts index 118aa037c4..4ccbf3cbcc 100644 --- a/src/__tests__/contracts-schema-public.test.ts +++ b/src/__tests__/contracts-schema-public.test.ts @@ -1,22 +1,17 @@ -import { test } from 'vitest'; -import assert from 'node:assert/strict'; -import fs from 'node:fs'; -import path from 'node:path'; -import { AppError } from '../sdk/index.ts'; -import type { CommandResult } from '../core/command-descriptor/command-result.ts'; -import type { AppStateCommandResult } from '../contracts/app-state.ts'; -import type { ClipboardCommandResult } from '../contracts/clipboard.ts'; -import type { BootCommandResult, ShutdownCommandResult } from '../contracts/device.ts'; +import type { ViewportCommandResult } from '@agent-device/contracts/capture'; +import type { + AppStateCommandResult, + BootCommandResult, + ShutdownCommandResult, +} from '@agent-device/contracts/device'; import type { AppSwitcherCommandResult, BackCommandResult, + ClipboardCommandResult, HomeCommandResult, OrientationCommandResult, TvRemoteCommandResult, -} from '../contracts/navigation.ts'; -import type { ViewportCommandResult } from '../contracts/viewport.ts'; -import { centerOfRect, defaultHintForCode, normalizeError } from '../sdk/contracts.ts'; -import type { DaemonError } from '../sdk/contracts.ts'; +} from '@agent-device/contracts/interaction'; import { daemonRuntimeSchema, jsonRpcRequestSchema, @@ -24,6 +19,14 @@ import { type Rect, type SnapshotNode, } from '@agent-device/kernel/contracts'; +import assert from 'node:assert/strict'; +import fs from 'node:fs'; +import path from 'node:path'; +import { test } from 'vitest'; +import type { CommandResult } from '../core/command-descriptor/command-result.ts'; +import { centerOfRect, defaultHintForCode, normalizeError } from '../sdk/contracts.ts'; +import type { DaemonError } from '../sdk/contracts.ts'; +import { AppError } from '../sdk/index.ts'; const invalidArgsCode = 'INVALID_ARGS' satisfies AppErrorCode; const rect = { x: 1, y: 2, width: 3, height: 4 } satisfies Rect; diff --git a/src/contracts/__tests__/apple-os-capability-table-parity.test.ts b/src/__tests__/contracts/apple-os-capability-table-parity.test.ts similarity index 98% rename from src/contracts/__tests__/apple-os-capability-table-parity.test.ts rename to src/__tests__/contracts/apple-os-capability-table-parity.test.ts index 36f334d3c2..4f6206437b 100644 --- a/src/contracts/__tests__/apple-os-capability-table-parity.test.ts +++ b/src/__tests__/contracts/apple-os-capability-table-parity.test.ts @@ -1,6 +1,6 @@ import assert from 'node:assert/strict'; import { test } from 'vitest'; -import { isAudioProbeSupportedDevice } from '../audio-probe-support.ts'; +import { isAudioProbeSupportedDevice } from '@agent-device/contracts/platform'; import { isIosFamily, isMacOs, @@ -23,9 +23,9 @@ import { TVOS_SIMULATOR, VISIONOS_SIMULATOR, WEB_DESKTOP_DEVICE, -} from '../../__tests__/test-utils/index.ts'; +} from '../test-utils/index.ts'; import { APPLE_OS_CAPABILITIES } from '../../platforms/apple/capabilities.ts'; -import { getPlugin } from '../platform-plugin.ts'; +import { getPlugin } from '../../core/platform-plugin-registry.ts'; import { registerBuiltinPlatformPlugins } from '../../core/interactors/register-builtins.ts'; // Phase 3 step d.5 table-equivalence gate. The AppleOS-axis predicates diff --git a/src/contracts/__tests__/interaction-contract-coverage.test.ts b/src/__tests__/contracts/interaction-contract-coverage.test.ts similarity index 95% rename from src/contracts/__tests__/interaction-contract-coverage.test.ts rename to src/__tests__/contracts/interaction-contract-coverage.test.ts index c58ae7cd38..1f9378f683 100644 --- a/src/contracts/__tests__/interaction-contract-coverage.test.ts +++ b/src/__tests__/contracts/interaction-contract-coverage.test.ts @@ -4,10 +4,10 @@ import { INTERACTION_DISPATCH_PATHS, INTERACTION_GUARANTEES, INTERACTION_PATH_IDS, -} from '../interaction-guarantees.ts'; +} from '@agent-device/contracts/interaction'; import { CONTRACT_COVERAGE } from '../../../test/integration/interaction-contract/index.ts'; -// ADR 0011 Layer-3 gate: the contract scenario suite is registry-driven. Every +// ADR 0011 Layer-3 root gate: the contract scenario suite is registry-driven. Every // matrix cell that claims enforcement (runtime, runner, or delegated) must be // proven by at least one scenario in test/integration/interaction-contract/, // and no scenario may claim a waived or inapplicable cell — coverage of the diff --git a/src/contracts/__tests__/interaction-guarantees.test.ts b/src/__tests__/contracts/interaction-guarantees.test.ts similarity index 98% rename from src/contracts/__tests__/interaction-guarantees.test.ts rename to src/__tests__/contracts/interaction-guarantees.test.ts index 74ed940d0d..1bfded8b0b 100644 --- a/src/contracts/__tests__/interaction-guarantees.test.ts +++ b/src/__tests__/contracts/interaction-guarantees.test.ts @@ -7,9 +7,9 @@ import { INTERACTION_DISPATCH_PATHS, INTERACTION_GUARANTEES, INTERACTION_PATH_IDS, -} from '../interaction-guarantees.ts'; +} from '@agent-device/contracts/interaction'; -// ADR 0011 Layer-1 gate: the matrix must stay complete (typed) AND honest +// ADR 0011 Layer-1 root gate: the matrix must stay complete (typed) AND honest // (referenced implementations exist, waivers carry reasons). A cell that // points at a deleted symbol or an empty excuse fails here, not on-device. diff --git a/src/contracts/__tests__/platform-plugin-parity.test.ts b/src/__tests__/contracts/platform-plugin-parity.test.ts similarity index 97% rename from src/contracts/__tests__/platform-plugin-parity.test.ts rename to src/__tests__/contracts/platform-plugin-parity.test.ts index ff9e62b3a7..e3eb124d7e 100644 --- a/src/contracts/__tests__/platform-plugin-parity.test.ts +++ b/src/__tests__/contracts/platform-plugin-parity.test.ts @@ -7,13 +7,13 @@ import { registeredPlatforms, registerPlatformPlugin, tryGetPlugin, -} from '../platform-plugin.ts'; +} from '../../core/platform-plugin-registry.ts'; import { BUILTIN_PLATFORM_PLUGINS, registerBuiltinPlatformPlugins, } from '../../core/interactors/register-builtins.ts'; -// Idempotently populate the registry for this test module. +// Idempotently populate the root-owned registry for this test module. registerBuiltinPlatformPlugins(); // Independent copy of the internal platform accept-set. The CLI `--platform` diff --git a/src/contracts/__tests__/runner-source-assertions.ts b/src/__tests__/contracts/runner-source-assertions.ts similarity index 97% rename from src/contracts/__tests__/runner-source-assertions.ts rename to src/__tests__/contracts/runner-source-assertions.ts index d1fede88ed..e7de0567cf 100644 --- a/src/contracts/__tests__/runner-source-assertions.ts +++ b/src/__tests__/contracts/runner-source-assertions.ts @@ -2,7 +2,7 @@ import assert from 'node:assert/strict'; import fs from 'node:fs'; import path from 'node:path'; -export const PROJECT_ROOT = path.resolve(import.meta.dirname, '..', '..', '..'); +export const PROJECT_ROOT = path.resolve(import.meta.dirname, '../../..'); const RUNNER_SOURCES_DIR = path.join( PROJECT_ROOT, diff --git a/src/__tests__/npm-package-scripts.test.ts b/src/__tests__/npm-package-scripts.test.ts index c3ed16dda6..3ec791ca3e 100644 --- a/src/__tests__/npm-package-scripts.test.ts +++ b/src/__tests__/npm-package-scripts.test.ts @@ -29,6 +29,8 @@ test('prepack builds the complete package without stopping the development daemo assert.equal(packageJson.scripts['build:dev'], undefined); assert.match(packageSmokeWorkflow, /run: pnpm prepack/); for (const input of [ + 'pnpm-workspace.yaml', + 'packages/**', 'scripts/patch-xcuitest-runner-icon.ts', 'scripts/sync-mcp-metadata.mjs', 'scripts/write-xcuitest-cache-metadata.mjs', diff --git a/src/__tests__/provider-device-runtime.test.ts b/src/__tests__/provider-device-runtime.test.ts index 831f292585..4888770441 100644 --- a/src/__tests__/provider-device-runtime.test.ts +++ b/src/__tests__/provider-device-runtime.test.ts @@ -6,9 +6,9 @@ import { getProviderDeviceInteractor, installProviderDeviceApp, setActiveProviderDeviceRuntimes, - type ProviderDeviceRuntime, } from '../provider-device-runtime.ts'; -import type { Interactor } from '../contracts/interactor-types.ts'; +import type { ProviderDeviceRuntime } from '@agent-device/contracts/device'; +import type { Interactor } from '@agent-device/contracts/interaction'; import type { SimulatorLease } from '../daemon/lease-registry.ts'; import type { DeviceInfo } from '@agent-device/kernel/device'; diff --git a/src/__tests__/snapshot-diagnostics.test.ts b/src/__tests__/snapshot-diagnostics.test.ts index 22620f4e35..70ebb35bfd 100644 --- a/src/__tests__/snapshot-diagnostics.test.ts +++ b/src/__tests__/snapshot-diagnostics.test.ts @@ -3,7 +3,7 @@ import { mergeSnapshotDiagnostics, recordSnapshotTiming, summarizeSnapshotDiagnostics, -} from '../contracts/snapshot-diagnostics.ts'; +} from '@agent-device/contracts/capture'; test('records session snapshot timing stats', () => { const session = {}; diff --git a/src/__tests__/test-utils/property-arbitraries.ts b/src/__tests__/test-utils/property-arbitraries.ts index e029e0fac6..6e51316cf6 100644 --- a/src/__tests__/test-utils/property-arbitraries.ts +++ b/src/__tests__/test-utils/property-arbitraries.ts @@ -1,8 +1,12 @@ +import { + GESTURE_KINDS, + SCROLL_DIRECTIONS, + SWIPE_PRESETS, + type GesturePayload, +} from '@agent-device/contracts/interaction'; +import type { Point, RawSnapshotNode, Rect } from '@agent-device/kernel/snapshot'; import fc from 'fast-check'; import { INTERNAL_COMMANDS, PUBLIC_COMMANDS } from '../../command-catalog.ts'; -import { GESTURE_KINDS, type GesturePayload } from '../../contracts/gesture-input.ts'; -import { SCROLL_DIRECTIONS, SWIPE_PRESETS } from '../../contracts/scroll-gesture.ts'; -import type { Point, RawSnapshotNode, Rect } from '@agent-device/kernel/snapshot'; import { SELECTOR_KEY_NAMES, type SelectorKey, type SelectorTerm } from '../../selectors/parse.ts'; /** diff --git a/src/agent-device-client.ts b/src/agent-device-client.ts index 3dad68d44c..f95eeec288 100644 --- a/src/agent-device-client.ts +++ b/src/agent-device-client.ts @@ -1,19 +1,40 @@ -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'; + readSerializedSnapshotCaptureAnnotations, + readSnapshotDiagnosticsSummary, +} from '@agent-device/contracts/capture'; +import type { + AgentDeviceClientConfig, + AgentDeviceDaemonTransport, + AppCloseOptions, + AppDeployOptions, + AppInstallFromSourceOptions, + AppInstallOptions, + AppListOptions, + AppOpenOptions, + CaptureScreenshotOptions, + CaptureScreenshotResult, + CaptureSnapshotOptions, + CaptureSnapshotResult, + FlingOptions, + InternalRequestOptions, + Lease, + MaterializationReleaseOptions, + PanOptions, + PinchOptions, + RotateGestureOptions, + SessionSaveScriptOptions, + SessionSaveScriptResult, + SwipeGestureOptions, + TransformGestureOptions, +} from '@agent-device/contracts/client'; +import type { OrientationCommandResult } from '@agent-device/contracts/interaction'; +import type { AgentArtifactsResult } from '@agent-device/contracts/observability'; +import type { MetroPrepareOptions } from '@agent-device/contracts/remote'; import { - prepareDaemonCommandRequest, - type DaemonCommandName, -} from './commands/command-projection.ts'; -import { systemCommandFamily } from './commands/system/index.ts'; -import { buildRequestFlags } from './commands/command-flags.ts'; + isNonDefaultResponseLevel, + type ResponseLevel, + type SessionRuntimeHints, +} from '@agent-device/kernel/contracts'; import { AppError, throwDaemonError } from '@agent-device/kernel/errors'; import { buildMeta, @@ -31,60 +52,33 @@ import { readSnapshotNodes, resolveSessionName, } from './client/client-normalizers.ts'; -import { readScreenshotResultData } from './utils/screenshot-result.ts'; -import { isRecord } from './utils/parsing.ts'; import type { - AppCloseOptions, - AppDeployOptions, - AppInstallFromSourceOptions, - AppInstallOptions, - AppListOptions, - AppOpenOptions, - MaterializationReleaseOptions, -} from './contracts/client-app.ts'; -import type { - CaptureScreenshotOptions, - CaptureScreenshotResult, - CaptureSnapshotOptions, - CaptureSnapshotResult, -} from './contracts/client-capture.ts'; -import type { - AgentDeviceClientConfig, - AgentDeviceDaemonTransport, -} from './contracts/client-connection.ts'; -import type { - FlingOptions, - PanOptions, - PinchOptions, - RotateGestureOptions, - SwipeGestureOptions, - TransformGestureOptions, -} from './contracts/client-gesture.ts'; -import type { Lease } from './contracts/client-lease.ts'; -import type { InternalRequestOptions } from './contracts/client-request.ts'; -import type { - SessionSaveScriptOptions, - SessionSaveScriptResult, -} from './contracts/client-session.ts'; -import type { MetroPrepareOptions } from './contracts/metro.ts'; -import type { - AgentDeviceCommandClient, AgentDeviceClient, + AgentDeviceCommandClient, MetroPrepareResult, RotateCommandResult, } from './client/client-types.ts'; -import type { OrientationCommandResult } from './contracts/navigation.ts'; -import type { CommandResult } from './core/command-descriptor/command-result.ts'; +import { INTERNAL_COMMANDS } from './command-catalog.ts'; +import { buildRequestFlags } from './commands/command-flags.ts'; import { - isNonDefaultResponseLevel, - type ResponseLevel, - type SessionRuntimeHints, -} from '@agent-device/kernel/contracts'; -import { readSerializedSnapshotCaptureAnnotations } from './contracts/snapshot-capture-annotations.ts'; -import { readSnapshotDiagnosticsSummary } from './contracts/snapshot-diagnostics.ts'; -import type { CommandFlags } from './core/dispatch-context.ts'; -import type { AgentArtifactsResult } from './contracts/cloud-artifacts.ts'; + prepareDaemonCommandRequest, + type DaemonCommandName, +} from './commands/command-projection.ts'; +import { systemCommandFamily } from './commands/system/index.ts'; import type { ProjectedNavigationCommandClient } from './commands/system/navigation-projection.ts'; +import type { CommandResult } from './core/command-descriptor/command-result.ts'; +import type { CommandFlags } from './core/dispatch-context.ts'; +import { sendToDaemon } from './daemon/client/daemon-client.ts'; +import { resolveDaemonPaths } from './daemon/config.ts'; +import { prepareMetroRuntime, reloadMetro } from './metro/client-metro.ts'; +import { + clearMetroSessionHints, + readMetroSessionHints, + writeMetroSessionHints, + type MetroSessionHints, +} from './metro/metro-session-hints.ts'; +import { isRecord } from './utils/parsing.ts'; +import { readScreenshotResultData } from './utils/screenshot-result.ts'; type ProjectedSystemCommandClient = ProjectedNavigationCommandClient & Pick; diff --git a/src/backend.ts b/src/backend.ts index 91cc1c27fd..446fbf21bd 100644 --- a/src/backend.ts +++ b/src/backend.ts @@ -1,13 +1,20 @@ -import type { AlertAction, AlertInfo } from './contracts/alert-contract.ts'; -import type { AppsFilter } from './contracts/app-inventory.ts'; -import type { JsonObject } from './contracts/json.ts'; import type { - Point, - Rect, - SnapshotNode, - SnapshotOptions, - SnapshotState, -} from '@agent-device/kernel/snapshot'; + SnapshotCaptureAnnotations, + SnapshotDiagnosticsSummary, +} from '@agent-device/contracts/capture'; +import type { JsonObject } from '@agent-device/contracts/client'; +import type { AppsFilter, DeviceRotation } from '@agent-device/contracts/device'; +import type { + AlertAction, + AlertInfo, + BackMode, + ClickButton, + GesturePlan, + ScrollDirection, + TvRemoteButton, +} from '@agent-device/contracts/interaction'; +import type { RecordingExportQuality } from '@agent-device/contracts/recording'; +import type { SessionSurface } from '@agent-device/contracts/session'; import type { NetworkIncludeMode } from '@agent-device/kernel/contracts'; import type { DeviceTarget, @@ -15,17 +22,14 @@ import type { PlatformSelector, PublicPlatform, } from '@agent-device/kernel/device'; -import type { BackMode } from './contracts/back-mode.ts'; +import type { + Point, + Rect, + SnapshotNode, + SnapshotOptions, + SnapshotState, +} from '@agent-device/kernel/snapshot'; import type { RepeatedInput } from './commands/command-input.ts'; -import type { ClickButton } from './contracts/click-button.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 { GesturePlan } from './contracts/gesture-plan-types.ts'; -import type { RecordingExportQuality } from './contracts/recording-export-quality.ts'; -import type { SnapshotDiagnosticsSummary } from './contracts/snapshot-diagnostics.ts'; -import type { SnapshotCaptureAnnotations } from './contracts/snapshot-capture-annotations.ts'; import type { ScreenshotResultData } from './utils/screenshot-result.ts'; // The backend's public leaf platform (approach b): backends distinguish iOS from diff --git a/src/cli-schema/types.ts b/src/cli-schema/types.ts index 0b76dc909b..4107169b2b 100644 --- a/src/cli-schema/types.ts +++ b/src/cli-schema/types.ts @@ -1,5 +1,5 @@ import type { FlagKey } from '../commands/cli-grammar/flag-types.ts'; -import type { CliFlags } from '../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; export type CommandSchema = { helpDescription: string; diff --git a/src/cli.ts b/src/cli.ts index 65b757efe9..a5effa40ff 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -11,7 +11,7 @@ import { readVersion } from './utils/version.ts'; import { pathToFileURL } from 'node:url'; import { sendToDaemon } from './daemon/client/daemon-client.ts'; import fs from 'node:fs'; -import type { BatchStep } from './contracts/client-replay.ts'; +import type { BatchStep } from '@agent-device/contracts/client'; import type { ReplayTestReporterRuntime } from './replay/test/reporting.ts'; import { createAgentDeviceClient, @@ -41,7 +41,7 @@ import { } from './remote/remote-connection-state.ts'; import { resolveRemoteAuthForCli } from './cli/auth-session.ts'; import type { FlagKey } from './commands/cli-grammar/flag-types.ts'; -import type { CliFlags } from './contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import type { SessionRuntimeHints } from '@agent-device/kernel/contracts'; import { INTERNAL_COMMANDS, isKnownCliCommandName } from './command-catalog.ts'; diff --git a/src/cli/auth-session.ts b/src/cli/auth-session.ts index 11135570f6..c6c47ca49f 100644 --- a/src/cli/auth-session.ts +++ b/src/cli/auth-session.ts @@ -2,7 +2,7 @@ import fs from 'node:fs'; import path from 'node:path'; import { runCmd } from '../utils/exec.ts'; import { AppError } from '@agent-device/kernel/errors'; -import type { CliFlags } from '../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import type { EnvMap } from '../utils/env-map.ts'; import { readCloudJsonResponse } from './cloud-response.ts'; diff --git a/src/cli/batch-steps.ts b/src/cli/batch-steps.ts index 82c466fd51..8465549e69 100644 --- a/src/cli/batch-steps.ts +++ b/src/cli/batch-steps.ts @@ -1,9 +1,9 @@ -import type { BatchStep } from '../contracts/client-replay.ts'; +import type { BatchStep } from '@agent-device/contracts/client'; import { type SessionRuntimeHints } from '@agent-device/kernel/contracts'; -import { parseBatchStepRuntime } from '../contracts/batch-contract.ts'; +import { parseBatchStepRuntime } from '@agent-device/contracts/command'; import { readInputFromCli } from '../commands/cli-grammar.ts'; import { isCommandName, type CommandName } from '../commands/command-metadata.ts'; -import type { CliFlags } from '../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import { AppError } from '@agent-device/kernel/errors'; import { isRecord } from '../utils/parsing.ts'; import { assertCommandPositionalArity } from '../cli-schema/command-schema.ts'; diff --git a/src/cli/commands/__tests__/generic.test.ts b/src/cli/commands/__tests__/generic.test.ts index 2cb9758cde..38d26bbf57 100644 --- a/src/cli/commands/__tests__/generic.test.ts +++ b/src/cli/commands/__tests__/generic.test.ts @@ -2,7 +2,7 @@ import { test } from 'vitest'; import assert from 'node:assert/strict'; import { createAgentDeviceClient } from '../../../agent-device-client.ts'; import type { DaemonResponse } from '@agent-device/kernel/contracts'; -import type { CliFlags } from '../../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import type { ClientBackedCliCommandName } from '../client-backed.ts'; import { runGenericClientBackedCommand } from '../generic.ts'; diff --git a/src/cli/commands/__tests__/screenshot.test.ts b/src/cli/commands/__tests__/screenshot.test.ts index 6957925538..d8240a889f 100644 --- a/src/cli/commands/__tests__/screenshot.test.ts +++ b/src/cli/commands/__tests__/screenshot.test.ts @@ -2,7 +2,7 @@ import { test } from 'vitest'; import assert from 'node:assert/strict'; import { createAgentDeviceClient } from '../../../agent-device-client.ts'; import type { DaemonResponse } from '@agent-device/kernel/contracts'; -import type { CliFlags } from '../../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import { screenshotCommand } from '../screenshot.ts'; async function captureStdout(fn: () => Promise): Promise { diff --git a/src/cli/commands/agent-cdp.ts b/src/cli/commands/agent-cdp.ts index dfd3b70f30..b651da22f5 100644 --- a/src/cli/commands/agent-cdp.ts +++ b/src/cli/commands/agent-cdp.ts @@ -2,7 +2,7 @@ import { runCmdStreaming } from '../../utils/exec.ts'; import { AppError } from '@agent-device/kernel/errors'; import { isRemoteBridgeBackend } from './remote-bridge.ts'; import type { SessionRuntimeHints } from '@agent-device/kernel/contracts'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; const AGENT_CDP_VERSION = '1.6.1'; export const AGENT_CDP_PACKAGE = `agent-cdp@${AGENT_CDP_VERSION}`; diff --git a/src/cli/commands/connection-runtime.ts b/src/cli/commands/connection-runtime.ts index 39b49cf7fe..5ed8fcfe41 100644 --- a/src/cli/commands/connection-runtime.ts +++ b/src/cli/commands/connection-runtime.ts @@ -21,12 +21,12 @@ import { type RemoteConnectionRequestMetadata, } from '../../remote/remote-connection-state.ts'; import { profileToCliFlags } from '../remote-config-flags.ts'; -import type { BatchStep } from '../../contracts/client-replay.ts'; +import type { BatchStep } from '@agent-device/contracts/client'; import { AppError } from '@agent-device/kernel/errors'; import type { LeaseBackend, SessionRuntimeHints } from '@agent-device/kernel/contracts'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import type { AgentDeviceClient, Lease } from '../../agent-device-client.ts'; -import type { CloudProviderSessionResult } from '../../contracts/cloud-artifacts.ts'; +import type { CloudProviderSessionResult } from '@agent-device/contracts/observability'; import { INTERNAL_COMMANDS, PUBLIC_COMMANDS } from '../../command-catalog.ts'; import { readMetroPrepareKind } from '../../commands/metro/prepare-kind.ts'; import { connectionProviderRequiresRemoteDaemon } from '../connection/provider-policy.ts'; diff --git a/src/cli/commands/connection.ts b/src/cli/commands/connection.ts index 0421ca617a..4050a291c9 100644 --- a/src/cli/commands/connection.ts +++ b/src/cli/commands/connection.ts @@ -1,5 +1,8 @@ import crypto from 'node:crypto'; -import type { CloudArtifact, CloudProviderSessionResult } from '../../contracts/cloud-artifacts.ts'; +import type { + CloudArtifact, + CloudProviderSessionResult, +} from '@agent-device/contracts/observability'; import { resolveDaemonPaths } from '../../daemon/config.ts'; import { resolveRemoteConfigProfile } from '../../remote/remote-config.ts'; import { @@ -36,7 +39,7 @@ import { } from './connection-runtime.ts'; import { writeCommandOutput } from './shared.ts'; import type { LeaseBackend } from '@agent-device/kernel/contracts'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import type { ClientCommandHandler } from './router-types.ts'; export const connectCommand: ClientCommandHandler = async ({ positionals, flags, client }) => { diff --git a/src/cli/commands/generic.ts b/src/cli/commands/generic.ts index 066de6e34c..ea5aeafaa4 100644 --- a/src/cli/commands/generic.ts +++ b/src/cli/commands/generic.ts @@ -2,8 +2,8 @@ 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 '../../contracts/replay.ts'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { ReplaySuiteResult } from '@agent-device/contracts/replay'; +import type { CliFlags } from '@agent-device/contracts/command'; import { readCommandMessage } from '../../utils/success-text.ts'; import { isNonDefaultResponseLevel } from '@agent-device/kernel/contracts'; import { writeCommandOutput } from './shared.ts'; diff --git a/src/cli/commands/proxy.ts b/src/cli/commands/proxy.ts index 392b54edcb..3e312e970d 100644 --- a/src/cli/commands/proxy.ts +++ b/src/cli/commands/proxy.ts @@ -7,7 +7,7 @@ import { } from '../../daemon/client/daemon-client-lifecycle.ts'; import { AppError } from '@agent-device/kernel/errors'; import { colorize, supportsColor } from '../../utils/output.ts'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import { writeCommandOutput } from './shared.ts'; import type { ClientCommandHandler } from './router-types.ts'; diff --git a/src/cli/commands/react-devtools.ts b/src/cli/commands/react-devtools.ts index 4091222ebe..1b0dcfd6d3 100644 --- a/src/cli/commands/react-devtools.ts +++ b/src/cli/commands/react-devtools.ts @@ -5,7 +5,7 @@ import { } from '../../client/client-react-devtools-companion.ts'; import { AppError } from '@agent-device/kernel/errors'; import { isRemoteBridgeBackend } from './remote-bridge.ts'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; const AGENT_REACT_DEVTOOLS_VERSION = '0.4.0'; export const AGENT_REACT_DEVTOOLS_PACKAGE = `agent-react-devtools@${AGENT_REACT_DEVTOOLS_VERSION}`; diff --git a/src/cli/commands/remote-bridge.ts b/src/cli/commands/remote-bridge.ts index c91d5ce744..fbaece35a7 100644 --- a/src/cli/commands/remote-bridge.ts +++ b/src/cli/commands/remote-bridge.ts @@ -1,4 +1,4 @@ -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; export function isRemoteBridgeBackend(leaseBackend: CliFlags['leaseBackend']): boolean { return leaseBackend === 'android-instance' || leaseBackend === 'ios-instance'; diff --git a/src/cli/commands/router-types.ts b/src/cli/commands/router-types.ts index b41288dc8c..b07e9d6322 100644 --- a/src/cli/commands/router-types.ts +++ b/src/cli/commands/router-types.ts @@ -1,4 +1,4 @@ -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import type { AgentDeviceClient } from '../../agent-device-client.ts'; import type { CliCommandName } from '../../command-catalog.ts'; import type { ReplayTestReporterRuntime } from '../../replay/test/reporting.ts'; diff --git a/src/cli/commands/router.ts b/src/cli/commands/router.ts index 260dee0129..c667c7c8be 100644 --- a/src/cli/commands/router.ts +++ b/src/cli/commands/router.ts @@ -1,4 +1,4 @@ -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import type { AgentDeviceClient } from '../../agent-device-client.ts'; import { isClientBackedCliCommandName, type ClientBackedCliCommandName } from './client-backed.ts'; import { connectCommand, connectionCommand, disconnectCommand } from './connection.ts'; diff --git a/src/cli/commands/screenshot.ts b/src/cli/commands/screenshot.ts index e98f562170..02ca0ffc54 100644 --- a/src/cli/commands/screenshot.ts +++ b/src/cli/commands/screenshot.ts @@ -1,4 +1,5 @@ import { formatScreenshotDiffText, formatSnapshotDiffText } from '../../utils/output.ts'; +import type { ScreenshotDiffResult } from '../../screenshot-diff/screenshot-diff.ts'; import { AppError } from '@agent-device/kernel/errors'; import { isNonDefaultResponseLevel } from '@agent-device/kernel/contracts'; import { resolveUserPath } from '../../utils/path-resolution.ts'; @@ -6,7 +7,7 @@ import type { AgentDeviceBackend } from '../../backend.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 '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import { writeCommandOutput } from './shared.ts'; import type { ClientCommandHandler } from './router-types.ts'; @@ -82,7 +83,7 @@ export const diffCommand: ClientCommandHandler = async ({ positionals, flags, cl surface: flags.surface, }); - writeCommandOutput(flags, result, () => formatScreenshotDiffText(result)); + writeCommandOutput(flags, result, () => formatScreenshotDiffText(result as ScreenshotDiffResult)); return true; }; diff --git a/src/cli/commands/shared.ts b/src/cli/commands/shared.ts index 343c73b240..fcccf30810 100644 --- a/src/cli/commands/shared.ts +++ b/src/cli/commands/shared.ts @@ -1,4 +1,4 @@ -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import { printJson } from '../../utils/output.ts'; export function writeCommandOutput( diff --git a/src/cli/commands/web.ts b/src/cli/commands/web.ts index e6ca25e8ed..361b064aae 100644 --- a/src/cli/commands/web.ts +++ b/src/cli/commands/web.ts @@ -1,6 +1,6 @@ import type { AgentBrowserToolStatus } from '../../platforms/web/agent-browser-tool.ts'; import { AppError } from '@agent-device/kernel/errors'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import { printJson } from '../../utils/output.ts'; type PublicAgentBrowserToolStatus = Omit; diff --git a/src/cli/connection/cloud-profile.ts b/src/cli/connection/cloud-profile.ts index afc1f08459..5cebab7e37 100644 --- a/src/cli/connection/cloud-profile.ts +++ b/src/cli/connection/cloud-profile.ts @@ -1,6 +1,6 @@ import type { RemoteConfigProfile } from '../../remote/remote-config-schema.ts'; import { AppError } from '@agent-device/kernel/errors'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import type { EnvMap } from '../../utils/env-map.ts'; import { resolveCloudAccessForConnect } from '../auth-session.ts'; import { readCloudJsonResponse } from '../cloud-response.ts'; diff --git a/src/cli/connection/cloud-webdriver-profile.ts b/src/cli/connection/cloud-webdriver-profile.ts index a256918360..661ff4f422 100644 --- a/src/cli/connection/cloud-webdriver-profile.ts +++ b/src/cli/connection/cloud-webdriver-profile.ts @@ -3,7 +3,7 @@ import type { CloudWebDriverKnownProviderName } from '../../cloud-webdriver/prov import type { RemoteConfigProfile } from '../../remote/remote-config-schema.ts'; import { AppError } from '@agent-device/kernel/errors'; import type { PlatformSelector } from '@agent-device/kernel/device'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import type { EnvMap } from '../../utils/env-map.ts'; import { readMetroProfileFields } from './profile-fields.ts'; import { persistAndResolveGeneratedProfile } from './generated-config.ts'; diff --git a/src/cli/connection/generated-config.ts b/src/cli/connection/generated-config.ts index 15e0805ad9..c3127914c2 100644 --- a/src/cli/connection/generated-config.ts +++ b/src/cli/connection/generated-config.ts @@ -8,7 +8,7 @@ import type { } from '../../remote/remote-config-schema.ts'; import { AppError, asAppError } from '@agent-device/kernel/errors'; import type { EnvMap } from '../../utils/env-map.ts'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import { profileToCliFlags } from '../remote-config-flags.ts'; const GENERATED_REMOTE_CONFIG_SECRET_KEYS = new Set(['daemonAuthToken', 'metroBearerToken']); diff --git a/src/cli/connection/limrun-profile.ts b/src/cli/connection/limrun-profile.ts index 4a09c41159..9a50fe7d7b 100644 --- a/src/cli/connection/limrun-profile.ts +++ b/src/cli/connection/limrun-profile.ts @@ -1,7 +1,7 @@ import { resolveDaemonPaths } from '../../daemon/config.ts'; import type { RemoteConfigProfile } from '../../remote/remote-config-schema.ts'; import { AppError } from '@agent-device/kernel/errors'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import type { EnvMap } from '../../utils/env-map.ts'; import { readMetroProfileFields } from './profile-fields.ts'; import { persistAndResolveGeneratedProfile } from './generated-config.ts'; diff --git a/src/cli/connection/profile-fields.ts b/src/cli/connection/profile-fields.ts index 816abd2f4d..ad64c9eeb9 100644 --- a/src/cli/connection/profile-fields.ts +++ b/src/cli/connection/profile-fields.ts @@ -1,5 +1,5 @@ -import type { RemoteConfigMetroOptions } from '../../contracts/remote-config-fields.ts'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { RemoteConfigMetroOptions } from '@agent-device/contracts/remote'; +import type { CliFlags } from '@agent-device/contracts/command'; export function readMetroProfileFields(flags: CliFlags): RemoteConfigMetroOptions { return { diff --git a/src/cli/connection/proxy-profile.ts b/src/cli/connection/proxy-profile.ts index 68446eb821..d8d4a22890 100644 --- a/src/cli/connection/proxy-profile.ts +++ b/src/cli/connection/proxy-profile.ts @@ -1,6 +1,6 @@ import type { RemoteConfigProfile } from '../../remote/remote-config-schema.ts'; import { AppError } from '@agent-device/kernel/errors'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import type { EnvMap } from '../../utils/env-map.ts'; import { readMetroProfileFields } from './profile-fields.ts'; import { persistAndResolveGeneratedProfile } from './generated-config.ts'; diff --git a/src/cli/parser/__tests__/command-suggestions.test.ts b/src/cli/parser/__tests__/command-suggestions.test.ts index 3d5589e8cd..1e05e8fcf4 100644 --- a/src/cli/parser/__tests__/command-suggestions.test.ts +++ b/src/cli/parser/__tests__/command-suggestions.test.ts @@ -4,7 +4,7 @@ import { isKnownCliCommandName } from '../../../command-catalog.ts'; import { keyboardCliReader } from '../../../commands/system/index.ts'; import { AppError } from '@agent-device/kernel/errors'; import { parseArgs } from '../args.ts'; -import type { CliFlags } from '../../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import { listCommandAliasSuggestionEntries, suggestCommandFor } from '../command-suggestions.ts'; // Guards against the curated alias map drifting to a command that no longer diff --git a/src/cli/remote-config-flags.ts b/src/cli/remote-config-flags.ts index 3fdb1cead9..d59693a92e 100644 --- a/src/cli/remote-config-flags.ts +++ b/src/cli/remote-config-flags.ts @@ -1,4 +1,4 @@ -import type { CliFlags } from '../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import { REMOTE_CONFIG_FIELD_SPECS, type RemoteConfigProfile, diff --git a/src/cli/resolve-cli-options.ts b/src/cli/resolve-cli-options.ts index c8cd81d62e..9f75f5dd2c 100644 --- a/src/cli/resolve-cli-options.ts +++ b/src/cli/resolve-cli-options.ts @@ -1,4 +1,4 @@ -import type { CliFlags } from '../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import { mergeDefinedFlags } from '../utils/merge-flags.ts'; import { finalizeParsedArgs, parseRawArgs } from './parser/args.ts'; import { resolveConfigBackedFlagDefaults } from '../cli-schema/cli-config.ts'; diff --git a/src/client/client-companion-tunnel-contract.ts b/src/client/client-companion-tunnel-contract.ts index 4e7d671776..d00dc7f97d 100644 --- a/src/client/client-companion-tunnel-contract.ts +++ b/src/client/client-companion-tunnel-contract.ts @@ -19,11 +19,8 @@ export const ENV_COMPANION_TUNNEL_SESSION = 'AGENT_DEVICE_COMPANION_TUNNEL_SESSI // The scope SHAPE is declared in contracts/ so zones that only need the shape do not have to // declare themselves in terms of client/. Re-exported here for this module's existing consumers. -export type { - CompanionTunnelScope, - MetroBridgeScope, -} from '../contracts/companion-tunnel-scope.ts'; -import type { CompanionTunnelScope } from '../contracts/companion-tunnel-scope.ts'; +export type { CompanionTunnelScope, MetroBridgeScope } from '@agent-device/contracts/remote'; +import type { CompanionTunnelScope } from '@agent-device/contracts/remote'; export class MissingCompanionEnvError extends Error { override name = 'MissingCompanionEnvError'; diff --git a/src/client/client-normalizers.ts b/src/client/client-normalizers.ts index 998d74bcfe..32ca5498dc 100644 --- a/src/client/client-normalizers.ts +++ b/src/client/client-normalizers.ts @@ -1,7 +1,14 @@ -import type { DaemonRequest, SessionRuntimeHints } from '../daemon/types.ts'; -import { AppError, type NormalizedError } from '@agent-device/kernel/errors'; -import type { SnapshotNode } from '@agent-device/kernel/snapshot'; -import { buildAppIdentifiers, buildDeviceIdentifiers } from '../contracts/result-serialization.ts'; +import type { + AgentDeviceDevice, + AgentDeviceSession, + AgentDeviceSessionDevice, + AppDeployResult, + AppInstallFromSourceResult, + InternalRequestOptions, + MaterializationReleaseResult, + StartupPerfSample, +} from '@agent-device/contracts/client'; +import type { TargetShutdownResult } from '@agent-device/contracts/device'; import { isAppleOs, isApplePlatform, @@ -9,20 +16,10 @@ import { isSerialAddressablePlatform, type AppleOS, } from '@agent-device/kernel/device'; +import { AppError, type NormalizedError } from '@agent-device/kernel/errors'; +import type { SnapshotNode } from '@agent-device/kernel/snapshot'; import { leaseScopeFromOptions, leaseScopeToRequestMeta } from '../core/lease-scope.ts'; -import type { - AppDeployResult, - AppInstallFromSourceResult, - MaterializationReleaseResult, -} from '../contracts/client-app.ts'; -import type { - AgentDeviceDevice, - AgentDeviceSession, - AgentDeviceSessionDevice, - StartupPerfSample, -} from '../contracts/client-device-view.ts'; -import type { InternalRequestOptions } from '../contracts/client-request.ts'; -import type { TargetShutdownResult } from '../contracts/target-shutdown-contract.ts'; +import type { DaemonRequest, SessionRuntimeHints } from '../daemon/types.ts'; import { asRecord, isRecord, @@ -35,6 +32,7 @@ import { readRequiredString, stripUndefined, } from '../utils/parsing.ts'; +import { buildAppIdentifiers, buildDeviceIdentifiers } from '../utils/result-serialization.ts'; export { readOptionalString, readRequiredString } from '../utils/parsing.ts'; diff --git a/src/client/client-types.ts b/src/client/client-types.ts index ebf76ff0fa..cbdd92a048 100644 --- a/src/client/client-types.ts +++ b/src/client/client-types.ts @@ -19,20 +19,7 @@ // The relocated vocabulary keeps its published import path through this module — a wildcard per // family rather than 84 named re-exports, so no name is published twice under two spellings. -export type * from '../contracts/client-app.ts'; -export type * from '../contracts/client-capture.ts'; -export type * from '../contracts/client-connection.ts'; -export type * from '../contracts/client-device-view.ts'; -export type * from '../contracts/client-gesture.ts'; -export type * from '../contracts/client-lease.ts'; -export type * from '../contracts/client-observability.ts'; -export type * from '../contracts/client-replay.ts'; -export type * from '../contracts/client-request.ts'; -export type * from '../contracts/client-selector-read.ts'; -export type * from '../contracts/client-session.ts'; -export type * from '../contracts/client-settings.ts'; -export type * from '../contracts/client-system.ts'; -export type * from '../contracts/client-target.ts'; +export type * from '@agent-device/contracts/client'; // The Metro command vocabulary answers its question in the contracts/metro.ts domain file; named // rather than wildcarded so the daemon-side Metro shapes there stay out of the published surface. @@ -41,7 +28,7 @@ export type { MetroPrepareResult, MetroReloadOptions, MetroReloadResult, -} from '../contracts/metro.ts'; +} from '@agent-device/contracts/remote'; // Contracts/kernel types re-exported into the PUBLISHED surface: `agent-device-client.ts` picks // these up via `export type *`, and that is their only job — every internal consumer imports @@ -49,19 +36,27 @@ export type { // right and exactly not actionable: deleting them would remove names from the package's public // types. Suppressed per name rather than baselined so the reason travels with the code. // fallow-ignore-next-line unused-type -export type { TargetShutdownResult } from '../contracts/target-shutdown-contract.ts'; +export type { TargetShutdownResult } from '@agent-device/contracts/device'; // fallow-ignore-next-line unused-type export type { MetroBridgeScope } from './client-companion-tunnel-contract.ts'; // fallow-ignore-next-line unused-type -export type { AppsFilter } from '../contracts/app-inventory.ts'; +export type { AppsFilter } from '@agent-device/contracts/device'; // fallow-ignore-next-line unused-type -export type { AlertAction } from '../contracts/alert-contract.ts'; +export type { AlertAction } from '@agent-device/contracts/interaction'; // fallow-ignore-next-line unused-type export type { AppleOS } from '@agent-device/kernel/device'; // fallow-ignore-next-line unused-type -export type { JsonObject } from '../contracts/json.ts'; +export type { JsonObject } from '@agent-device/contracts/client'; +export type { BatchRunResult } from '../core/batch.ts'; import type { + AgentDeviceCapabilitiesResult, + AgentDeviceClientConfig, + AgentDeviceDevice, + AgentDeviceRequestOverrides, + AgentDeviceSelectionOptions, + AgentDeviceSession, + AlertCommandOptions, AppCloseOptions, AppCloseResult, AppDeployOptions, @@ -73,93 +68,70 @@ import type { AppOpenOptions, AppOpenResult, AppPushOptions, + AppStateCommandOptions, AppTriggerEventOptions, - MaterializationReleaseOptions, - MaterializationReleaseResult, -} from '../contracts/client-app.ts'; -import type { + AudioOptions, + BatchRunOptions, CaptureDiffOptions, CaptureScreenshotOptions, CaptureScreenshotResult, CaptureSnapshotOptions, CaptureSnapshotResult, -} from '../contracts/client-capture.ts'; -import type { - AgentDeviceClientConfig, - AgentDeviceRequestOverrides, - AgentDeviceSelectionOptions, - DeviceCommandBaseOptions, -} from '../contracts/client-connection.ts'; -import type { - AgentDeviceCapabilitiesResult, - AgentDeviceDevice, - AgentDeviceSession, + ClickOptions, + ClipboardCommandOptions, + CloudArtifactsOptions, + CommandRequestResult, DeviceBootOptions, + DeviceCommandBaseOptions, DeviceShutdownOptions, -} from '../contracts/client-device-view.ts'; -import type { - ClickOptions, + DoctorCommandOptions, + EventsOptions, FillOptions, + FindOptions, FlingOptions, FocusOptions, - LongPressOptions, - PanOptions, - PinchOptions, - PressOptions, - RotateGestureOptions, - ScrollOptions, - SwipeGestureOptions, - SwipeOptions, - TransformGestureOptions, - TypeTextOptions, -} from '../contracts/client-gesture.ts'; -import type { - CloudArtifactsOptions, + GetOptions, + IsOptions, + KeyboardCommandOptions, Lease, LeaseAllocateOptions, LeaseScopedOptions, -} from '../contracts/client-lease.ts'; -import type { - AudioOptions, - EventsOptions, LogsOptions, + LongPressOptions, + MaterializationReleaseOptions, + MaterializationReleaseResult, NetworkOptions, + PanOptions, PerfOptions, + PinchOptions, + PrepareCommandOptions, + PressOptions, + ReactNativeCommandOptions, RecordOptions, - TraceOptions, -} from '../contracts/client-observability.ts'; -import type { - BatchRunOptions, ReplayRunOptions, ReplayTestOptions, -} from '../contracts/client-replay.ts'; -import type { CommandRequestResult } from '../contracts/client-request.ts'; -import type { FindOptions, GetOptions, IsOptions } from '../contracts/client-selector-read.ts'; -import type { + RotateGestureOptions, + ScrollOptions, SessionCloseResult, SessionSaveScriptOptions, SessionSaveScriptResult, -} from '../contracts/client-session.ts'; -import type { SettingsUpdateOptions } from '../contracts/client-settings.ts'; -import type { - AlertCommandOptions, - AppStateCommandOptions, - ClipboardCommandOptions, - DoctorCommandOptions, - KeyboardCommandOptions, - PrepareCommandOptions, - ReactNativeCommandOptions, + SettingsUpdateOptions, + SwipeGestureOptions, + SwipeOptions, + TraceOptions, + TransformGestureOptions, + TypeTextOptions, ViewportCommandOptions, WaitCommandOptions, -} from '../contracts/client-system.ts'; +} from '@agent-device/contracts/client'; import type { MetroPrepareOptions, MetroPrepareResult, MetroReloadOptions, MetroReloadResult, -} from '../contracts/metro.ts'; +} from '@agent-device/contracts/remote'; -import type { RotateCommandResult } from '../contracts/navigation.ts'; +import type { RotateCommandResult } from '@agent-device/contracts/interaction'; import type { NavigationCommandOptions, @@ -167,29 +139,30 @@ import type { } from '../commands/system/navigation-projection.ts'; import type { BatchRunResult } from '../core/batch.ts'; -export type { BatchRunResult } from '../core/batch.ts'; -import type { DebugSymbolsOptions, DebugSymbolsResult } from '../contracts/debug-symbols.ts'; - -import type { CommandResult } from '../core/command-descriptor/command-result.ts'; import type { AgentArtifactsResult, CloudProviderSessionResult, -} from '../contracts/cloud-artifacts.ts'; + DebugSymbolsOptions, + DebugSymbolsResult, +} from '@agent-device/contracts/observability'; +import type { CommandResult } from '../core/command-descriptor/command-result.ts'; -export type { DebugSymbolsOptions, DebugSymbolsResult } from '../contracts/debug-symbols.ts'; +export type { DiffSnapshotCommandResult } from '@agent-device/contracts/capture'; +export type { PrepareCommandResult, PushCommandResult } from '@agent-device/contracts/command'; +export type { TriggerAppEventCommandResult } from '@agent-device/contracts/device'; export type { /** @deprecated Renamed to `OrientationCommandResult`. Retained until the next major. */ RotateCommandResult, -} from '../contracts/navigation.ts'; -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, TraceCommandResult } from '../contracts/recording.ts'; -export type { ReplayCommandResult, ReplaySuiteResult } from '../contracts/replay.ts'; + WaitCommandResult, +} from '@agent-device/contracts/interaction'; +export type { + DebugSymbolsOptions, + DebugSymbolsResult, + DoctorCommandResult, +} from '@agent-device/contracts/observability'; +export type { RecordingCommandResult, TraceCommandResult } from '@agent-device/contracts/recording'; +export type { ReplayCommandResult, ReplaySuiteResult } from '@agent-device/contracts/replay'; export type BackCommandOptions = DeviceCommandBaseOptions & NavigationCommandOptions<'back'>; diff --git a/src/cloud-webdriver/artifact-results.ts b/src/cloud-webdriver/artifact-results.ts index 786a93c453..bf02c7c77e 100644 --- a/src/cloud-webdriver/artifact-results.ts +++ b/src/cloud-webdriver/artifact-results.ts @@ -1,4 +1,4 @@ -import type { CloudArtifact, CloudArtifactsResult } from '../contracts/cloud-artifacts.ts'; +import type { CloudArtifact, CloudArtifactsResult } from '@agent-device/contracts/observability'; export function cloudArtifactsReadyOrPending(options: { provider: string; diff --git a/src/cloud-webdriver/aws-device-farm-artifacts.ts b/src/cloud-webdriver/aws-device-farm-artifacts.ts index e8d44575de..8dbbdacdd3 100644 --- a/src/cloud-webdriver/aws-device-farm-artifacts.ts +++ b/src/cloud-webdriver/aws-device-farm-artifacts.ts @@ -1,4 +1,4 @@ -import type { CloudArtifact, CloudArtifactsResult } from '../contracts/cloud-artifacts.ts'; +import type { CloudArtifact, CloudArtifactsResult } from '@agent-device/contracts/observability'; import type { AwsDeviceFarmClient } from './aws-device-farm.ts'; import { cloudArtifactsReadyOrPending } from './artifact-results.ts'; diff --git a/src/cloud-webdriver/aws-device-farm.ts b/src/cloud-webdriver/aws-device-farm.ts index 2892a635dc..cce2e99333 100644 --- a/src/cloud-webdriver/aws-device-farm.ts +++ b/src/cloud-webdriver/aws-device-farm.ts @@ -15,8 +15,7 @@ import type { CloudWebDriverRuntimeOptions, CloudWebDriverPrepareSession, } from './runtime.ts'; -import type { DeviceLease } from '../contracts/device-provider.ts'; -import type { ProviderDeviceRuntime } from '../provider-device-runtime.ts'; +import type { DeviceLease, ProviderDeviceRuntime } from '@agent-device/contracts/device'; import { runCmd } from '../utils/exec.ts'; import { sleep } from '../utils/timeouts.ts'; import { AppError } from '@agent-device/kernel/errors'; diff --git a/src/cloud-webdriver/browserstack.ts b/src/cloud-webdriver/browserstack.ts index d83b448f41..c4490e0e47 100644 --- a/src/cloud-webdriver/browserstack.ts +++ b/src/cloud-webdriver/browserstack.ts @@ -1,6 +1,6 @@ import fs from 'node:fs/promises'; import path from 'node:path'; -import type { CloudArtifact, CloudArtifactsResult } from '../contracts/cloud-artifacts.ts'; +import type { CloudArtifact, CloudArtifactsResult } from '@agent-device/contracts/observability'; import { createCloudWebDriverCapabilities, type CloudWebDriverCapabilityOverrides, @@ -12,8 +12,7 @@ import { type CloudWebDriverRuntimeOptions, type CloudWebDriverUploadApp, } from './runtime.ts'; -import type { ProviderDeviceRuntime } from '../provider-device-runtime.ts'; -import type { DeviceLease } from '../contracts/device-provider.ts'; +import type { DeviceLease, ProviderDeviceRuntime } from '@agent-device/contracts/device'; import { AppError } from '@agent-device/kernel/errors'; import { CLOUD_WEBDRIVER_PROVIDERS } from './providers.ts'; import { agentDeviceRequestHeaders } from './request-headers.ts'; diff --git a/src/cloud-webdriver/capabilities.ts b/src/cloud-webdriver/capabilities.ts index f8b0704934..4e31a4013b 100644 --- a/src/cloud-webdriver/capabilities.ts +++ b/src/cloud-webdriver/capabilities.ts @@ -1,4 +1,4 @@ -import type { SnapshotResult } from '../contracts/interactor-types.ts'; +import type { SnapshotResult } from '@agent-device/contracts/interaction'; import type { CloudWebDriverPlatform } from './runtime.ts'; export type CloudWebDriverOperation = diff --git a/src/cloud-webdriver/provider-definitions.ts b/src/cloud-webdriver/provider-definitions.ts index 8b190e322b..4a8cdebd04 100644 --- a/src/cloud-webdriver/provider-definitions.ts +++ b/src/cloud-webdriver/provider-definitions.ts @@ -1,9 +1,8 @@ import fs from 'node:fs'; import path from 'node:path'; -import type { CloudArtifactsResult } from '../contracts/cloud-artifacts.ts'; -import type { DaemonRequest } from '@agent-device/kernel/contracts'; +import type { CloudArtifactsResult } from '@agent-device/contracts/observability'; +import type { LeaseLifecycleContext, ProviderDeviceRuntime } from '@agent-device/contracts/device'; import { AppError } from '@agent-device/kernel/errors'; -import type { ProviderDeviceRuntime } from '../provider-device-runtime.ts'; import { AWS_DEVICE_FARM_CAPABILITY_OVERRIDES, createAwsCliDeviceFarmClient, @@ -98,7 +97,7 @@ export const CLOUD_WEBDRIVER_PROVIDER_DEFINITIONS: readonly CloudWebDriverProvid 'providerApp', 'BrowserStack requires --provider-app .', ), - cwd: request.meta?.cwd, + cwd: request.cwd, username, accessKey, uploadEndpoint: env.BROWSERSTACK_APP_UPLOAD_ENDPOINT, @@ -239,7 +238,10 @@ function isProviderAppReference(value: string): boolean { return value.startsWith('bs://') || /^https?:\/\//.test(value); } -function requireRequest(req: DaemonRequest | undefined, providerLabel: string): DaemonRequest { +function requireRequest( + req: LeaseLifecycleContext | undefined, + providerLabel: string, +): LeaseLifecycleContext { if (req) return req; throw new AppError( 'INVALID_ARGS', @@ -247,26 +249,22 @@ function requireRequest(req: DaemonRequest | undefined, providerLabel: string): ); } -function requireRequestPlatform(req: DaemonRequest, providerLabel: string): CloudWebDriverPlatform { +function requireRequestPlatform( + req: LeaseLifecycleContext, + providerLabel: string, +): CloudWebDriverPlatform { const platform = req.flags?.platform; if (platform === 'android' || platform === 'ios') return platform; throw new AppError('INVALID_ARGS', `${providerLabel} requires --platform ios|android.`); } -function requireFlag( - req: DaemonRequest, - key: keyof NonNullable, - message: string, -): string { +function requireFlag(req: LeaseLifecycleContext, key: string, message: string): string { const value = readFlag(req, key); if (value) return value; throw new AppError('INVALID_ARGS', message); } -function readFlag( - req: DaemonRequest, - key: keyof NonNullable, -): string | undefined { +function readFlag(req: LeaseLifecycleContext, key: string): string | undefined { const value = req.flags?.[key]; return typeof value === 'string' && value.length > 0 ? value : undefined; } @@ -282,9 +280,9 @@ function requireEnv( } function requireAwsValue( - req: DaemonRequest, + req: LeaseLifecycleContext, env: DefaultCloudWebDriverProviderRuntimeEnv, - flagKey: keyof NonNullable, + flagKey: string, primaryEnv: keyof DefaultCloudWebDriverProviderRuntimeEnv, fallbackEnv: keyof DefaultCloudWebDriverProviderRuntimeEnv, ): string { @@ -297,7 +295,7 @@ function requireAwsValue( } function readAwsInteractionMode( - req: DaemonRequest, + req: LeaseLifecycleContext, ): 'INTERACTIVE' | 'NO_VIDEO' | 'VIDEO_ONLY' | undefined { const value = readFlag(req, 'awsInteractionMode'); if (value === 'INTERACTIVE' || value === 'NO_VIDEO' || value === 'VIDEO_ONLY') return value; diff --git a/src/cloud-webdriver/provider-registry.ts b/src/cloud-webdriver/provider-registry.ts index 95e0c1fa04..f9557be39a 100644 --- a/src/cloud-webdriver/provider-registry.ts +++ b/src/cloud-webdriver/provider-registry.ts @@ -1,4 +1,7 @@ -import type { CloudArtifactsQuery, CloudArtifactsResult } from '../contracts/cloud-artifacts.ts'; +import type { + CloudArtifactsQuery, + CloudArtifactsResult, +} from '@agent-device/contracts/observability'; import { findCloudWebDriverProviderDefinition, type DefaultCloudWebDriverArtifactEnv, diff --git a/src/cloud-webdriver/provider-runtimes.ts b/src/cloud-webdriver/provider-runtimes.ts index 7b79f085e0..851205f122 100644 --- a/src/cloud-webdriver/provider-runtimes.ts +++ b/src/cloud-webdriver/provider-runtimes.ts @@ -1,4 +1,4 @@ -import type { ProviderDeviceRuntime } from '../provider-device-runtime.ts'; +import type { ProviderDeviceRuntime } from '@agent-device/contracts/device'; import { CLOUD_WEBDRIVER_PROVIDER_DEFINITIONS, type DefaultCloudWebDriverProviderRuntimeEnv, diff --git a/src/cloud-webdriver/runtime-helpers.ts b/src/cloud-webdriver/runtime-helpers.ts index 9b05cdba13..2aa4fe3a15 100644 --- a/src/cloud-webdriver/runtime-helpers.ts +++ b/src/cloud-webdriver/runtime-helpers.ts @@ -1,8 +1,8 @@ -import type { SnapshotResult } from '../contracts/interactor-types.ts'; +import type { SnapshotResult } from '@agent-device/contracts/interaction'; import type { ProviderDeviceInstallOptions, ProviderDeviceInstallResult, -} from '../provider-device-runtime.ts'; +} from '@agent-device/contracts/device'; import type { CloudWebDriverPlatform, CloudWebDriverUploadResult } from './runtime.ts'; export function providerInstallResult( diff --git a/src/cloud-webdriver/runtime.ts b/src/cloud-webdriver/runtime.ts index f4fa3b1783..2821d424c9 100644 --- a/src/cloud-webdriver/runtime.ts +++ b/src/cloud-webdriver/runtime.ts @@ -2,19 +2,17 @@ import type { CloudArtifactProvider, CloudArtifactsQuery, CloudArtifactsResult, -} from '../contracts/cloud-artifacts.ts'; +} from '@agent-device/contracts/observability'; import type { DeviceInventoryProvider, DeviceLease, + LeaseLifecycleContext, LeaseLifecycleProvider, -} from '../contracts/device-provider.ts'; -import type { Interactor } from '../contracts/interactor-types.ts'; -import type { DaemonRequest } from '@agent-device/kernel/contracts'; -import type { ProviderDeviceInstallOptions, ProviderDeviceInstallResult, ProviderDeviceRuntime, -} from '../provider-device-runtime.ts'; +} from '@agent-device/contracts/device'; +import type { Interactor } from '@agent-device/contracts/interaction'; import { deviceFieldsFromPublicPlatform, publicPlatformString, @@ -81,7 +79,7 @@ export type CloudWebDriverListArtifacts = (params: { export type CloudWebDriverPrepareSession = (params: { lease: DeviceLease; - req?: DaemonRequest; + req?: LeaseLifecycleContext; base: CloudWebDriverBaseSession; }) => Promise; @@ -162,7 +160,7 @@ class CloudWebDriverRuntime implements ProviderDeviceRuntime { overrides: options.capabilityOverrides, }); this.leaseLifecycle = { - allocate: async (lease, context) => await this.allocate(lease, context?.req), + allocate: async (lease, context) => await this.allocate(lease, context), heartbeat: async (lease) => this.heartbeat(lease), release: async (lease) => await this.release(lease), }; @@ -216,7 +214,7 @@ class CloudWebDriverRuntime implements ProviderDeviceRuntime { private async allocate( lease: DeviceLease, - req?: DaemonRequest, + req?: LeaseLifecycleContext, ): Promise | undefined> { if (lease.leaseProvider !== this.provider) return undefined; if (this.sessionsByLeaseId.has(lease.leaseId)) return this.heartbeat(lease); @@ -308,7 +306,7 @@ class CloudWebDriverRuntime implements ProviderDeviceRuntime { private async prepareSession( lease: DeviceLease, - req: DaemonRequest | undefined, + req: LeaseLifecycleContext | undefined, ): Promise { const base = this.baseSessionForLease(lease); return this.options.prepareSession diff --git a/src/cloud-webdriver/webdriver-interactor.ts b/src/cloud-webdriver/webdriver-interactor.ts index 91775401a5..ce24ba2b46 100644 --- a/src/cloud-webdriver/webdriver-interactor.ts +++ b/src/cloud-webdriver/webdriver-interactor.ts @@ -1,25 +1,25 @@ +import type { DeviceRotation } from '@agent-device/contracts/device'; import type { + BackMode, + GesturePlan, Interactor, ScreenshotOptions, + ScrollDirection, SnapshotOptions, SnapshotResult, -} from '../contracts/interactor-types.ts'; -import type { BackMode } from '../contracts/back-mode.ts'; -import type { DeviceRotation } from '../contracts/device-rotation.ts'; -import type { ScrollDirection } from '../contracts/scroll-gesture.ts'; -import type { GesturePlan } from '../contracts/gesture-plan.ts'; -import type { TvRemoteButton } from '../contracts/tv-remote.ts'; -import type { SettingOptions } from '../platforms/permission-utils.ts'; + TvRemoteButton, +} from '@agent-device/contracts/interaction'; +import { buildScrollGesturePlan } from '@agent-device/contracts/interaction'; +import type { SettingOptions } from '@agent-device/contracts/settings'; import { AppError } from '@agent-device/kernel/errors'; -import { buildScrollGesturePlan } from '../contracts/scroll-gesture.ts'; import { capabilitySupported, unsupportedCapabilityMessage, type CloudWebDriverOperation, type CloudWebDriverProviderCapabilities, } from './capabilities.ts'; -import { touchPointer } from './webdriver-gestures.ts'; import type { W3CPointerAction, WebDriverClient, WebDriverWindowRect } from './webdriver-client.ts'; +import { touchPointer } from './webdriver-gestures.ts'; import { scrollFrameFromWebDriverSource } from './webdriver-scroll-frame.ts'; import { parseWebDriverSource } from './webdriver-source.ts'; diff --git a/src/cloud-webdriver/webdriver-utils.ts b/src/cloud-webdriver/webdriver-utils.ts index ff42e6f545..a4c887f526 100644 --- a/src/cloud-webdriver/webdriver-utils.ts +++ b/src/cloud-webdriver/webdriver-utils.ts @@ -1,4 +1,4 @@ -import type { DeviceLease } from '../contracts/device-provider.ts'; +import type { DeviceLease } from '@agent-device/contracts/device'; export type LeaseValue = T | ((lease: DeviceLease) => T); diff --git a/src/commands/__tests__/command-flags.test.ts b/src/commands/__tests__/command-flags.test.ts index ee36d25f94..7110915220 100644 --- a/src/commands/__tests__/command-flags.test.ts +++ b/src/commands/__tests__/command-flags.test.ts @@ -1,7 +1,7 @@ import assert from 'node:assert/strict'; import { test } from 'vitest'; -import type { InternalRequestOptions } from '../../contracts/client-request.ts'; +import type { InternalRequestOptions } from '@agent-device/contracts/client'; import { findCommandMetadata } from '../command-metadata.ts'; import { readMetadataCommandFlags } from '../command-flags.ts'; diff --git a/src/commands/batch/index.ts b/src/commands/batch/index.ts index 7c744c1a93..5c68950fd4 100644 --- a/src/commands/batch/index.ts +++ b/src/commands/batch/index.ts @@ -1,4 +1,4 @@ -import type { BatchRunOptions } from '../../contracts/client-replay.ts'; +import type { BatchRunOptions } from '@agent-device/contracts/client'; import type { CommandSchemaOverride } from '../../cli-schema/types.ts'; import { commonInputFromFlags } from '../cli-grammar/common.ts'; import type { CliReader } from '../cli-grammar/types.ts'; diff --git a/src/commands/batch/metadata.ts b/src/commands/batch/metadata.ts index 5c3b7b073b..ebb45bfbca 100644 --- a/src/commands/batch/metadata.ts +++ b/src/commands/batch/metadata.ts @@ -5,7 +5,7 @@ import { parseBatchStepRuntime, readBatchStepInputObject, readBatchStepRecord, -} from '../../contracts/batch-contract.ts'; +} from '@agent-device/contracts/command'; import { AppError } from '@agent-device/kernel/errors'; import { type SessionRuntimeHints } from '@agent-device/kernel/contracts'; import { diff --git a/src/commands/batch/projection.ts b/src/commands/batch/projection.ts index e19c2d3050..3827e15b9f 100644 --- a/src/commands/batch/projection.ts +++ b/src/commands/batch/projection.ts @@ -7,7 +7,7 @@ import { parseBatchStepRuntime, readBatchStepInputObject, readBatchStepRecord, -} from '../../contracts/batch-contract.ts'; +} from '@agent-device/contracts/command'; import type { DaemonBatchStep } from '../../core/batch.ts'; import { AppError } from '@agent-device/kernel/errors'; import { request } from '../cli-grammar/common.ts'; diff --git a/src/commands/capture/alert.ts b/src/commands/capture/alert.ts index 874b65af19..0b5d2b3b0b 100644 --- a/src/commands/capture/alert.ts +++ b/src/commands/capture/alert.ts @@ -1,6 +1,6 @@ -import { ALERT_ACTIONS, type AlertAction } from '../../contracts/alert-contract.ts'; +import { ALERT_ACTIONS, type AlertAction } from '@agent-device/contracts/interaction'; import { PUBLIC_COMMANDS } from '../../command-catalog.ts'; -import type { AlertCommandOptions } from '../../contracts/client-system.ts'; +import type { AlertCommandOptions } from '@agent-device/contracts/client'; import { compactRecord, enumField, integerField } from '../command-input.ts'; import { defineExecutableCommand } from '../command-contract.ts'; import { diff --git a/src/commands/capture/index.test.ts b/src/commands/capture/index.test.ts index 8788b868c4..045766c52b 100644 --- a/src/commands/capture/index.test.ts +++ b/src/commands/capture/index.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from 'vitest'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import { alertCliReader, alertDaemonWriter } from './alert.ts'; import { diffCliReader } from './diff.ts'; import { snapshotCliOutput } from './output.ts'; diff --git a/src/commands/capture/output.test.ts b/src/commands/capture/output.test.ts index 972f537f94..76ecc9e6d2 100644 --- a/src/commands/capture/output.test.ts +++ b/src/commands/capture/output.test.ts @@ -1,7 +1,7 @@ import { test } from 'vitest'; import assert from 'node:assert/strict'; import { attachRefs, type RawSnapshotNode } from '@agent-device/kernel/snapshot'; -import type { CaptureSnapshotResult } from '../../contracts/client-capture.ts'; +import type { CaptureSnapshotResult } from '@agent-device/contracts/client'; import { snapshotCliOutput } from './output.ts'; function buildResult(raw: RawSnapshotNode[]): CaptureSnapshotResult { diff --git a/src/commands/capture/output.ts b/src/commands/capture/output.ts index caeca340f8..707c5d21e8 100644 --- a/src/commands/capture/output.ts +++ b/src/commands/capture/output.ts @@ -1,5 +1,5 @@ -import { serializeSnapshotResult } from '../../contracts/result-serialization.ts'; -import type { CaptureSnapshotResult } from '../../contracts/client-capture.ts'; +import { serializeSnapshotResult } from '../../utils/result-serialization.ts'; +import type { CaptureSnapshotResult } from '@agent-device/contracts/client'; import { dedupeInheritedSnapshotLabels } from '../../snapshot/snapshot-label-dedup.ts'; import { formatSnapshotText } from '../../utils/output.ts'; import type { CliOutput } from '../command-contract.ts'; diff --git a/src/commands/capture/runtime/diff-screenshot.ts b/src/commands/capture/runtime/diff-screenshot.ts index 1a9fc44177..24c310f256 100644 --- a/src/commands/capture/runtime/diff-screenshot.ts +++ b/src/commands/capture/runtime/diff-screenshot.ts @@ -14,7 +14,6 @@ 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 { @@ -38,7 +37,9 @@ export type DiffScreenshotCommandOptions = CommandContext & { surface?: BackendScreenshotOptions['surface']; }; -export type { DiffScreenshotCommandResult } from '../../../contracts/diff.ts'; +export type DiffScreenshotCommandResult = ScreenshotDiffResult & { + artifacts?: ArtifactDescriptor[]; +}; const DEFAULT_SCREENSHOT_DIFF_THRESHOLD = 0.1; diff --git a/src/commands/capture/runtime/snapshot.ts b/src/commands/capture/runtime/snapshot.ts index 6fa300a002..62fe5ea6aa 100644 --- a/src/commands/capture/runtime/snapshot.ts +++ b/src/commands/capture/runtime/snapshot.ts @@ -1,38 +1,38 @@ -import type { BackendSnapshotResult } from '../../../backend.ts'; -import type { DiffSnapshotCommandResult } from '../../../contracts/diff.ts'; -import type { SnapshotDiagnosticsSummary } from '../../../contracts/snapshot-diagnostics.ts'; -import type { AgentDeviceRuntime, CommandSessionRecord } from '../../../runtime-contract.ts'; import { publicSnapshotCaptureAnnotations, snapshotCaptureAnnotationsFrom, + type DiffSnapshotCommandResult, type PublicSnapshotCaptureAnnotations, type SnapshotCaptureAnnotations, -} from '../../../contracts/snapshot-capture-annotations.ts'; -import { renderSnapshotQualityWarnings } from '../../../snapshot/snapshot-quality.ts'; + type SnapshotDiagnosticsSummary, +} from '@agent-device/contracts/capture'; import { AppError } from '@agent-device/kernel/errors'; -import { - buildSnapshotDiff, - countSnapshotComparableLines, -} from '../../../snapshot/snapshot-diff.ts'; import type { SnapshotNode, SnapshotState, SnapshotUnchanged, SnapshotVisibility, } from '@agent-device/kernel/snapshot'; +import type { BackendSnapshotResult } from '../../../backend.ts'; +import type { AgentDeviceRuntime, CommandSessionRecord } from '../../../runtime-contract.ts'; +import { + buildSnapshotDiff, + countSnapshotComparableLines, +} from '../../../snapshot/snapshot-diff.ts'; +import { renderSnapshotQualityWarnings } from '../../../snapshot/snapshot-quality.ts'; import { buildSnapshotVisibility } from '../../../snapshot/snapshot-visibility.ts'; import { ANDROID_SYSTEM_SURFACE_DISCLOSURE } from '../../../snapshot/system-surface-disclosure.ts'; import { formatReactNativeOverlayWarning } from '../../react-native/overlay.ts'; -import { - buildUnchangedSnapshotMetadata, - ensureSnapshotPresentationKey, -} from './snapshot-unchanged.ts'; +import { now } from '../../runtime-common.ts'; import type { DiffSnapshotCommandOptions, RuntimeCommand, SnapshotCommandOptions, } from '../../runtime-types.ts'; -import { now } from '../../runtime-common.ts'; +import { + buildUnchangedSnapshotMetadata, + ensureSnapshotPresentationKey, +} from './snapshot-unchanged.ts'; export type SnapshotCommandResult = { nodes: SnapshotNode[]; @@ -44,7 +44,7 @@ export type SnapshotCommandResult = { snapshotDiagnostics?: SnapshotDiagnosticsSummary; } & PublicSnapshotCaptureAnnotations; -export type { DiffSnapshotCommandResult } from '../../../contracts/diff.ts'; +export type { DiffSnapshotCommandResult } from '@agent-device/contracts/capture'; type SnapshotCapture = { snapshot: SnapshotState; diff --git a/src/commands/capture/screenshot-options.test.ts b/src/commands/capture/screenshot-options.test.ts index ba19b600d8..6b71e91193 100644 --- a/src/commands/capture/screenshot-options.test.ts +++ b/src/commands/capture/screenshot-options.test.ts @@ -8,7 +8,7 @@ import { readScreenshotScriptFlag, screenshotFlagsFromOptions, screenshotOptionsFromFlags, -} from '../../contracts/screenshot.ts'; +} from '@agent-device/contracts/capture'; test('screenshot flag projection maps CLI flags to runtime options', () => { assert.deepEqual( diff --git a/src/commands/capture/screenshot.ts b/src/commands/capture/screenshot.ts index ba65e539eb..d1b2014b61 100644 --- a/src/commands/capture/screenshot.ts +++ b/src/commands/capture/screenshot.ts @@ -1,11 +1,11 @@ import { PUBLIC_COMMANDS } from '../../command-catalog.ts'; -import type { CaptureScreenshotOptions } from '../../contracts/client-capture.ts'; -import { SESSION_SURFACES } from '../../contracts/session-surface.ts'; +import type { CaptureScreenshotOptions } from '@agent-device/contracts/client'; +import { SESSION_SURFACES } from '@agent-device/contracts/session'; import { SCREENSHOT_COMMAND_FLAG_KEYS, screenshotFlagsFromOptions, screenshotOptionsFromFlags, -} from '../../contracts/screenshot.ts'; +} from '@agent-device/contracts/capture'; import { booleanField, enumField, integerField, stringField } from '../command-input.ts'; import { defineExecutableCommand } from '../command-contract.ts'; import { commonInputFromFlags, optionalString, request } from '../cli-grammar/common.ts'; diff --git a/src/commands/capture/settings.ts b/src/commands/capture/settings.ts index 3501697268..c64b149629 100644 --- a/src/commands/capture/settings.ts +++ b/src/commands/capture/settings.ts @@ -1,8 +1,8 @@ import { PUBLIC_COMMANDS } from '../../command-catalog.ts'; -import type { SettingsUpdateOptions } from '../../contracts/client-settings.ts'; -import { SETTINGS_USAGE_OVERRIDE } from '../../contracts/settings-contract.ts'; +import type { SettingsUpdateOptions } from '@agent-device/contracts/client'; +import { SETTINGS_USAGE_OVERRIDE } from '@agent-device/contracts/settings'; import type { CommandSchemaOverride } from '../../cli-schema/types.ts'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import { AppError } from '@agent-device/kernel/errors'; import { readLocationCoordinate } from '../../utils/location-coordinates.ts'; import { defineExecutableCommand } from '../command-contract.ts'; diff --git a/src/commands/capture/wait.ts b/src/commands/capture/wait.ts index 914e77805b..7c2872bf70 100644 --- a/src/commands/capture/wait.ts +++ b/src/commands/capture/wait.ts @@ -1,5 +1,5 @@ import { PUBLIC_COMMANDS } from '../../command-catalog.ts'; -import type { WaitCommandOptions } from '../../contracts/client-system.ts'; +import type { WaitCommandOptions } from '@agent-device/contracts/client'; import { parseWaitPositionals } from '../../core/wait-positionals.ts'; import { SELECTOR_SNAPSHOT_FLAGS } from '../cli-grammar/flag-groups.ts'; import { type CliFlags } from '../cli-grammar/flag-types.ts'; diff --git a/src/commands/cli-command-aliases.ts b/src/commands/cli-command-aliases.ts index a860461254..3daaf596d9 100644 --- a/src/commands/cli-command-aliases.ts +++ b/src/commands/cli-command-aliases.ts @@ -1,4 +1,4 @@ -import type { CliFlags } from '../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; type BooleanCliFlagKey = { [Key in keyof CliFlags]-?: Exclude extends boolean ? Key : never; diff --git a/src/commands/cli-grammar/common.ts b/src/commands/cli-grammar/common.ts index 9193039988..b7cdb029a9 100644 --- a/src/commands/cli-grammar/common.ts +++ b/src/commands/cli-grammar/common.ts @@ -1,19 +1,22 @@ -import type { InternalRequestOptions } from '../../contracts/client-request.ts'; -import type { ElementTarget, InteractionTarget } from '../../contracts/client-target.ts'; -import { splitSelectorFromArgs } from '../../selectors/parse.ts'; +import type { + ElementTarget, + InteractionTarget, + InternalRequestOptions, +} from '@agent-device/contracts/client'; +import type { CliFlags } from '@agent-device/contracts/command'; +import { AppError } from '@agent-device/kernel/errors'; import { checkElementTargetArgs, checkGetFormat, SELECTOR_EXPRESSION_REQUIRED_MESSAGE, } from '../../selectors/arguments.ts'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; -import { AppError } from '@agent-device/kernel/errors'; +import { splitSelectorFromArgs } from '../../selectors/parse.ts'; import { compactRecord, type SelectorSnapshotInput } from '../command-input.ts'; import type { + CommandInput, + DaemonCommandRequest, DaemonWriter, SelectionOptions, - DaemonCommandRequest, - CommandInput, } from './types.ts'; export function direct( diff --git a/src/commands/cli-grammar/flag-definitions-action.ts b/src/commands/cli-grammar/flag-definitions-action.ts index de93bbd739..9b274bdb7c 100644 --- a/src/commands/cli-grammar/flag-definitions-action.ts +++ b/src/commands/cli-grammar/flag-definitions-action.ts @@ -1,5 +1,5 @@ import { RESPONSE_LEVELS } from '@agent-device/kernel/contracts'; -import { RECORDING_SCOPE_VALUES } from '../../contracts/recording-scope.ts'; +import { RECORDING_SCOPE_VALUES } from '@agent-device/contracts/recording'; import type { FlagDefinition } from './flag-types.ts'; export const ACTION_FLAG_DEFINITIONS: readonly FlagDefinition[] = [ diff --git a/src/commands/cli-grammar/flag-definitions-target.ts b/src/commands/cli-grammar/flag-definitions-target.ts index 38c62b39be..b5b0855691 100644 --- a/src/commands/cli-grammar/flag-definitions-target.ts +++ b/src/commands/cli-grammar/flag-definitions-target.ts @@ -1,6 +1,6 @@ -import { SESSION_SURFACES } from '../../contracts/session-surface.ts'; +import { SESSION_SURFACES } from '@agent-device/contracts/session'; import { PLATFORM_SELECTORS } from '@agent-device/kernel/device'; -import { PERF_KIND_VALUES } from '../../contracts/perf.ts'; +import { PERF_KIND_VALUES } from '@agent-device/contracts/observability'; import type { FlagDefinition } from './flag-types.ts'; export const TARGET_FLAG_DEFINITIONS: readonly FlagDefinition[] = [ diff --git a/src/commands/cli-grammar/flag-definitions-workflow.ts b/src/commands/cli-grammar/flag-definitions-workflow.ts index af6d3ec288..c23fd58d82 100644 --- a/src/commands/cli-grammar/flag-definitions-workflow.ts +++ b/src/commands/cli-grammar/flag-definitions-workflow.ts @@ -1,4 +1,4 @@ -import { SCREENSHOT_SPECIFIC_FLAG_DEFINITIONS } from '../../contracts/screenshot.ts'; +import { SCREENSHOT_SPECIFIC_FLAG_DEFINITIONS } from '@agent-device/contracts/capture'; import type { FlagDefinition } from './flag-types.ts'; export const WORKFLOW_FLAG_DEFINITIONS: readonly FlagDefinition[] = [ diff --git a/src/commands/cli-grammar/flag-types.ts b/src/commands/cli-grammar/flag-types.ts index 979186d4b0..f46c19f505 100644 --- a/src/commands/cli-grammar/flag-types.ts +++ b/src/commands/cli-grammar/flag-types.ts @@ -1,6 +1,6 @@ -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; -export type { CliFlags } from '../../contracts/cli-flags.ts'; +export type { CliFlags } from '@agent-device/contracts/command'; export type FlagKey = keyof CliFlags; type FlagType = 'boolean' | 'int' | 'enum' | 'string' | 'booleanOrString'; diff --git a/src/commands/cli-grammar/registry.ts b/src/commands/cli-grammar/registry.ts index 1e28b1014e..2453534bf2 100644 --- a/src/commands/cli-grammar/registry.ts +++ b/src/commands/cli-grammar/registry.ts @@ -1,4 +1,4 @@ -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import type { CommandName } from '../command-metadata.ts'; import { listCommandFamilyCliReaders } from '../family/registry.ts'; diff --git a/src/commands/cli-grammar/types.ts b/src/commands/cli-grammar/types.ts index 3b1d6480d3..4dd8b7f631 100644 --- a/src/commands/cli-grammar/types.ts +++ b/src/commands/cli-grammar/types.ts @@ -1,7 +1,7 @@ -import type { InternalRequestOptions } from '../../contracts/client-request.ts'; +import type { InternalRequestOptions } from '@agent-device/contracts/client'; import type { CommandFlags } from '../../core/dispatch-context.ts'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; -import type { ClickButton } from '../../contracts/click-button.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; +import type { ClickButton } from '@agent-device/contracts/interaction'; export type DaemonCommandRequest = { command: string; diff --git a/src/commands/cli-runner.ts b/src/commands/cli-runner.ts index 530f91c74c..4812e7e501 100644 --- a/src/commands/cli-runner.ts +++ b/src/commands/cli-runner.ts @@ -3,7 +3,7 @@ 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 '../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; type CliRunOptions = { client: AgentDeviceClient; diff --git a/src/commands/command-flags.ts b/src/commands/command-flags.ts index c8177a4ef8..e989b51c33 100644 --- a/src/commands/command-flags.ts +++ b/src/commands/command-flags.ts @@ -1,9 +1,9 @@ -import { screenshotFlagsFromOptions } from '../contracts/screenshot.ts'; +import { screenshotFlagsFromOptions } from '@agent-device/contracts/capture'; import type { CommandFlags } from '../core/dispatch-context.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 '../contracts/client-request.ts'; +import type { InternalRequestOptions } from '@agent-device/contracts/client'; import type { CommandMetadata } from './command-contract.ts'; const CLI_FLAG_KEYS: ReadonlySet = new Set( diff --git a/src/commands/command-input.ts b/src/commands/command-input.ts index 20c10769de..c745bc79f7 100644 --- a/src/commands/command-input.ts +++ b/src/commands/command-input.ts @@ -1,17 +1,18 @@ import type { AgentDeviceRequestOverrides, AgentDeviceSelectionOptions, -} from '../contracts/client-connection.ts'; -import type { ElementTarget, InteractionTarget } from '../contracts/client-target.ts'; + ElementTarget, + InteractionTarget, +} from '@agent-device/contracts/client'; +import { readOptionalInteger as optionalInteger } from '@agent-device/contracts/command'; import { DEVICE_TARGETS, PLATFORM_SELECTORS, type DeviceTarget, type PlatformSelector, } from '@agent-device/kernel/device'; -import type { JsonSchema } from './command-contract.ts'; import { AppError } from '@agent-device/kernel/errors'; -import { readOptionalInteger as optionalInteger } from '../contracts/input-validation.ts'; +import type { JsonSchema } from './command-contract.ts'; const INTERACTION_TARGET_KINDS = ['ref', 'selector', 'point'] as const; diff --git a/src/commands/debugging/index.test.ts b/src/commands/debugging/index.test.ts index 165c81759e..c53d77978e 100644 --- a/src/commands/debugging/index.test.ts +++ b/src/commands/debugging/index.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from 'vitest'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import { debugCliReader, debugCommandDefinition, debugCommandMetadata } from './index.ts'; describe('debugging command interface', () => { diff --git a/src/commands/debugging/output.ts b/src/commands/debugging/output.ts index 832bc71041..fc915d0acf 100644 --- a/src/commands/debugging/output.ts +++ b/src/commands/debugging/output.ts @@ -1,4 +1,4 @@ -import type { DebugSymbolsResult } from '../../contracts/debug-symbols.ts'; +import type { DebugSymbolsResult } from '@agent-device/contracts/observability'; import type { CliOutput } from '../command-contract.ts'; import { resultOutput, type CliOutputFormatter } from '../output-common.ts'; diff --git a/src/commands/interaction/gesture.test.ts b/src/commands/interaction/gesture.test.ts index 02b53fde68..1d0e83f172 100644 --- a/src/commands/interaction/gesture.test.ts +++ b/src/commands/interaction/gesture.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from 'vitest'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import { gestureCliReaders, gestureDaemonWriters } from './gesture.ts'; const NO_FLAGS = {} as CliFlags; diff --git a/src/commands/interaction/gesture.ts b/src/commands/interaction/gesture.ts index 34092d98da..9bdf7d4fe1 100644 --- a/src/commands/interaction/gesture.ts +++ b/src/commands/interaction/gesture.ts @@ -1,10 +1,10 @@ import { PUBLIC_COMMANDS } from '../../command-catalog.ts'; import { compactRecord } from '../command-input.ts'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import { commonInputFromFlags, request } from '../cli-grammar/common.ts'; import type { CliReader, DaemonWriter } from '../cli-grammar/types.ts'; import { readGestureInput } from './metadata.ts'; -import { gesturePayloadFromPositionals } from '../../contracts/gesture-normalization.ts'; +import { gesturePayloadFromPositionals } from '@agent-device/contracts/interaction'; export const gestureCliReaders = { gesture: gestureInputFromCli, diff --git a/src/commands/interaction/index.ts b/src/commands/interaction/index.ts index 25bf8be6a0..574e6bce83 100644 --- a/src/commands/interaction/index.ts +++ b/src/commands/interaction/index.ts @@ -1,8 +1,11 @@ import type { ClickOptions, FillOptions, + FindOptions, FlingOptions, FocusOptions, + GetOptions, + IsOptions, LongPressOptions, PanOptions, PinchOptions, @@ -13,20 +16,18 @@ import type { SwipeOptions, TransformGestureOptions, TypeTextOptions, -} from '../../contracts/client-gesture.ts'; -import type { FindOptions, GetOptions, IsOptions } from '../../contracts/client-selector-read.ts'; +} from '@agent-device/contracts/client'; import type { CommandSchemaOverride } from '../../cli-schema/types.ts'; +import { + commandSupportsSettleObservation, + commandSupportsVerifyEvidence, +} from '../../core/command-descriptor/registry.ts'; import { REPEATED_TOUCH_FLAGS, SELECTOR_SNAPSHOT_FLAGS, SETTLE_FLAGS, } from '../cli-grammar/flag-groups.ts'; import { type FlagKey } from '../cli-grammar/flag-types.ts'; -import { - commandSupportsSettleObservation, - commandSupportsVerifyEvidence, -} from '../../core/command-descriptor/registry.ts'; -import { defineCommandFacet, defineCommandFamilyFromFacets } from '../family/types.ts'; import { defineExecutableCommand } from '../command-contract.ts'; import { commonToClientOptions, @@ -35,6 +36,9 @@ import { toRepeatedOptions, toSelectorSnapshotOptions, } from '../command-input.ts'; +import { defineCommandFacet, defineCommandFamilyFromFacets } from '../family/types.ts'; +import { gestureCliReaders, gestureDaemonWriters } from './gesture.ts'; +import { interactionCliReaders, interactionDaemonWriters } from './interactions.ts'; import { interactionCommandMetadata, type ClickInput, @@ -49,8 +53,6 @@ import { type SwipeGestureInput, type TransformInput, } from './metadata.ts'; -import { gestureCliReaders, gestureDaemonWriters } from './gesture.ts'; -import { interactionCliReaders, interactionDaemonWriters } from './interactions.ts'; import { interactionCliOutputFormatters } from './output.ts'; import { selectorCliReaders, selectorDaemonWriters } from './selectors.ts'; diff --git a/src/commands/interaction/interactions.test.ts b/src/commands/interaction/interactions.test.ts index 56ec1a8139..cc9995d7cd 100644 --- a/src/commands/interaction/interactions.test.ts +++ b/src/commands/interaction/interactions.test.ts @@ -1,7 +1,7 @@ import { expect, test } from 'vitest'; import { interactionCliReaders, interactionDaemonWriters } from './interactions.ts'; import { AppError } from '@agent-device/kernel/errors'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; const BASE_FLAGS: CliFlags = { json: false, help: false, version: false }; diff --git a/src/commands/interaction/interactions.ts b/src/commands/interaction/interactions.ts index a4cc9f3b33..eaf41ba68a 100644 --- a/src/commands/interaction/interactions.ts +++ b/src/commands/interaction/interactions.ts @@ -1,39 +1,40 @@ -import { PUBLIC_COMMANDS } from '../../command-catalog.ts'; import type { + ElementTarget, FillOptions, + InteractionTarget, LongPressOptions, TypeTextOptions, -} from '../../contracts/client-gesture.ts'; -import type { ElementTarget, InteractionTarget } from '../../contracts/client-target.ts'; +} from '@agent-device/contracts/client'; +import { + assertNoRemovedSwipeInput, + swipePayloadFromPositionals, +} from '@agent-device/contracts/interaction'; +import { AppError } from '@agent-device/kernel/errors'; +import { PUBLIC_COMMANDS } from '../../command-catalog.ts'; import { readFillTargetFromPositionals, readInteractionTargetFromPositionals, } from '../../core/interaction-positionals.ts'; -import { AppError } from '@agent-device/kernel/errors'; -import { - assertNoRemovedSwipeInput, - swipePayloadFromPositionals, -} from '../../contracts/gesture-normalization.ts'; -import type { ScrollInputDirection } from './runtime/gestures.ts'; import { commonInputFromFlags, direct, elementTargetPositionals, interactionTargetPositionals, isFiniteNumberString, + observationRecordInputFromFlags, optionalCliNumber, optionalNumber, readElementTargetFromPositionals, readGetFormat, - observationRecordInputFromFlags, + repeatedInputFromFlags, request, requiredDaemonString, - repeatedInputFromFlags, selectorSnapshotInputFromFlags, settleInputFromFlags, targetInputFromClientTarget, } from '../cli-grammar/common.ts'; import type { CliReader, DaemonWriter } from '../cli-grammar/types.ts'; +import type { ScrollInputDirection } from './runtime/gestures.ts'; export const interactionCliReaders = { click: (positionals, flags) => ({ diff --git a/src/commands/interaction/metadata.ts b/src/commands/interaction/metadata.ts index bbb2ab1250..c37cf16756 100644 --- a/src/commands/interaction/metadata.ts +++ b/src/commands/interaction/metadata.ts @@ -1,3 +1,26 @@ +import { + CLICK_BUTTONS, + GESTURE_KINDS, + readGesturePayload, + SCROLL_DIRECTIONS, + SCROLL_DURATION_MAX_MS, + SWIPE_PATTERNS, + SWIPE_PAUSE_MAX_MS, + SWIPE_PRESETS, + SWIPE_REPETITION_MAX, + type FlingGesturePayload, + type PanGesturePayload, + type PinchGesturePayload, + type RotateGesturePayload, + type SwipeGesturePayload, + type TransformGesturePayload, +} from '@agent-device/contracts/interaction'; +import type { PostActionObservationSupportFor } from '../../core/command-descriptor/post-action-observation.ts'; +import { + commandSupportsSettleObservation, + commandSupportsVerifyEvidence, +} from '../../core/command-descriptor/registry.ts'; +import { FIND_LOCATORS } from '../../selectors/find.ts'; import { defineCommandMetadata } from '../command-contract.ts'; import { booleanField, @@ -20,32 +43,7 @@ import { type InferCommandInput, } from '../command-input.ts'; import { defineFieldCommandMetadata } from '../field-command-contract.ts'; -import { CLICK_BUTTONS } from '../../contracts/click-button.ts'; -import { SCROLL_DURATION_MAX_MS } from '../../contracts/scroll-command.ts'; -import { - SCROLL_DIRECTIONS, - SWIPE_PAUSE_MAX_MS, - SWIPE_PATTERNS, - SWIPE_PRESETS, - SWIPE_REPETITION_MAX, -} from '../../contracts/scroll-gesture.ts'; import { SCROLL_INPUT_DIRECTIONS } from './runtime/gestures.ts'; -import { FIND_LOCATORS } from '../../selectors/find.ts'; -import { - commandSupportsSettleObservation, - commandSupportsVerifyEvidence, -} from '../../core/command-descriptor/registry.ts'; -import type { PostActionObservationSupportFor } from '../../core/command-descriptor/post-action-observation.ts'; -import { - GESTURE_KINDS, - readGesturePayload, - type FlingGesturePayload, - type PanGesturePayload, - type PinchGesturePayload, - type RotateGesturePayload, - type SwipeGesturePayload, - type TransformGesturePayload, -} from '../../contracts/gesture-input.ts'; const FIND_ACTION_VALUES = [ 'click', diff --git a/src/commands/interaction/output.ts b/src/commands/interaction/output.ts index a650c785b9..fea37ef7b2 100644 --- a/src/commands/interaction/output.ts +++ b/src/commands/interaction/output.ts @@ -1,4 +1,4 @@ -import type { CommandRequestResult } from '../../contracts/client-request.ts'; +import type { CommandRequestResult } from '@agent-device/contracts/client'; import type { CliOutput } from '../command-contract.ts'; import { readCommandMessage } from '../../utils/success-text.ts'; import { messageCliOutput, resultOutput, type CliOutputFormatter } from '../output-common.ts'; diff --git a/src/commands/interaction/runtime/gesture-command.ts b/src/commands/interaction/runtime/gesture-command.ts index 03dd50cc67..fdc49c459d 100644 --- a/src/commands/interaction/runtime/gesture-command.ts +++ b/src/commands/interaction/runtime/gesture-command.ts @@ -1,6 +1,6 @@ import type { AgentDeviceRuntime, CommandContext } from '../../../runtime-contract.ts'; -import type { GestureIntent, GestureSemanticInput } from '../../../contracts/gesture-plan-types.ts'; -import { buildGesturePlan } from '../../../contracts/gesture-plan.ts'; +import type { GestureIntent, GestureSemanticInput } from '@agent-device/contracts/interaction'; +import { buildGesturePlan } from '@agent-device/contracts/interaction'; import type { Point, Rect } from '@agent-device/kernel/snapshot'; import { AppError } from '@agent-device/kernel/errors'; import { successText } from '../../../utils/success-text.ts'; diff --git a/src/commands/interaction/runtime/gestures.ts b/src/commands/interaction/runtime/gestures.ts index 2339c2cc8d..7819b809ef 100644 --- a/src/commands/interaction/runtime/gestures.ts +++ b/src/commands/interaction/runtime/gestures.ts @@ -1,13 +1,16 @@ -import { AppError } from '@agent-device/kernel/errors'; -import type { Point } from '@agent-device/kernel/snapshot'; +import type { + LongPressCommandResult, + ScrollDirection, + ScrollInputDirection, +} from '@agent-device/contracts/interaction'; import { assertExclusiveScrollDistanceInputs, honoredScrollDurationMs, normalizeScrollDurationMs, -} from '../../../contracts/scroll-command.ts'; +} from '@agent-device/contracts/interaction'; +import { AppError } from '@agent-device/kernel/errors'; +import type { Point } from '@agent-device/kernel/snapshot'; import type { AgentDeviceRuntime, CommandContext } from '../../../runtime-contract.ts'; -import { requireIntInRange } from '../../../utils/validation.ts'; -import { successText } from '../../../utils/success-text.ts'; import { captureScrollEdgeState, formatScrollEdgeMessage, @@ -16,6 +19,8 @@ import { type ScrollEdgeState, type ScrollEdgeTarget, } from '../../../utils/scroll-edge-state.ts'; +import { successText } from '../../../utils/success-text.ts'; +import { requireIntInRange } from '../../../utils/validation.ts'; import { toBackendContext } from '../../runtime-common.ts'; import { toBackendResult, @@ -23,19 +28,18 @@ import { type BackendResultVariant, type RuntimeCommand, } from '../../runtime-types.ts'; -import type { LongPressCommandResult } from '../../../contracts/interaction.ts'; +import { + applyPostActionObservation, + planPostActionObservation, + type SettlePostActionObservationOptions, +} from './post-action-observation.ts'; import { assertSupportedInteractionSurface, + resolveInteractionTarget, type ExpectedResolvedTarget, type InteractionTarget, type ResolvedInteractionTarget, - resolveInteractionTarget, } from './resolution.ts'; -import { - applyPostActionObservation, - planPostActionObservation, - type SettlePostActionObservationOptions, -} from './post-action-observation.ts'; export type FocusCommandOptions = CommandContext & { target: InteractionTarget; @@ -58,8 +62,7 @@ export type GestureDirection = ScrollDirection; export { SCROLL_INPUT_DIRECTIONS, type ScrollInputDirection, -} from '../../../contracts/scroll-gesture.ts'; -import type { ScrollDirection, ScrollInputDirection } from '../../../contracts/scroll-gesture.ts'; +} from '@agent-device/contracts/interaction'; export type ScrollTarget = | InteractionTarget diff --git a/src/commands/interaction/runtime/interactions.ts b/src/commands/interaction/runtime/interactions.ts index 91ab00757b..82f2823245 100644 --- a/src/commands/interaction/runtime/interactions.ts +++ b/src/commands/interaction/runtime/interactions.ts @@ -1,35 +1,35 @@ +import type { + ClickButton, + FillCommandResult, + PressCommandResult, + ResolvedTarget, +} from '@agent-device/contracts/interaction'; import { AppError } from '@agent-device/kernel/errors'; -import type { ClickButton } from '../../../contracts/click-button.ts'; +import type { Point } from '@agent-device/kernel/snapshot'; import type { AgentDeviceRuntime, CommandContext } from '../../../runtime-contract.ts'; import { isFillableType } from '../../../snapshot/snapshot-processing.ts'; -import type { Point } from '@agent-device/kernel/snapshot'; -import { requireIntInRange } from '../../../utils/validation.ts'; import { successText } from '../../../utils/success-text.ts'; import { findMistargetedTypeRefToken } from '../../../utils/type-target-warning.ts'; -import type { - FillCommandResult, - PressCommandResult, - ResolvedTarget, -} from '../../../contracts/interaction.ts'; +import { requireIntInRange } from '../../../utils/validation.ts'; +import type { RepeatedInput } from '../../command-input.ts'; import { toBackendContext } from '../../runtime-common.ts'; import { toBackendResult, type BackendResultEnvelope, type RuntimeCommand, } from '../../runtime-types.ts'; -import type { RepeatedInput } from '../../command-input.ts'; -import { - EXACT_REF_RESOLUTION, - type ExpectedResolvedTarget, - type InteractionTarget, - preflightNativeRefInteraction, - resolveInteractionTarget, -} from './resolution.ts'; import { applyPostActionObservation, planPostActionObservation, type PostActionObservationOptions, } from './post-action-observation.ts'; +import { + EXACT_REF_RESOLUTION, + preflightNativeRefInteraction, + resolveInteractionTarget, + type ExpectedResolvedTarget, + type InteractionTarget, +} from './resolution.ts'; export { focusCommand, longPressCommand, scrollCommand } from './gestures.ts'; export type { diff --git a/src/commands/interaction/runtime/post-action-observation.ts b/src/commands/interaction/runtime/post-action-observation.ts index c807e79e09..fb7224147b 100644 --- a/src/commands/interaction/runtime/post-action-observation.ts +++ b/src/commands/interaction/runtime/post-action-observation.ts @@ -6,7 +6,7 @@ import type { ResolvedInteractionTarget, SettleObservation, SettleParams, -} from '../../../contracts/interaction.ts'; +} from '@agent-device/contracts/interaction'; import { captureInteractionSnapshot } from './resolution.ts'; import { settleAfterInteraction, settleEvidence } from './settle.ts'; diff --git a/src/commands/interaction/runtime/resolution.ts b/src/commands/interaction/runtime/resolution.ts index 1bb4f369cf..3d91517dea 100644 --- a/src/commands/interaction/runtime/resolution.ts +++ b/src/commands/interaction/runtime/resolution.ts @@ -39,7 +39,7 @@ import type { ResolutionDiagnosticEntry, ResolutionDisclosure, ResolvedInteractionTarget, -} from '../../../contracts/interaction.ts'; +} from '@agent-device/contracts/interaction'; import { now, toBackendContext } from '../../runtime-common.ts'; import { resolveActionableTouchResolution } from '../../../core/interaction-targeting.ts'; import { diff --git a/src/commands/interaction/runtime/selector-read-utils.ts b/src/commands/interaction/runtime/selector-read-utils.ts index 6c34ea30ee..73a6aadd27 100644 --- a/src/commands/interaction/runtime/selector-read-utils.ts +++ b/src/commands/interaction/runtime/selector-read-utils.ts @@ -1,4 +1,4 @@ -import type { RefTarget, SelectorTarget } from '../../../contracts/interaction.ts'; +import type { RefTarget, SelectorTarget } from '@agent-device/contracts/interaction'; import { AppError } from '@agent-device/kernel/errors'; import type { SnapshotQualityVerdict } from '../../../snapshot/snapshot-quality.ts'; import type { FindLocator } from '../../../selectors/find.ts'; diff --git a/src/commands/interaction/runtime/selector-read.ts b/src/commands/interaction/runtime/selector-read.ts index 3d0176c348..59ed5bfb48 100644 --- a/src/commands/interaction/runtime/selector-read.ts +++ b/src/commands/interaction/runtime/selector-read.ts @@ -23,7 +23,7 @@ import type { ElementTarget, ResolvedTarget, SelectorTarget, -} from '../../../contracts/interaction.ts'; +} from '@agent-device/contracts/interaction'; import type { RuntimeCommand } from '../../runtime-types.ts'; import { assertExpectedResolvedTarget, type ExpectedResolvedTarget } from './resolution.ts'; import { diff --git a/src/commands/interaction/runtime/settle.ts b/src/commands/interaction/runtime/settle.ts index bd103393b1..0d2abaa275 100644 --- a/src/commands/interaction/runtime/settle.ts +++ b/src/commands/interaction/runtime/settle.ts @@ -15,7 +15,7 @@ import type { SettleObservation, SettleParams, SettleTailEntry, -} from '../../../contracts/interaction.ts'; +} from '@agent-device/contracts/interaction'; import type { CapturedSnapshot } from './selector-read-shared.ts'; import { DEFAULT_STABLE_QUIET_MS, diff --git a/src/commands/interaction/selectors.ts b/src/commands/interaction/selectors.ts index 61d4fad7c1..47aa567ee4 100644 --- a/src/commands/interaction/selectors.ts +++ b/src/commands/interaction/selectors.ts @@ -1,6 +1,6 @@ import { PUBLIC_COMMANDS } from '../../command-catalog.ts'; -import type { FindOptions, IsOptions } from '../../contracts/client-selector-read.ts'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { FindOptions, IsOptions } from '@agent-device/contracts/client'; +import type { CliFlags } from '@agent-device/contracts/command'; import { AppError } from '@agent-device/kernel/errors'; import { checkIsPredicate, normalizeIsPositionals } from '../../selectors/predicates.ts'; import { diff --git a/src/commands/management/app-inventory-contract.ts b/src/commands/management/app-inventory-contract.ts index 5b47228dd5..2b6ae26867 100644 --- a/src/commands/management/app-inventory-contract.ts +++ b/src/commands/management/app-inventory-contract.ts @@ -1 +1 @@ -export * from '../../contracts/app-inventory.ts'; +export * from '@agent-device/contracts/device'; diff --git a/src/commands/management/app.test.ts b/src/commands/management/app.test.ts index c93cab9da6..343fe9fac1 100644 --- a/src/commands/management/app.test.ts +++ b/src/commands/management/app.test.ts @@ -3,7 +3,7 @@ import { randomUUID } from 'node:crypto'; import { mkdirSync, rmSync } from 'node:fs'; import os from 'node:os'; import path from 'node:path'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import { parseArgs } from '../../cli/parser/args.ts'; import { createAgentDeviceClient } from '../../agent-device-client.ts'; import type { DaemonRequest, DaemonResponse } from '@agent-device/kernel/contracts'; diff --git a/src/commands/management/app.ts b/src/commands/management/app.ts index 7ed6caba6a..d25dbdde0e 100644 --- a/src/commands/management/app.ts +++ b/src/commands/management/app.ts @@ -1,7 +1,7 @@ import { PUBLIC_COMMANDS } from '../../command-catalog.ts'; -import type { AppCloseOptions, AppOpenOptions } from '../../contracts/client-app.ts'; -import { DEFAULT_APPS_FILTER } from '../../contracts/app-inventory.ts'; -import { SESSION_SURFACES } from '../../contracts/session-surface.ts'; +import type { AppCloseOptions, AppOpenOptions } from '@agent-device/contracts/client'; +import { DEFAULT_APPS_FILTER } from '@agent-device/contracts/device'; +import { SESSION_SURFACES } from '@agent-device/contracts/session'; import type { CommandSchemaOverride } from '../../cli-schema/types.ts'; import { assertResolvedAppsFilter } from './app-inventory-contract.ts'; import { diff --git a/src/commands/management/install.ts b/src/commands/management/install.ts index 6a796940a0..5f918d84c0 100644 --- a/src/commands/management/install.ts +++ b/src/commands/management/install.ts @@ -1,6 +1,6 @@ import { INTERNAL_COMMANDS, PUBLIC_COMMANDS } from '../../command-catalog.ts'; import type { DaemonInstallSource } from '@agent-device/kernel/contracts'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import type { CommandSchemaOverride } from '../../cli-schema/types.ts'; import { AppError } from '@agent-device/kernel/errors'; import { parseGitHubActionsArtifactInstallSourceSpec } from '../../utils/install-source-config.ts'; diff --git a/src/commands/management/output.test.ts b/src/commands/management/output.test.ts index 4ad009ada8..abbf005204 100644 --- a/src/commands/management/output.test.ts +++ b/src/commands/management/output.test.ts @@ -1,8 +1,8 @@ import { describe, expect, test } from 'vitest'; import { doctorCliOutput, managementCliOutputFormatters, openCliOutput } from './output.ts'; -import { markDoctorProgressRendered } from '../../contracts/cli-doctor-output.ts'; +import { markDoctorProgressRendered } from '../../utils/doctor-progress.ts'; import { withNoColor } from '../../__tests__/test-utils/index.ts'; -import type { AppOpenResult } from '../../contracts/client-app.ts'; +import type { AppOpenResult } from '@agent-device/contracts/client'; describe('openCliOutput', () => { test('prints session state directory on a second line', () => { diff --git a/src/commands/management/output.ts b/src/commands/management/output.ts index 5ae5db7775..e48df94439 100644 --- a/src/commands/management/output.ts +++ b/src/commands/management/output.ts @@ -1,39 +1,35 @@ -import { - serializeCloseResult, - serializeDeployResult, - serializeDevice, - serializeInstallFromSourceResult, - serializeOpenResult, - serializeSessionListEntry, -} from '../../contracts/result-serialization.ts'; import type { + AgentDeviceCapabilitiesResult, + AgentDeviceDevice, + AgentDeviceSession, AppCloseResult, AppDeployResult, AppInstallFromSourceResult, AppOpenResult, -} from '../../contracts/client-app.ts'; -import type { - AgentDeviceCapabilitiesResult, - AgentDeviceDevice, - AgentDeviceSession, -} from '../../contracts/client-device-view.ts'; -import type { CommandRequestResult } from '../../contracts/client-request.ts'; -import type { + CommandRequestResult, SessionCloseResult, SessionSaveScriptResult, -} from '../../contracts/client-session.ts'; +} from '@agent-device/contracts/client'; import type { AgentArtifactsResult, CloudArtifactsResult, DaemonArtifactsResult, -} from '../../contracts/cloud-artifacts.ts'; -import { readCommandMessage } from '../../utils/success-text.ts'; -import type { CliOutput } from '../command-contract.ts'; +} from '@agent-device/contracts/observability'; import { consumeDoctorProgressRendered, formatDoctorCheckDetailLines, formatDoctorCheckSummaryLine, -} from '../../contracts/cli-doctor-output.ts'; +} from '../../utils/doctor-progress.ts'; +import { + serializeCloseResult, + serializeDeployResult, + serializeDevice, + serializeInstallFromSourceResult, + serializeOpenResult, + serializeSessionListEntry, +} from '../../utils/result-serialization.ts'; +import { readCommandMessage } from '../../utils/success-text.ts'; +import type { CliOutput } from '../command-contract.ts'; import { messageCliOutput, messageOutput, diff --git a/src/commands/management/push.ts b/src/commands/management/push.ts index 5d1e6b116b..e684efd7f9 100644 --- a/src/commands/management/push.ts +++ b/src/commands/management/push.ts @@ -1,24 +1,27 @@ -import { PUBLIC_COMMANDS } from '../../command-catalog.ts'; -import type { AppPushOptions, AppTriggerEventOptions } from '../../contracts/client-app.ts'; -import type { JsonObject } from '../../contracts/json.ts'; +import type { + AppPushOptions, + AppTriggerEventOptions, + JsonObject, +} from '@agent-device/contracts/client'; import type { CommandSchemaOverride } from '../../cli-schema/types.ts'; +import { PUBLIC_COMMANDS } from '../../command-catalog.ts'; +import { + commonInputFromFlags, + direct, + readJsonObject, + requiredString, +} from '../cli-grammar/common.ts'; +import type { CliReader, DaemonWriter } from '../cli-grammar/types.ts'; +import { defineExecutableCommand } from '../command-contract.ts'; import { jsonSchemaField, looseObjectField, looseObjectSchema, - type CommandField, requiredField, stringField, stringSchema, + type CommandField, } from '../command-input.ts'; -import { defineExecutableCommand } from '../command-contract.ts'; -import { - commonInputFromFlags, - direct, - readJsonObject, - requiredString, -} from '../cli-grammar/common.ts'; -import type { CliReader, DaemonWriter } from '../cli-grammar/types.ts'; import { defineCommandFacet } from '../family/types.ts'; import { defineFieldCommandMetadata } from '../field-command-contract.ts'; diff --git a/src/commands/management/runtime/apps.test.ts b/src/commands/management/runtime/apps.test.ts index 3b0a0bbd8b..13ce778010 100644 --- a/src/commands/management/runtime/apps.test.ts +++ b/src/commands/management/runtime/apps.test.ts @@ -6,7 +6,7 @@ import type { BackendOpenTarget, BackendPushInput, } from '../../../backend.ts'; -import type { JsonObject } from '../../../contracts/json.ts'; +import type { JsonObject } from '@agent-device/contracts/client'; import { createLocalArtifactAdapter } from '../../../io.ts'; import { createAgentDevice, diff --git a/src/commands/management/runtime/apps.ts b/src/commands/management/runtime/apps.ts index c0cace4678..a8e324ae17 100644 --- a/src/commands/management/runtime/apps.ts +++ b/src/commands/management/runtime/apps.ts @@ -6,7 +6,7 @@ import type { BackendOpenTarget, BackendPushInput, } from '../../../backend.ts'; -import type { JsonObject } from '../../../contracts/json.ts'; +import type { JsonObject } from '@agent-device/contracts/client'; import type { FileInputRef } from '../../../io.ts'; import type { AgentDeviceRuntime, CommandContext } from '../../../runtime-contract.ts'; import { assertResolvedAppsFilter } from '../app-inventory-contract.ts'; diff --git a/src/commands/management/session.test.ts b/src/commands/management/session.test.ts index ad8ea22227..a919c0e48b 100644 --- a/src/commands/management/session.test.ts +++ b/src/commands/management/session.test.ts @@ -3,7 +3,7 @@ import { createAgentDeviceClient } from '../../agent-device-client.ts'; import { parseArgs } from '../../cli/parser/args.ts'; import { buildCommandUsageText } from '../../cli/parser/cli-help.ts'; import type { DaemonRequest, DaemonResponse } from '@agent-device/kernel/contracts'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import { sessionCommandFacet } from './session.ts'; function flags(overrides: Partial = {}): CliFlags { diff --git a/src/commands/management/viewport.ts b/src/commands/management/viewport.ts index d1bd07c877..1ee2f8fb85 100644 --- a/src/commands/management/viewport.ts +++ b/src/commands/management/viewport.ts @@ -1,5 +1,5 @@ import { PUBLIC_COMMANDS } from '../../command-catalog.ts'; -import type { ViewportCommandOptions } from '../../contracts/client-system.ts'; +import type { ViewportCommandOptions } from '@agent-device/contracts/client'; import { readViewportDimension } from '../../core/viewport-dimension.ts'; import type { CommandSchemaOverride } from '../../cli-schema/types.ts'; import { integerField, requiredField } from '../command-input.ts'; diff --git a/src/commands/metro/index.test.ts b/src/commands/metro/index.test.ts index d15619cbc8..45d23c45ea 100644 --- a/src/commands/metro/index.test.ts +++ b/src/commands/metro/index.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from 'vitest'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import { metroCliReader, metroCommandDefinition, metroCommandMetadata } from './index.ts'; function flags(overrides: Partial = {}): CliFlags { diff --git a/src/commands/metro/index.ts b/src/commands/metro/index.ts index 7d98750a4a..f292437969 100644 --- a/src/commands/metro/index.ts +++ b/src/commands/metro/index.ts @@ -3,7 +3,7 @@ import type { MetroPrepareResult, MetroReloadOptions, MetroReloadResult, -} from '../../contracts/metro.ts'; +} from '@agent-device/contracts/remote'; import { AppError } from '@agent-device/kernel/errors'; import type { CommandSchemaOverride } from '../../cli-schema/types.ts'; import { diff --git a/src/commands/metro/prepare-kind.ts b/src/commands/metro/prepare-kind.ts index 2a088c2d52..1aa151c658 100644 --- a/src/commands/metro/prepare-kind.ts +++ b/src/commands/metro/prepare-kind.ts @@ -1,5 +1,5 @@ import { AppError } from '@agent-device/kernel/errors'; -import type { MetroPrepareKind } from '../../contracts/metro.ts'; +import type { MetroPrepareKind } from '@agent-device/contracts/remote'; const METRO_PREPARE_KIND_VALUES: readonly MetroPrepareKind[] = [ 'auto', diff --git a/src/commands/observability/index.test.ts b/src/commands/observability/index.test.ts index 405efbefbe..4e9f5562e4 100644 --- a/src/commands/observability/index.test.ts +++ b/src/commands/observability/index.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from 'vitest'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import { audioCliReader, audioCommandDefinition, diff --git a/src/commands/observability/index.ts b/src/commands/observability/index.ts index d0a89d193a..28610b9846 100644 --- a/src/commands/observability/index.ts +++ b/src/commands/observability/index.ts @@ -3,7 +3,7 @@ import type { EventsOptions, LogsOptions, NetworkOptions, -} from '../../contracts/client-observability.ts'; +} from '@agent-device/contracts/client'; import { NETWORK_INCLUDE_MODES, type NetworkIncludeMode } from '@agent-device/kernel/contracts'; import { AppError } from '@agent-device/kernel/errors'; import { parseStringMember } from '../../utils/string-enum.ts'; diff --git a/src/commands/observability/log-command-contract.ts b/src/commands/observability/log-command-contract.ts index 0c7fab38ea..68a4a10ca3 100644 --- a/src/commands/observability/log-command-contract.ts +++ b/src/commands/observability/log-command-contract.ts @@ -1 +1 @@ -export * from '../../contracts/logs.ts'; +export * from '@agent-device/contracts/observability'; diff --git a/src/commands/observability/output.ts b/src/commands/observability/output.ts index 2e54e0c4e6..b851079099 100644 --- a/src/commands/observability/output.ts +++ b/src/commands/observability/output.ts @@ -1,6 +1,6 @@ import type { BackendNetworkEntry } from '../../backend.ts'; import type { NetworkIncludeMode } from '@agent-device/kernel/contracts'; -import type { NetworkEntry } from '../../contracts/network-log.ts'; +import type { NetworkEntry } from '@agent-device/contracts/observability'; import type { CliOutput } from '../command-contract.ts'; import { resultOutput, type CliOutputFormatter } from '../output-common.ts'; diff --git a/src/commands/perf/index.test.ts b/src/commands/perf/index.test.ts index 9d2adc538c..6b87996444 100644 --- a/src/commands/perf/index.test.ts +++ b/src/commands/perf/index.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from 'vitest'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import { perfCliReader, perfCommandDefinition, diff --git a/src/commands/perf/index.ts b/src/commands/perf/index.ts index 9fe8d9e15e..761fff50d8 100644 --- a/src/commands/perf/index.ts +++ b/src/commands/perf/index.ts @@ -1,4 +1,4 @@ -import type { PerfOptions } from '../../contracts/client-observability.ts'; +import type { PerfOptions } from '@agent-device/contracts/client'; import { AppError } from '@agent-device/kernel/errors'; import type { CommandSchemaOverride } from '../../cli-schema/types.ts'; import { enumField, stringField } from '../command-input.ts'; diff --git a/src/commands/perf/output.ts b/src/commands/perf/output.ts index cbb1361963..47b2465bab 100644 --- a/src/commands/perf/output.ts +++ b/src/commands/perf/output.ts @@ -1,4 +1,4 @@ -import type { CommandRequestResult } from '../../contracts/client-request.ts'; +import type { CommandRequestResult } from '@agent-device/contracts/client'; import { isRecord } from '../../utils/parsing.ts'; import type { CliOutput } from '../command-contract.ts'; import { resultOutput, type CliOutputFormatter } from '../output-common.ts'; diff --git a/src/commands/perf/perf-command-contract.ts b/src/commands/perf/perf-command-contract.ts index d69a17cb5d..68a4a10ca3 100644 --- a/src/commands/perf/perf-command-contract.ts +++ b/src/commands/perf/perf-command-contract.ts @@ -1 +1 @@ -export * from '../../contracts/perf.ts'; +export * from '@agent-device/contracts/observability'; diff --git a/src/commands/react-native/index.test.ts b/src/commands/react-native/index.test.ts index 0c9c117319..7dde12495f 100644 --- a/src/commands/react-native/index.test.ts +++ b/src/commands/react-native/index.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from 'vitest'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import { reactNativeCliReader, reactNativeCommandDefinition, diff --git a/src/commands/recording/index.test.ts b/src/commands/recording/index.test.ts index 72d6c927ea..c7b5e0996d 100644 --- a/src/commands/recording/index.test.ts +++ b/src/commands/recording/index.test.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from 'vitest'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import { recordCliReader, recordCommandDefinition, diff --git a/src/commands/recording/index.ts b/src/commands/recording/index.ts index 180e3c7dc4..7c63adb878 100644 --- a/src/commands/recording/index.ts +++ b/src/commands/recording/index.ts @@ -1,9 +1,12 @@ -import type { RecordOptions } from '../../contracts/client-observability.ts'; -import { RECORDING_EXPORT_QUALITIES } from '../../contracts/recording-export-quality.ts'; -import { RECORDING_SCOPE_VALUES } from '../../contracts/recording-scope.ts'; +import type { RecordOptions } from '@agent-device/contracts/client'; +import { + RECORDING_EXPORT_QUALITIES, + RECORDING_SCOPE_VALUES, +} from '@agent-device/contracts/recording'; import { AppError } from '@agent-device/kernel/errors'; import type { CommandSchemaOverride } from '../../cli-schema/types.ts'; -import { defineCommandFacet, defineCommandFamilyFromFacets } from '../family/types.ts'; +import { commonInputFromFlags, direct, optionalString } from '../cli-grammar/common.ts'; +import type { CliReader, DaemonWriter } from '../cli-grammar/types.ts'; import { defineExecutableCommand } from '../command-contract.ts'; import { booleanField, @@ -12,9 +15,8 @@ import { requiredField, stringField, } from '../command-input.ts'; +import { defineCommandFacet, defineCommandFamilyFromFacets } from '../family/types.ts'; import { defineFieldCommandMetadata } from '../field-command-contract.ts'; -import { commonInputFromFlags, direct, optionalString } from '../cli-grammar/common.ts'; -import type { CliReader, DaemonWriter } from '../cli-grammar/types.ts'; import { recordingCliOutputFormatters } from './output.ts'; const RECORD_COMMAND_NAME = 'record'; diff --git a/src/commands/recording/output.ts b/src/commands/recording/output.ts index a10f04b9a6..6c1d75aeae 100644 --- a/src/commands/recording/output.ts +++ b/src/commands/recording/output.ts @@ -1,4 +1,4 @@ -import type { CommandRequestResult } from '../../contracts/client-request.ts'; +import type { CommandRequestResult } from '@agent-device/contracts/client'; import type { CliOutput } from '../command-contract.ts'; import { resultOutput, type CliOutputFormatter } from '../output-common.ts'; diff --git a/src/commands/recording/runtime/recording.ts b/src/commands/recording/runtime/recording.ts index 9042dac5d9..de58b01dca 100644 --- a/src/commands/recording/runtime/recording.ts +++ b/src/commands/recording/runtime/recording.ts @@ -12,7 +12,7 @@ import { requireIntInRange } from '../../../utils/validation.ts'; import { recordingQualityInputToExportQuality, type RecordingExportQuality, -} from '../../../contracts/recording-export-quality.ts'; +} from '@agent-device/contracts/recording'; import type { BackendResultEnvelope, BackendResultVariant, diff --git a/src/commands/replay/index.test.ts b/src/commands/replay/index.test.ts index ef46e1e8db..dadbd72a0d 100644 --- a/src/commands/replay/index.test.ts +++ b/src/commands/replay/index.test.ts @@ -1,5 +1,5 @@ import { afterEach, describe, expect, test } from 'vitest'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import { replayCliReader, replayCommandDefinition, diff --git a/src/commands/runtime-types.ts b/src/commands/runtime-types.ts index d8c8f0476b..ff89c4164c 100644 --- a/src/commands/runtime-types.ts +++ b/src/commands/runtime-types.ts @@ -1,6 +1,6 @@ import type { FileOutputRef } from '../io.ts'; import type { AgentDeviceRuntime, CommandContext } from '../runtime-contract.ts'; -import type { SessionSurface } from '../contracts/session-surface.ts'; +import type { SessionSurface } from '@agent-device/contracts/session'; export type CommandResult = Record; diff --git a/src/commands/system/index.test.ts b/src/commands/system/index.test.ts index e78d0dc922..14cc3b7cc7 100644 --- a/src/commands/system/index.test.ts +++ b/src/commands/system/index.test.ts @@ -7,7 +7,7 @@ import type { TvRemoteCommandOptions, } from '../../client/client-types.ts'; import type { CommandResult } from '../../core/command-descriptor/command-result.ts'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import { appStateCliReader, appStateDaemonWriter, diff --git a/src/commands/system/index.ts b/src/commands/system/index.ts index fabee3a6e5..3ae047a296 100644 --- a/src/commands/system/index.ts +++ b/src/commands/system/index.ts @@ -1,20 +1,23 @@ -import type { ClipboardCommandOptions } from '../../contracts/client-system.ts'; -import type { BackMode } from '../../contracts/back-mode.ts'; -import { BACK_MODES } from '../../contracts/back-mode.ts'; -import { parseDeviceRotation, DEVICE_ROTATIONS } from '../../contracts/device-rotation.ts'; +import type { ClipboardCommandOptions } from '@agent-device/contracts/client'; +import { DEVICE_ROTATIONS, parseDeviceRotation } from '@agent-device/contracts/device'; +import type { BackMode } from '@agent-device/contracts/interaction'; import { + BACK_MODES, parseTvRemoteButton, TV_REMOTE_BUTTON_USAGE, TV_REMOTE_BUTTONS, tvRemoteDurationMode, -} from '../../contracts/tv-remote.ts'; +} from '@agent-device/contracts/interaction'; import { AppError } from '@agent-device/kernel/errors'; import type { CommandSchemaOverride } from '../../cli-schema/types.ts'; import { - defineCommandFacet, - defineCommandFamilyFromFacets, - projectCommandOutputSchemas, -} from '../family/types.ts'; + commonInputFromFlags, + direct, + optionalString, + request, + requiredDaemonString, +} from '../cli-grammar/common.ts'; +import type { CliReader, DaemonWriter } from '../cli-grammar/types.ts'; import { defineExecutableCommand } from '../command-contract.ts'; import { compactRecord, @@ -23,15 +26,12 @@ import { requiredField, stringField, } from '../command-input.ts'; -import { defineFieldCommandMetadata } from '../field-command-contract.ts'; import { - commonInputFromFlags, - direct, - optionalString, - request, - requiredDaemonString, -} from '../cli-grammar/common.ts'; -import type { CliReader, DaemonWriter } from '../cli-grammar/types.ts'; + defineCommandFacet, + defineCommandFamilyFromFacets, + projectCommandOutputSchemas, +} from '../family/types.ts'; +import { defineFieldCommandMetadata } from '../field-command-contract.ts'; import { NAVIGATION_COMMAND_PROJECTIONS } from './navigation-projection.ts'; import { systemCliOutputFormatters } from './output.ts'; diff --git a/src/commands/system/navigation-projection.ts b/src/commands/system/navigation-projection.ts index ade211431d..9102093b17 100644 --- a/src/commands/system/navigation-projection.ts +++ b/src/commands/system/navigation-projection.ts @@ -1,13 +1,15 @@ -import { BACK_MODES, type BackMode } from '../../contracts/back-mode.ts'; -import { DEVICE_ROTATIONS, type DeviceRotation } from '../../contracts/device-rotation.ts'; -import type { - AppSwitcherCommandResult, - BackCommandResult, - HomeCommandResult, - OrientationCommandResult, - TvRemoteCommandResult, -} from '../../contracts/navigation.ts'; -import { TV_REMOTE_BUTTONS, type TvRemoteButton } from '../../contracts/tv-remote.ts'; +import { DEVICE_ROTATIONS, type DeviceRotation } from '@agent-device/contracts/device'; +import { + BACK_MODES, + TV_REMOTE_BUTTONS, + type AppSwitcherCommandResult, + type BackCommandResult, + type HomeCommandResult, + type OrientationCommandResult, + type TvRemoteCommandResult, + type BackMode, + type TvRemoteButton, +} from '@agent-device/contracts/interaction'; import type { ExecutableCommandProjection } from '../command-contract.ts'; declare const navigationCommandProjectionType: unique symbol; diff --git a/src/commands/system/output.ts b/src/commands/system/output.ts index 933019702a..6ba5306409 100644 --- a/src/commands/system/output.ts +++ b/src/commands/system/output.ts @@ -1,6 +1,8 @@ -import type { AppStateCommandResult } from '../../contracts/app-state.ts'; -import type { ClipboardCommandResult } from '../../contracts/clipboard.ts'; -import type { KeyboardCommandResult } from '../../contracts/keyboard.ts'; +import type { AppStateCommandResult } from '@agent-device/contracts/device'; +import type { + ClipboardCommandResult, + KeyboardCommandResult, +} from '@agent-device/contracts/interaction'; import type { CliOutput } from '../command-contract.ts'; import { messageCliOutput, diff --git a/src/commands/system/runtime/system.ts b/src/commands/system/runtime/system.ts index f97aa41883..cdf24e0025 100644 --- a/src/commands/system/runtime/system.ts +++ b/src/commands/system/runtime/system.ts @@ -7,8 +7,8 @@ import type { BackendTvRemoteOptions, } from '../../../backend.ts'; import type { CommandContext } from '../../../runtime-contract.ts'; -import type { BackMode } from '../../../contracts/back-mode.ts'; -import { parseTvRemoteButton } from '../../../contracts/tv-remote.ts'; +import type { BackMode } from '@agent-device/contracts/interaction'; +import { parseTvRemoteButton } from '@agent-device/contracts/interaction'; import { AppError } from '@agent-device/kernel/errors'; import { successText } from '../../../utils/success-text.ts'; import { requireIntInRange } from '../../../utils/validation.ts'; diff --git a/src/compat/maestro/__tests__/daemon-runtime-public-operation.test.ts b/src/compat/maestro/__tests__/daemon-runtime-public-operation.test.ts index a0bb385511..aff939628e 100644 --- a/src/compat/maestro/__tests__/daemon-runtime-public-operation.test.ts +++ b/src/compat/maestro/__tests__/daemon-runtime-public-operation.test.ts @@ -1,8 +1,10 @@ +import { + buildGesturePlan, + normalizePublicGesture, + readGesturePayload, +} from '@agent-device/contracts/interaction'; import assert from 'node:assert/strict'; import { describe, expect, test } from 'vitest'; -import { buildGesturePlan } from '../../../contracts/gesture-plan.ts'; -import { readGesturePayload } from '../../../contracts/gesture-input.ts'; -import { normalizePublicGesture } from '../../../contracts/gesture-normalization.ts'; import { projectMaestroPublicOperation, type MaestroPublicOperation, diff --git a/src/compat/maestro/export-flow.ts b/src/compat/maestro/export-flow.ts index 165880e3f9..1759db16ae 100644 --- a/src/compat/maestro/export-flow.ts +++ b/src/compat/maestro/export-flow.ts @@ -1,5 +1,5 @@ -import type { SessionAction } from '../../contracts/session-action.ts'; -import { GESTURE_FLING_DURATION_MS } from '../../contracts/gesture-plan.ts'; +import type { SessionAction } from '@agent-device/contracts/session'; +import { GESTURE_FLING_DURATION_MS } from '@agent-device/contracts/interaction'; import { parseSelectorChain, type Selector } from '../../selectors/index.ts'; import type { SelectorTerm } from '../../selectors/parse.ts'; import { AppError } from '@agent-device/kernel/errors'; diff --git a/src/compat/maestro/runtime-port-geometry.ts b/src/compat/maestro/runtime-port-geometry.ts index aff57f249f..b7de30c7a1 100644 --- a/src/compat/maestro/runtime-port-geometry.ts +++ b/src/compat/maestro/runtime-port-geometry.ts @@ -1,5 +1,5 @@ import { AppError } from '@agent-device/kernel/errors'; -import { buildInPageSwipeGesturePlan } from '../../contracts/scroll-gesture.ts'; +import { buildInPageSwipeGesturePlan } from '@agent-device/contracts/interaction'; import { isPositiveFiniteRect } from '@agent-device/kernel/rect'; import type { Rect, SnapshotState } from '@agent-device/kernel/snapshot'; import { diff --git a/src/contracts/diff.ts b/src/contracts/diff.ts deleted file mode 100644 index 7c1e6740f9..0000000000 --- a/src/contracts/diff.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { ArtifactDescriptor } from '../io.ts'; -import type { ScreenshotDiffResult } from '../screenshot-diff/screenshot-diff.ts'; -import type { SnapshotDiffLine, SnapshotDiffSummary } from '../snapshot/snapshot-diff.ts'; - -export type DiffScreenshotCommandResult = ScreenshotDiffResult & { - artifacts?: ArtifactDescriptor[]; -}; - -export type DiffSnapshotCommandResult = { - mode: 'snapshot'; - baselineInitialized: boolean; - summary: SnapshotDiffSummary; - lines: SnapshotDiffLine[]; - warnings?: string[]; -}; diff --git a/src/core/__tests__/capability-plugin-routing-parity.test.ts b/src/core/__tests__/capability-plugin-routing-parity.test.ts index e0ac0d1193..1ebe09bb76 100644 --- a/src/core/__tests__/capability-plugin-routing-parity.test.ts +++ b/src/core/__tests__/capability-plugin-routing-parity.test.ts @@ -29,7 +29,7 @@ import { unsupportedHintForDevice, type CommandCapability, } from '../capabilities.ts'; -import { getPlugin } from '../../contracts/platform-plugin.ts'; +import { getPlugin } from '../platform-plugin-registry.ts'; import { registerBuiltinPlatformPlugins } from '../interactors/register-builtins.ts'; // Phase 3 step (b) parity gate. Independent oracles pin that the migration is diff --git a/src/core/__tests__/dispatch-interactions.test.ts b/src/core/__tests__/dispatch-interactions.test.ts index 50f18422cf..56204c79e5 100644 --- a/src/core/__tests__/dispatch-interactions.test.ts +++ b/src/core/__tests__/dispatch-interactions.test.ts @@ -12,7 +12,7 @@ vi.mock('../../platforms/apple/core/runner/runner-client.ts', async (importOrigi }); import { handlePressCommand } from '../dispatch-interactions.ts'; -import type { Interactor } from '../../contracts/interactor-types.ts'; +import type { Interactor } from '@agent-device/contracts/interaction'; import type { RunnerCommand } from '../../platforms/apple/core/runner/runner-contract.ts'; import { AppError } from '@agent-device/kernel/errors'; import { ANDROID_EMULATOR, IOS_SIMULATOR } from '../../__tests__/test-utils/device-fixtures.ts'; diff --git a/src/core/__tests__/dispatch-scroll.test.ts b/src/core/__tests__/dispatch-scroll.test.ts index ba54a8a9f3..95f6747ca0 100644 --- a/src/core/__tests__/dispatch-scroll.test.ts +++ b/src/core/__tests__/dispatch-scroll.test.ts @@ -3,7 +3,7 @@ import assert from 'node:assert/strict'; import { dispatchCommand } from '../dispatch.ts'; import { handleLongPressCommand, handleScrollCommand } from '../dispatch-interactions.ts'; import { AppError } from '@agent-device/kernel/errors'; -import type { Interactor } from '../../contracts/interactor-types.ts'; +import type { Interactor } from '@agent-device/contracts/interaction'; import { IOS_SIMULATOR } from '../../__tests__/test-utils/device-fixtures.ts'; test('dispatch scroll rejects mixing amount and --pixels', async () => { diff --git a/src/core/__tests__/gesture-capabilities.test.ts b/src/core/__tests__/gesture-capabilities.test.ts index 3434f90aa3..3e3bc01483 100644 --- a/src/core/__tests__/gesture-capabilities.test.ts +++ b/src/core/__tests__/gesture-capabilities.test.ts @@ -1,10 +1,10 @@ import assert from 'node:assert/strict'; import { test } from 'vitest'; -import type { GestureSemanticInput } from '../../contracts/gesture-plan-types.ts'; +import type { GestureSemanticInput } from '@agent-device/contracts/interaction'; import { normalizePublicGesture, normalizePublicSwipeMotion, -} from '../../contracts/gesture-normalization.ts'; +} from '@agent-device/contracts/interaction'; import { requireGestureSupported } from '../capabilities.ts'; import { AppError } from '@agent-device/kernel/errors'; import type { DeviceInfo } from '@agent-device/kernel/device'; diff --git a/src/core/__tests__/gesture-plan-test-utils.ts b/src/core/__tests__/gesture-plan-test-utils.ts index 8607738f4e..bd4df18c52 100644 --- a/src/core/__tests__/gesture-plan-test-utils.ts +++ b/src/core/__tests__/gesture-plan-test-utils.ts @@ -4,7 +4,7 @@ import { buildGesturePlan, type GesturePlan, type MultiTouchGesturePlan, -} from '../../contracts/gesture-plan.ts'; +} from '@agent-device/contracts/interaction'; export const PORTRAIT: Rect = { x: 0, y: 0, width: 390, height: 844 }; export const LANDSCAPE: Rect = { x: 0, y: 0, width: 844, height: 390 }; diff --git a/src/core/__tests__/gesture-plan-viewport.test.ts b/src/core/__tests__/gesture-plan-viewport.test.ts index 4d4c983cb0..4d6b59fdd8 100644 --- a/src/core/__tests__/gesture-plan-viewport.test.ts +++ b/src/core/__tests__/gesture-plan-viewport.test.ts @@ -1,13 +1,14 @@ -import assert from 'node:assert/strict'; -import fc from 'fast-check'; -import { describe, test } from 'vitest'; -import { buildGesturePlan, GESTURE_SAMPLE_INTERVAL_MS } from '../../contracts/gesture-plan.ts'; import { + buildGesturePlan, + GESTURE_SAMPLE_INTERVAL_MS, gesturePayloadFromPositionals, normalizePublicGesture, -} from '../../contracts/gesture-normalization.ts'; +} from '@agent-device/contracts/interaction'; import { PUBLIC_PLATFORMS } from '@agent-device/kernel/device'; import { AppError } from '@agent-device/kernel/errors'; +import fc from 'fast-check'; +import assert from 'node:assert/strict'; +import { describe, test } from 'vitest'; import { COMPACT_VIEWPORTS, gestureInViewportArb, diff --git a/src/core/__tests__/gesture-plan.test.ts b/src/core/__tests__/gesture-plan.test.ts index 38d3ec3980..27f0dfe00a 100644 --- a/src/core/__tests__/gesture-plan.test.ts +++ b/src/core/__tests__/gesture-plan.test.ts @@ -1,6 +1,9 @@ import assert from 'node:assert/strict'; import { describe, test } from 'vitest'; -import { buildGesturePlan, GESTURE_INITIAL_ANGLE_DEGREES } from '../../contracts/gesture-plan.ts'; +import { + buildGesturePlan, + GESTURE_INITIAL_ANGLE_DEGREES, +} from '@agent-device/contracts/interaction'; import { centroid, distance, diff --git a/src/core/__tests__/snapshot-chrome-android-statusbar.test.ts b/src/core/__tests__/snapshot-chrome-android-statusbar.test.ts index 02d1d2bf86..13d3df2f55 100644 --- a/src/core/__tests__/snapshot-chrome-android-statusbar.test.ts +++ b/src/core/__tests__/snapshot-chrome-android-statusbar.test.ts @@ -8,7 +8,7 @@ import { walkInteractiveOnlyAndroidFixture, walkNonRawAndroidFixture, } from '../../__tests__/test-utils/android-ui-hierarchy-fixtures.ts'; -import { isAndroidSystemChromeWindowResourceId } from '../../contracts/android-system-chrome.ts'; +import { isAndroidSystemChromeWindowResourceId } from '@agent-device/contracts/platform'; /** * The `walk*AndroidFixture` helpers run a real `--raw` device capture through diff --git a/src/core/app-events.ts b/src/core/app-events.ts index 9f568236ee..2844975bd9 100644 --- a/src/core/app-events.ts +++ b/src/core/app-events.ts @@ -5,7 +5,7 @@ import { type DeviceInfo, } from '@agent-device/kernel/device'; import { AppError } from '@agent-device/kernel/errors'; -import type { JsonObject } from '../contracts/json.ts'; +import type { JsonObject } from '@agent-device/contracts/client'; type AppEventDevice = Pick; diff --git a/src/core/batch.ts b/src/core/batch.ts index 3f6032bb17..4b13931ee8 100644 --- a/src/core/batch.ts +++ b/src/core/batch.ts @@ -1,7 +1,7 @@ // The step SHAPE lives in contracts/ so the public API vocabulary can be stated in terms of it // without depending on core/; re-exported here for this module's existing consumers. -export type { DaemonBatchStep } from '../contracts/batch-step.ts'; -import type { DaemonBatchStep } from '../contracts/batch-step.ts'; +export type { DaemonBatchStep } from '@agent-device/contracts/command'; +import type { DaemonBatchStep } from '@agent-device/contracts/command'; import { type DaemonRequest, type DaemonResponse, @@ -15,7 +15,7 @@ import { assertBatchStepCount, isValidBatchMaxSteps, parseBatchStepRuntime, -} from '../contracts/batch-contract.ts'; +} from '@agent-device/contracts/command'; import { BATCH_DAEMON_STEP_KEYS, INHERITED_PARENT_FLAG_KEYS, diff --git a/src/core/capabilities.ts b/src/core/capabilities.ts index 8df9f42284..ecbbd8eeea 100644 --- a/src/core/capabilities.ts +++ b/src/core/capabilities.ts @@ -1,11 +1,11 @@ import { deriveCapabilityMatrix } from './command-descriptor/derive.ts'; import { commandDescriptors } from './command-descriptor/registry.ts'; -import { tryGetPlugin } from '../contracts/platform-plugin.ts'; +import { tryGetPlugin } from './platform-plugin-registry.ts'; import { registerBuiltinPlatformPlugins } from './interactors/register-builtins.ts'; import type { DeviceInfo } from '@agent-device/kernel/device'; import { AppError } from '@agent-device/kernel/errors'; -import type { GestureSemanticInput } from '../contracts/gesture-plan-types.ts'; -import { assertAppleMultiTouchSupported } from '../contracts/apple-multitouch-support.ts'; +import type { GestureSemanticInput } from '@agent-device/contracts/interaction'; +import { assertAppleMultiTouchSupported } from '@agent-device/contracts/platform'; // Populate the PlatformPlugin registry once at module load (idempotent; registers // only lazy closures, so no leaf code is imported and CLI cold-start is unaffected diff --git a/src/core/command-descriptor/__tests__/command-result.test.ts b/src/core/command-descriptor/__tests__/command-result.test.ts index c61b4a5445..0329565830 100644 --- a/src/core/command-descriptor/__tests__/command-result.test.ts +++ b/src/core/command-descriptor/__tests__/command-result.test.ts @@ -1,30 +1,32 @@ -import { expect, test } from 'vitest'; import type { - FillCommandResponseData, - LongPressCommandResponseData, - PressCommandResponseData, - FindCommandResponseData, -} from '../../../contracts/interaction.ts'; -import type { BootCommandResult, ShutdownCommandResult } from '../../../contracts/device.ts'; -import type { ViewportCommandResult } from '../../../contracts/viewport.ts'; + DiffSnapshotCommandResult, + ViewportCommandResult, +} from '@agent-device/contracts/capture'; +import type { PrepareCommandResult, PushCommandResult } from '@agent-device/contracts/command'; +import type { + AppStateCommandResult, + BootCommandResult, + ShutdownCommandResult, + TriggerAppEventCommandResult, +} from '@agent-device/contracts/device'; import type { AppSwitcherCommandResult, BackCommandResult, + ClipboardCommandResult, + FillCommandResponseData, + FindCommandResponseData, HomeCommandResult, + KeyboardCommandResult, + LongPressCommandResponseData, OrientationCommandResult, + PressCommandResponseData, TvRemoteCommandResult, -} from '../../../contracts/navigation.ts'; -import type { ClipboardCommandResult } from '../../../contracts/clipboard.ts'; -import type { AppStateCommandResult } from '../../../contracts/app-state.ts'; -import type { KeyboardCommandResult } from '../../../contracts/keyboard.ts'; -import type { WaitCommandResult } from '../../../contracts/wait.ts'; -import type { PrepareCommandResult } from '../../../contracts/prepare.ts'; -import type { PushCommandResult } from '../../../contracts/push.ts'; -import type { TriggerAppEventCommandResult } from '../../../contracts/app-events.ts'; -import type { DoctorCommandResult } from '../../../contracts/doctor.ts'; -import type { DiffSnapshotCommandResult } from '../../../contracts/diff.ts'; -import type { RecordingCommandResult, TraceCommandResult } from '../../../contracts/recording.ts'; -import type { ReplayCommandResult, ReplaySuiteResult } from '../../../contracts/replay.ts'; + WaitCommandResult, +} from '@agent-device/contracts/interaction'; +import type { DoctorCommandResult } from '@agent-device/contracts/observability'; +import type { RecordingCommandResult, TraceCommandResult } from '@agent-device/contracts/recording'; +import type { ReplayCommandResult, ReplaySuiteResult } from '@agent-device/contracts/replay'; +import { expect, test } from 'vitest'; import type { CommandResult, CommandResultMap } from '../command-result.ts'; /** diff --git a/src/core/command-descriptor/command-result.ts b/src/core/command-descriptor/command-result.ts index 1d41f4f720..3af279f050 100644 --- a/src/core/command-descriptor/command-result.ts +++ b/src/core/command-descriptor/command-result.ts @@ -1,35 +1,37 @@ import type { - ClickCommandResponseData, - FillCommandResponseData, - FindCommandResponseData, - LongPressCommandResponseData, - PressCommandResponseData, -} from '../../contracts/interaction.ts'; -import type { BootCommandResult, ShutdownCommandResult } from '../../contracts/device.ts'; -import type { ViewportCommandResult } from '../../contracts/viewport.ts'; + DiffSnapshotCommandResult, + ViewportCommandResult, +} from '@agent-device/contracts/capture'; +import type { PrepareCommandResult, PushCommandResult } from '@agent-device/contracts/command'; +import type { + AppStateCommandResult, + BootCommandResult, + ShutdownCommandResult, + TriggerAppEventCommandResult, +} from '@agent-device/contracts/device'; import type { AppSwitcherCommandResult, BackCommandResult, + ClickCommandResponseData, + ClipboardCommandResult, + FillCommandResponseData, + FindCommandResponseData, HomeCommandResult, + KeyboardCommandResult, + LongPressCommandResponseData, OrientationCommandResult, + PressCommandResponseData, TvRemoteCommandResult, -} from '../../contracts/navigation.ts'; -import type { ClipboardCommandResult } from '../../contracts/clipboard.ts'; -import type { AppStateCommandResult } from '../../contracts/app-state.ts'; -import type { KeyboardCommandResult } from '../../contracts/keyboard.ts'; -import type { WaitCommandResult } from '../../contracts/wait.ts'; -import type { PrepareCommandResult } from '../../contracts/prepare.ts'; -import type { PushCommandResult } from '../../contracts/push.ts'; -import type { TriggerAppEventCommandResult } from '../../contracts/app-events.ts'; -import type { DoctorCommandResult } from '../../contracts/doctor.ts'; -import type { DiffSnapshotCommandResult } from '../../contracts/diff.ts'; -import type { RecordingCommandResult, TraceCommandResult } from '../../contracts/recording.ts'; -import type { ReplayCommandResult, ReplaySuiteResult } from '../../contracts/replay.ts'; + WaitCommandResult, +} from '@agent-device/contracts/interaction'; +import type { DoctorCommandResult } from '@agent-device/contracts/observability'; +import type { RecordingCommandResult, TraceCommandResult } from '@agent-device/contracts/recording'; +import type { ReplayCommandResult, ReplaySuiteResult } from '@agent-device/contracts/replay'; /** * The additive typed-result spine (ADR-0008, Phase 1 step 6). * - * Maps a command name to the per-command result type from `src/contracts/*`. It + * Maps a command name to the per-command result type from `@agent-device/contracts`. It * is SEEDED, not exhaustive: a command is listed here only once its accurate, * closed result shape lives in the contracts layer. Commands whose daemon * handler spreads dynamic/Record data (screenshot overlays, gesture diff --git a/src/core/command-descriptor/registry.ts b/src/core/command-descriptor/registry.ts index caa02111da..349b4bb33a 100644 --- a/src/core/command-descriptor/registry.ts +++ b/src/core/command-descriptor/registry.ts @@ -1,8 +1,8 @@ import type { CommandCapability } from '../capabilities.ts'; // The typed-flags request from contracts/, not the daemon's server-side refinement: these // descriptors read `command`, `positionals` and `flags` and never touch `internal`. -import type { DispatchedCommand } from '../../contracts/dispatched-command.ts'; -import type { RefFrameEffect } from '../../contracts/ref-frame-effect.ts'; +import type { DispatchedCommand } from '@agent-device/contracts/command'; +import type { RefFrameEffect } from '@agent-device/contracts/replay'; import { isReadOnlyFindAction, parseFindArgs } from '../../selectors/find.ts'; import { resolveWaitBudgetMs } from '../wait-positionals.ts'; import { diff --git a/src/core/command-descriptor/types.ts b/src/core/command-descriptor/types.ts index cadc69c65e..f16589591f 100644 --- a/src/core/command-descriptor/types.ts +++ b/src/core/command-descriptor/types.ts @@ -2,7 +2,7 @@ import type { CommandCapability } from '../capabilities.ts'; import type { DaemonCommandDescriptor } from '../../daemon/daemon-command-registry.ts'; // The typed-flags request from contracts/, not the daemon's server-side refinement: these // descriptors read `command`, `positionals` and `flags` and never touch `internal`. -import type { DispatchedCommand } from '../../contracts/dispatched-command.ts'; +import type { DispatchedCommand } from '@agent-device/contracts/command'; import type { PostActionObservationSupport } from './post-action-observation.ts'; export type ResponseDataFieldTransform = { diff --git a/src/core/dispatch-context.ts b/src/core/dispatch-context.ts index 85e77d2583..396501ece1 100644 --- a/src/core/dispatch-context.ts +++ b/src/core/dispatch-context.ts @@ -1,14 +1,16 @@ // CommandFlags and MaestroRuntimeFlags are declared in contracts/ so both sides of the process // boundary can be stated in terms of them; re-exported here because this is where consumers // already import them from. -export type { CommandFlags } from '../contracts/command-flags.ts'; -import type { ScreenshotDispatchFlags } from '../contracts/screenshot.ts'; -import type { BackMode } from '../contracts/back-mode.ts'; -import type { ClickButton } from '../contracts/click-button.ts'; -import type { ElementSelectorKey } from '../contracts/interactor-types.ts'; -import type { SwipePattern } from '../contracts/scroll-gesture.ts'; -import type { SessionSurface } from '../contracts/session-surface.ts'; -import type { RunnerLogicalLeaseContext } from '../contracts/runner-lease-context.ts'; +export type { CommandFlags } from '@agent-device/contracts/command'; +import type { ScreenshotDispatchFlags } from '@agent-device/contracts/capture'; +import type { + BackMode, + ClickButton, + ElementSelectorKey, + SwipePattern, +} from '@agent-device/contracts/interaction'; +import type { RunnerLogicalLeaseContext } from '@agent-device/contracts/platform'; +import type { SessionSurface } from '@agent-device/contracts/session'; import type { Point } from '@agent-device/kernel/snapshot'; export type DispatchContext = ScreenshotDispatchFlags & { diff --git a/src/core/dispatch-interactions.ts b/src/core/dispatch-interactions.ts index 718cdab415..b0a90d540c 100644 --- a/src/core/dispatch-interactions.ts +++ b/src/core/dispatch-interactions.ts @@ -1,4 +1,17 @@ -import { AppError } from '@agent-device/kernel/errors'; +import { + assertExclusiveScrollDistanceInputs, + getClickButtonValidationError, + honoredScrollDurationMs, + MAESTRO_NON_HITTABLE_FALLBACK_MESSAGE, + normalizeScrollDurationMs, + parseScrollDirection, + resolveClickButton, + type ClickButton, + type Interactor, + type RunnerCallOptions, + type ScrollCommandOptions, + type ScrollDirection, +} from '@agent-device/contracts/interaction'; import { isIosFamily, isMacOs, @@ -6,20 +19,8 @@ import { publicPlatformString, type DeviceInfo, } from '@agent-device/kernel/device'; -import { successText, withSuccessText } from '../utils/success-text.ts'; -import { findMistargetedTypeRefToken } from '../utils/type-target-warning.ts'; -import { parseScrollDirection, type ScrollDirection } from '../contracts/scroll-gesture.ts'; -import { - assertExclusiveScrollDistanceInputs, - honoredScrollDurationMs, - normalizeScrollDurationMs, - type ScrollCommandOptions, -} from '../contracts/scroll-command.ts'; -import { - getClickButtonValidationError, - resolveClickButton, - type ClickButton, -} from '../contracts/click-button.ts'; +import { AppError } from '@agent-device/kernel/errors'; +import type { RunnerSequenceStep } from '../platforms/apple/core/runner/runner-contract.ts'; import { captureScrollEdgeState, formatScrollEdgeMessage, @@ -27,20 +28,16 @@ import { type ScrollEdge, type ScrollEdgeState, } from '../utils/scroll-edge-state.ts'; +import { successText, withSuccessText } from '../utils/success-text.ts'; +import { findMistargetedTypeRefToken } from '../utils/type-target-warning.ts'; +import type { DispatchContext } from './dispatch-context.ts'; import { - requireIntInRange, - shouldUseIosPressSequence, chunkRunnerSequenceStepsByBudget, computeDeterministicJitter, + requireIntInRange, runRepeatedSeries, + shouldUseIosPressSequence, } from './dispatch-series.ts'; -import type { RunnerSequenceStep } from '../platforms/apple/core/runner/runner-contract.ts'; -import type { DispatchContext } from './dispatch-context.ts'; -import { - MAESTRO_NON_HITTABLE_FALLBACK_MESSAGE, - type Interactor, - type RunnerCallOptions, -} from '../contracts/interactor-types.ts'; type ScrollTarget = { direction: ScrollDirection; diff --git a/src/core/dispatch-payload.ts b/src/core/dispatch-payload.ts index 7abe6f776c..c581c86224 100644 --- a/src/core/dispatch-payload.ts +++ b/src/core/dispatch-payload.ts @@ -1,7 +1,7 @@ import { promises as fs } from 'node:fs'; import { AppError } from '@agent-device/kernel/errors'; import { resolvePayloadInput } from '../utils/payload-input.ts'; -import type { JsonObject } from '../contracts/json.ts'; +import type { JsonObject } from '@agent-device/contracts/client'; export async function readNotificationPayload(payloadArg: string): Promise { const source = resolvePayloadInput(payloadArg, { subject: 'Push payload' }); diff --git a/src/core/dispatch-resolve.ts b/src/core/dispatch-resolve.ts index 69b2134347..cf8832d247 100644 --- a/src/core/dispatch-resolve.ts +++ b/src/core/dispatch-resolve.ts @@ -1,23 +1,25 @@ -import type { DeviceInventoryProvider } from '../contracts/device-provider.ts'; -import { AsyncLocalStorage } from 'node:async_hooks'; -import { AppError } from '@agent-device/kernel/errors'; +import type { CliFlags } from '@agent-device/contracts/command'; +import type { + DeviceInventoryProvider, + DeviceInventoryRequest, +} from '@agent-device/contracts/device'; import { isApplePlatform, isIosFamily, matchesDeviceSelector, - resolveDevice, resolveAppleSimulatorSetPathForSelector, + resolveDevice, type DeviceInfo, type DeviceTarget, type PlatformSelector, } from '@agent-device/kernel/device'; -import { withDiagnosticTimer } from '../utils/diagnostics.ts'; +import { AppError } from '@agent-device/kernel/errors'; +import { AsyncLocalStorage } from 'node:async_hooks'; import { resolveAndroidSerialAllowlist, resolveIosSimulatorDeviceSetPath, } from '../utils/device-isolation.ts'; -import type { CliFlags } from '../contracts/cli-flags.ts'; -import type { DeviceInventoryRequest } from '../contracts/device-inventory.ts'; +import { withDiagnosticTimer } from '../utils/diagnostics.ts'; import { listLocalDeviceInventory } from './platform-inventory.ts'; export type ResolveDeviceFlags = Pick< CliFlags, diff --git a/src/core/dispatch.ts b/src/core/dispatch.ts index 0343a1ca3d..1a429b66fe 100644 --- a/src/core/dispatch.ts +++ b/src/core/dispatch.ts @@ -1,21 +1,24 @@ -import { promises as fs } from 'node:fs'; -import pathModule from 'node:path'; -import { AppError } from '@agent-device/kernel/errors'; -import { isIosFamily, type DeviceInfo } from '@agent-device/kernel/device'; -import { getInteractor } from './interactors.ts'; -import type { Interactor, RunnerContext } from '../contracts/interactor-types.ts'; -import { isDeepLinkTarget } from '../contracts/open-target.ts'; -import { parseTriggerAppEventArgs, resolveAppEventUrl } from './app-events.ts'; +import { screenshotOptionsFromFlags } from '@agent-device/contracts/capture'; +import { isDeepLinkTarget } from '@agent-device/contracts/command'; +import { parseDeviceRotation } from '@agent-device/contracts/device'; +import type { GesturePlan, Interactor, RunnerContext } from '@agent-device/contracts/interaction'; +import { parseTvRemoteButton } from '@agent-device/contracts/interaction'; import { LAUNCH_CONSOLE_DIRECT_APP_ONLY_MESSAGE, LAUNCH_CONSOLE_IOS_SIMULATOR_ONLY_MESSAGE, -} from '../contracts/launch-console.ts'; +} from '@agent-device/contracts/observability'; +import { isIosFamily, type DeviceInfo } from '@agent-device/kernel/device'; +import { AppError } from '@agent-device/kernel/errors'; +import type { Rect } from '@agent-device/kernel/snapshot'; +import { promises as fs } from 'node:fs'; +import pathModule from 'node:path'; import { emitDiagnostic, withDiagnosticTimer } from '../utils/diagnostics.ts'; +import { isKeyboardAction, type KeyboardAction } from '../utils/keyboard-actions.ts'; import { readLocationCoordinate } from '../utils/location-coordinates.ts'; import { successText, withSuccessText } from '../utils/success-text.ts'; import { requireIntInRange } from '../utils/validation.ts'; -import { screenshotOptionsFromFlags } from '../contracts/screenshot.ts'; -import { isKeyboardAction, type KeyboardAction } from '../utils/keyboard-actions.ts'; +import { parseTriggerAppEventArgs, resolveAppEventUrl } from './app-events.ts'; +import type { DescriptorDispatchCommandName } from './command-descriptor/registry.ts'; import type { DispatchContext } from './dispatch-context.ts'; import { handleFillCommand, @@ -27,15 +30,11 @@ import { handleTypeCommand, } from './dispatch-interactions.ts'; import { readNotificationPayload } from './dispatch-payload.ts'; -import { parseDeviceRotation } from '../contracts/device-rotation.ts'; -import { parseTvRemoteButton } from '../contracts/tv-remote.ts'; +import { getInteractor } from './interactors.ts'; import { readViewportDimension } from './viewport-dimension.ts'; -import type { DescriptorDispatchCommandName } from './command-descriptor/registry.ts'; -import type { GesturePlan } from '../contracts/gesture-plan-types.ts'; -import type { Rect } from '@agent-device/kernel/snapshot'; -export { resolveTargetDevice } from './dispatch-resolve.ts'; export type { CommandFlags, DispatchContext } from './dispatch-context.ts'; +export { resolveTargetDevice } from './dispatch-resolve.ts'; export async function dispatchCommand( device: DeviceInfo, diff --git a/src/core/interactors.ts b/src/core/interactors.ts index d7a00658a1..d9344946e0 100644 --- a/src/core/interactors.ts +++ b/src/core/interactors.ts @@ -1,8 +1,8 @@ import { publicPlatformString, type DeviceInfo } from '@agent-device/kernel/device'; import { AppError } from '@agent-device/kernel/errors'; import { getProviderDeviceInteractor, isActiveProviderDevice } from '../provider-device-runtime.ts'; -import type { Interactor, RunnerContext } from '../contracts/interactor-types.ts'; -import { getPlugin } from '../contracts/platform-plugin.ts'; +import type { Interactor, RunnerContext } from '@agent-device/contracts/interaction'; +import { getPlugin } from './platform-plugin-registry.ts'; import { registerBuiltinPlatformPlugins } from './interactors/register-builtins.ts'; // Populate the platform-plugin registry once, at module load (only registers diff --git a/src/core/interactors/android.ts b/src/core/interactors/android.ts index 1b43fa4032..3295372225 100644 --- a/src/core/interactors/android.ts +++ b/src/core/interactors/android.ts @@ -34,8 +34,8 @@ import { screenshotAndroid } from '../../platforms/android/screenshot.ts'; import { withDiagnosticTimer } from '../../utils/diagnostics.ts'; import { withMethodScope } from '../../utils/method-scope.ts'; import type { DeviceInfo } from '@agent-device/kernel/device'; -import type { Interactor, RunnerContext } from '../../contracts/interactor-types.ts'; -import { snapshotCaptureAnnotationsFrom } from '../../contracts/snapshot-capture-annotations.ts'; +import type { Interactor, RunnerContext } from '@agent-device/contracts/interaction'; +import { snapshotCaptureAnnotationsFrom } from '@agent-device/contracts/capture'; export function createAndroidInteractor( device: DeviceInfo, diff --git a/src/core/interactors/linux.ts b/src/core/interactors/linux.ts index fa2753fd14..4f5b64bf59 100644 --- a/src/core/interactors/linux.ts +++ b/src/core/interactors/linux.ts @@ -17,10 +17,10 @@ import { swipeLinux, typeLinux, } from '../../platforms/linux/input-actions.ts'; -import { singlePointerPlanEndpoints } from '../../contracts/gesture-plan.ts'; +import { singlePointerPlanEndpoints } from '@agent-device/contracts/interaction'; import { screenshotLinux } from '../../platforms/linux/screenshot.ts'; import { snapshotLinux } from '../../platforms/linux/snapshot.ts'; -import type { Interactor } from '../../contracts/interactor-types.ts'; +import type { Interactor } from '@agent-device/contracts/interaction'; export function createLinuxInteractor(): Interactor { return { diff --git a/src/core/interactors/register-builtins.ts b/src/core/interactors/register-builtins.ts index bba5ee6381..f7cb55939e 100644 --- a/src/core/interactors/register-builtins.ts +++ b/src/core/interactors/register-builtins.ts @@ -1,14 +1,12 @@ -import { registerPlatformPlugin, type PlatformPlugin } from '../../contracts/platform-plugin.ts'; +import type { RunnerContext } from '@agent-device/contracts/interaction'; +import type { PlatformPlugin } from '@agent-device/contracts/platform'; +import { registerPlatformPlugin } from '../platform-plugin-registry.ts'; import { applePlugin } from '../../platforms/apple/plugin.ts'; import { vegaPlugin } from '../../platforms/vega/plugin.ts'; import { PUBLIC_COMMANDS } from '../../command-catalog.ts'; -import { isAudioProbeSupportedDevice } from '../../contracts/audio-probe-support.ts'; -import { - WEB_DESKTOP_DEVICE, - type DeviceInventoryRequest, -} from '../../contracts/device-inventory.ts'; +import { isAudioProbeSupportedDevice } from '@agent-device/contracts/platform'; +import { WEB_DESKTOP_DEVICE, type DeviceInventoryRequest } from '@agent-device/contracts/device'; import type { Platform, DeviceInfo } from '@agent-device/kernel/device'; -import type { RunnerContext } from '../../contracts/interactor-types.ts'; import { resolveAndroidDiscoverySerialAllowlist } from '../platform-inventory.ts'; // The builtin-plugin wiring lives at the interactor seam (src/core/interactors/) — diff --git a/src/core/interactors/web.ts b/src/core/interactors/web.ts index bb486f4292..4d16a7cc76 100644 --- a/src/core/interactors/web.ts +++ b/src/core/interactors/web.ts @@ -1,4 +1,4 @@ -import type { Interactor } from '../../contracts/interactor-types.ts'; +import type { Interactor } from '@agent-device/contracts/interaction'; import { AppError } from '@agent-device/kernel/errors'; import { withDiagnosticTimer } from '../../utils/diagnostics.ts'; import { resolveWebProvider } from '../../platforms/web/provider.ts'; diff --git a/src/core/platform-inventory.ts b/src/core/platform-inventory.ts index 9c8027035f..c0c05239cd 100644 --- a/src/core/platform-inventory.ts +++ b/src/core/platform-inventory.ts @@ -4,7 +4,7 @@ import { shouldUseHostMacFastPath, WEB_DESKTOP_DEVICE, type DeviceInventoryRequest, -} from '../contracts/device-inventory.ts'; +} from '@agent-device/contracts/device'; export async function listLocalDeviceInventory( request: DeviceInventoryRequest, diff --git a/src/core/platform-plugin-registry.ts b/src/core/platform-plugin-registry.ts new file mode 100644 index 0000000000..56d293cfa7 --- /dev/null +++ b/src/core/platform-plugin-registry.ts @@ -0,0 +1,35 @@ +import type { Platform } from '@agent-device/kernel/device'; +import { AppError } from '@agent-device/kernel/errors'; +import type { PlatformPlugin } from '@agent-device/contracts/platform'; + +const registry = new Map(); + +/** + * Registers `plugin` for each leaf platform it owns. Throws on duplicate + * registration so platform ownership cannot silently become last-writer-wins. + */ +export function registerPlatformPlugin(plugin: PlatformPlugin): void { + for (const platform of plugin.platforms) { + if (registry.has(platform)) { + throw new Error(`PlatformPlugin already registered for platform "${platform}"`); + } + registry.set(platform, plugin); + } +} + +export function getPlugin(platform: Platform): PlatformPlugin { + const plugin = registry.get(platform); + if (!plugin) { + throw new AppError('UNSUPPORTED_PLATFORM', `Unsupported platform: ${platform}`); + } + return plugin; +} + +export function tryGetPlugin(platform: Platform): PlatformPlugin | undefined { + return registry.get(platform); +} + +/** @internal Registered leaf platforms in insertion order, for parity gates. */ +export function registeredPlatforms(): Platform[] { + return [...registry.keys()]; +} diff --git a/src/core/snapshot-chrome.ts b/src/core/snapshot-chrome.ts index d3914be1dc..8bec0342d9 100644 --- a/src/core/snapshot-chrome.ts +++ b/src/core/snapshot-chrome.ts @@ -2,7 +2,7 @@ import { ANDROID_SYSTEM_CHROME_PACKAGE, hasAndroidSystemChromeProvenance, isAndroidSystemChromeWindowResourceId, -} from '../contracts/android-system-chrome.ts'; +} from '@agent-device/contracts/platform'; import type { SnapshotNode } from '@agent-device/kernel/snapshot'; import { isAndroidInputMethodSnapshotNode } from '../snapshot/android-input-method-overlays.ts'; import { normalizeType } from '../utils/text-surface.ts'; diff --git a/src/daemon/__tests__/applog-plugin-routing-parity.test.ts b/src/daemon/__tests__/applog-plugin-routing-parity.test.ts index 2b97452a6a..995ea020c9 100644 --- a/src/daemon/__tests__/applog-plugin-routing-parity.test.ts +++ b/src/daemon/__tests__/applog-plugin-routing-parity.test.ts @@ -19,10 +19,10 @@ import { TVOS_SIMULATOR, WEB_DESKTOP_DEVICE, } from '../../__tests__/test-utils/index.ts'; -import { getPlugin } from '../../contracts/platform-plugin.ts'; +import { getPlugin } from '../../core/platform-plugin-registry.ts'; import { registerBuiltinPlatformPlugins } from '../../core/interactors/register-builtins.ts'; import { resolveLogBackend } from '../app-log.ts'; -import type { LogBackend } from '../../contracts/logs.ts'; +import type { LogBackend } from '@agent-device/contracts/observability'; // Phase 3 step b.3 (issue #974) parity gate for the daemon app-log facet. The // per-platform branch of `resolveLogBackend` now flows through the PlatformPlugin diff --git a/src/daemon/__tests__/perf-plugin-routing-parity.test.ts b/src/daemon/__tests__/perf-plugin-routing-parity.test.ts index b0e31c3d87..b07d8b7b76 100644 --- a/src/daemon/__tests__/perf-plugin-routing-parity.test.ts +++ b/src/daemon/__tests__/perf-plugin-routing-parity.test.ts @@ -1,4 +1,4 @@ -import type { PerfMetricsSamplerTag } from '../../contracts/perf.ts'; +import type { PerfMetricsSamplerTag } from '@agent-device/contracts/observability'; import assert from 'node:assert/strict'; import { test } from 'vitest'; import { AppError } from '@agent-device/kernel/errors'; @@ -23,7 +23,7 @@ import { TVOS_SIMULATOR, WEB_DESKTOP_DEVICE, } from '../../__tests__/test-utils/index.ts'; -import { getPlugin } from '../../contracts/platform-plugin.ts'; +import { getPlugin } from '../../core/platform-plugin-registry.ts'; import { registerBuiltinPlatformPlugins } from '../../core/interactors/register-builtins.ts'; import { buildPerfResponseData } from '../handlers/session-perf.ts'; import { PERF_UNAVAILABLE_REASON } from '../handlers/session-startup-metrics.ts'; diff --git a/src/daemon/__tests__/provider-lease-expiry.test.ts b/src/daemon/__tests__/provider-lease-expiry.test.ts index 634e069786..00a06fc1a3 100644 --- a/src/daemon/__tests__/provider-lease-expiry.test.ts +++ b/src/daemon/__tests__/provider-lease-expiry.test.ts @@ -4,7 +4,7 @@ import path from 'node:path'; import { expect, test, vi } from 'vitest'; import { createExpiredProviderLeaseReleaser } from '../provider-lease-expiry.ts'; import { LeaseRegistry } from '../lease-registry.ts'; -import type { DeviceLease } from '../../contracts/device-provider.ts'; +import type { DeviceLease } from '@agent-device/contracts/device'; test('retries an expired live-only provider lease release after a transient failure', async () => { vi.useFakeTimers(); diff --git a/src/daemon/__tests__/providers-plugin-routing-parity.test.ts b/src/daemon/__tests__/providers-plugin-routing-parity.test.ts index b6a5ff0b2f..814088977f 100644 --- a/src/daemon/__tests__/providers-plugin-routing-parity.test.ts +++ b/src/daemon/__tests__/providers-plugin-routing-parity.test.ts @@ -1,4 +1,4 @@ -import type { PlatformGatedProviderResolverKey } from '../../contracts/platform-providers.ts'; +import type { PlatformGatedProviderResolverKey } from '@agent-device/contracts/platform'; import assert from 'node:assert/strict'; import { test } from 'vitest'; import { @@ -22,7 +22,7 @@ import { VISIONOS_SIMULATOR, WEB_DESKTOP_DEVICE, } from '../../__tests__/test-utils/index.ts'; -import { getPlugin, tryGetPlugin } from '../../contracts/platform-plugin.ts'; +import { getPlugin, tryGetPlugin } from '../../core/platform-plugin-registry.ts'; import { registerBuiltinPlatformPlugins } from '../../core/interactors/register-builtins.ts'; import { withRequestPlatformProviderScope, diff --git a/src/daemon/__tests__/recording-plugin-routing-parity.test.ts b/src/daemon/__tests__/recording-plugin-routing-parity.test.ts index d1ab57c262..3a655663fe 100644 --- a/src/daemon/__tests__/recording-plugin-routing-parity.test.ts +++ b/src/daemon/__tests__/recording-plugin-routing-parity.test.ts @@ -1,4 +1,4 @@ -import type { RecordingBackendTag } from '../../contracts/recording.ts'; +import type { RecordingBackendTag } from '@agent-device/contracts/recording'; import assert from 'node:assert/strict'; import { test } from 'vitest'; import { @@ -22,7 +22,7 @@ import { VISIONOS_SIMULATOR, WEB_DESKTOP_DEVICE, } from '../../__tests__/test-utils/index.ts'; -import { getPlugin, tryGetPlugin } from '../../contracts/platform-plugin.ts'; +import { getPlugin, tryGetPlugin } from '../../core/platform-plugin-registry.ts'; import { registerBuiltinPlatformPlugins } from '../../core/interactors/register-builtins.ts'; import { resolveRecordingBackendForDevice } from '../handlers/record-trace-recording-backends.ts'; diff --git a/src/daemon/__tests__/request-router-android-modal.test.ts b/src/daemon/__tests__/request-router-android-modal.test.ts index 45ac8b6431..c75ea0cd30 100644 --- a/src/daemon/__tests__/request-router-android-modal.test.ts +++ b/src/daemon/__tests__/request-router-android-modal.test.ts @@ -21,10 +21,8 @@ import { createRequestHandler } from '../request-router.ts'; import type { SessionState } from '../types.ts'; import { LeaseRegistry } from '../lease-registry.ts'; import { makeSessionStore } from '../../__tests__/test-utils/store-factory.ts'; -import { - createProviderDeviceRuntimeRequestProviders, - type ProviderDeviceRuntime, -} from '../../provider-device-runtime.ts'; +import { createProviderDeviceRuntimeRequestProviders } from '../../provider-device-runtime.ts'; +import type { ProviderDeviceRuntime } from '@agent-device/contracts/device'; vi.mock('../../platforms/android/snapshot.ts', async (importOriginal) => { const actual = await importOriginal(); diff --git a/src/daemon/app-log-process.ts b/src/daemon/app-log-process.ts index 6dbe44f2e9..c1a064f1a0 100644 --- a/src/daemon/app-log-process.ts +++ b/src/daemon/app-log-process.ts @@ -1,7 +1,7 @@ import fs from 'node:fs'; import path from 'node:path'; import { readProcessCommand, readProcessStartTime } from '../utils/host-process.ts'; -import type { LogBackend } from '../contracts/logs.ts'; +import type { LogBackend } from '@agent-device/contracts/observability'; import type { ExecResult } from '../utils/exec.ts'; export const APP_LOG_PID_FILENAME = 'app-log.pid'; diff --git a/src/daemon/app-log.ts b/src/daemon/app-log.ts index 3bb12e4ce2..be2e51d273 100644 --- a/src/daemon/app-log.ts +++ b/src/daemon/app-log.ts @@ -2,7 +2,7 @@ import fs from 'node:fs'; import path from 'node:path'; import { isIosFamily, isMacOs, type DeviceInfo } from '@agent-device/kernel/device'; import { AppError } from '@agent-device/kernel/errors'; -import { tryGetPlugin } from '../contracts/platform-plugin.ts'; +import { tryGetPlugin } from '../core/platform-plugin-registry.ts'; import { registerBuiltinPlatformPlugins } from '../core/interactors/register-builtins.ts'; import { createScopedProvider } from '../utils/scoped-provider.ts'; import { @@ -27,7 +27,7 @@ import { type NetworkDump, type NetworkIncludeMode, } from './network-log.ts'; -import type { LogBackend } from '../contracts/logs.ts'; +import type { LogBackend } from '@agent-device/contracts/observability'; // Populate the PlatformPlugin registry once at module load (idempotent; registers // only lazy closures, so no leaf code is imported and CLI cold-start is unaffected diff --git a/src/daemon/apple-runner-options.ts b/src/daemon/apple-runner-options.ts index 4215d15f4a..37bf0a9822 100644 --- a/src/daemon/apple-runner-options.ts +++ b/src/daemon/apple-runner-options.ts @@ -1,5 +1,5 @@ -import { isDeepLinkTarget } from '../contracts/open-target.ts'; -import type { SessionSurface } from '../contracts/session-surface.ts'; +import { isDeepLinkTarget } from '@agent-device/contracts/command'; +import type { SessionSurface } from '@agent-device/contracts/session'; import type { AppleRunnerLifecycleOptions } from '../platforms/apple/core/runner/runner-provider.ts'; import { prewarmAppleRunnerCache } from '../platforms/apple/core/runner/runner-client.ts'; import { isIosFamily, type DeviceInfo } from '@agent-device/kernel/device'; diff --git a/src/daemon/audio-probe.ts b/src/daemon/audio-probe.ts index 5944fff9bc..e5da65cb88 100644 --- a/src/daemon/audio-probe.ts +++ b/src/daemon/audio-probe.ts @@ -4,7 +4,7 @@ import { emptyAudioProbeResult, normalizeAudioProbeRecord, type AudioProbeResult, -} from '../contracts/audio-probe-result.ts'; +} from '@agent-device/contracts/platform'; import type { HostAudioProbeBackend } from '../platforms/audio-probe-backend.ts'; import { AppError } from '@agent-device/kernel/errors'; import { sleep } from '../utils/timeouts.ts'; diff --git a/src/daemon/client/daemon-client-progress.ts b/src/daemon/client/daemon-client-progress.ts index c1aa1e0004..404bf53268 100644 --- a/src/daemon/client/daemon-client-progress.ts +++ b/src/daemon/client/daemon-client-progress.ts @@ -4,7 +4,7 @@ import { AppError } from '@agent-device/kernel/errors'; import type { DaemonRequest, DaemonResponse } from '../types.ts'; import type { RequestProgressEvent, RequestProgressSink } from '../../request/progress.ts'; import { consumeTextLines } from '../../utils/line-stream.ts'; -import { markDoctorProgressRendered } from '../../contracts/cli-doctor-output.ts'; +import { markDoctorProgressRendered } from '../../utils/doctor-progress.ts'; import { isDaemonProgressEnvelope, isDaemonResponseEnvelope, diff --git a/src/daemon/context.ts b/src/daemon/context.ts index 1a3c6ee73b..26de7d0411 100644 --- a/src/daemon/context.ts +++ b/src/daemon/context.ts @@ -1,9 +1,9 @@ import type { CommandFlags, DispatchContext } from '../core/dispatch-context.ts'; -import { resolveClickButton } from '../contracts/click-button.ts'; +import { resolveClickButton } from '@agent-device/contracts/interaction'; import { screenshotFlagsFromOptions, type ScreenshotRuntimeFlags, -} from '../contracts/screenshot.ts'; +} from '@agent-device/contracts/capture'; import { getDiagnosticsMeta } from '../utils/diagnostics.ts'; import { resolveRunnerLogicalLeaseContext } from './lease-context.ts'; import type { DaemonRequest } from './types.ts'; diff --git a/src/daemon/daemon-command-registry.ts b/src/daemon/daemon-command-registry.ts index c644027e2d..28fd833e58 100644 --- a/src/daemon/daemon-command-registry.ts +++ b/src/daemon/daemon-command-registry.ts @@ -9,8 +9,8 @@ export type SessionCommandKind = 'inventory' | 'state' | 'observability' | 'publ // Declared in contracts/ so core/ can classify commands without importing the daemon; // re-exported here because the descriptor shape below is stated in terms of it. -export type { RefFrameEffect } from '../contracts/ref-frame-effect.ts'; -import type { RefFrameEffect } from '../contracts/ref-frame-effect.ts'; +export type { RefFrameEffect } from '@agent-device/contracts/replay'; +import type { RefFrameEffect } from '@agent-device/contracts/replay'; /** * Request-sensitive form of {@link RefFrameEffect}. Commands whose subactions diff --git a/src/daemon/daemon-shutdown-report.ts b/src/daemon/daemon-shutdown-report.ts index 4dcdbd7f59..53128eb98c 100644 --- a/src/daemon/daemon-shutdown-report.ts +++ b/src/daemon/daemon-shutdown-report.ts @@ -1,6 +1,6 @@ import fs from 'node:fs'; import path from 'node:path'; -import type { DeviceLease } from '../contracts/device-provider.ts'; +import type { DeviceLease } from '@agent-device/contracts/device'; const SHUTDOWN_REPORT_FILE = 'daemon-shutdown.json'; diff --git a/src/daemon/direct-ios-selector.ts b/src/daemon/direct-ios-selector.ts index f07e0c5536..0df9cd39d2 100644 --- a/src/daemon/direct-ios-selector.ts +++ b/src/daemon/direct-ios-selector.ts @@ -3,7 +3,7 @@ import { isActiveProviderDevice } from '../provider-device-runtime.ts'; import type { SessionState } from './types.ts'; import { tryParseSelectorChain } from '../selectors/index.ts'; import { asAppError } from '@agent-device/kernel/errors'; -import type { ElementSelectorTapOptions } from '../contracts/interactor-types.ts'; +import type { ElementSelectorTapOptions } from '@agent-device/contracts/interaction'; export type DirectIosSelectorTarget = ElementSelectorTapOptions & { raw: string }; diff --git a/src/daemon/handlers/__tests__/session-doctor-android.test.ts b/src/daemon/handlers/__tests__/session-doctor-android.test.ts index 43da5bdd11..27ebb16654 100644 --- a/src/daemon/handlers/__tests__/session-doctor-android.test.ts +++ b/src/daemon/handlers/__tests__/session-doctor-android.test.ts @@ -34,7 +34,7 @@ import { setAndroidTestImeActiveForTests, } from '../../../platforms/android/ime-lifecycle.ts'; import type { AndroidAdbExecutor } from '../../../platforms/android/adb-executor.ts'; -import type { DoctorCheck } from '../../../contracts/doctor.ts'; +import type { DoctorCheck } from '@agent-device/contracts/observability'; afterEach(() => { resetAndroidTestImeActivationCacheForTests(); diff --git a/src/daemon/handlers/__tests__/session-doctor-device.test.ts b/src/daemon/handlers/__tests__/session-doctor-device.test.ts index 6d904ecc4e..b343b44ccc 100644 --- a/src/daemon/handlers/__tests__/session-doctor-device.test.ts +++ b/src/daemon/handlers/__tests__/session-doctor-device.test.ts @@ -6,7 +6,7 @@ import type { DeviceInfo } from '@agent-device/kernel/device'; import { attachAdbFailureHint } from '../../../platforms/android/adb-executor.ts'; import type { DaemonRequest } from '../../types.ts'; import { appendDeviceInventoryCheck } from '../session-doctor-device.ts'; -import type { DoctorCheck } from '../../../contracts/doctor.ts'; +import type { DoctorCheck } from '@agent-device/contracts/observability'; const BOOTED_IOS_SIMULATOR: DeviceInfo = { platform: 'apple', diff --git a/src/daemon/handlers/__tests__/session-doctor-toolchain.test.ts b/src/daemon/handlers/__tests__/session-doctor-toolchain.test.ts index 2403862265..a75cbab134 100644 --- a/src/daemon/handlers/__tests__/session-doctor-toolchain.test.ts +++ b/src/daemon/handlers/__tests__/session-doctor-toolchain.test.ts @@ -3,7 +3,7 @@ import { test } from 'vitest'; import type { VegaToolProvider } from '../../../platforms/vega/tool-provider.ts'; import { withVegaToolProvider } from '../../../platforms/vega/tool-provider.ts'; import { appendToolchainChecks } from '../session-doctor-toolchain.ts'; -import type { DoctorCheck } from '../../../contracts/doctor.ts'; +import type { DoctorCheck } from '@agent-device/contracts/observability'; test('Vega doctor reports CLI version and connected-device readiness through semantic provider', async () => { const provider = makeVegaProvider('VirtualDevice : tv - aarch64 - VegaOS\n'); diff --git a/src/daemon/handlers/__tests__/session-doctor-web.test.ts b/src/daemon/handlers/__tests__/session-doctor-web.test.ts index f07c8d6e21..517979ece4 100644 --- a/src/daemon/handlers/__tests__/session-doctor-web.test.ts +++ b/src/daemon/handlers/__tests__/session-doctor-web.test.ts @@ -5,7 +5,7 @@ import path from 'node:path'; import { beforeEach, test, vi } from 'vitest'; import type { AgentBrowserProcessSummary } from '../../../platforms/web/agent-browser-lifecycle.ts'; import { installFakeManagedAgentBrowser } from '../../../platforms/web/__tests__/test-utils.ts'; -import type { DoctorCheck } from '../../../contracts/doctor.ts'; +import type { DoctorCheck } from '@agent-device/contracts/observability'; vi.mock('../../../platforms/web/agent-browser-lifecycle.ts', async () => { const actual = await vi.importActual< diff --git a/src/daemon/handlers/__tests__/snapshot-handler.test.ts b/src/daemon/handlers/__tests__/snapshot-handler.test.ts index 43b070f778..74fbc0cdc4 100644 --- a/src/daemon/handlers/__tests__/snapshot-handler.test.ts +++ b/src/daemon/handlers/__tests__/snapshot-handler.test.ts @@ -13,7 +13,7 @@ import { buildSnapshotSignatures } from '../../android-snapshot-freshness.ts'; import { buildInteractionSurfaceSignature } from '../../interaction-outcome-policy.ts'; import { buildSnapshotPresentationKey } from '@agent-device/kernel/snapshot'; import { snapshotCliOutput } from '../../../commands/capture/output.ts'; -import type { CaptureSnapshotResult } from '../../../contracts/client-capture.ts'; +import type { CaptureSnapshotResult } from '@agent-device/contracts/client'; vi.mock('../../../core/dispatch.ts', async (importOriginal) => { const actual = await importOriginal(); diff --git a/src/daemon/handlers/install-source.ts b/src/daemon/handlers/install-source.ts index fdf478a94e..a31256260a 100644 --- a/src/daemon/handlers/install-source.ts +++ b/src/daemon/handlers/install-source.ts @@ -1,8 +1,6 @@ import { isIosFamily } from '@agent-device/kernel/device'; -import { - installProviderDeviceInstallablePath, - type ProviderDeviceInstallResult, -} from '../../provider-device-runtime.ts'; +import type { ProviderDeviceInstallResult } from '@agent-device/contracts/device'; +import { installProviderDeviceInstallablePath } from '../../provider-device-runtime.ts'; import { resolveTargetDevice, type CommandFlags } from '../../core/dispatch.ts'; import { ensureDeviceReady } from '../device-ready.ts'; import { getRequestSignal } from '../../request/cancel.ts'; @@ -15,7 +13,7 @@ import { resolveInstallSource } from '../install-source-resolution.ts'; import { SessionStore } from '../session-store.ts'; import type { DaemonRequest, DaemonResponse, SessionState } from '../types.ts'; -import { resolveInstallFromSourceResultTarget } from '../../contracts/result-serialization.ts'; +import { resolveInstallFromSourceResultTarget } from '../../utils/result-serialization.ts'; import { AppError, normalizeError } from '@agent-device/kernel/errors'; import { withSuccessText } from '../../utils/success-text.ts'; import { requireCommandSupported } from './response.ts'; diff --git a/src/daemon/handlers/interaction-flags.ts b/src/daemon/handlers/interaction-flags.ts index ed2d0cfeed..b894acad83 100644 --- a/src/daemon/handlers/interaction-flags.ts +++ b/src/daemon/handlers/interaction-flags.ts @@ -1,6 +1,6 @@ import type { CommandFlags } from '../../core/dispatch.ts'; import type { PostActionObservationCommandName } from '../../core/command-descriptor/post-action-observation.ts'; -import type { SettleParams } from '../../contracts/interaction.ts'; +import type { SettleParams } from '@agent-device/contracts/interaction'; import type { DaemonResponse } from '../types.ts'; import { errorResponse } from './response.ts'; diff --git a/src/daemon/handlers/interaction-gesture.ts b/src/daemon/handlers/interaction-gesture.ts index 5555ddb2d6..1bae0baad2 100644 --- a/src/daemon/handlers/interaction-gesture.ts +++ b/src/daemon/handlers/interaction-gesture.ts @@ -1,26 +1,25 @@ -import { readGesturePayload, type GesturePayload } from '../../contracts/gesture-input.ts'; +import { readOptionalInteger } from '@agent-device/contracts/command'; import { assertNoRemovedSwipeInput, + GESTURE_FLING_DURATION_MS, gesturePayloadToPositionals, normalizePublicGesture, normalizePublicSwipeMotion, - type SwipePayload, -} from '../../contracts/gesture-normalization.ts'; -import { requireGestureSupported } from '../../core/capabilities.ts'; -import { GESTURE_FLING_DURATION_MS } from '../../contracts/gesture-plan.ts'; -import { + readGesturePayload, SWIPE_PAUSE_MAX_MS, SWIPE_REPETITION_MAX, SWIPE_SERIES_MAX_SCHEDULED_DURATION_MS, -} from '../../contracts/scroll-gesture.ts'; + type GesturePayload, + type GestureSemanticInput, + type SwipePayload, +} from '@agent-device/contracts/interaction'; import { AppError, normalizeError } from '@agent-device/kernel/errors'; -import { readOptionalInteger } from '../../contracts/input-validation.ts'; import type { Point } from '@agent-device/kernel/snapshot'; -import type { GestureSemanticInput } from '../../contracts/gesture-plan-types.ts'; +import { requireGestureSupported } from '../../core/capabilities.ts'; import { isActiveProviderDevice } from '../../provider-device-runtime.ts'; import { sleep } from '../../utils/timeouts.ts'; -import type { DaemonResponse, SessionState } from '../types.ts'; import { ensureAndroidBlockingSystemDialogReady } from '../android-system-dialog.ts'; +import type { DaemonResponse, SessionState } from '../types.ts'; import type { InteractionHandlerParams } from './interaction-common.ts'; import { finalizeTouchInteraction } from './interaction-common.ts'; import { createInteractionRuntime } from './interaction-runtime.ts'; diff --git a/src/daemon/handlers/interaction-touch-reference-frame.ts b/src/daemon/handlers/interaction-touch-reference-frame.ts index 731cf23ea9..58a791e5a3 100644 --- a/src/daemon/handlers/interaction-touch-reference-frame.ts +++ b/src/daemon/handlers/interaction-touch-reference-frame.ts @@ -1,5 +1,5 @@ import type { CommandFlags } from '../../core/dispatch.ts'; -import type { GestureReferenceFrame } from '../../contracts/scroll-gesture.ts'; +import type { GestureReferenceFrame } from '@agent-device/contracts/interaction'; import type { SnapshotNode } from '@agent-device/kernel/snapshot'; import { getAndroidScreenSize } from '../../platforms/android/input-actions.ts'; import { emitDiagnostic } from '../../utils/diagnostics.ts'; diff --git a/src/daemon/handlers/interaction-touch-response.ts b/src/daemon/handlers/interaction-touch-response.ts index 5351cf8acb..9780b94e1b 100644 --- a/src/daemon/handlers/interaction-touch-response.ts +++ b/src/daemon/handlers/interaction-touch-response.ts @@ -1,14 +1,14 @@ -import type { GestureReferenceFrame } from '../../contracts/scroll-gesture.ts'; import type { FillCommandResult, + GestureReferenceFrame, LongPressCommandResult, PressCommandResult, RecordingTargetOverride, ResolutionDisclosure, SettleObservation, -} from '../../contracts/interaction.ts'; -import type { RecordedTargetCapture } from '../session-target-evidence.ts'; +} from '@agent-device/contracts/interaction'; import { successText } from '../../utils/success-text.ts'; +import type { RecordedTargetCapture } from '../session-target-evidence.ts'; import { interactionResultExtra } from './interaction-touch-targets.ts'; /** diff --git a/src/daemon/handlers/interaction-touch-targets.ts b/src/daemon/handlers/interaction-touch-targets.ts index 7dc12d44ac..271ac29c45 100644 --- a/src/daemon/handlers/interaction-touch-targets.ts +++ b/src/daemon/handlers/interaction-touch-targets.ts @@ -3,7 +3,7 @@ import type { InteractionTarget, LongPressCommandResult, PressCommandResult, -} from '../../contracts/interaction.ts'; +} from '@agent-device/contracts/interaction'; import { readFillTargetFromPositionals, type DecodedFillTarget, diff --git a/src/daemon/handlers/interaction-touch.ts b/src/daemon/handlers/interaction-touch.ts index c89e4ff2ba..4f5d73be4b 100644 --- a/src/daemon/handlers/interaction-touch.ts +++ b/src/daemon/handlers/interaction-touch.ts @@ -1,72 +1,72 @@ -import type { GestureReferenceFrame } from '../../contracts/scroll-gesture.ts'; -import { - transformInteractionResponseData, - type InteractionResponseDataTransformCommand, -} from '../../core/interaction-response-data-transform.ts'; -import { isApplePlatform, publicPlatformString } from '@agent-device/kernel/device'; -import { normalizeAppleRunnerResultForResponse } from '../../platforms/apple/core/runner/runner-result-response-normalization.ts'; -import { - buttonTag, - getClickButtonValidationError, - resolveClickButton, -} from '../../contracts/click-button.ts'; import type { FillCommandResult, + GestureReferenceFrame, InteractionTarget, LongPressCommandResult, PressCommandResult, -} from '../../contracts/interaction.ts'; +} from '@agent-device/contracts/interaction'; +import { + buttonTag, + getClickButtonValidationError, + resolveClickButton, +} from '@agent-device/contracts/interaction'; +import { isApplePlatform, publicPlatformString } from '@agent-device/kernel/device'; import { asAppError, normalizeError } from '@agent-device/kernel/errors'; +import { + commandSupportsSettleObservation, + commandSupportsVerifyEvidence, +} from '../../core/command-descriptor/registry.ts'; +import { dispatchCommand, type CommandFlags } from '../../core/dispatch.ts'; +import { + transformInteractionResponseData, + type InteractionResponseDataTransformCommand, +} from '../../core/interaction-response-data-transform.ts'; +import { normalizeAppleRunnerResultForResponse } from '../../platforms/apple/core/runner/runner-result-response-normalization.ts'; import type { ReplayTargetGuardDenotation } from '../../replay/target-identity-node.ts'; -import type { DaemonResponse, SessionState } from '../types.ts'; -import { finalizeTouchInteraction, type InteractionHandlerParams } from './interaction-common.ts'; +import { emitDiagnostic } from '../../utils/diagnostics.ts'; +import { getActiveAndroidSnapshotFreshness } from '../android-snapshot-freshness.ts'; +import { + ensureAndroidBlockingSystemDialogReady, + type AndroidBlockingDialogReadinessResult, +} from '../android-system-dialog.ts'; +import { + isDirectIosSelectorFallbackError, + readSimpleIosSelectorTarget, + type DirectIosSelectorTarget, +} from '../direct-ios-selector.ts'; +import { expireRefFrame } from '../ref-frame.ts'; import { markSessionPartialRefsIssued, resolveRefStalenessWarning } from '../session-snapshot.ts'; +import type { DaemonResponse, SessionState } from '../types.ts'; import { - buildInteractionResponseData, - type InteractionResponsePayloads, -} from './interaction-touch-response.ts'; -import type { CaptureSnapshotForSession } from './interaction-snapshot.ts'; + assertAndroidPressStayedInApp, + isAndroidEscapeError, +} from './interaction-android-escape.ts'; +import { finalizeTouchInteraction, type InteractionHandlerParams } from './interaction-common.ts'; import { readSettleRequest, settleFlagGuardResponse, type RefSnapshotFlagGuardResponse, } from './interaction-flags.ts'; +import { assertRecordedFillParameterization } from './interaction-recorded-input.ts'; +import { refMutationAdmissionResponse } from './interaction-ref-policy.ts'; +import { createInteractionRuntime } from './interaction-runtime.ts'; +import type { CaptureSnapshotForSession } from './interaction-snapshot.ts'; +import { unsupportedMacOsDesktopSurfaceInteraction } from './interaction-touch-policy.ts'; import { readSnapshotNodesReferenceFrame, resolveDirectTouchReferenceFrameSafely, } from './interaction-touch-reference-frame.ts'; -import { unsupportedMacOsDesktopSurfaceInteraction } from './interaction-touch-policy.ts'; -import { errorResponse, noActiveSessionError, requireCommandSupported } from './response.ts'; import { - assertAndroidPressStayedInApp, - isAndroidEscapeError, -} from './interaction-android-escape.ts'; -import { createInteractionRuntime } from './interaction-runtime.ts'; + buildInteractionResponseData, + type InteractionResponsePayloads, +} from './interaction-touch-response.ts'; import { formatTouchTargetLabel, parseFillTarget, parseLongPressTarget, parseTouchTarget, } from './interaction-touch-targets.ts'; -import { getActiveAndroidSnapshotFreshness } from '../android-snapshot-freshness.ts'; -import { emitDiagnostic } from '../../utils/diagnostics.ts'; -import { dispatchCommand, type CommandFlags } from '../../core/dispatch.ts'; -import { - commandSupportsSettleObservation, - commandSupportsVerifyEvidence, -} from '../../core/command-descriptor/registry.ts'; -import { - isDirectIosSelectorFallbackError, - readSimpleIosSelectorTarget, - type DirectIosSelectorTarget, -} from '../direct-ios-selector.ts'; -import { - ensureAndroidBlockingSystemDialogReady, - type AndroidBlockingDialogReadinessResult, -} from '../android-system-dialog.ts'; -import { refMutationAdmissionResponse } from './interaction-ref-policy.ts'; -import { expireRefFrame } from '../ref-frame.ts'; -import { assertRecordedFillParameterization } from './interaction-recorded-input.ts'; +import { errorResponse, noActiveSessionError, requireCommandSupported } from './response.ts'; export async function handleTouchInteractionCommands( params: InteractionHandlerParams & { diff --git a/src/daemon/handlers/lease.ts b/src/daemon/handlers/lease.ts index 3156bc2e7e..9a7920fcb8 100644 --- a/src/daemon/handlers/lease.ts +++ b/src/daemon/handlers/lease.ts @@ -1,9 +1,9 @@ -import type { LeaseLifecycleProvider } from '../../contracts/device-provider.ts'; +import type { LeaseLifecycleContext, LeaseLifecycleProvider } from '@agent-device/contracts/device'; import { PUBLIC_COMMANDS } from '../../command-catalog.ts'; import type { AgentArtifactsResult, CloudArtifactProvider, -} from '../../contracts/cloud-artifacts.ts'; +} from '@agent-device/contracts/observability'; import type { DaemonRequest, DaemonResponse } from '../types.ts'; import type { LeaseRegistry } from '../lease-registry.ts'; import type { SessionStore } from '../session-store.ts'; @@ -63,7 +63,7 @@ export async function handleLeaseCommands(args: LeaseHandlerArgs): Promise | undefined; try { - providerData = await leaseLifecycleProvider?.allocate?.(lease, { req }); + providerData = await leaseLifecycleProvider?.allocate?.(lease, leaseLifecycleContext(req)); } catch (error) { leaseRegistry.releaseLease( leaseScopeToReleaseRequest({ @@ -85,7 +85,10 @@ export async function handleLeaseCommands(args: LeaseHandlerArgs): Promise; diff --git a/src/daemon/handlers/record-trace-recording-backends.ts b/src/daemon/handlers/record-trace-recording-backends.ts index d1c9bab1d5..8661782c1f 100644 --- a/src/daemon/handlers/record-trace-recording-backends.ts +++ b/src/daemon/handlers/record-trace-recording-backends.ts @@ -1,7 +1,7 @@ -import type { RecordingBackendTag } from '../../contracts/recording.ts'; +import type { RecordingBackendTag } from '@agent-device/contracts/recording'; import fs from 'node:fs'; import path from 'node:path'; -import { tryGetPlugin } from '../../contracts/platform-plugin.ts'; +import { tryGetPlugin } from '../../core/platform-plugin-registry.ts'; import { registerBuiltinPlatformPlugins } from '../../core/interactors/register-builtins.ts'; import type { DaemonRequest, DaemonResponse, SessionState } from '../types.ts'; import type { SessionStore } from '../session-store.ts'; @@ -12,7 +12,7 @@ import { } from '../../recording/output-path.ts'; import { resolveWebProvider } from '../../platforms/web/provider.ts'; import { IOS_RUNNER_CONTAINER_BUNDLE_IDS } from '../../platforms/apple/core/runner/runner-client.ts'; -import { isWholeScreenRecordingScope } from '../../contracts/recording-scope.ts'; +import { isWholeScreenRecordingScope } from '@agent-device/contracts/recording'; import { errorResponse } from './response.ts'; import { startAndroidRecording, stopAndroidRecording } from './record-trace-android.ts'; import { recoverMissingAndroidRecording } from './record-trace-android-recovery.ts'; diff --git a/src/daemon/handlers/record-trace-recording.ts b/src/daemon/handlers/record-trace-recording.ts index 6f151c60e8..4415a3601d 100644 --- a/src/daemon/handlers/record-trace-recording.ts +++ b/src/daemon/handlers/record-trace-recording.ts @@ -1,14 +1,16 @@ +import { + DEFAULT_RECORDING_EXPORT_QUALITY, + RECORDING_EXPORT_QUALITIES, + RECORDING_SCOPE_VALUES, + type RecordingCommandResult, + type RecordingScope, + isWholeScreenRecordingScope, + recordingQualityInputToExportQuality, +} from '@agent-device/contracts/recording'; +import { AppError, toAppErrorCode } from '@agent-device/kernel/errors'; import fs from 'node:fs'; import path from 'node:path'; -import { AppError, toAppErrorCode } from '@agent-device/kernel/errors'; -import { sleep } from '../../utils/timeouts.ts'; import { resolveTargetDevice } from '../../core/dispatch.ts'; -import { ensureDeviceReady } from '../device-ready.ts'; -import { SessionStore } from '../session-store.ts'; -import type { DaemonArtifact, DaemonRequest, DaemonResponse, SessionState } from '../types.ts'; -import { runCmd } from '../../utils/exec.ts'; -import { isPlayableVideo, waitForStableFile } from '../../utils/video.ts'; -import { deriveRecordingTelemetryPath } from '../recording-telemetry.ts'; import { runAppleRunnerCommand } from '../../platforms/apple/core/runner/runner-client.ts'; import { runXcrun } from '../../platforms/apple/core/tool-provider.ts'; import { @@ -16,18 +18,15 @@ import { resizeRecording, trimRecordingStart, } from '../../recording/overlay.ts'; -import { - DEFAULT_RECORDING_EXPORT_QUALITY, - RECORDING_EXPORT_QUALITIES, - recordingQualityInputToExportQuality, -} from '../../contracts/recording-export-quality.ts'; -import { - RECORDING_SCOPE_VALUES, - type RecordingScope, - isWholeScreenRecordingScope, -} from '../../contracts/recording-scope.ts'; +import { runCmd } from '../../utils/exec.ts'; +import { sleep } from '../../utils/timeouts.ts'; +import { isPlayableVideo, waitForStableFile } from '../../utils/video.ts'; +import { ensureDeviceReady } from '../device-ready.ts'; import { resolveRecordingProvider } from '../recording-provider.ts'; -import { errorResponse, requireCommandSupported } from './response.ts'; +import { deriveRecordingTelemetryPath } from '../recording-telemetry.ts'; +import { hasExplicitSessionFlag, resolveImplicitSessionScope } from '../session-routing.ts'; +import { SessionStore } from '../session-store.ts'; +import type { DaemonArtifact, DaemonRequest, DaemonResponse, SessionState } from '../types.ts'; import { recordSessionAction } from './handler-utils.ts'; import { deriveAndroidChunkOutPath } from './record-trace-android-chunks.ts'; import { @@ -35,8 +34,7 @@ import { stopActiveRecording, } from './record-trace-recording-backends.ts'; import type { RecordTraceDeps, RecordingBase } from './record-trace-types.ts'; -import type { RecordingCommandResult } from '../../contracts/recording.ts'; -import { hasExplicitSessionFlag, resolveImplicitSessionScope } from '../session-routing.ts'; +import { errorResponse, requireCommandSupported } from './response.ts'; const IOS_DEVICE_RECORD_MIN_FPS = 1; const IOS_DEVICE_RECORD_MAX_FPS = 120; diff --git a/src/daemon/handlers/record-trace-types.ts b/src/daemon/handlers/record-trace-types.ts index 897790794b..b43330dcca 100644 --- a/src/daemon/handlers/record-trace-types.ts +++ b/src/daemon/handlers/record-trace-types.ts @@ -1,15 +1,14 @@ -import type { RecordingProvider } from '../recording-provider.ts'; -import type { runCmd } from '../../utils/exec.ts'; -import type { isPlayableVideo, waitForStableFile } from '../../utils/video.ts'; +import type { RecordingExportQuality, RecordingScope } from '@agent-device/contracts/recording'; import type { runAppleRunnerCommand } from '../../platforms/apple/core/runner/runner-client.ts'; import type { overlayRecordingTouches, resizeRecording, trimRecordingStart, } from '../../recording/overlay.ts'; +import type { runCmd } from '../../utils/exec.ts'; +import type { isPlayableVideo, waitForStableFile } from '../../utils/video.ts'; +import type { RecordingProvider } from '../recording-provider.ts'; import type { RecordingGestureEvent } from '../types.ts'; -import type { RecordingExportQuality } from '../../contracts/recording-export-quality.ts'; -import type { RecordingScope } from '../../contracts/recording-scope.ts'; export type RecordTraceDeps = { runCmd: typeof runCmd; diff --git a/src/daemon/handlers/record-trace.ts b/src/daemon/handlers/record-trace.ts index 02a2bdb1e5..ee163a94e6 100644 --- a/src/daemon/handlers/record-trace.ts +++ b/src/daemon/handlers/record-trace.ts @@ -5,7 +5,7 @@ import { SessionStore } from '../session-store.ts'; import { handleRecordCommand } from './record-trace-recording.ts'; import { errorResponse } from './response.ts'; import { recordSessionAction } from './handler-utils.ts'; -import type { TraceCommandResult } from '../../contracts/recording.ts'; +import type { TraceCommandResult } from '@agent-device/contracts/recording'; export async function handleRecordTraceCommands(params: { req: DaemonRequest; diff --git a/src/daemon/handlers/session-close.ts b/src/daemon/handlers/session-close.ts index d45a2ac08d..6cf5d148c5 100644 --- a/src/daemon/handlers/session-close.ts +++ b/src/daemon/handlers/session-close.ts @@ -26,7 +26,7 @@ import { expireRefFrame } from '../ref-frame.ts'; import { stopSessionRecordingForTeardown } from './record-trace-recording.ts'; import type { LeaseRegistry } from '../lease-registry.ts'; import { releaseSessionLease } from '../lease-lifecycle.ts'; -import type { LeaseLifecycleProvider } from '../../contracts/device-provider.ts'; +import type { LeaseLifecycleProvider } from '@agent-device/contracts/device'; import { reportSessionCleanupFailures, restoreSessionAndroidIme, diff --git a/src/daemon/handlers/session-deploy.ts b/src/daemon/handlers/session-deploy.ts index 9ef9cfc2e2..e08c429cba 100644 --- a/src/daemon/handlers/session-deploy.ts +++ b/src/daemon/handlers/session-deploy.ts @@ -5,7 +5,7 @@ import { isIosFamily, type DeviceInfo } from '@agent-device/kernel/device'; import type { DaemonRequest, DaemonResponse } from '../types.ts'; import { SessionStore } from '../session-store.ts'; import { recordSessionAction } from './handler-utils.ts'; -import { resolveDeployResultTarget } from '../../contracts/result-serialization.ts'; +import { resolveDeployResultTarget } from '../../utils/result-serialization.ts'; import { withSuccessText } from '../../utils/success-text.ts'; import { requireSessionOrExplicitSelector, resolveCommandDevice } from './session-device-utils.ts'; import { errorResponse, requireCommandSupported } from './response.ts'; diff --git a/src/daemon/handlers/session-doctor-android.ts b/src/daemon/handlers/session-doctor-android.ts index 303710ed27..793d5bc74c 100644 --- a/src/daemon/handlers/session-doctor-android.ts +++ b/src/daemon/handlers/session-doctor-android.ts @@ -11,7 +11,7 @@ import { resolveAndroidImeHelperArtifact } from '../../platforms/android/ime-hel import type { DeviceInfo } from '@agent-device/kernel/device'; import { normalizeError } from '@agent-device/kernel/errors'; import { appendDoctorCheck } from './session-doctor-output.ts'; -import type { DoctorCheck } from '../../contracts/doctor.ts'; +import type { DoctorCheck } from '@agent-device/contracts/observability'; const ANDROID_PROBE_TIMEOUT_MS = 2000; diff --git a/src/daemon/handlers/session-doctor-app.ts b/src/daemon/handlers/session-doctor-app.ts index dc6d170422..191b27d3c1 100644 --- a/src/daemon/handlers/session-doctor-app.ts +++ b/src/daemon/handlers/session-doctor-app.ts @@ -7,7 +7,7 @@ import { import { AppError, normalizeError } from '@agent-device/kernel/errors'; import type { SessionState } from '../types.ts'; import { appendDoctorCheck } from './session-doctor-output.ts'; -import type { DoctorCheck } from '../../contracts/doctor.ts'; +import type { DoctorCheck } from '@agent-device/contracts/observability'; export async function appendAppChecks( checks: DoctorCheck[], diff --git a/src/daemon/handlers/session-doctor-device.ts b/src/daemon/handlers/session-doctor-device.ts index 0fe91f5ce2..5acc8902e9 100644 --- a/src/daemon/handlers/session-doctor-device.ts +++ b/src/daemon/handlers/session-doctor-device.ts @@ -7,7 +7,7 @@ import { LOCAL_DEVICE_INVENTORY_PLATFORM_SELECTORS, type DeviceInventoryGroup, type DeviceInventoryRequest, -} from '../../contracts/device-inventory.ts'; +} from '@agent-device/contracts/device'; import { matchesDeviceSelector, publicPlatformString, @@ -18,7 +18,7 @@ import { } from '@agent-device/kernel/device'; import { normalizeError } from '@agent-device/kernel/errors'; import type { DaemonRequest, SessionState } from '../types.ts'; -import type { DoctorCheck } from '../../contracts/doctor.ts'; +import type { DoctorCheck } from '@agent-device/contracts/observability'; import { appendDoctorCheck } from './session-doctor-output.ts'; export type DoctorDeviceInventory = { diff --git a/src/daemon/handlers/session-doctor-metro.ts b/src/daemon/handlers/session-doctor-metro.ts index e49abcf89d..cf8240441c 100644 --- a/src/daemon/handlers/session-doctor-metro.ts +++ b/src/daemon/handlers/session-doctor-metro.ts @@ -1,4 +1,4 @@ -import type { DoctorCheck, DoctorKind } from '../../contracts/doctor.ts'; +import type { DoctorCheck, DoctorKind } from '@agent-device/contracts/observability'; import { runCmd } from '../../utils/exec.ts'; const METRO_PROBE_TIMEOUT_MS = 1500; diff --git a/src/daemon/handlers/session-doctor-options.ts b/src/daemon/handlers/session-doctor-options.ts index a2b148e1da..3c30155ca9 100644 --- a/src/daemon/handlers/session-doctor-options.ts +++ b/src/daemon/handlers/session-doctor-options.ts @@ -3,7 +3,7 @@ import { publicPlatformString } from '@agent-device/kernel/device'; import type { SessionStore } from '../session-store.ts'; import type { DaemonRequest, SessionState } from '../types.ts'; import type { DoctorOptions } from './session-doctor-types.ts'; -import type { DoctorCheck, DoctorKind } from '../../contracts/doctor.ts'; +import type { DoctorCheck, DoctorKind } from '@agent-device/contracts/observability'; const DEFAULT_METRO_HOST = '127.0.0.1'; const DEFAULT_METRO_PORT = 8081; diff --git a/src/daemon/handlers/session-doctor-output.ts b/src/daemon/handlers/session-doctor-output.ts index 8c7db154ec..191e8f4e29 100644 --- a/src/daemon/handlers/session-doctor-output.ts +++ b/src/daemon/handlers/session-doctor-output.ts @@ -2,8 +2,8 @@ import { emitRequestProgress } from '../../request/progress.ts'; import { formatDoctorCheckDetailLines, formatDoctorCheckSummaryLine, -} from '../../contracts/doctor-output.ts'; -import type { DoctorCheck, DoctorStatus } from '../../contracts/doctor.ts'; +} from '../../utils/doctor-output.ts'; +import type { DoctorCheck, DoctorStatus } from '@agent-device/contracts/observability'; export function summarizeDoctorStatus(checks: DoctorCheck[]): 'pass' | 'warn' | 'fail' { if (checks.some((check) => check.status === 'fail')) return 'fail'; diff --git a/src/daemon/handlers/session-doctor-toolchain.ts b/src/daemon/handlers/session-doctor-toolchain.ts index 87313e2377..9e205f0d52 100644 --- a/src/daemon/handlers/session-doctor-toolchain.ts +++ b/src/daemon/handlers/session-doctor-toolchain.ts @@ -3,7 +3,7 @@ import path from 'node:path'; import type { PlatformSelector } from '@agent-device/kernel/device'; import { runCmd } from '../../utils/exec.ts'; import { appendDoctorCheck } from './session-doctor-output.ts'; -import type { DoctorCheck } from '../../contracts/doctor.ts'; +import type { DoctorCheck } from '@agent-device/contracts/observability'; const TOOLCHAIN_TIMEOUT_MS = 3_000; type AndroidLicenseState = 'accepted' | 'missing' | 'unknown'; diff --git a/src/daemon/handlers/session-doctor-types.ts b/src/daemon/handlers/session-doctor-types.ts index 833eaf10d1..6298a77b1d 100644 --- a/src/daemon/handlers/session-doctor-types.ts +++ b/src/daemon/handlers/session-doctor-types.ts @@ -1,6 +1,4 @@ -import type { DoctorKind } from '../../contracts/doctor.ts'; - -export type { DoctorCheck, DoctorKind, DoctorStatus } from '../../contracts/doctor.ts'; +import type { DoctorKind } from '@agent-device/contracts/observability'; export type DoctorOptions = { targetApp?: string; diff --git a/src/daemon/handlers/session-doctor-web.ts b/src/daemon/handlers/session-doctor-web.ts index bf93231eaf..121ff43ea5 100644 --- a/src/daemon/handlers/session-doctor-web.ts +++ b/src/daemon/handlers/session-doctor-web.ts @@ -1,7 +1,7 @@ import { inspectManagedAgentBrowserProcesses } from '../../platforms/web/agent-browser-lifecycle.ts'; import { getManagedAgentBrowserStatus } from '../../platforms/web/agent-browser-tool.ts'; import { appendDoctorCheck } from './session-doctor-output.ts'; -import type { DoctorCheck } from '../../contracts/doctor.ts'; +import type { DoctorCheck } from '@agent-device/contracts/observability'; export async function appendWebBrowserLifecycleCheck( checks: DoctorCheck[], diff --git a/src/daemon/handlers/session-doctor.ts b/src/daemon/handlers/session-doctor.ts index d16542407b..7d59a04526 100644 --- a/src/daemon/handlers/session-doctor.ts +++ b/src/daemon/handlers/session-doctor.ts @@ -29,7 +29,7 @@ import { } from './session-doctor-output.ts'; import { appendToolchainChecks } from './session-doctor-toolchain.ts'; import type { DoctorOptions } from './session-doctor-types.ts'; -import type { DoctorCheck, DoctorCommandResult } from '../../contracts/doctor.ts'; +import type { DoctorCheck, DoctorCommandResult } from '@agent-device/contracts/observability'; import { hasCachedAppleRunnerArtifact, prewarmAppleRunnerCache, diff --git a/src/daemon/handlers/session-inventory.ts b/src/daemon/handlers/session-inventory.ts index 9532f9ead9..be1e195626 100644 --- a/src/daemon/handlers/session-inventory.ts +++ b/src/daemon/handlers/session-inventory.ts @@ -1,6 +1,6 @@ import { isCommandSupportedOnDevice, listCapabilityCommands } from '../../core/capabilities.ts'; import { listDeviceInventory } from '../../core/dispatch-resolve.ts'; -import { assertResolvedAppsFilter } from '../../contracts/app-inventory.ts'; +import { assertResolvedAppsFilter } from '@agent-device/contracts/device'; import { asAppError } from '@agent-device/kernel/errors'; import { isApplePlatform, @@ -114,17 +114,15 @@ export async function handleSessionInventoryCommands(params: { } if (req.command === 'capabilities') { - const session = sessionStore.get(sessionName); - const flags = req.flags ?? {}; - const guard = requireSessionOrExplicitSelector(req.command, session, flags); - if (guard) return guard; - - const device = await resolveCommandDevice({ - session, - flags, + const resolution = await resolveInventoryCommandDevice({ + req, + sessionName, + sessionStore, ensureReady: false, allowStoppedAndroidAvdPlaceholders: true, }); + if ('response' in resolution) return resolution.response; + const { device } = resolution; return { ok: true, data: { @@ -137,16 +135,14 @@ export async function handleSessionInventoryCommands(params: { } if (req.command === 'apps') { - const session = sessionStore.get(sessionName); - const flags = req.flags ?? {}; - const guard = requireSessionOrExplicitSelector(req.command, session, flags); - if (guard) return guard; - - const device = await resolveCommandDevice({ - session, - flags, + const resolution = await resolveInventoryCommandDevice({ + req, + sessionName, + sessionStore, ensureReady: true, }); + if ('response' in resolution) return resolution.response; + const { device } = resolution; const unsupported = requireCommandSupported('apps', device); if (unsupported) return unsupported; @@ -177,6 +173,30 @@ export async function handleSessionInventoryCommands(params: { return null; } +async function resolveInventoryCommandDevice(params: { + req: DaemonRequest; + sessionName: string; + sessionStore: SessionStore; + ensureReady: boolean; + allowStoppedAndroidAvdPlaceholders?: boolean; +}): Promise<{ device: DeviceInfo } | { response: DaemonResponse }> { + const { req, sessionName, sessionStore, ensureReady, allowStoppedAndroidAvdPlaceholders } = + params; + const session = sessionStore.get(sessionName); + const flags = req.flags ?? {}; + const response = requireSessionOrExplicitSelector(req.command, session, flags); + if (response) return { response }; + + return { + device: await resolveCommandDevice({ + session, + flags, + ensureReady, + allowStoppedAndroidAvdPlaceholders, + }), + }; +} + function publicDeviceInfo({ simulatorSetPath: _simulatorSetPath, iosPhysicalDeviceBackend: _iosPhysicalDeviceBackend, diff --git a/src/daemon/handlers/session-native-perf.ts b/src/daemon/handlers/session-native-perf.ts index 843ab82d6b..e2132a3f7b 100644 --- a/src/daemon/handlers/session-native-perf.ts +++ b/src/daemon/handlers/session-native-perf.ts @@ -4,7 +4,7 @@ import { isPerfSubject, PERF_KIND_ERROR_MESSAGE, PERF_SUBJECT_ERROR_MESSAGE, -} from '../../contracts/perf.ts'; +} from '@agent-device/contracts/observability'; import type { AndroidAdbExecutor } from '../../platforms/android/adb-executor.ts'; import { startAndroidPerfettoTrace, diff --git a/src/daemon/handlers/session-observability.ts b/src/daemon/handlers/session-observability.ts index 892fc7af03..ed69dd4ade 100644 --- a/src/daemon/handlers/session-observability.ts +++ b/src/daemon/handlers/session-observability.ts @@ -3,19 +3,22 @@ import { isPerfArea, isPerfKind, isPerfMemoryKind, + LOG_ACTION_VALUES as LOG_ACTIONS, PERF_ACTION_ERROR_MESSAGE, PERF_AREA_ERROR_MESSAGE, PERF_KIND_ERROR_MESSAGE, PERF_MEMORY_KIND_ERROR_MESSAGE, + type LogBackend, + type LogAction as LogsAction, type PerfAction, type PerfArea, type PerfKind, -} from '../../contracts/perf.ts'; +} from '@agent-device/contracts/observability'; +import { uniqueStrings } from '@agent-device/kernel/collections'; +import { NETWORK_INCLUDE_MODES, type NetworkIncludeMode } from '@agent-device/kernel/contracts'; import { AppError, normalizeError } from '@agent-device/kernel/errors'; -import { resolveWebProvider } from '../../platforms/web/provider.ts'; import type { AndroidAdbExecutor } from '../../platforms/android/adb-executor.ts'; -import type { DaemonRequest, DaemonResponse, DaemonResponseData, SessionState } from '../types.ts'; -import type { SessionStore } from '../session-store.ts'; +import { resolveWebProvider } from '../../platforms/web/provider.ts'; import { appendAppLogMarker, clearAppLogFiles, @@ -29,22 +32,17 @@ import { type AppLogResult, type AppLogState, } from '../app-log.ts'; +import type { SessionStore } from '../session-store.ts'; +import type { DaemonRequest, DaemonResponse, DaemonResponseData, SessionState } from '../types.ts'; +import { errorResponse, requireCommandSupported, type DaemonFailureResponse } from './response.ts'; +import { handleAudioCommand } from './session-audio.ts'; +import { handleNativePerfCommand as handleAndroidNativePerfCommand } from './session-native-perf.ts'; +import { handleNativePerfCommand as handleAppleNativePerfCommand } from './session-perf-xctrace.ts'; import { buildPerfFramesResponseData, buildPerfMemoryResponseData, buildPerfResponseData, } from './session-perf.ts'; -import { handleNativePerfCommand as handleAndroidNativePerfCommand } from './session-native-perf.ts'; -import { errorResponse, requireCommandSupported, type DaemonFailureResponse } from './response.ts'; -import { handleAudioCommand } from './session-audio.ts'; -import { handleNativePerfCommand as handleAppleNativePerfCommand } from './session-perf-xctrace.ts'; -import { NETWORK_INCLUDE_MODES, type NetworkIncludeMode } from '@agent-device/kernel/contracts'; -import { uniqueStrings } from '@agent-device/kernel/collections'; -import { - LOG_ACTION_VALUES as LOG_ACTIONS, - type LogAction as LogsAction, - type LogBackend, -} from '../../contracts/logs.ts'; const LOG_ACTIONS_MESSAGE = `logs requires ${LOG_ACTIONS.slice(0, -1).join(', ')}, or ${LOG_ACTIONS.at(-1)}`; const NETWORK_ACTIONS = ['dump', 'log'] as const; diff --git a/src/daemon/handlers/session-open-launch-url.ts b/src/daemon/handlers/session-open-launch-url.ts index 8bbee5c6b8..bbd7b29071 100644 --- a/src/daemon/handlers/session-open-launch-url.ts +++ b/src/daemon/handlers/session-open-launch-url.ts @@ -1,4 +1,4 @@ -import { isDeepLinkTarget } from '../../contracts/open-target.ts'; +import { isDeepLinkTarget } from '@agent-device/contracts/command'; import { dispatchCommand } from '../../core/dispatch.ts'; import type { DeviceInfo } from '@agent-device/kernel/device'; import type { DaemonRequest, SessionRuntimeHints } from '../types.ts'; diff --git a/src/daemon/handlers/session-open-prepare.ts b/src/daemon/handlers/session-open-prepare.ts index 42d8d6d879..294b085cde 100644 --- a/src/daemon/handlers/session-open-prepare.ts +++ b/src/daemon/handlers/session-open-prepare.ts @@ -1,4 +1,4 @@ -import { isDeepLinkTarget } from '../../contracts/open-target.ts'; +import { isDeepLinkTarget } from '@agent-device/contracts/command'; import { ensureDeviceReady } from '../device-ready.ts'; import type { DeviceInfo } from '@agent-device/kernel/device'; import type { DaemonRequest, DaemonResponse, SessionRuntimeHints, SessionState } from '../types.ts'; @@ -21,7 +21,7 @@ import { resolveMacOsSurfaceAppState, resolveRequestedOpenSurface, } from './session-open-surface.ts'; -import type { SessionSurface } from '../../contracts/session-surface.ts'; +import type { SessionSurface } from '@agent-device/contracts/session'; type OpenCommandDetails = { appBundleId?: string; diff --git a/src/daemon/handlers/session-open-surface.ts b/src/daemon/handlers/session-open-surface.ts index c98c9f074f..245bbbdc3c 100644 --- a/src/daemon/handlers/session-open-surface.ts +++ b/src/daemon/handlers/session-open-surface.ts @@ -1,4 +1,4 @@ -import { parseSessionSurface, type SessionSurface } from '../../contracts/session-surface.ts'; +import { parseSessionSurface, type SessionSurface } from '@agent-device/contracts/session'; import { resolveFrontmostMacOsApp } from '../../platforms/apple/os/macos/helper.ts'; import { isIosFamily, diff --git a/src/daemon/handlers/session-open-target.ts b/src/daemon/handlers/session-open-target.ts index c36b8f89c8..5ac81f7998 100644 --- a/src/daemon/handlers/session-open-target.ts +++ b/src/daemon/handlers/session-open-target.ts @@ -2,7 +2,7 @@ import { isDeepLinkTarget, isWebUrl, resolveIosDeviceDeepLinkBundleId, -} from '../../contracts/open-target.ts'; +} from '@agent-device/contracts/command'; import { isIosFamily, isMacOs, diff --git a/src/daemon/handlers/session-open.ts b/src/daemon/handlers/session-open.ts index 9999fe422d..d7269969df 100644 --- a/src/daemon/handlers/session-open.ts +++ b/src/daemon/handlers/session-open.ts @@ -1,6 +1,6 @@ import path from 'node:path'; import { dispatchCommand, resolveTargetDevice } from '../../core/dispatch.ts'; -import type { SessionSurface } from '../../contracts/session-surface.ts'; +import type { SessionSurface } from '@agent-device/contracts/session'; import { contextFromFlags } from '../context.ts'; import { createRequestCanceledError, isRequestCanceled } from '../../request/cancel.ts'; import { diff --git a/src/daemon/handlers/session-perf-xctrace.ts b/src/daemon/handlers/session-perf-xctrace.ts index 5de86078f5..f75cf44949 100644 --- a/src/daemon/handlers/session-perf-xctrace.ts +++ b/src/daemon/handlers/session-perf-xctrace.ts @@ -9,7 +9,7 @@ import { type AppleXctracePerfMode, type AppleXctracePerfResult, } from '../../platforms/apple/core/perf-xctrace.ts'; -import { PERF_AREA_ERROR_MESSAGE } from '../../contracts/perf.ts'; +import { PERF_AREA_ERROR_MESSAGE } from '@agent-device/contracts/observability'; import { errorResponse, type DaemonFailureResponse } from './response.ts'; import { recordSessionAction } from './handler-utils.ts'; diff --git a/src/daemon/handlers/session-perf.ts b/src/daemon/handlers/session-perf.ts index 56a3d792f9..a9e71c7c7d 100644 --- a/src/daemon/handlers/session-perf.ts +++ b/src/daemon/handlers/session-perf.ts @@ -2,7 +2,7 @@ import path from 'node:path'; import type { SessionAction, SessionState } from '../types.ts'; import { AppError, normalizeError } from '@agent-device/kernel/errors'; import { isApplePlatform, publicPlatformString } from '@agent-device/kernel/device'; -import { tryGetPlugin } from '../../contracts/platform-plugin.ts'; +import { tryGetPlugin } from '../../core/platform-plugin-registry.ts'; import { registerBuiltinPlatformPlugins } from '../../core/interactors/register-builtins.ts'; import type { AndroidAdbExecutor } from '../../platforms/android/adb-executor.ts'; import { @@ -29,7 +29,7 @@ import { sampleAppleFramePerf, sampleApplePerfMetrics, } from '../../platforms/apple/core/perf.ts'; -import type { PerfKind, PerfMetricsSamplerTag } from '../../contracts/perf.ts'; +import type { PerfKind, PerfMetricsSamplerTag } from '@agent-device/contracts/observability'; import { SessionStore } from '../session-store.ts'; import { PERF_STARTUP_SAMPLE_LIMIT, diff --git a/src/daemon/handlers/session-replay-action-runtime.ts b/src/daemon/handlers/session-replay-action-runtime.ts index 581916d115..6feacc0c8f 100644 --- a/src/daemon/handlers/session-replay-action-runtime.ts +++ b/src/daemon/handlers/session-replay-action-runtime.ts @@ -6,7 +6,7 @@ import { AppError, normalizeError } from '@agent-device/kernel/errors'; import { gesturePayloadFromPositionals, swipePayloadFromPositionals, -} from '../../contracts/gesture-normalization.ts'; +} from '@agent-device/contracts/interaction'; import { buildDisplayPositionals } from '../session-event-action.ts'; import { appendReplayTraceEvent } from './session-replay-trace.ts'; import { inferFillText } from '../action-utils.ts'; diff --git a/src/daemon/handlers/session-replay-maestro-failure.ts b/src/daemon/handlers/session-replay-maestro-failure.ts index 70c917dfc5..d44dec6dc0 100644 --- a/src/daemon/handlers/session-replay-maestro-failure.ts +++ b/src/daemon/handlers/session-replay-maestro-failure.ts @@ -18,7 +18,7 @@ import { type ReplayVarScrubEntry, } from '../../replay/divergence.ts'; import { formatScriptArg } from '../../replay/script-utils.ts'; -import type { SnapshotDiagnosticsSummary } from '../../contracts/snapshot-diagnostics.ts'; +import type { SnapshotDiagnosticsSummary } from '@agent-device/contracts/capture'; import { SessionStore } from '../session-store.ts'; import type { DaemonRequest, DaemonResponse, SessionState } from '../types.ts'; import type { ReplayReportAction } from './session-replay-report-action.ts'; diff --git a/src/daemon/handlers/session-replay-maestro-response.ts b/src/daemon/handlers/session-replay-maestro-response.ts index cddc050b02..16a21738dc 100644 --- a/src/daemon/handlers/session-replay-maestro-response.ts +++ b/src/daemon/handlers/session-replay-maestro-response.ts @@ -1,7 +1,7 @@ -import type { ReplayCommandResult } from '../../contracts/replay.ts'; +import type { ReplayCommandResult } from '@agent-device/contracts/replay'; import type { MaestroReplayPlan } from '../../compat/maestro/replay-plan-types.ts'; import { normalizeError } from '@agent-device/kernel/errors'; -import { summarizeSnapshotTimingSamples } from '../../contracts/snapshot-diagnostics.ts'; +import { summarizeSnapshotTimingSamples } from '@agent-device/contracts/capture'; import type { DaemonRequest, DaemonResponse } from '../types.ts'; import { SessionStore } from '../session-store.ts'; import { diff --git a/src/daemon/handlers/session-replay-runtime-failure-response.ts b/src/daemon/handlers/session-replay-runtime-failure-response.ts index 7993d81ba7..1aae0a2bb2 100644 --- a/src/daemon/handlers/session-replay-runtime-failure-response.ts +++ b/src/daemon/handlers/session-replay-runtime-failure-response.ts @@ -1,6 +1,6 @@ import { scrubReplayVarValues, type ReplayVarScrubEntry } from '../../replay/divergence.ts'; import { formatDivergenceActionLabel } from '../../replay/script-utils.ts'; -import type { SnapshotDiagnosticsSummary } from '../../contracts/snapshot-diagnostics.ts'; +import type { SnapshotDiagnosticsSummary } from '@agent-device/contracts/capture'; import { buildDisplayPositionals } from '../session-event-action.ts'; import type { DaemonResponse, SessionAction } from '../types.ts'; diff --git a/src/daemon/handlers/session-replay-runtime-failure.ts b/src/daemon/handlers/session-replay-runtime-failure.ts index 48e670bd02..975ea512d4 100644 --- a/src/daemon/handlers/session-replay-runtime-failure.ts +++ b/src/daemon/handlers/session-replay-runtime-failure.ts @@ -3,7 +3,7 @@ import { summarizeSnapshotTimingSamples, type SnapshotDiagnosticsSummary, type SnapshotTimingSample, -} from '../../contracts/snapshot-diagnostics.ts'; +} from '@agent-device/contracts/capture'; import { SessionStore } from '../session-store.ts'; import type { DaemonRequest, DaemonResponse, SessionAction } from '../types.ts'; import { buildReplayFailureDivergence } from './session-replay-divergence.ts'; diff --git a/src/daemon/handlers/session-replay-runtime.ts b/src/daemon/handlers/session-replay-runtime.ts index 0119d2d555..37877cfc0c 100644 --- a/src/daemon/handlers/session-replay-runtime.ts +++ b/src/daemon/handlers/session-replay-runtime.ts @@ -36,8 +36,8 @@ import { import { summarizeSnapshotTimingSamples, type SnapshotTimingSample, -} from '../../contracts/snapshot-diagnostics.ts'; -import type { ReplayCommandResult } from '../../contracts/replay.ts'; +} from '@agent-device/contracts/capture'; +import type { ReplayCommandResult } from '@agent-device/contracts/replay'; import type { ReplayDivergenceResume } from '../../replay/divergence.ts'; import { isRecord } from '../../utils/parsing.ts'; import { collectReplayActionArtifactPaths } from './session-replay-runtime-artifacts.ts'; diff --git a/src/daemon/handlers/session-runtime-command.ts b/src/daemon/handlers/session-runtime-command.ts index 121a8ca9cc..0a34167cba 100644 --- a/src/daemon/handlers/session-runtime-command.ts +++ b/src/daemon/handlers/session-runtime-command.ts @@ -9,10 +9,8 @@ import { mergeRuntimeHints, toRuntimePlatform, } from './session-runtime.ts'; -import { - configureProviderPortReverse, - type ProviderPortReverseOptions, -} from '../../provider-device-runtime.ts'; +import { type ProviderPortReverseOptions } from '@agent-device/contracts/device'; +import { configureProviderPortReverse } from '../../provider-device-runtime.ts'; type RuntimeAction = 'set' | 'show' | 'clear'; type PortReverseParseResult = diff --git a/src/daemon/handlers/session-test-attempt.ts b/src/daemon/handlers/session-test-attempt.ts index e28cf42a71..a2e1a9656d 100644 --- a/src/daemon/handlers/session-test-attempt.ts +++ b/src/daemon/handlers/session-test-attempt.ts @@ -1,7 +1,7 @@ import path from 'node:path'; import { emitRequestProgress } from '../../request/progress.ts'; import type { DaemonResponse } from '../types.ts'; -import type { ReplaySuiteTestFailed, ReplaySuiteTestResult } from '../../contracts/replay.ts'; +import type { ReplaySuiteTestFailed, ReplaySuiteTestResult } from '@agent-device/contracts/replay'; import { buildReplayTestArtifactSlug, materializeReplayTestAttemptArtifacts, @@ -17,7 +17,7 @@ import { runReplayTestAttempt } from './session-test-runtime.ts'; import type { ReplayTestRuntimeDependencies } from './session-test-types.ts'; import type { ReplayTestShardContext } from './session-test-sharding.ts'; import { isRequestCanceled } from '../../request/cancel.ts'; -import { readSnapshotDiagnosticsSummary } from '../../contracts/snapshot-diagnostics.ts'; +import { readSnapshotDiagnosticsSummary } from '@agent-device/contracts/capture'; type ReplayTestCaseResult = Extract; type ReplayTestAttemptFailure = NonNullable< diff --git a/src/daemon/handlers/session-test-infrastructure.ts b/src/daemon/handlers/session-test-infrastructure.ts index 51c529d5f4..736b032cb5 100644 --- a/src/daemon/handlers/session-test-infrastructure.ts +++ b/src/daemon/handlers/session-test-infrastructure.ts @@ -1,6 +1,6 @@ import { isInfrastructureBootFailureReason } from '../../platforms/boot-diagnostics.ts'; import type { DaemonResponse } from '../types.ts'; -import type { ReplaySuiteTestResult } from '../../contracts/replay.ts'; +import type { ReplaySuiteTestResult } from '@agent-device/contracts/replay'; const REPLAY_INFRASTRUCTURE_FAILURE_MESSAGE_PATTERNS = [ 'failed to start daemon', diff --git a/src/daemon/handlers/session-test.ts b/src/daemon/handlers/session-test.ts index 10db76ade7..67f0b78fff 100644 --- a/src/daemon/handlers/session-test.ts +++ b/src/daemon/handlers/session-test.ts @@ -5,7 +5,7 @@ import type { ReplaySuiteResult, ReplaySuiteTestFailed, ReplaySuiteTestResult, -} from '../../contracts/replay.ts'; +} from '@agent-device/contracts/replay'; import { resolveReplayTestArtifactsDir } from './session-test-artifacts.ts'; import { emitRequestProgress } from '../../request/progress.ts'; import { @@ -24,7 +24,7 @@ import { type ReplayTestShardPlan, } from './session-test-sharding.ts'; import { isRequestCanceled } from '../../request/cancel.ts'; -import { mergeSnapshotDiagnostics } from '../../contracts/snapshot-diagnostics.ts'; +import { mergeSnapshotDiagnostics } from '@agent-device/contracts/capture'; type ReplayTestEntry = ReturnType[number]; type ReplayTestQueuedEntry = { diff --git a/src/daemon/handlers/session.ts b/src/daemon/handlers/session.ts index c982da2202..d9b73885e0 100644 --- a/src/daemon/handlers/session.ts +++ b/src/daemon/handlers/session.ts @@ -44,7 +44,7 @@ import { expireRefFrame } from '../ref-frame.ts'; import { LeaseRegistry } from '../lease-registry.ts'; import { PREPARE_REQUEST_TIMEOUT_MS } from '../../core/command-descriptor/timeout-policy.ts'; import { Deadline } from '../../utils/retry.ts'; -import type { LeaseLifecycleProvider } from '../../contracts/device-provider.ts'; +import type { LeaseLifecycleProvider } from '@agent-device/contracts/device'; const PREPARE_IOS_RUNNER_TIMING_NOTE = 'Top-level prepare timing fields are diagnostic and may overlap; use timing.additiveParts for additive wall-clock phases.'; diff --git a/src/daemon/handlers/snapshot-alert.ts b/src/daemon/handlers/snapshot-alert.ts index 4336a6f756..c63c0756b0 100644 --- a/src/daemon/handlers/snapshot-alert.ts +++ b/src/daemon/handlers/snapshot-alert.ts @@ -4,7 +4,7 @@ import { ALERT_POLL_INTERVAL_MS as POLL_INTERVAL_MS, DEFAULT_ALERT_TIMEOUT_MS as DEFAULT_TIMEOUT_MS, type AlertAction, -} from '../../contracts/alert-contract.ts'; +} from '@agent-device/contracts/interaction'; import { sleep } from '../../utils/timeouts.ts'; import { runAppleRunnerCommand } from '../../platforms/apple/core/runner/runner-client.ts'; import { runMacOsAlertAction } from '../../platforms/apple/os/macos/helper.ts'; diff --git a/src/daemon/handlers/snapshot-capture.ts b/src/daemon/handlers/snapshot-capture.ts index 0eae9875a5..e5c4f447ff 100644 --- a/src/daemon/handlers/snapshot-capture.ts +++ b/src/daemon/handlers/snapshot-capture.ts @@ -1,8 +1,9 @@ -import { dispatchCommand, type CommandFlags } from '../../core/dispatch.ts'; +import { + recordSnapshotTiming, + snapshotCaptureAnnotationsFrom, + type SnapshotCaptureAnnotations, +} from '@agent-device/contracts/capture'; import { isMacOs, isMobilePlatform, publicPlatformString } from '@agent-device/kernel/device'; -import { sleep } from '../../utils/timeouts.ts'; -import { runMacOsSnapshotAction } from '../../platforms/apple/os/macos/helper.ts'; -import { snapshotLinux } from '../../platforms/linux/snapshot.ts'; import { attachRefs, buildSnapshotPresentationKey, @@ -13,10 +14,18 @@ import { type SnapshotBackend, type SnapshotState, } from '@agent-device/kernel/snapshot'; +import { dispatchCommand, type CommandFlags } from '../../core/dispatch.ts'; +import { runMacOsSnapshotAction } from '../../platforms/apple/os/macos/helper.ts'; +import { snapshotLinux } from '../../platforms/linux/snapshot.ts'; +import { isAndroidInputMethodSnapshotNode } from '../../snapshot/android-input-method-overlays.ts'; import { annotateCoveredSnapshotNodes } from '../../snapshot/snapshot-occlusion.ts'; +import { + findNodeByLabel, + pruneGroupNodes, + resolveRefLabel, +} from '../../snapshot/snapshot-processing.ts'; import { normalizeSnapshotTree } from '../../snapshot/snapshot-tree.ts'; -import { isAndroidInputMethodSnapshotNode } from '../../snapshot/android-input-method-overlays.ts'; -import type { SessionState } from '../types.ts'; +import { sleep } from '../../utils/timeouts.ts'; import { ANDROID_FRESHNESS_RETRY_DEADLINE_MS, ANDROID_FRESHNESS_RETRY_DELAYS_MS, @@ -37,18 +46,9 @@ import { retryPendingInteractionOutcome, } from '../interaction-outcome-policy.ts'; import { capturePostGestureStabilizedResult } from '../post-gesture-stabilization.ts'; -import { - findNodeByLabel, - pruneGroupNodes, - resolveRefLabel, -} from '../../snapshot/snapshot-processing.ts'; -import { errorResponse, type DaemonFailureResponse } from './response.ts'; import { presentIosInteractiveSnapshot } from '../snapshot-presentation/ios/index.ts'; -import { - snapshotCaptureAnnotationsFrom, - type SnapshotCaptureAnnotations, -} from '../../contracts/snapshot-capture-annotations.ts'; -import { recordSnapshotTiming } from '../../contracts/snapshot-diagnostics.ts'; +import type { SessionState } from '../types.ts'; +import { errorResponse, type DaemonFailureResponse } from './response.ts'; type CaptureSnapshotParams = { device: SessionState['device']; diff --git a/src/daemon/handlers/snapshot-settings.ts b/src/daemon/handlers/snapshot-settings.ts index c5d80e3426..b544c0e5ae 100644 --- a/src/daemon/handlers/snapshot-settings.ts +++ b/src/daemon/handlers/snapshot-settings.ts @@ -3,7 +3,7 @@ import { getUnsupportedMacOsSettingMessage, isMacOsSettingSupported, SETTINGS_INVALID_ARGS_MESSAGE, -} from '../../contracts/settings-contract.ts'; +} from '@agent-device/contracts/settings'; import { dispatchCommand } from '../../core/dispatch.ts'; import { contextFromFlags } from '../context.ts'; import { SessionStore } from '../session-store.ts'; diff --git a/src/daemon/lease-context.ts b/src/daemon/lease-context.ts index fd1a0635bb..f36cc3d0a0 100644 --- a/src/daemon/lease-context.ts +++ b/src/daemon/lease-context.ts @@ -1,7 +1,7 @@ import type { DaemonRequest } from './types.ts'; import type { LeaseBackend } from '@agent-device/kernel/contracts'; -import type { DeviceLease } from '../contracts/device-provider.ts'; -import type { RunnerLogicalLeaseContext } from '../contracts/runner-lease-context.ts'; +import type { DeviceLease } from '@agent-device/contracts/device'; +import type { RunnerLogicalLeaseContext } from '@agent-device/contracts/platform'; import { stripUndefined } from '../utils/parsing.ts'; import { DEFAULT_PROXY_LEASE_TTL_MS, diff --git a/src/daemon/lease-lifecycle.ts b/src/daemon/lease-lifecycle.ts index 1c1626d77d..0741ae57e9 100644 --- a/src/daemon/lease-lifecycle.ts +++ b/src/daemon/lease-lifecycle.ts @@ -2,7 +2,7 @@ import { emitDiagnostic } from '../utils/diagnostics.ts'; import { leaseScopeToReleaseRequest } from '../core/lease-scope.ts'; import { clearAdvisoryDeviceClaim } from './device-claims.ts'; import type { LeaseRegistry } from './lease-registry.ts'; -import type { DeviceLease, LeaseLifecycleProvider } from '../contracts/device-provider.ts'; +import type { DeviceLease, LeaseLifecycleProvider } from '@agent-device/contracts/device'; import { buildSessionLeaseFromRequest, type SessionLease } from './lease-context.ts'; import { assertRequestLeaseAdmission, diff --git a/src/daemon/lease-registry.ts b/src/daemon/lease-registry.ts index 98d4f157ba..beb307c72f 100644 --- a/src/daemon/lease-registry.ts +++ b/src/daemon/lease-registry.ts @@ -1,4 +1,4 @@ -import type { DeviceLease } from '../contracts/device-provider.ts'; +import type { DeviceLease } from '@agent-device/contracts/device'; import crypto from 'node:crypto'; import type { LeaseBackend } from '@agent-device/kernel/contracts'; import { AppError } from '@agent-device/kernel/errors'; diff --git a/src/daemon/network-log.ts b/src/daemon/network-log.ts index e1fd5ff3e3..3eb1633afa 100644 --- a/src/daemon/network-log.ts +++ b/src/daemon/network-log.ts @@ -18,9 +18,8 @@ const ANDROID_NEARBY_LINE_RADIUS = 5; const ANDROID_PACKET_SCAN_RADIUS = 12; const NETWORK_LOG_MEMORY_PATH = ''; +import type { LogBackend, NetworkEntry } from '@agent-device/contracts/observability'; import type { NetworkIncludeMode } from '@agent-device/kernel/contracts'; -import type { LogBackend } from '../contracts/logs.ts'; -import type { NetworkEntry } from '../contracts/network-log.ts'; export type { NetworkIncludeMode }; export type NetworkDump = { diff --git a/src/daemon/open-device-selection.ts b/src/daemon/open-device-selection.ts index 9625b832e4..9cc7d4ac00 100644 --- a/src/daemon/open-device-selection.ts +++ b/src/daemon/open-device-selection.ts @@ -1,4 +1,4 @@ -import { isDeepLinkTarget } from '../contracts/open-target.ts'; +import { isDeepLinkTarget } from '@agent-device/contracts/command'; import type { ResolveTargetDeviceOptions } from '../core/dispatch-resolve.ts'; export function buildOpenTargetDeviceResolutionOptions( diff --git a/src/daemon/provider-lease-expiry.ts b/src/daemon/provider-lease-expiry.ts index 470f6ad975..a6fe82d41f 100644 --- a/src/daemon/provider-lease-expiry.ts +++ b/src/daemon/provider-lease-expiry.ts @@ -1,7 +1,10 @@ import fs from 'node:fs'; import path from 'node:path'; -import type { ProviderExpiredLeaseRecovery } from '../provider-device-runtime.ts'; -import type { DeviceLease, LeaseLifecycleProvider } from '../contracts/device-provider.ts'; +import type { + DeviceLease, + LeaseLifecycleProvider, + ProviderExpiredLeaseRecovery, +} from '@agent-device/contracts/device'; import { releaseExpiredProviderLease } from './lease-lifecycle.ts'; import { emitDiagnostic } from '../utils/diagnostics.ts'; import { sleep } from '../utils/timeouts.ts'; diff --git a/src/daemon/recording-gestures.ts b/src/daemon/recording-gestures.ts index e8bae604b9..84c2ed7561 100644 --- a/src/daemon/recording-gestures.ts +++ b/src/daemon/recording-gestures.ts @@ -11,7 +11,7 @@ import { buildScrollGesturePlan, type ScrollDirection, type SwipePattern, -} from '../contracts/scroll-gesture.ts'; +} from '@agent-device/contracts/interaction'; import { getSnapshotReferenceFrame, type TouchReferenceFrame as ReferenceFrame, diff --git a/src/daemon/replay-device-selection.ts b/src/daemon/replay-device-selection.ts index f1198a8435..b2f49f66f0 100644 --- a/src/daemon/replay-device-selection.ts +++ b/src/daemon/replay-device-selection.ts @@ -3,7 +3,7 @@ import { parseReplayInput } from '../compat/replay-input.ts'; import { parseMaestroProgram } from '../compat/maestro/program-ir-parser.ts'; import type { ResolveTargetDeviceOptions } from '../core/dispatch-resolve.ts'; import type { MaestroProgram } from '../compat/maestro/program-ir.ts'; -import { isDeepLinkTarget } from '../contracts/open-target.ts'; +import { isDeepLinkTarget } from '@agent-device/contracts/command'; import { appleSimulatorAppTargetForOpenTarget } from './open-device-selection.ts'; import { SessionStore } from './session-store.ts'; import type { CommandFlags } from '../core/dispatch.ts'; diff --git a/src/daemon/request-admission.ts b/src/daemon/request-admission.ts index 96341f4593..b9cb43477b 100644 --- a/src/daemon/request-admission.ts +++ b/src/daemon/request-admission.ts @@ -10,7 +10,7 @@ import { } from './lease-context.ts'; import { leaseScopeToHeartbeatRequest } from '../core/lease-scope.ts'; import type { LeaseRegistry } from './lease-registry.ts'; -import type { DeviceLease } from '../contracts/device-provider.ts'; +import type { DeviceLease } from '@agent-device/contracts/device'; import type { DaemonRequest, SessionState } from './types.ts'; export function scopeRequestSession(req: DaemonRequest): DaemonRequest { diff --git a/src/daemon/request-handler-chain.ts b/src/daemon/request-handler-chain.ts index 2c69bb629a..1c85cd9f19 100644 --- a/src/daemon/request-handler-chain.ts +++ b/src/daemon/request-handler-chain.ts @@ -1,11 +1,11 @@ import type { CommandFlags } from '../core/dispatch.ts'; -import type { CloudArtifactProvider } from '../contracts/cloud-artifacts.ts'; +import type { CloudArtifactProvider } from '@agent-device/contracts/observability'; import type { AndroidAdbExecutor } from '../platforms/android/adb-executor.ts'; import { AppError } from '@agent-device/kernel/errors'; import { getDaemonCommandRoute } from './daemon-command-registry.ts'; import * as genericRequestHandlerModule from './request-generic-dispatch.ts'; import type { DaemonCommandContext } from './context.ts'; -import type { LeaseLifecycleProvider } from '../contracts/device-provider.ts'; +import type { LeaseLifecycleProvider } from '@agent-device/contracts/device'; import type { LeaseRegistry } from './lease-registry.ts'; import type { SessionStore } from './session-store.ts'; import type { DaemonInvokeFn, DaemonRequest, DaemonResponse } from './types.ts'; diff --git a/src/daemon/request-platform-providers.ts b/src/daemon/request-platform-providers.ts index b83f86cec0..41d9bd3854 100644 --- a/src/daemon/request-platform-providers.ts +++ b/src/daemon/request-platform-providers.ts @@ -1,7 +1,7 @@ -import type { PlatformGatedProviderResolverKey } from '../contracts/platform-providers.ts'; +import type { PlatformGatedProviderResolverKey } from '@agent-device/contracts/platform'; import { resolveTargetDevice } from '../core/dispatch-resolve.ts'; import { registerBuiltinPlatformPlugins } from '../core/interactors/register-builtins.ts'; -import { tryGetPlugin } from '../contracts/platform-plugin.ts'; +import { tryGetPlugin } from '../core/platform-plugin-registry.ts'; import type { AndroidAdbExecutor, AndroidAdbProvider } from '../platforms/android/adb-executor.ts'; import type { AppleRunnerCommandExecutor, diff --git a/src/daemon/request-router.ts b/src/daemon/request-router.ts index 3571a3e324..39a0418895 100644 --- a/src/daemon/request-router.ts +++ b/src/daemon/request-router.ts @@ -2,7 +2,7 @@ import { withTargetDeviceResolutionScope } from '../core/dispatch-resolve.ts'; import type { DeviceInventoryProvider, LeaseLifecycleProvider, -} from '../contracts/device-provider.ts'; +} from '@agent-device/contracts/device'; import { AppError, normalizeError, @@ -12,7 +12,7 @@ import { import { supportedPlatformsForCommand } from '../core/capabilities.ts'; import { timingSafeStringEqual } from '../utils/timing-safe-equal.ts'; import type { DaemonArtifactType, ResponseCost } from '@agent-device/kernel/contracts'; -import type { CloudArtifactProvider } from '../contracts/cloud-artifacts.ts'; +import type { CloudArtifactProvider } from '@agent-device/contracts/observability'; import type { DaemonInvokeFn, DaemonRequest, DaemonResponse, DaemonResponseData } from './types.ts'; import { RESPONSE_VIEWS } from './response-views.ts'; import { SessionStore } from './session-store.ts'; diff --git a/src/daemon/screenshot-runtime.ts b/src/daemon/screenshot-runtime.ts index f0d0be199b..4795113bcf 100644 --- a/src/daemon/screenshot-runtime.ts +++ b/src/daemon/screenshot-runtime.ts @@ -6,7 +6,10 @@ import type { AgentDeviceBackend } from '../backend.ts'; import type { ArtifactAdapter } from '../io.ts'; import { createAgentDevice, localCommandPolicy } from '../runtime.ts'; import { dispatchCommand } from '../core/dispatch.ts'; -import { screenshotFlagsFromOptions, screenshotOptionsFromFlags } from '../contracts/screenshot.ts'; +import { + screenshotFlagsFromOptions, + screenshotOptionsFromFlags, +} from '@agent-device/contracts/capture'; import { AppError } from '@agent-device/kernel/errors'; import { readScreenshotResultData } from '../utils/screenshot-result.ts'; import type { DaemonCommandContext } from './context.ts'; diff --git a/src/daemon/selector-recording.ts b/src/daemon/selector-recording.ts index 211c350cc3..638772aba4 100644 --- a/src/daemon/selector-recording.ts +++ b/src/daemon/selector-recording.ts @@ -1,6 +1,6 @@ import type { DaemonRequest } from './types.ts'; import type { SnapshotNode } from '@agent-device/kernel/snapshot'; -import { stripAndroidSystemChromeProvenanceFromNode } from '../contracts/android-system-chrome.ts'; +import { stripAndroidSystemChromeProvenanceFromNode } from '@agent-device/contracts/platform'; import { SessionStore } from './session-store.ts'; import { isInteractiveObservation } from './session-action-recorder.ts'; import { diff --git a/src/daemon/server/daemon-session-lease-finalizer.test.ts b/src/daemon/server/daemon-session-lease-finalizer.test.ts index 92ea31938c..7b4859f965 100644 --- a/src/daemon/server/daemon-session-lease-finalizer.test.ts +++ b/src/daemon/server/daemon-session-lease-finalizer.test.ts @@ -4,7 +4,7 @@ import path from 'node:path'; import { expect, test, vi } from 'vitest'; import { makeIosSession } from '../../__tests__/test-utils/session-factories.ts'; import { LeaseRegistry } from '../lease-registry.ts'; -import type { DeviceLease } from '../../contracts/device-provider.ts'; +import type { DeviceLease } from '@agent-device/contracts/device'; import { createExpiredProviderLeaseReleaser } from '../provider-lease-expiry.ts'; import { finalizeDaemonSessionLease } from './daemon-session-lease-finalizer.ts'; diff --git a/src/daemon/session-action-recorder.ts b/src/daemon/session-action-recorder.ts index d337403c95..5ec04328e3 100644 --- a/src/daemon/session-action-recorder.ts +++ b/src/daemon/session-action-recorder.ts @@ -1,5 +1,5 @@ import type { CommandFlags } from '../core/dispatch.ts'; -import { SCREENSHOT_ACTION_FLAG_KEYS } from '../contracts/screenshot.ts'; +import { SCREENSHOT_ACTION_FLAG_KEYS } from '@agent-device/contracts/capture'; import { emitDiagnostic } from '../utils/diagnostics.ts'; import type { DaemonRequest, SessionAction, SessionRuntimeHints, SessionState } from './types.ts'; import { expandSessionPath } from './session-paths.ts'; diff --git a/src/daemon/session-event-action-presentation.ts b/src/daemon/session-event-action-presentation.ts index 132a92e1bd..da5c51ffae 100644 --- a/src/daemon/session-event-action-presentation.ts +++ b/src/daemon/session-event-action-presentation.ts @@ -1,19 +1,18 @@ +import { DEVICE_ROTATIONS } from '@agent-device/contracts/device'; +import { BACK_MODES, TV_REMOTE_BUTTONS } from '@agent-device/contracts/interaction'; import { PUBLIC_COMMANDS } from '../command-catalog.ts'; -import { BACK_MODES } from '../contracts/back-mode.ts'; -import { DEVICE_ROTATIONS } from '../contracts/device-rotation.ts'; -import { TV_REMOTE_BUTTONS } from '../contracts/tv-remote.ts'; import { isKeyboardAction } from '../utils/keyboard-actions.ts'; -import type { DaemonRequest, SessionAction } from './types.ts'; import { compactSessionEventDetails as compactDetails, - readBoundedSessionEventString, - readRequestedScreenshotFileName, readSessionEventBoolean as readBoolean, + readBoundedSessionEventString, readSessionEventEnum as readEnum, + readRequestedScreenshotFileName, readSessionEventFileName, readSessionEventNumber, readSessionEventString, } from './session-event-request.ts'; +import type { DaemonRequest, SessionAction } from './types.ts'; const SCROLL_DIRECTIONS = ['up', 'down', 'left', 'right'] as const; const SCROLL_EDGES = ['top', 'bottom'] as const; diff --git a/src/daemon/session-event-action.ts b/src/daemon/session-event-action.ts index 494a38867e..9309a18f9d 100644 --- a/src/daemon/session-event-action.ts +++ b/src/daemon/session-event-action.ts @@ -1,11 +1,8 @@ -import { INTERNAL_COMMANDS, PUBLIC_COMMANDS } from '../command-catalog.ts'; -import { BACK_MODES } from '../contracts/back-mode.ts'; -import { RECORDING_SCOPE_VALUES } from '../contracts/recording-scope.ts'; -import { SESSION_SURFACES } from '../contracts/session-surface.ts'; -import { SWIPE_PATTERNS } from '../contracts/scroll-gesture.ts'; -import { CLICK_BUTTONS } from '../contracts/click-button.ts'; +import { BACK_MODES, CLICK_BUTTONS, SWIPE_PATTERNS } from '@agent-device/contracts/interaction'; +import { RECORDING_SCOPE_VALUES } from '@agent-device/contracts/recording'; +import { SESSION_SURFACES } from '@agent-device/contracts/session'; import { DEVICE_TARGETS, PLATFORM_SELECTORS, PUBLIC_PLATFORMS } from '@agent-device/kernel/device'; -import type { SessionAction } from './types.ts'; +import { INTERNAL_COMMANDS, PUBLIC_COMMANDS } from '../command-catalog.ts'; import { buildInstallActionSummary, buildStructuredActionDetails, @@ -13,11 +10,12 @@ import { } from './session-event-action-presentation.ts'; import { compactSessionEventDetails as compactDetails, - readBoundedSessionEventString as readString, readSessionEventBoolean as readBoolean, readSessionEventEnum as readEnum, readSessionEventNumber as readNumber, + readBoundedSessionEventString as readString, } from './session-event-request.ts'; +import type { SessionAction } from './types.ts'; export function buildActionSummary(action: SessionAction): string { switch (action.command) { diff --git a/src/daemon/snapshot-runtime.ts b/src/daemon/snapshot-runtime.ts index e838389bcc..dd486e9744 100644 --- a/src/daemon/snapshot-runtime.ts +++ b/src/daemon/snapshot-runtime.ts @@ -1,27 +1,29 @@ +import { + snapshotCaptureAnnotationsFrom, + summarizeSnapshotDiagnostics, +} from '@agent-device/contracts/capture'; +import { stripAndroidSystemChromeProvenance } from '@agent-device/contracts/platform'; import { isIosFamily, publicPlatformString } from '@agent-device/kernel/device'; +import { AppError } from '@agent-device/kernel/errors'; import type { AgentDeviceBackend, BackendSnapshotResult } from '../backend.ts'; import type { CommandSessionRecord } from '../runtime.ts'; import { createAgentDevice } from '../runtime.ts'; -import { AppError } from '@agent-device/kernel/errors'; import type { SnapshotDiffSummary } from '../snapshot/snapshot-diff.ts'; -import type { DaemonRequest, DaemonResponse, DaemonResponseData, SessionState } from './types.ts'; -import { SessionStore } from './session-store.ts'; -import { isInteractiveObservation } from './session-action-recorder.ts'; +import { maybeBuildAndroidSnapshotTimeoutFailure } from './android-snapshot-timeout-evidence.ts'; import { errorResponse, requireCommandSupported } from './handlers/response.ts'; import { captureSnapshot, resolveSnapshotScope } from './handlers/snapshot-capture.ts'; -import { snapshotCaptureAnnotationsFrom } from '../contracts/snapshot-capture-annotations.ts'; import { buildSnapshotSession, resolveSessionDevice, withSessionlessRunnerCleanup, } from './handlers/snapshot-session.ts'; +import { activateCompleteRefFrame } from './ref-frame.ts'; import { createDaemonRuntimePolicy } from './runtime-policy.ts'; import { createDaemonRuntimeSessionStore } from './runtime-session.ts'; -import { maybeBuildAndroidSnapshotTimeoutFailure } from './android-snapshot-timeout-evidence.ts'; -import { summarizeSnapshotDiagnostics } from '../contracts/snapshot-diagnostics.ts'; +import { isInteractiveObservation } from './session-action-recorder.ts'; import { setSnapshotLineage } from './session-snapshot.ts'; -import { activateCompleteRefFrame } from './ref-frame.ts'; -import { stripAndroidSystemChromeProvenance } from '../contracts/android-system-chrome.ts'; +import { SessionStore } from './session-store.ts'; +import type { DaemonRequest, DaemonResponse, DaemonResponseData, SessionState } from './types.ts'; export async function dispatchSnapshotViaRuntime(params: { req: DaemonRequest; diff --git a/src/daemon/target-shutdown.ts b/src/daemon/target-shutdown.ts index 2fad2a2eb6..697ebe8f28 100644 --- a/src/daemon/target-shutdown.ts +++ b/src/daemon/target-shutdown.ts @@ -1,6 +1,6 @@ import { runAndroidAdb } from '../platforms/android/adb.ts'; import { getSimulatorState, shutdownSimulator } from '../platforms/apple/core/simulator.ts'; -import type { TargetShutdownResult } from '../contracts/target-shutdown-contract.ts'; +import type { TargetShutdownResult } from '@agent-device/contracts/device'; import type { DeviceInfo } from '@agent-device/kernel/device'; import { normalizeError } from '@agent-device/kernel/errors'; import { isAndroidEmulator, isIosSimulator } from './device-targets.ts'; diff --git a/src/daemon/touch-reference-frame.ts b/src/daemon/touch-reference-frame.ts index 2c69d55445..eed4c8fb27 100644 --- a/src/daemon/touch-reference-frame.ts +++ b/src/daemon/touch-reference-frame.ts @@ -1,7 +1,7 @@ import { inferGestureReferenceFrame, type GestureReferenceFrame, -} from '../contracts/scroll-gesture.ts'; +} from '@agent-device/contracts/interaction'; import type { SnapshotState } from '@agent-device/kernel/snapshot'; export type TouchReferenceFrame = GestureReferenceFrame; diff --git a/src/daemon/types.ts b/src/daemon/types.ts index 183729c202..864d1466a6 100644 --- a/src/daemon/types.ts +++ b/src/daemon/types.ts @@ -1,37 +1,39 @@ +import type { CommandFlags } from '@agent-device/contracts/command'; import type { + GestureExecutionProfile, + GestureReferenceFrame, + ScrollDirection, +} from '@agent-device/contracts/interaction'; +import type { LogBackend } from '@agent-device/contracts/observability'; +import type { RecordingExportQuality, RecordingScope } from '@agent-device/contracts/recording'; +import type { SessionAction, SessionSurface } from '@agent-device/contracts/session'; +import type { + LeaseBackend, DaemonArtifact as PublicDaemonArtifact, - DaemonRequest as WireRequest, + DaemonInstallSource as PublicDaemonInstallSource, DaemonRequestMeta as PublicDaemonRequestMeta, DaemonResponse as PublicDaemonResponse, DaemonResponseData as PublicDaemonResponseData, - DaemonInstallSource as PublicDaemonInstallSource, - LeaseBackend, SessionRuntimeHints as PublicSessionRuntimeHints, + DaemonRequest as WireRequest, } from '@agent-device/kernel/contracts'; -import type { CommandFlags } from '../contracts/command-flags.ts'; -import type { GestureReferenceFrame, ScrollDirection } from '../contracts/scroll-gesture.ts'; -import type { LogBackend } from '../contracts/logs.ts'; -import type { SessionSurface } from '../contracts/session-surface.ts'; -import type { RecordingExportQuality } from '../contracts/recording-export-quality.ts'; -import type { RecordingScope } from '../contracts/recording-scope.ts'; import type { DeviceInfo, Platform, PlatformSelector } from '@agent-device/kernel/device'; -import type { ExecBackgroundResult, ExecResult } from '../utils/exec.ts'; import type { Rect, SnapshotState } from '@agent-device/kernel/snapshot'; -import type { GestureExecutionProfile } from '../contracts/gesture-plan-types.ts'; +import type { ExecBackgroundResult, ExecResult } from '../utils/exec.ts'; // Type-only import; erased at runtime. ref-frame.ts imports SessionState from // here, so this back-edge must stay type-only to avoid a runtime cycle. -import type { RefFrameScope, RefFrameState } from './ref-frame.ts'; -import type { TargetAnnotationV1 } from '../replay/target-identity.ts'; -import type { ReplayTargetGuardDenotation } from '../replay/target-identity-node.ts'; -import type { AppLogFailure, AppLogState } from './app-log-process.ts'; -import type { DeviceLease } from '../contracts/device-provider.ts'; +import type { SnapshotDiagnosticsState } from '@agent-device/contracts/capture'; +import type { DeviceLease } from '@agent-device/contracts/device'; +import type { AudioProbeSource } from '@agent-device/contracts/platform'; import type { AndroidNativePerfSession } from '../platforms/android/perf.ts'; import type { AppleXctracePerfCapture, AppleXctracePerfMode, } from '../platforms/apple/core/perf-xctrace.ts'; -import type { AudioProbeSource } from '../contracts/audio-probe-result.ts'; -import type { SnapshotDiagnosticsState } from '../contracts/snapshot-diagnostics.ts'; +import type { ReplayTargetGuardDenotation } from '../replay/target-identity-node.ts'; +import type { TargetAnnotationV1 } from '../replay/target-identity.ts'; +import type { AppLogFailure, AppLogState } from './app-log-process.ts'; +import type { RefFrameScope, RefFrameState } from './ref-frame.ts'; export type DaemonInstallSource = PublicDaemonInstallSource; export type SessionRuntimeHints = PublicSessionRuntimeHints; export type DaemonArtifact = PublicDaemonArtifact; @@ -514,5 +516,4 @@ export type SessionState = { // The recorded-action SHAPE lives in contracts/ so replay/ and compat/ can read a script // without depending on the server; re-exported here for the daemon's own consumers. -export type { SessionAction } from '../contracts/session-action.ts'; -import type { SessionAction } from '../contracts/session-action.ts'; +export type { SessionAction } from '@agent-device/contracts/session'; diff --git a/src/mcp/__tests__/command-tools-parity.test.ts b/src/mcp/__tests__/command-tools-parity.test.ts index a3d5d0e494..ec93fcbdb8 100644 --- a/src/mcp/__tests__/command-tools-parity.test.ts +++ b/src/mcp/__tests__/command-tools-parity.test.ts @@ -4,7 +4,7 @@ import os from 'node:os'; import path from 'node:path'; import { afterEach, test, vi } from 'vitest'; import { createAgentDeviceClient } from '../../agent-device-client.ts'; -import type { AgentDeviceDaemonTransport } from '../../contracts/client-connection.ts'; +import type { AgentDeviceDaemonTransport } from '@agent-device/contracts/client'; import type { AgentDeviceClient } from '../../client/client-types.ts'; import type { CommandExecutionResult } from '../../commands/command-surface.ts'; import { createCommandToolExecutor, listCommandTools } from '../command-tools.ts'; diff --git a/src/mcp/command-output-schemas.ts b/src/mcp/command-output-schemas.ts index 98b8f51de5..47a6f111b1 100644 --- a/src/mcp/command-output-schemas.ts +++ b/src/mcp/command-output-schemas.ts @@ -2,7 +2,7 @@ import type { JsonSchema } from '../commands/command-contract.ts'; import { projectedSystemCommandOutputSchemas } from '../commands/system/index.ts'; import type { CommandResultMap } from '../core/command-descriptor/command-result.ts'; import { booleanSchema, looseObjectSchema, stringSchema } from '../commands/command-input.ts'; -import { SESSION_SURFACES } from '../contracts/session-surface.ts'; +import { SESSION_SURFACES } from '@agent-device/contracts/session'; import { DEVICE_TARGETS, PUBLIC_PLATFORMS } from '@agent-device/kernel/device'; /** @@ -129,7 +129,7 @@ function interactionResponseDataSchema(extra: InteractionExtra = {}): JsonSchema ); } -// ResolutionDiagnosticEntry (src/contracts/interaction.ts) — a disambiguation +// ResolutionDiagnosticEntry (packages/contracts/src/interaction.ts) — a disambiguation // winner or losing alternative. Never a snapshot ref. const resolutionDiagnosticEntrySchema: JsonSchema = objectSchema( { @@ -142,7 +142,7 @@ const resolutionDiagnosticEntrySchema: JsonSchema = objectSchema( ['diagnosticRef'], ); -// ResolutionDisclosure (src/contracts/interaction.ts) — never ref-issuing; +// ResolutionDisclosure (packages/contracts/src/interaction.ts) — never ref-issuing; // absent on paths where the guarantee is inapplicable (ADR 0012 decision 2). // `alternatives` rides default/full levels only; the digest view omits it. const resolutionDisclosureSchema: JsonSchema = { @@ -197,7 +197,7 @@ const resolutionDisclosureSchema: JsonSchema = { ], }; -// InteractionEvidence (src/contracts/interaction.ts) — opt-in `--verify` cheap +// InteractionEvidence (packages/contracts/src/interaction.ts) — opt-in `--verify` cheap // post-condition evidence (#1047). const interactionEvidenceSchema: JsonSchema = objectSchema( { @@ -212,7 +212,7 @@ const interactionEvidenceSchema: JsonSchema = objectSchema( ['nodeCount', 'interactiveNodeCount', 'digest', 'changedFromBefore'], ); -// SettleObservation (src/contracts/interaction.ts) — opt-in `--settle` settled +// SettleObservation (packages/contracts/src/interaction.ts) — opt-in `--settle` settled // diff observation (#1101). const settleObservationSchema: JsonSchema = objectSchema( { @@ -280,7 +280,7 @@ const settleObservationSchema: JsonSchema = objectSchema( ['settled', 'waitedMs', 'captures', 'quietMs', 'timeoutMs'], ); -// boot / shutdown share the resolved-device header (src/contracts/device.ts). +// boot / shutdown share the resolved-device header (packages/contracts/src/device.ts). const deviceHeaderProperties: Record = { // Public leaf vocabulary (ios | macos | android | linux | web): boot/shutdown // emit publicPlatformString, never the internal `apple` platform. @@ -357,7 +357,7 @@ export const COMMAND_OUTPUT_SCHEMAS = { 'Daemon response data for the find command.', ), - // src/contracts/device.ts + // packages/contracts/src/device.ts boot: objectSchema({ ...deviceHeaderProperties, booted: { type: 'boolean', const: true } }, [ ...deviceHeaderRequired, 'booted', @@ -367,16 +367,16 @@ export const COMMAND_OUTPUT_SCHEMAS = { 'shutdown', ]), - // src/contracts/viewport.ts + // packages/contracts/src/viewport.ts viewport: objectSchema( { width: numberSchema(), height: numberSchema(), message: stringSchema() }, ['width', 'height', 'message'], ), - // src/contracts/navigation.ts, projected from executable command contracts. + // packages/contracts/src/navigation.ts, projected from executable command contracts. ...projectedSystemCommandOutputSchemas, - // src/contracts/wait.ts — compact public daemon projection. + // packages/contracts/src/wait.ts — compact public daemon projection. wait: objectSchema( { waitedMs: numberSchema(), @@ -391,12 +391,12 @@ export const COMMAND_OUTPUT_SCHEMAS = { ['waitedMs'], ), - // src/contracts/prepare.ts — prepare is not MCP-exposed, but the schema stays + // packages/contracts/src/prepare.ts — prepare is not MCP-exposed, but the schema stays // map-complete with CommandResultMap. prepare: objectSchema( { action: constSchema('ios-runner'), - // PublicPlatform leaf, mirroring PrepareCommandResult (src/contracts/prepare.ts). + // PublicPlatform leaf, mirroring PrepareCommandResult (packages/contracts/src/prepare.ts). platform: enumSchema(PUBLIC_PLATFORMS), deviceId: stringSchema(), deviceName: stringSchema(), @@ -450,7 +450,7 @@ export const COMMAND_OUTPUT_SCHEMAS = { ], ), - // src/contracts/push.ts — discriminated union on public platform. + // packages/contracts/src/push.ts — discriminated union on public platform. push: { type: 'object', oneOf: [ @@ -471,7 +471,7 @@ export const COMMAND_OUTPUT_SCHEMAS = { ], }, - // src/contracts/app-events.ts + // packages/contracts/src/app-events.ts 'trigger-app-event': objectSchema( { event: stringSchema(), @@ -482,7 +482,7 @@ export const COMMAND_OUTPUT_SCHEMAS = { ['event', 'eventUrl', 'transport', 'message'], ), - // src/contracts/clipboard.ts — discriminated union on `action`. + // packages/contracts/src/clipboard.ts — discriminated union on `action`. clipboard: { type: 'object', oneOf: [ @@ -494,7 +494,7 @@ export const COMMAND_OUTPUT_SCHEMAS = { ], }, - // src/contracts/app-state.ts — discriminated union on `platform`. + // packages/contracts/src/app-state.ts — discriminated union on `platform`. appstate: { type: 'object', oneOf: [ @@ -524,7 +524,7 @@ export const COMMAND_OUTPUT_SCHEMAS = { ], }, - // src/contracts/keyboard.ts — flat closed shape; `platform`/`action` always present. + // packages/contracts/src/keyboard.ts — flat closed shape; `platform`/`action` always present. keyboard: objectSchema( { platform: enumSchema(['android', 'ios']), @@ -544,7 +544,7 @@ export const COMMAND_OUTPUT_SCHEMAS = { ['platform', 'action'], ), - // src/contracts/doctor.ts + // packages/contracts/src/doctor.ts doctor: objectSchema( { status: enumSchema(['pass', 'warn', 'fail', 'info']), @@ -572,7 +572,7 @@ export const COMMAND_OUTPUT_SCHEMAS = { ['status', 'summary', 'kind', 'checks'], ), - // src/contracts/diff.ts — the public Node command accepts snapshot diffs. + // packages/contracts/src/diff.ts — the public Node command accepts snapshot diffs. diff: objectSchema( { mode: constSchema('snapshot'), @@ -601,7 +601,7 @@ export const COMMAND_OUTPUT_SCHEMAS = { ['mode', 'baselineInitialized', 'summary', 'lines'], ), - // src/contracts/replay.ts + // packages/contracts/src/replay.ts replay: objectSchema( { replayed: numberSchema(), @@ -642,7 +642,7 @@ export const COMMAND_OUTPUT_SCHEMAS = { ], ), - // src/contracts/recording.ts + // packages/contracts/src/recording.ts record: { type: 'object', oneOf: [ diff --git a/src/mcp/command-tools.ts b/src/mcp/command-tools.ts index 01ad920244..fa1b080a3f 100644 --- a/src/mcp/command-tools.ts +++ b/src/mcp/command-tools.ts @@ -1,4 +1,4 @@ -import type { AgentDeviceClientConfig } from '../contracts/client-connection.ts'; +import type { AgentDeviceClientConfig } from '@agent-device/contracts/client'; import type { AgentDeviceClient } from '../client/client-types.ts'; import type { JsonSchema } from '../commands/command-contract.ts'; import type { CommandExecutionResult } from '../commands/command-surface.ts'; diff --git a/src/mcp/tool-input-config.ts b/src/mcp/tool-input-config.ts index e8e727a98c..fc207f2105 100644 --- a/src/mcp/tool-input-config.ts +++ b/src/mcp/tool-input-config.ts @@ -1,6 +1,6 @@ import { isFlagSupportedForCommand } from '../cli-schema/option-schema.ts'; import type { FlagKey } from '../commands/cli-grammar/flag-types.ts'; -import type { CliFlags } from '../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import type { JsonSchema } from '../commands/command-contract.ts'; import type { CommandName } from '../commands/command-metadata.ts'; import { resolveConfigBackedFlagDefaults } from '../cli-schema/cli-config.ts'; diff --git a/src/mcp/tool-result.ts b/src/mcp/tool-result.ts index 2eb4e650ff..ceec24e5a4 100644 --- a/src/mcp/tool-result.ts +++ b/src/mcp/tool-result.ts @@ -1,6 +1,6 @@ import type { CommandName } from '../commands/command-metadata.ts'; import type { CommandExecutionResult } from '../commands/command-surface.ts'; -import { serializeDevice } from '../contracts/result-serialization.ts'; +import { serializeDevice } from '../utils/result-serialization.ts'; type CollectionCommandName = { [Name in CommandName]: CommandExecutionResult extends readonly unknown[] ? Name : never; diff --git a/src/metro/client-metro.ts b/src/metro/client-metro.ts index 2d41df6005..ad8637c6ef 100644 --- a/src/metro/client-metro.ts +++ b/src/metro/client-metro.ts @@ -1,12 +1,12 @@ // The result PAYLOADS are declared in contracts/metro.ts so the public API can name them // without depending on this zone; re-exported here for existing consumers. -export type { PrepareMetroRuntimeResult, ReloadMetroResult } from '../contracts/metro.ts'; +export type { PrepareMetroRuntimeResult, ReloadMetroResult } from '@agent-device/contracts/remote'; import type { MetroPrepareKind, PrepareMetroRuntimeResult, ReloadMetroResult, ResolvedMetroKind, -} from '../contracts/metro.ts'; +} from '@agent-device/contracts/remote'; import fs from 'node:fs'; import path from 'node:path'; import { sleep } from '../utils/timeouts.ts'; diff --git a/src/metro/metro-types.ts b/src/metro/metro-types.ts index 0aaa57c65a..2c704f9e15 100644 --- a/src/metro/metro-types.ts +++ b/src/metro/metro-types.ts @@ -5,7 +5,7 @@ export type MetroRuntimeHints = SessionRuntimeHints; // The bridge RESULT shape is declared in contracts/metro.ts, because the public prepare result // embeds it and that shape had to move below both `metro/` and the command surface. -export type { MetroBridgeResult } from '../contracts/metro.ts'; +export type { MetroBridgeResult } from '@agent-device/contracts/remote'; export type MetroBridgeRuntimePayload = { metro_host?: string; diff --git a/src/platforms/android/__tests__/input-ownership.test.ts b/src/platforms/android/__tests__/input-ownership.test.ts index be65d8f57f..75236ea295 100644 --- a/src/platforms/android/__tests__/input-ownership.test.ts +++ b/src/platforms/android/__tests__/input-ownership.test.ts @@ -4,7 +4,7 @@ import { classifyAndroidInputOwnership, parseAndroidInputMethodPackage, readAndroidActiveInputMethodPackage, -} from '../../../contracts/android-input-ownership.ts'; +} from '@agent-device/contracts/platform'; test('classifies active input method package as IME-owned', () => { assert.deepEqual( diff --git a/src/platforms/android/__tests__/touch-executor.test.ts b/src/platforms/android/__tests__/touch-executor.test.ts index db398d70dc..e09c1628e6 100644 --- a/src/platforms/android/__tests__/touch-executor.test.ts +++ b/src/platforms/android/__tests__/touch-executor.test.ts @@ -1,7 +1,7 @@ import assert from 'node:assert/strict'; import { test } from 'vitest'; import { ANDROID_EMULATOR } from '../../../__tests__/test-utils/index.ts'; -import { buildGesturePlan } from '../../../contracts/gesture-plan.ts'; +import { buildGesturePlan } from '@agent-device/contracts/interaction'; import { withAndroidAdbProvider } from '../adb-executor.ts'; import { executeAndroidTouchPlan, readAndroidGestureViewport } from '../touch-executor.ts'; diff --git a/src/platforms/android/__tests__/touch-helper.fixtures.ts b/src/platforms/android/__tests__/touch-helper.fixtures.ts index 5206a34170..6b5d258ba3 100644 --- a/src/platforms/android/__tests__/touch-helper.fixtures.ts +++ b/src/platforms/android/__tests__/touch-helper.fixtures.ts @@ -1,5 +1,5 @@ import { ANDROID_EMULATOR } from '../../../__tests__/test-utils/index.ts'; -import { buildGesturePlan } from '../../../contracts/gesture-plan.ts'; +import { buildGesturePlan } from '@agent-device/contracts/interaction'; import type { DeviceInfo } from '@agent-device/kernel/device'; import type { AndroidAdbExecutor } from '../adb-executor.ts'; import type { AndroidTouchPlan } from '../touch-plan.ts'; diff --git a/src/platforms/android/__tests__/touch-helper.test.ts b/src/platforms/android/__tests__/touch-helper.test.ts index e84e671958..2505d548e6 100644 --- a/src/platforms/android/__tests__/touch-helper.test.ts +++ b/src/platforms/android/__tests__/touch-helper.test.ts @@ -1,6 +1,6 @@ import assert from 'node:assert/strict'; import { afterEach, beforeEach, test, vi } from 'vitest'; -import { buildGesturePlan } from '../../../contracts/gesture-plan.ts'; +import { buildGesturePlan } from '@agent-device/contracts/interaction'; import { AppError } from '@agent-device/kernel/errors'; import { withAndroidAdbProvider } from '../adb-executor.ts'; import { resetAndroidSnapshotHelperSessions } from '../snapshot-helper-session.ts'; diff --git a/src/platforms/android/alert-detection.ts b/src/platforms/android/alert-detection.ts index 88cad15005..65daddcf15 100644 --- a/src/platforms/android/alert-detection.ts +++ b/src/platforms/android/alert-detection.ts @@ -1,5 +1,5 @@ import { centerOfRect, type RawSnapshotNode } from '@agent-device/kernel/snapshot'; -import type { AlertInfo, AlertSource } from '../../contracts/alert-contract.ts'; +import type { AlertInfo, AlertSource } from '@agent-device/contracts/interaction'; type AndroidAlertButtonRole = 'accept' | 'dismiss' | 'neutral'; diff --git a/src/platforms/android/alert.ts b/src/platforms/android/alert.ts index 97f8c7cf8e..f621e8c5b0 100644 --- a/src/platforms/android/alert.ts +++ b/src/platforms/android/alert.ts @@ -1,9 +1,9 @@ -import type { AlertAction } from '../../contracts/alert-contract.ts'; +import type { AlertAction } from '@agent-device/contracts/interaction'; import { ALERT_ACTION_RETRY_MS, ALERT_POLL_INTERVAL_MS, DEFAULT_ALERT_TIMEOUT_MS, -} from '../../contracts/alert-contract.ts'; +} from '@agent-device/contracts/interaction'; import { AppError } from '@agent-device/kernel/errors'; import { withDiagnosticTimer } from '../../utils/diagnostics.ts'; import { successText } from '../../utils/success-text.ts'; diff --git a/src/platforms/android/app-helpers.ts b/src/platforms/android/app-helpers.ts index 49fc3dddaf..1b1f0da407 100644 --- a/src/platforms/android/app-helpers.ts +++ b/src/platforms/android/app-helpers.ts @@ -1,4 +1,4 @@ -import { resolveAppsFilter, type AppsFilter } from '../../contracts/app-inventory.ts'; +import { resolveAppsFilter, type AppsFilter } from '@agent-device/contracts/device'; import { androidAdbResultError, type AndroidAdbExecutor } from './adb-executor.ts'; import { parseAndroidForegroundApp, diff --git a/src/platforms/android/app-lifecycle.ts b/src/platforms/android/app-lifecycle.ts index 24af6ee5fd..1dc4b17efa 100644 --- a/src/platforms/android/app-lifecycle.ts +++ b/src/platforms/android/app-lifecycle.ts @@ -4,9 +4,9 @@ import path from 'node:path'; import { resolveFileOverridePath, runCmd, whichCmd } from '../../utils/exec.ts'; import { AppError } from '@agent-device/kernel/errors'; import { sleep } from '../../utils/timeouts.ts'; -import type { AppsFilter } from '../../contracts/app-inventory.ts'; +import type { AppsFilter } from '@agent-device/contracts/device'; import type { DeviceInfo } from '@agent-device/kernel/device'; -import { isDeepLinkTarget } from '../../contracts/open-target.ts'; +import { isDeepLinkTarget } from '@agent-device/contracts/command'; import { createAppResolutionCache, type AppResolutionCacheScope } from '../app-resolution-cache.ts'; import { waitForAndroidBoot } from './devices.ts'; import { runAndroidAdb } from './adb.ts'; diff --git a/src/platforms/android/device-input-state.ts b/src/platforms/android/device-input-state.ts index f00248d1b3..61d25630c2 100644 --- a/src/platforms/android/device-input-state.ts +++ b/src/platforms/android/device-input-state.ts @@ -13,7 +13,7 @@ import { isFallbackAndroidInputMethodResource, readAndroidActiveInputMethodPackage, type AndroidInputOwner, -} from '../../contracts/android-input-ownership.ts'; +} from '@agent-device/contracts/platform'; const ANDROID_INPUT_TYPE_CLASS_MASK = 0x0000000f; const ANDROID_INPUT_TYPE_CLASS_TEXT = 0x00000001; diff --git a/src/platforms/android/fill-verification.ts b/src/platforms/android/fill-verification.ts index 4f9eaf7085..9a6682ac12 100644 --- a/src/platforms/android/fill-verification.ts +++ b/src/platforms/android/fill-verification.ts @@ -10,7 +10,7 @@ import { } from './fill-diagnostics.ts'; import { sleep } from './adb.ts'; import { getAndroidKeyboardState } from './device-input-state.ts'; -import { isAndroidInputMethodOwnedNode } from '../../contracts/android-input-ownership.ts'; +import { isAndroidInputMethodOwnedNode } from '@agent-device/contracts/platform'; import { captureAndroidUiHierarchyXml } from './snapshot.ts'; import { androidUiNodes, type AndroidUiNodeMetadata } from './ui-hierarchy.ts'; diff --git a/src/platforms/android/input-actions.ts b/src/platforms/android/input-actions.ts index cb7c28446e..b76f41ed74 100644 --- a/src/platforms/android/input-actions.ts +++ b/src/platforms/android/input-actions.ts @@ -1,16 +1,21 @@ -import { AppError } from '@agent-device/kernel/errors'; +import type { DeviceRotation } from '@agent-device/contracts/device'; +import { + buildGesturePlan, + buildScrollGesturePlan, + GESTURE_DURATION_MIN_MS, + toAndroidTvRemoteKeyevent, + type ScrollDirection, + type TvRemoteButton, +} from '@agent-device/contracts/interaction'; import type { DeviceInfo } from '@agent-device/kernel/device'; +import { AppError } from '@agent-device/kernel/errors'; import { emitDiagnostic } from '../../utils/diagnostics.ts'; -import type { DeviceRotation } from '../../contracts/device-rotation.ts'; -import { buildGesturePlan, GESTURE_DURATION_MIN_MS } from '../../contracts/gesture-plan.ts'; -import { buildScrollGesturePlan, type ScrollDirection } from '../../contracts/scroll-gesture.ts'; -import { toAndroidTvRemoteKeyevent, type TvRemoteButton } from '../../contracts/tv-remote.ts'; -import { runAndroidAdb, sleep } from './adb.ts'; import { resolveAndroidAdbExecutor, resolveAndroidTextInjector, type AndroidTextInputAction, } from './adb-executor.ts'; +import { runAndroidAdb, sleep } from './adb.ts'; import { getAndroidKeyboardState, type AndroidKeyboardState } from './device-input-state.ts'; import { androidFillFailureDetails, @@ -18,13 +23,13 @@ import { verifyAndroidFilledText, type AndroidFillVerification, } from './fill-verification.ts'; -import { isAndroidTestImeActive } from './ime-lifecycle.ts'; -import { executeAndroidTouchPlan, readAndroidGestureViewport } from './touch-executor.ts'; import { clearAndroidImeHelperText, resolveAndroidImeHelperArtifact, sendAndroidImeHelperText, } from './ime-helper.ts'; +import { isAndroidTestImeActive } from './ime-lifecycle.ts'; +import { executeAndroidTouchPlan, readAndroidGestureViewport } from './touch-executor.ts'; export { readAndroidTextAtPoint } from './fill-verification.ts'; diff --git a/src/platforms/android/settings.ts b/src/platforms/android/settings.ts index 872a11f1c0..ae079f0149 100644 --- a/src/platforms/android/settings.ts +++ b/src/platforms/android/settings.ts @@ -9,7 +9,7 @@ import { parsePermissionAction, parsePermissionTarget, type SettingOptions, -} from '../permission-utils.ts'; +} from '@agent-device/contracts/settings'; import { parseAppearanceAction } from '../appearance.ts'; import { parseSettingState } from '../setting-state.ts'; import { runAndroidAdb } from './adb.ts'; diff --git a/src/platforms/android/snapshot-content-recovery.ts b/src/platforms/android/snapshot-content-recovery.ts index 6998405e9c..9aa5f2b5be 100644 --- a/src/platforms/android/snapshot-content-recovery.ts +++ b/src/platforms/android/snapshot-content-recovery.ts @@ -1,8 +1,10 @@ -import type { AndroidSnapshotBackendMetadata } from './snapshot-types.ts'; -import { isAndroidInputMethodOwnedNode } from '../../contracts/android-input-ownership.ts'; -import { hasAndroidSystemChromeProvenance } from '../../contracts/android-system-chrome.ts'; +import { + hasAndroidSystemChromeProvenance, + isAndroidInputMethodOwnedNode, +} from '@agent-device/contracts/platform'; import type { AndroidContentRecoveryReason } from '../../snapshot/snapshot-quality.ts'; import { classifyAndroidAlertIdentifier } from './alert-detection.ts'; +import type { AndroidSnapshotBackendMetadata } from './snapshot-types.ts'; import { androidUiNodes, type AndroidUiNodeMetadata } from './ui-hierarchy.ts'; const ANDROID_WINDOW_TYPE_APPLICATION = 1; diff --git a/src/platforms/android/touch-helper.ts b/src/platforms/android/touch-helper.ts index d01fb95028..e339cc68ce 100644 --- a/src/platforms/android/touch-helper.ts +++ b/src/platforms/android/touch-helper.ts @@ -1,4 +1,4 @@ -import type { PointerTrajectory } from '../../contracts/gesture-plan.ts'; +import type { PointerTrajectory } from '@agent-device/contracts/interaction'; import type { DeviceInfo } from '@agent-device/kernel/device'; import type { Rect } from '@agent-device/kernel/snapshot'; import { AppError } from '@agent-device/kernel/errors'; diff --git a/src/platforms/android/touch-plan.ts b/src/platforms/android/touch-plan.ts index c6c3ee422a..96a1a2247e 100644 --- a/src/platforms/android/touch-plan.ts +++ b/src/platforms/android/touch-plan.ts @@ -1,4 +1,4 @@ -import type { GesturePlan, PointerTrajectory } from '../../contracts/gesture-plan.ts'; +import type { GesturePlan, PointerTrajectory } from '@agent-device/contracts/interaction'; import type { Rect } from '@agent-device/kernel/snapshot'; export type AndroidLongPressTouchPlan = { diff --git a/src/platforms/android/ui-hierarchy.ts b/src/platforms/android/ui-hierarchy.ts index dc4eb5624d..c0c58ef405 100644 --- a/src/platforms/android/ui-hierarchy.ts +++ b/src/platforms/android/ui-hierarchy.ts @@ -5,7 +5,7 @@ import { intersectArea } from '../../utils/screenshot-geometry.ts'; import { type AndroidSystemChromeProvenance, isAndroidSystemChromeWindowResourceId, -} from '../../contracts/android-system-chrome.ts'; +} from '@agent-device/contracts/platform'; type AndroidRawSnapshotNode = RawSnapshotNode & AndroidSystemChromeProvenance; diff --git a/src/platforms/apple/__tests__/interactor-runner-provider.test.ts b/src/platforms/apple/__tests__/interactor-runner-provider.test.ts index 47372713d1..9041673055 100644 --- a/src/platforms/apple/__tests__/interactor-runner-provider.test.ts +++ b/src/platforms/apple/__tests__/interactor-runner-provider.test.ts @@ -1,15 +1,14 @@ +import type { GesturePlan, Interactor, RunnerContext } from '@agent-device/contracts/interaction'; +import { AppError } from '@agent-device/kernel/errors'; import assert from 'node:assert/strict'; import { test } from 'vitest'; import { IOS_SIMULATOR } from '../../../__tests__/test-utils/index.ts'; -import { createAppleInteractor } from '../interactor.ts'; -import { AppError } from '@agent-device/kernel/errors'; -import type { GesturePlan } from '../../../contracts/gesture-plan-types.ts'; -import type { Interactor, RunnerContext } from '../../../contracts/interactor-types.ts'; +import type { RunnerCommand } from '../core/runner/runner-contract.ts'; import type { AppleRunnerCommandOptions, AppleRunnerProvider, } from '../core/runner/runner-provider.ts'; -import type { RunnerCommand } from '../core/runner/runner-contract.ts'; +import { createAppleInteractor } from '../interactor.ts'; type RecordedRunnerCall = { command: RunnerCommand; options: AppleRunnerCommandOptions }; diff --git a/src/platforms/apple/__tests__/watchos-sentinel.test.ts b/src/platforms/apple/__tests__/watchos-sentinel.test.ts index 3f5b8f26ae..ca291e8999 100644 --- a/src/platforms/apple/__tests__/watchos-sentinel.test.ts +++ b/src/platforms/apple/__tests__/watchos-sentinel.test.ts @@ -1,7 +1,7 @@ import { test, expect } from 'vitest'; import { createAppleInteractor } from '../interactor.ts'; import type { DeviceInfo } from '@agent-device/kernel/device'; -import type { RunnerContext } from '../../../contracts/interactor-types.ts'; +import type { RunnerContext } from '@agent-device/contracts/interaction'; import { AppError } from '@agent-device/kernel/errors'; // watchOS is an explicit unsupported sentinel: XCUITest cannot drive watchOS UI, diff --git a/src/platforms/apple/core/__tests__/interactions.test.ts b/src/platforms/apple/core/__tests__/interactions.test.ts index 789446b965..9e36e579a9 100644 --- a/src/platforms/apple/core/__tests__/interactions.test.ts +++ b/src/platforms/apple/core/__tests__/interactions.test.ts @@ -3,7 +3,7 @@ import assert from 'node:assert/strict'; import { iosRunnerOverrides, performGestureApple } from '../../interactions.ts'; import { runAppleRunnerCommand } from '../runner/runner-client.ts'; import { AppError } from '@agent-device/kernel/errors'; -import type { GesturePlan } from '../../../../contracts/gesture-plan.ts'; +import type { GesturePlan } from '@agent-device/contracts/interaction'; import { requireGestureSupported } from '../../../../core/capabilities.ts'; import { IOS_TEST_DEVICE, diff --git a/src/platforms/apple/core/app-launch.ts b/src/platforms/apple/core/app-launch.ts index cae20e6c6a..c06bd7585f 100644 --- a/src/platforms/apple/core/app-launch.ts +++ b/src/platforms/apple/core/app-launch.ts @@ -7,13 +7,13 @@ import { execFailureDetails } from '../../../utils/exec.ts'; import { LAUNCH_CONSOLE_DIRECT_APP_ONLY_MESSAGE, LAUNCH_CONSOLE_IOS_SIMULATOR_ONLY_MESSAGE, -} from '../../../contracts/launch-console.ts'; +} from '@agent-device/contracts/observability'; import { Deadline, retryWithPolicy } from '../../../utils/retry.ts'; import { isDeepLinkTarget, isWebUrl, resolveIosDeviceDeepLinkBundleId, -} from '../../../contracts/open-target.ts'; +} from '@agent-device/contracts/command'; import { IOS_APP_LAUNCH_TIMEOUT_MS, IOS_SIMULATOR_TERMINATE_TIMEOUT_MS } from './config.ts'; import { resolveIosPhysicalDeviceControl } from './physical-device-control.ts'; import { runAppleRunnerCommand } from './runner/runner-client.ts'; diff --git a/src/platforms/apple/core/app-resolution.ts b/src/platforms/apple/core/app-resolution.ts index ec52e594e0..ba83603aa4 100644 --- a/src/platforms/apple/core/app-resolution.ts +++ b/src/platforms/apple/core/app-resolution.ts @@ -2,7 +2,7 @@ import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { isIosFamily, isMacOs, type DeviceInfo } from '@agent-device/kernel/device'; import { AppError } from '@agent-device/kernel/errors'; -import type { AppsFilter } from '../../../contracts/app-inventory.ts'; +import type { AppsFilter } from '@agent-device/contracts/device'; import { createAppResolutionCache, type AppResolutionCacheScope, diff --git a/src/platforms/apple/core/app-settings.ts b/src/platforms/apple/core/app-settings.ts index 4ed9b4dec7..f0da0d061e 100644 --- a/src/platforms/apple/core/app-settings.ts +++ b/src/platforms/apple/core/app-settings.ts @@ -1,33 +1,33 @@ -import { promises as fs } from 'node:fs'; -import path from 'node:path'; -import { isIosFamily, isMacOs, type DeviceInfo } from '@agent-device/kernel/device'; -import { AppError } from '@agent-device/kernel/errors'; -import { requireLocationCoordinates } from '../../../utils/location-coordinates.ts'; -import { requireExecSuccess } from '../../../utils/exec.ts'; -import { resolveIosSimulatorDeviceSetPath } from '../../../utils/device-isolation.ts'; -import { getUnsupportedMacOsSettingMessage } from '../../../contracts/settings-contract.ts'; import { + getUnsupportedMacOsSettingMessage, parsePermissionAction, parsePermissionTarget, type SettingOptions, -} from '../../permission-utils.ts'; +} from '@agent-device/contracts/settings'; +import { isIosFamily, isMacOs, type DeviceInfo } from '@agent-device/kernel/device'; +import { AppError } from '@agent-device/kernel/errors'; +import { promises as fs } from 'node:fs'; +import path from 'node:path'; +import { resolveIosSimulatorDeviceSetPath } from '../../../utils/device-isolation.ts'; +import { requireExecSuccess } from '../../../utils/exec.ts'; +import { requireLocationCoordinates } from '../../../utils/location-coordinates.ts'; import { parseAppearanceAction } from '../../appearance.ts'; -import { parseSettingState } from '../../setting-state.ts'; import { summarizeCommandAttemptFailures, type CommandAttemptFailure, } from '../../command-attempts.ts'; -import { ensureBootedSimulator, requireSimulatorDevice } from './simulator.ts'; -import { runXcrun } from './tool-provider.ts'; +import { parseSettingState } from '../../setting-state.ts'; import { setMacOsAppearance } from '../os/macos/apps.ts'; import { runMacOsPermissionAction, type MacOsPermissionTarget } from '../os/macos/helper.ts'; +import { closeIosApp } from './app-launch.ts'; +import { resolveIosApp } from './app-resolution.ts'; +import { runSimctl, simctlArgs } from './apps-simctl.ts'; import { invalidateSimulatorStatusBarOverrideCache, rememberClearedStatusBarOverrides, } from './screenshot-status-bar.ts'; -import { closeIosApp } from './app-launch.ts'; -import { resolveIosApp } from './app-resolution.ts'; -import { runSimctl, simctlArgs } from './apps-simctl.ts'; +import { ensureBootedSimulator, requireSimulatorDevice } from './simulator.ts'; +import { runXcrun } from './tool-provider.ts'; let cachedSimctlPrivacyServices: Set | null = null; let cachedSimctlPrivacyServicesCacheKey: string | undefined; diff --git a/src/platforms/apple/core/debug-symbols.ts b/src/platforms/apple/core/debug-symbols.ts index eade8afbcb..3a7038aee4 100644 --- a/src/platforms/apple/core/debug-symbols.ts +++ b/src/platforms/apple/core/debug-symbols.ts @@ -4,7 +4,10 @@ import { readAppleCrashArtifact } from './debug-symbols/crash-artifact.ts'; import { matchImagesToDsyms, readDsymPaths, readDsymSlices } from './debug-symbols/dsym.ts'; import { summarizeCrashArtifact } from './debug-symbols/report.ts'; import { resolveAppleTools, symbolicateAddresses } from './debug-symbols/symbolication.ts'; -import type { DebugSymbolsOptions, DebugSymbolsResult } from '../../../contracts/debug-symbols.ts'; +import type { + DebugSymbolsOptions, + DebugSymbolsResult, +} from '@agent-device/contracts/observability'; import { AppError } from '@agent-device/kernel/errors'; const MAX_CRASH_ARTIFACT_BYTES = 64 * 1024 * 1024; diff --git a/src/platforms/apple/core/debug-symbols/report.ts b/src/platforms/apple/core/debug-symbols/report.ts index ba87e06bf5..cee0016b2b 100644 --- a/src/platforms/apple/core/debug-symbols/report.ts +++ b/src/platforms/apple/core/debug-symbols/report.ts @@ -8,7 +8,7 @@ import type { import type { DebugSymbolsCrashFrame, DebugSymbolsCrashSummary, -} from '../../../../contracts/debug-symbols.ts'; +} from '@agent-device/contracts/observability'; import { isRecord } from '../../../../utils/parsing.ts'; import { addressKey, diff --git a/src/platforms/apple/core/debug-symbols/types.ts b/src/platforms/apple/core/debug-symbols/types.ts index 6d9653bd89..e6619e674e 100644 --- a/src/platforms/apple/core/debug-symbols/types.ts +++ b/src/platforms/apple/core/debug-symbols/types.ts @@ -1,8 +1,3 @@ -export type { - DebugSymbolsCrashFrame, - DebugSymbolsCrashSummary, -} from '../../../../contracts/debug-symbols.ts'; - export type AppleImage = { index?: number; name: string; diff --git a/src/platforms/apple/core/physical-device-apps.ts b/src/platforms/apple/core/physical-device-apps.ts index 0f98cb8250..66603b1dfd 100644 --- a/src/platforms/apple/core/physical-device-apps.ts +++ b/src/platforms/apple/core/physical-device-apps.ts @@ -1,4 +1,4 @@ -import type { AppsFilter } from '../../../contracts/app-inventory.ts'; +import type { AppsFilter } from '@agent-device/contracts/device'; import type { DeviceInfo } from '@agent-device/kernel/device'; import { IOS_DEVICE_INSTALL_TIMEOUT_MS } from './config.ts'; import { diff --git a/src/platforms/apple/core/physical-device-control.ts b/src/platforms/apple/core/physical-device-control.ts index 31a815fcb0..732f595e91 100644 --- a/src/platforms/apple/core/physical-device-control.ts +++ b/src/platforms/apple/core/physical-device-control.ts @@ -1,7 +1,7 @@ import type { DeviceInfo } from '@agent-device/kernel/device'; import { AppError } from '@agent-device/kernel/errors'; import { execFailureDetails } from '../../../utils/exec.ts'; -import type { AppsFilter } from '../../../contracts/app-inventory.ts'; +import type { AppsFilter } from '@agent-device/contracts/device'; import type { IosAppInfo, IosDeviceAppProcesses } from './app-info.ts'; import { installCoreDeviceApp, diff --git a/src/platforms/apple/core/runner/runner-contract.ts b/src/platforms/apple/core/runner/runner-contract.ts index 7f94de8d0e..96fc4ba998 100644 --- a/src/platforms/apple/core/runner/runner-contract.ts +++ b/src/platforms/apple/core/runner/runner-contract.ts @@ -1,10 +1,12 @@ import crypto from 'node:crypto'; +import type { DeviceRotation } from '@agent-device/contracts/device'; +import type { + ClickButton, + ElementSelectorKey, + GesturePlan, + ScrollDirection, +} from '@agent-device/contracts/interaction'; import { AppError } from '@agent-device/kernel/errors'; -import type { ClickButton } from '../../../../contracts/click-button.ts'; -import type { DeviceRotation } from '../../../../contracts/device-rotation.ts'; -import type { ScrollDirection } from '../../../../contracts/scroll-gesture.ts'; -import type { GesturePlan } from '../../../../contracts/gesture-plan.ts'; -import type { ElementSelectorKey } from '../../../../contracts/interactor-types.ts'; import { createRequestCanceledError, getRequestSignal, diff --git a/src/platforms/apple/core/runner/runner-lease.ts b/src/platforms/apple/core/runner/runner-lease.ts index 944eca83f0..69c4779ef6 100644 --- a/src/platforms/apple/core/runner/runner-lease.ts +++ b/src/platforms/apple/core/runner/runner-lease.ts @@ -7,7 +7,7 @@ import { AppError } from '@agent-device/kernel/errors'; import { acquireProcessLock } from '../../../../utils/process-lock.ts'; import { readProcessStartTime } from '../../../../utils/host-process.ts'; import { classifyOwnerLiveness } from '../../../../utils/owner-identity.ts'; -import type { RunnerLogicalLeaseContext } from '../../../../contracts/runner-lease-context.ts'; +import type { RunnerLogicalLeaseContext } from '@agent-device/contracts/platform'; const RUNNER_LEASE_SCHEMA_VERSION = 1; const RUNNER_LEASE_LOCK_TIMEOUT_MS = 30_000; diff --git a/src/platforms/apple/core/runner/runner-provider.ts b/src/platforms/apple/core/runner/runner-provider.ts index 3598c50e3b..0df2e6cd7e 100644 --- a/src/platforms/apple/core/runner/runner-provider.ts +++ b/src/platforms/apple/core/runner/runner-provider.ts @@ -1,5 +1,5 @@ import { AsyncLocalStorage } from 'node:async_hooks'; -import type { RunnerLogicalLeaseContext } from '../../../../contracts/runner-lease-context.ts'; +import type { RunnerLogicalLeaseContext } from '@agent-device/contracts/platform'; import type { DeviceInfo } from '@agent-device/kernel/device'; import type { Deadline } from '../../../../utils/retry.ts'; import type { RunnerCommand } from './runner-contract.ts'; diff --git a/src/platforms/apple/core/runner/runner-session-types.ts b/src/platforms/apple/core/runner/runner-session-types.ts index 9886c1ae1e..c8105b213f 100644 --- a/src/platforms/apple/core/runner/runner-session-types.ts +++ b/src/platforms/apple/core/runner/runner-session-types.ts @@ -1,4 +1,4 @@ -import type { RunnerLogicalLeaseContext } from '../../../../contracts/runner-lease-context.ts'; +import type { RunnerLogicalLeaseContext } from '@agent-device/contracts/platform'; import type { ExecResult } from '../../../../utils/exec.ts'; import type { DeviceInfo } from '@agent-device/kernel/device'; import type { RunnerXctestrunArtifact } from './runner-xctestrun.ts'; diff --git a/src/platforms/apple/core/runner/runner-session.ts b/src/platforms/apple/core/runner/runner-session.ts index 36e30e1326..b3dde74277 100644 --- a/src/platforms/apple/core/runner/runner-session.ts +++ b/src/platforms/apple/core/runner/runner-session.ts @@ -7,7 +7,7 @@ import { import { withKeyedLock } from '../../../../utils/keyed-lock.ts'; import { Deadline } from '../../../../utils/retry.ts'; import { isIosFamily, isApplePlatform, type DeviceInfo } from '@agent-device/kernel/device'; -import type { RunnerLogicalLeaseContext } from '../../../../contracts/runner-lease-context.ts'; +import type { RunnerLogicalLeaseContext } from '@agent-device/contracts/platform'; import type { AppleRunnerLifecycleOptions } from './runner-provider.ts'; import { emitRequestProgress } from '../../../../request/progress.ts'; import { createRequestCanceledError } from '../../../../request/cancel.ts'; diff --git a/src/platforms/apple/core/scroll.ts b/src/platforms/apple/core/scroll.ts index 8a4303e888..0ea0ebd92a 100644 --- a/src/platforms/apple/core/scroll.ts +++ b/src/platforms/apple/core/scroll.ts @@ -1,4 +1,4 @@ -import { buildScrollGesturePlan, type ScrollDirection } from '../../../contracts/scroll-gesture.ts'; +import { buildScrollGesturePlan, type ScrollDirection } from '@agent-device/contracts/interaction'; export type NormalizedScrollOptions = { amount?: number; diff --git a/src/platforms/apple/core/tool-provider-types.ts b/src/platforms/apple/core/tool-provider-types.ts index 7796c3e547..f16c121f64 100644 --- a/src/platforms/apple/core/tool-provider-types.ts +++ b/src/platforms/apple/core/tool-provider-types.ts @@ -1,4 +1,4 @@ -import type { AppsFilter } from '../../../contracts/app-inventory.ts'; +import type { AppsFilter } from '@agent-device/contracts/device'; import type { ExecOptions, ExecResult } from '../../../utils/exec.ts'; import type { IosAppInfo } from './app-info.ts'; diff --git a/src/platforms/apple/interactions.ts b/src/platforms/apple/interactions.ts index f7d975a58e..41c377f345 100644 --- a/src/platforms/apple/interactions.ts +++ b/src/platforms/apple/interactions.ts @@ -1,32 +1,32 @@ -import { isIosFamily, isMacOs, isTvOsDevice, type DeviceInfo } from '@agent-device/kernel/device'; -import { assertScrollGestureInput, type ScrollDirection } from '../../contracts/scroll-gesture.ts'; import { + assertScrollGestureInput, normalizeScrollDurationMs, SCROLL_DURATION_MAX_MS, -} from '../../contracts/scroll-command.ts'; + singlePointerPlanEndpoints, + type BackMode, + type GesturePlan, + type Interactor, + type RunnerCallOptions, + type RunnerContext, + type ScrollDirection, +} from '@agent-device/contracts/interaction'; +import { assertAppleMultiTouchSupported } from '@agent-device/contracts/platform'; +import { isIosFamily, isMacOs, isTvOsDevice, type DeviceInfo } from '@agent-device/kernel/device'; import { AppError } from '@agent-device/kernel/errors'; -import { singlePointerPlanEndpoints, type GesturePlan } from '../../contracts/gesture-plan.ts'; -import { assertAppleMultiTouchSupported } from '../../contracts/apple-multitouch-support.ts'; import { runAppleRunnerCommand } from './core/runner/runner-client.ts'; +import type { RunnerCommand } from './core/runner/runner-contract.ts'; import { buildRunnerSequenceCommand, parseRunnerSequenceResult, } from './core/runner/runner-sequence.ts'; -import type { RunnerCommand } from './core/runner/runner-contract.ts'; -import { appleRemotePressCommand } from './os/tvos/remote.ts'; -import { runMacosDesktopScroll } from './os/macos/desktop-scroll.ts'; import { normalizeAppleScrollResult, normalizeAppleScrollResultWithResolvedFrame, scrollRunnerFields, type AppleScrollOptions, } from './core/scroll.ts'; -import type { - BackMode, - Interactor, - RunnerCallOptions, - RunnerContext, -} from '../../contracts/interactor-types.ts'; +import { runMacosDesktopScroll } from './os/macos/desktop-scroll.ts'; +import { appleRemotePressCommand } from './os/tvos/remote.ts'; export type AppleBackRunnerCommand = 'backInApp' | 'backSystem'; type RunAppleRunnerCommand = typeof runAppleRunnerCommand; diff --git a/src/platforms/apple/interactor.ts b/src/platforms/apple/interactor.ts index 4153dcdb5f..9fa5e7b776 100644 --- a/src/platforms/apple/interactor.ts +++ b/src/platforms/apple/interactor.ts @@ -17,8 +17,8 @@ import { type AppleRunnerCommandExecutor, type AppleRunnerProvider, } from './core/runner/runner-provider.ts'; -import { toAppleTvRemoteButton } from '../../contracts/tv-remote.ts'; -import { DEVICE_ROTATIONS, type DeviceRotation } from '../../contracts/device-rotation.ts'; +import { toAppleTvRemoteButton } from '@agent-device/contracts/interaction'; +import { DEVICE_ROTATIONS, type DeviceRotation } from '@agent-device/contracts/device'; import { withDiagnosticTimer } from '../../utils/diagnostics.ts'; import { isMacOs, isTvOsDevice, type DeviceInfo } from '@agent-device/kernel/device'; import { AppError } from '@agent-device/kernel/errors'; @@ -29,7 +29,7 @@ import type { RunnerCallOptions, RunnerContext, ScreenshotOptions, -} from '../../contracts/interactor-types.ts'; +} from '@agent-device/contracts/interaction'; import { readSnapshotQualityVerdict, type SnapshotQualityVerdict, diff --git a/src/platforms/apple/os/macos/apps.ts b/src/platforms/apple/os/macos/apps.ts index 87be00ad66..8746296a4f 100644 --- a/src/platforms/apple/os/macos/apps.ts +++ b/src/platforms/apple/os/macos/apps.ts @@ -1,5 +1,5 @@ -import type { AppsFilter } from '../../../../contracts/app-inventory.ts'; -import { isDeepLinkTarget } from '../../../../contracts/open-target.ts'; +import type { AppsFilter } from '@agent-device/contracts/device'; +import { isDeepLinkTarget } from '@agent-device/contracts/command'; import type { DeviceInfo } from '@agent-device/kernel/device'; import { AppError } from '@agent-device/kernel/errors'; import { parseAppearanceAction } from '../../../appearance.ts'; diff --git a/src/platforms/apple/os/macos/desktop-scroll.ts b/src/platforms/apple/os/macos/desktop-scroll.ts index 5c6a05e1e8..a5b267dc45 100644 --- a/src/platforms/apple/os/macos/desktop-scroll.ts +++ b/src/platforms/apple/os/macos/desktop-scroll.ts @@ -1,6 +1,9 @@ +import type { + RunnerCallOptions, + RunnerContext, + ScrollDirection, +} from '@agent-device/contracts/interaction'; import type { DeviceInfo } from '@agent-device/kernel/device'; -import type { RunnerCallOptions, RunnerContext } from '../../../../contracts/interactor-types.ts'; -import type { ScrollDirection } from '../../../../contracts/scroll-gesture.ts'; import type { RunnerCommand } from '../../core/runner/runner-contract.ts'; import { normalizeAppleScrollResultWithResolvedFrame, diff --git a/src/platforms/apple/os/macos/helper.ts b/src/platforms/apple/os/macos/helper.ts index 72a45527a0..15f1c7ea18 100644 --- a/src/platforms/apple/os/macos/helper.ts +++ b/src/platforms/apple/os/macos/helper.ts @@ -9,7 +9,7 @@ import { runCmdBackground, type ExecBackgroundResult, } from '../../../../utils/exec.ts'; -import type { SessionSurface } from '../../../../contracts/session-surface.ts'; +import type { SessionSurface } from '@agent-device/contracts/session'; import { hasScopedAppleToolProvider, resolveAppleToolProvider, diff --git a/src/platforms/apple/os/macos/host-provider.ts b/src/platforms/apple/os/macos/host-provider.ts index 66c65c9232..7c7e1f9aef 100644 --- a/src/platforms/apple/os/macos/host-provider.ts +++ b/src/platforms/apple/os/macos/host-provider.ts @@ -1,7 +1,7 @@ import { promises as fs } from 'node:fs'; import os from 'node:os'; import path from 'node:path'; -import type { AppsFilter } from '../../../../contracts/app-inventory.ts'; +import type { AppsFilter } from '@agent-device/contracts/device'; import { AppError } from '@agent-device/kernel/errors'; import { requireExecSuccess } from '../../../../utils/exec.ts'; import { filterAppleAppsByBundlePrefix } from '../../core/app-filter.ts'; diff --git a/src/platforms/apple/plugin.ts b/src/platforms/apple/plugin.ts index 81bea527ba..c4b686c826 100644 --- a/src/platforms/apple/plugin.ts +++ b/src/platforms/apple/plugin.ts @@ -1,18 +1,18 @@ import { appleOsCapabilities } from './capabilities.ts'; -import type { PlatformPlugin } from '../../contracts/platform-plugin.ts'; +import type { PlatformPlugin } from '@agent-device/contracts/platform'; import { PUBLIC_COMMANDS } from '../../command-catalog.ts'; -import { isAudioProbeSupportedDevice } from '../../contracts/audio-probe-support.ts'; +import { isAudioProbeSupportedDevice } from '@agent-device/contracts/platform'; import { shouldUseHostMacFastPath, type DeviceInventoryRequest, -} from '../../contracts/device-inventory.ts'; +} from '@agent-device/contracts/device'; import { isMacOs, isTvOsDevice, resolveDeviceAppleOs, type DeviceInfo, } from '@agent-device/kernel/device'; -import type { RunnerContext } from '../../contracts/interactor-types.ts'; +import type { RunnerContext } from '@agent-device/contracts/interaction'; // --------------------------------------------------------------------------- // Apple family per-command capability closures. Originally RELOCATED VERBATIM from diff --git a/src/platforms/audio-probe-backend.ts b/src/platforms/audio-probe-backend.ts index 9e9ea2a46c..b105a587c2 100644 --- a/src/platforms/audio-probe-backend.ts +++ b/src/platforms/audio-probe-backend.ts @@ -1,5 +1,5 @@ -import type { AudioProbeSource } from '../contracts/audio-probe-result.ts'; -import { isHostSystemAudioProbeDevice } from '../contracts/audio-probe-support.ts'; +import type { AudioProbeSource } from '@agent-device/contracts/platform'; +import { isHostSystemAudioProbeDevice } from '@agent-device/contracts/platform'; import type { DeviceInfo } from '@agent-device/kernel/device'; import type { ExecBackgroundResult } from '../utils/exec.ts'; diff --git a/src/platforms/linux/input-actions.ts b/src/platforms/linux/input-actions.ts index 9662bf5935..24c0afa71d 100644 --- a/src/platforms/linux/input-actions.ts +++ b/src/platforms/linux/input-actions.ts @@ -1,7 +1,7 @@ import { ensureInputTool } from './linux-env.ts'; import { resolveLinuxToolProvider, type LinuxPointerButton } from './tool-provider.ts'; import { sleep } from '../../utils/timeouts.ts'; -import type { ScrollDirection } from '../../contracts/scroll-gesture.ts'; +import type { ScrollDirection } from '@agent-device/contracts/interaction'; // ── Low-level wrappers ───────────────────────────────────────────────── diff --git a/src/platforms/linux/snapshot.ts b/src/platforms/linux/snapshot.ts index 55d464cc1d..91ea2ff8c9 100644 --- a/src/platforms/linux/snapshot.ts +++ b/src/platforms/linux/snapshot.ts @@ -1,6 +1,6 @@ import type { RawSnapshotNode } from '@agent-device/kernel/snapshot'; import { captureAccessibilityTree, type SnapshotSurface } from './atspi-bridge.ts'; -import type { SessionSurface } from '../../contracts/session-surface.ts'; +import type { SessionSurface } from '@agent-device/contracts/session'; import { emitDiagnostic } from '../../utils/diagnostics.ts'; /** diff --git a/src/platforms/linux/tool-provider.ts b/src/platforms/linux/tool-provider.ts index 12c64cdd16..f0310e61f0 100644 --- a/src/platforms/linux/tool-provider.ts +++ b/src/platforms/linux/tool-provider.ts @@ -1,15 +1,14 @@ -import { runCmd, whichCmd, type ExecOptions, type ExecResult } from '../../utils/exec.ts'; -import { emitDiagnostic } from '../../utils/diagnostics.ts'; +import type { ClickButton, ScrollDirection } from '@agent-device/contracts/interaction'; import { AppError } from '@agent-device/kernel/errors'; +import { emitDiagnostic } from '../../utils/diagnostics.ts'; +import { runCmd, whichCmd, type ExecOptions, type ExecResult } from '../../utils/exec.ts'; import { createScopedProvider } from '../../utils/scoped-provider.ts'; import { sleep } from '../../utils/timeouts.ts'; -import type { ClickButton } from '../../contracts/click-button.ts'; import type { LinuxAccessibilityTree, LinuxSnapshotSurface, LinuxTraversalOptions, } from './accessibility-types.ts'; -import type { ScrollDirection } from '../../contracts/scroll-gesture.ts'; export type LinuxToolCommandExecutor = ( cmd: string, diff --git a/src/platforms/permission-utils.ts b/src/platforms/permission-utils.ts deleted file mode 100644 index 666a161255..0000000000 --- a/src/platforms/permission-utils.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { AppError } from '@agent-device/kernel/errors'; - -export type PermissionAction = 'grant' | 'deny' | 'reset'; -export type PermissionTarget = - | 'camera' - | 'microphone' - | 'photos' - | 'contacts' - | 'contacts-limited' - | 'notifications' - | 'calendar' - | 'location' - | 'location-always' - | 'media-library' - | 'motion' - | 'reminders' - | 'siri'; -export type SettingOptions = { - permissionTarget?: string; - permissionMode?: string; - latitude?: number; - longitude?: number; -}; -const PERMISSION_TARGETS: readonly PermissionTarget[] = [ - 'camera', - 'microphone', - 'photos', - 'contacts', - 'contacts-limited', - 'notifications', - 'calendar', - 'location', - 'location-always', - 'media-library', - 'motion', - 'reminders', - 'siri', -]; - -export function parsePermissionAction(action: string): PermissionAction { - const normalized = action.trim().toLowerCase(); - if (normalized === 'grant') return 'grant'; - if (normalized === 'deny') return 'deny'; - if (normalized === 'reset') return 'reset'; - throw new AppError('INVALID_ARGS', `Invalid permission action: ${action}. Use grant|deny|reset.`); -} - -export function parsePermissionTarget(value: string | undefined): PermissionTarget { - const normalized = value?.trim().toLowerCase(); - if ( - normalized === 'camera' || - normalized === 'microphone' || - normalized === 'photos' || - normalized === 'contacts' || - normalized === 'contacts-limited' || - normalized === 'notifications' || - normalized === 'calendar' || - normalized === 'location' || - normalized === 'location-always' || - normalized === 'media-library' || - normalized === 'motion' || - normalized === 'reminders' || - normalized === 'siri' - ) { - return normalized; - } - throw new AppError( - 'INVALID_ARGS', - `permission setting requires a target: ${PERMISSION_TARGETS.join('|')}`, - ); -} diff --git a/src/platforms/unsupported-interactor.ts b/src/platforms/unsupported-interactor.ts index 6be13604da..4781fb1e0a 100644 --- a/src/platforms/unsupported-interactor.ts +++ b/src/platforms/unsupported-interactor.ts @@ -1,5 +1,5 @@ import { AppError } from '@agent-device/kernel/errors'; -import type { Interactor } from '../contracts/interactor-types.ts'; +import type { Interactor } from '@agent-device/contracts/interaction'; export function createUnsupportedInteractor(platformLabel: string): Interactor { const unsupported = async (operation: string): Promise => { diff --git a/src/platforms/vega/__tests__/interactor.test.ts b/src/platforms/vega/__tests__/interactor.test.ts index 95644ccbe1..7df07f99c0 100644 --- a/src/platforms/vega/__tests__/interactor.test.ts +++ b/src/platforms/vega/__tests__/interactor.test.ts @@ -1,6 +1,6 @@ import assert from 'node:assert/strict'; import { beforeEach, test, vi } from 'vitest'; -import type { Interactor } from '../../../contracts/interactor-types.ts'; +import type { Interactor } from '@agent-device/contracts/interaction'; import { AppError } from '@agent-device/kernel/errors'; import type { DeviceInfo } from '@agent-device/kernel/device'; import { createVegaInteractor } from '../interactor.ts'; diff --git a/src/platforms/vega/input-actions.ts b/src/platforms/vega/input-actions.ts index 57aebd37fa..6dec8dc144 100644 --- a/src/platforms/vega/input-actions.ts +++ b/src/platforms/vega/input-actions.ts @@ -1,4 +1,4 @@ -import { toVegaTvRemoteKey, type TvRemoteButton } from '../../contracts/tv-remote.ts'; +import { toVegaTvRemoteKey, type TvRemoteButton } from '@agent-device/contracts/interaction'; import type { DeviceInfo } from '@agent-device/kernel/device'; import { requireExecSuccess } from '../../utils/exec.ts'; import { resolveVegaToolProvider } from './tool-provider.ts'; diff --git a/src/platforms/vega/interactor.ts b/src/platforms/vega/interactor.ts index f46bbbaee0..838a92465f 100644 --- a/src/platforms/vega/interactor.ts +++ b/src/platforms/vega/interactor.ts @@ -1,5 +1,5 @@ -import { isDeepLinkTarget } from '../../contracts/open-target.ts'; -import type { Interactor, RunnerContext } from '../../contracts/interactor-types.ts'; +import { isDeepLinkTarget } from '@agent-device/contracts/command'; +import type { Interactor, RunnerContext } from '@agent-device/contracts/interaction'; import type { DeviceInfo } from '@agent-device/kernel/device'; import { AppError } from '@agent-device/kernel/errors'; import { createUnsupportedInteractor } from '../unsupported-interactor.ts'; diff --git a/src/platforms/vega/plugin.ts b/src/platforms/vega/plugin.ts index f1bba33789..9cc1d07dd1 100644 --- a/src/platforms/vega/plugin.ts +++ b/src/platforms/vega/plugin.ts @@ -1,7 +1,7 @@ import { PUBLIC_COMMANDS } from '../../command-catalog.ts'; -import type { DeviceInventoryRequest } from '../../contracts/device-inventory.ts'; -import type { Interactor, RunnerContext } from '../../contracts/interactor-types.ts'; -import type { PlatformPlugin } from '../../contracts/platform-plugin.ts'; +import type { DeviceInventoryRequest } from '@agent-device/contracts/device'; +import type { Interactor, RunnerContext } from '@agent-device/contracts/interaction'; +import type { PlatformPlugin } from '@agent-device/contracts/platform'; import type { DeviceInfo } from '@agent-device/kernel/device'; const VEGA_VVD_ONLY_COMMANDS = [ diff --git a/src/platforms/vega/tool-provider.ts b/src/platforms/vega/tool-provider.ts index 913df02c90..a34d4a973b 100644 --- a/src/platforms/vega/tool-provider.ts +++ b/src/platforms/vega/tool-provider.ts @@ -2,7 +2,7 @@ import { constants } from 'node:fs'; import { access } from 'node:fs/promises'; import os from 'node:os'; import path from 'node:path'; -import type { VegaTvRemoteKey } from '../../contracts/tv-remote.ts'; +import type { VegaTvRemoteKey } from '@agent-device/contracts/interaction'; import { runCmd, whichCmd, type ExecOptions, type ExecResult } from '../../utils/exec.ts'; import { createScopedProvider } from '../../utils/scoped-provider.ts'; diff --git a/src/platforms/web/agent-browser-audio-probe.ts b/src/platforms/web/agent-browser-audio-probe.ts index 5068812d31..5eaf7fa7ea 100644 --- a/src/platforms/web/agent-browser-audio-probe.ts +++ b/src/platforms/web/agent-browser-audio-probe.ts @@ -1,7 +1,4 @@ -import { - normalizeAudioProbeRecord, - type AudioProbeResult, -} from '../../contracts/audio-probe-result.ts'; +import { normalizeAudioProbeRecord, type AudioProbeResult } from '@agent-device/contracts/platform'; import { isJsonObject, type JsonObject } from './json-utils.ts'; import type { WebAudioProbeOptions, WebAudioProbeResult } from './provider.ts'; diff --git a/src/platforms/web/provider.ts b/src/platforms/web/provider.ts index 6c52a4217b..db00ab3966 100644 --- a/src/platforms/web/provider.ts +++ b/src/platforms/web/provider.ts @@ -1,9 +1,9 @@ -import type { ScrollDirection } from '../../contracts/scroll-gesture.ts'; -import type { SessionSurface } from '../../contracts/session-surface.ts'; +import type { ScrollDirection } from '@agent-device/contracts/interaction'; +import type { SessionSurface } from '@agent-device/contracts/session'; import { createScopedProvider } from '../../utils/scoped-provider.ts'; import type { RawSnapshotNode } from '@agent-device/kernel/snapshot'; import type { BackendDumpNetworkOptions, BackendDumpNetworkResult } from '../../backend.ts'; -import type { AudioProbeResult } from '../../contracts/audio-probe-result.ts'; +import type { AudioProbeResult } from '@agent-device/contracts/platform'; import { createAgentBrowserWebProvider } from './agent-browser-provider.ts'; export type WebOpenOptions = { diff --git a/src/provider-device-runtime.ts b/src/provider-device-runtime.ts index 8b30a7fe19..c89692b8f0 100644 --- a/src/provider-device-runtime.ts +++ b/src/provider-device-runtime.ts @@ -1,84 +1,33 @@ -import { AsyncLocalStorage } from 'node:async_hooks'; -import type { - CloudArtifactProvider, - CloudArtifactsQuery, - CloudArtifactsResult, -} from './contracts/cloud-artifacts.ts'; -import type { Interactor, RunnerContext } from './contracts/interactor-types.ts'; import type { DeviceInventoryProvider, DeviceLease, LeaseLifecycleContext, LeaseLifecycleProvider, -} from './contracts/device-provider.ts'; + ProviderDeviceInstallOptions, + ProviderDeviceInstallResult, + ProviderDeviceRuntime, + ProviderExpiredLeaseRecovery, + ProviderPortReverseOptions, +} from '@agent-device/contracts/device'; +import type { Interactor, RunnerContext } from '@agent-device/contracts/interaction'; +import type { + CloudArtifactProvider, + CloudArtifactsQuery, + CloudArtifactsResult, +} from '@agent-device/contracts/observability'; +import { publicPlatformString, type DeviceInfo } from '@agent-device/kernel/device'; +import { AppError } from '@agent-device/kernel/errors'; +import { AsyncLocalStorage } from 'node:async_hooks'; import type { AppleRunnerProviderResolver } from './daemon/request-platform-providers.ts'; import type { AppleRunnerCommandExecutor, AppleRunnerProvider, } from './platforms/apple/core/runner/runner-provider.ts'; -import { publicPlatformString, type DeviceInfo } from '@agent-device/kernel/device'; -import { AppError } from '@agent-device/kernel/errors'; -export type ProviderDeviceInstallResult = { - bundleId?: string; - packageName?: string; - appName?: string; - launchTarget?: string; -}; - -export type ProviderDeviceInstallOptions = { - relaunch?: boolean; - appIdentifierHint?: string; - packageNameHint?: string; -}; - -export type ProviderDeviceRuntime = { - provider: string; - leaseLifecycle: LeaseLifecycleProvider; - recoverExpiredLease?: ProviderExpiredLeaseRecovery; - cloudArtifacts?: CloudArtifactProvider; - deviceInventoryProvider: DeviceInventoryProvider; - ownsDevice(device: DeviceInfo): boolean; - /** - * Builds the interactor for an owned device. `runnerContext` carries the - * per-request context (requestId for cancellation, appBundleId, log paths); - * runtimes composing the shared Apple interactor should thread it through so - * runner calls stay attributable to the request that issued them. - */ - getInteractor(device: DeviceInfo, runnerContext?: RunnerContext): Interactor | undefined; - /** - * Apple runner transport for an owned device. When present, the daemon scopes - * the WHOLE request with it (via the `appleRunnerProvider` request resolver), - * so daemon routes that issue runner commands outside interactor methods - * (keyboard, native alert, point read, iOS sequences) reach the provider - * transport instead of the local XCTest runtime. - */ - getAppleRunnerProvider?( +type AppleRunnerRuntimeExtension = ProviderDeviceRuntime & { + getAppleRunnerProvider( device: DeviceInfo, ): AppleRunnerProvider | AppleRunnerCommandExecutor | undefined; - installApp?( - device: DeviceInfo, - app: string, - appPath: string, - options?: ProviderDeviceInstallOptions, - ): Promise; - installInstallablePath?( - device: DeviceInfo, - installablePath: string, - options?: ProviderDeviceInstallOptions, - ): Promise; - configurePortReverse?( - options: ProviderPortReverseOptions, - ): Promise | undefined>; - shutdown(): Promise; -}; - -export type ProviderPortReverseOptions = { - leaseId: string; - provider?: string; - devicePort: number; - hostPort: number; - name: string; }; export type ProviderDeviceRuntimeRequestProviders = { @@ -93,8 +42,6 @@ export type ProviderDeviceRuntimeRequestProviders = { providerDeviceRuntimeScope?: (task: () => Promise) => Promise; }; -export type ProviderExpiredLeaseRecovery = (lease: DeviceLease) => Promise; - let activeProviderDeviceRuntimes: ProviderDeviceRuntime[] = []; const providerDeviceRuntimeScope = new AsyncLocalStorage(); @@ -205,17 +152,25 @@ export function createProviderDeviceRuntimeRequestProviders( function composeAppleRunnerProviderResolver( runtimes: ProviderDeviceRuntime[], ): AppleRunnerProviderResolver | undefined { - if (!runtimes.some((runtime) => runtime.getAppleRunnerProvider !== undefined)) return undefined; + if (!runtimes.some(hasAppleRunnerProvider)) return undefined; return (context) => { for (const runtime of runtimes) { - if (!runtime.ownsDevice(context.device)) continue; - const provider = runtime.getAppleRunnerProvider?.(context.device); + if (!hasAppleRunnerProvider(runtime) || !runtime.ownsDevice(context.device)) continue; + const provider = runtime.getAppleRunnerProvider(context.device); if (provider) return provider; } return undefined; }; } +function hasAppleRunnerProvider( + runtime: ProviderDeviceRuntime, +): runtime is AppleRunnerRuntimeExtension { + return ( + 'getAppleRunnerProvider' in runtime && typeof runtime.getAppleRunnerProvider === 'function' + ); +} + function composeExpiredLeaseRecovery( runtimes: ProviderDeviceRuntime[], ): ProviderExpiredLeaseRecovery | undefined { diff --git a/src/provider-device-runtimes.ts b/src/provider-device-runtimes.ts index 4835e7c41f..42c30c9325 100644 --- a/src/provider-device-runtimes.ts +++ b/src/provider-device-runtimes.ts @@ -1,7 +1,7 @@ import { createDefaultCloudWebDriverProviderRuntimes } from './cloud-webdriver/provider-runtimes.ts'; import { CLOUD_WEBDRIVER_PROVIDER_DEFINITIONS } from './cloud-webdriver/provider-definitions.ts'; import type { DefaultCloudWebDriverProviderRuntimeEnv } from './cloud-webdriver/provider-runtimes.ts'; -import type { ProviderDeviceRuntime } from './provider-device-runtime.ts'; +import type { ProviderDeviceRuntime } from '@agent-device/contracts/device'; import { LIMRUN_PROVIDER } from './providers/limrun/device.ts'; export type DefaultProviderDeviceRuntimeEnv = DefaultCloudWebDriverProviderRuntimeEnv & diff --git a/src/providers/limrun/android.ts b/src/providers/limrun/android.ts index a872c4fa30..bd0d7f444b 100644 --- a/src/providers/limrun/android.ts +++ b/src/providers/limrun/android.ts @@ -5,8 +5,13 @@ import { type InstanceClient as LimrunAndroidClient, } from '@limrun/api/instance-client'; import { createAndroidInteractor } from '../../core/interactors/android.ts'; -import type { Interactor } from '../../contracts/interactor-types.ts'; -import type { DeviceLease } from '../../contracts/device-provider.ts'; +import type { Interactor } from '@agent-device/contracts/interaction'; +import type { + DeviceLease, + ProviderDeviceInstallOptions, + ProviderDeviceInstallResult, + ProviderPortReverseOptions, +} from '@agent-device/contracts/device'; import { AppError } from '@agent-device/kernel/errors'; import type { DeviceInfo } from '@agent-device/kernel/device'; import { @@ -15,11 +20,6 @@ import { type AndroidAdbProvider, type AndroidPortReverseEndpoint, } from '../../platforms/android/adb-executor.ts'; -import type { - ProviderDeviceInstallOptions, - ProviderDeviceInstallResult, - ProviderPortReverseOptions, -} from '../../provider-device-runtime.ts'; import { runCmd } from '../../utils/exec.ts'; import { normalizeOptionalString } from './strings.ts'; diff --git a/src/providers/limrun/device-session.test.ts b/src/providers/limrun/device-session.test.ts index 1bb41b8282..61fb7af89d 100644 --- a/src/providers/limrun/device-session.test.ts +++ b/src/providers/limrun/device-session.test.ts @@ -1,6 +1,6 @@ import assert from 'node:assert/strict'; import { test, vi } from 'vitest'; -import type { DeviceLease } from '../../contracts/device-provider.ts'; +import type { DeviceLease } from '@agent-device/contracts/device'; import type { DeviceInfo } from '@agent-device/kernel/device'; import type { AndroidAdbExecutor, diff --git a/src/providers/limrun/device-session.ts b/src/providers/limrun/device-session.ts index 898533c878..0ee17e846c 100644 --- a/src/providers/limrun/device-session.ts +++ b/src/providers/limrun/device-session.ts @@ -1,5 +1,5 @@ -import type { Interactor } from '../../contracts/interactor-types.ts'; -import { resolveAppsFilter, type AppsFilter } from '../../contracts/app-inventory.ts'; +import type { Interactor } from '@agent-device/contracts/interaction'; +import { resolveAppsFilter, type AppsFilter } from '@agent-device/contracts/device'; import type { DeviceInfo } from '@agent-device/kernel/device'; import type { AndroidAdbProvider } from '../../platforms/android/adb-executor.ts'; import type { diff --git a/src/providers/limrun/device.ts b/src/providers/limrun/device.ts index a7d6011d71..dc6a5a9fef 100644 --- a/src/providers/limrun/device.ts +++ b/src/providers/limrun/device.ts @@ -1,4 +1,4 @@ -import type { DeviceLease } from '../../contracts/device-provider.ts'; +import type { DeviceLease } from '@agent-device/contracts/device'; import type { DeviceInfo } from '@agent-device/kernel/device'; export type LimrunPlatform = 'ios' | 'android'; diff --git a/src/providers/limrun/ios.ts b/src/providers/limrun/ios.ts index e6b8172000..b827bbb6a1 100644 --- a/src/providers/limrun/ios.ts +++ b/src/providers/limrun/ios.ts @@ -1,25 +1,25 @@ -import fs from 'node:fs'; -import os from 'node:os'; -import path from 'node:path'; -import type Limrun from '@limrun/api'; -import { - createInstanceClient as createIosInstanceClient, - type InstanceClient as LimrunIosClient, -} from '@limrun/api/ios-client'; -import type { DeviceRotation } from '../../contracts/device-rotation.ts'; -import { isDeepLinkTarget } from '../../contracts/open-target.ts'; +import { isDeepLinkTarget } from '@agent-device/contracts/command'; +import type { + DeviceLease, + DeviceRotation, + ProviderDeviceInstallOptions, + ProviderDeviceInstallResult, +} from '@agent-device/contracts/device'; import type { Interactor, SnapshotOptions, SnapshotResult, -} from '../../contracts/interactor-types.ts'; -import type { DeviceLease } from '../../contracts/device-provider.ts'; +} from '@agent-device/contracts/interaction'; import type { DeviceInfo } from '@agent-device/kernel/device'; import { AppError } from '@agent-device/kernel/errors'; -import type { - ProviderDeviceInstallOptions, - ProviderDeviceInstallResult, -} from '../../provider-device-runtime.ts'; +import type Limrun from '@limrun/api'; +import { + createInstanceClient as createIosInstanceClient, + type InstanceClient as LimrunIosClient, +} from '@limrun/api/ios-client'; +import fs from 'node:fs'; +import os from 'node:os'; +import path from 'node:path'; import { execFailureDetails, runCmd } from '../../utils/exec.ts'; import { sleep } from '../../utils/timeouts.ts'; import { flattenIosTree, toIosSelector, writeBase64File, type IosTreeNode } from './snapshot.ts'; diff --git a/src/providers/limrun/runtime.ts b/src/providers/limrun/runtime.ts index 77e7f61ac0..643a64eaf7 100644 --- a/src/providers/limrun/runtime.ts +++ b/src/providers/limrun/runtime.ts @@ -1,19 +1,17 @@ import Limrun from '@limrun/api'; -import type { Interactor } from '../../contracts/interactor-types.ts'; +import type { Interactor } from '@agent-device/contracts/interaction'; import type { DeviceInventoryProvider, DeviceLease, LeaseLifecycleProvider, -} from '../../contracts/device-provider.ts'; -import type { DeviceInfo } from '@agent-device/kernel/device'; -import { AppError } from '@agent-device/kernel/errors'; -import type { ProviderDeviceInstallOptions, ProviderDeviceInstallResult, ProviderDeviceRuntime, ProviderExpiredLeaseRecovery, ProviderPortReverseOptions, -} from '../../provider-device-runtime.ts'; +} from '@agent-device/contracts/device'; +import type { DeviceInfo } from '@agent-device/kernel/device'; +import { AppError } from '@agent-device/kernel/errors'; import { readVersion } from '../../utils/version.ts'; import { cleanupLimrunAndroidAdbTunnel, @@ -77,6 +75,8 @@ export class LimrunRuntime implements ProviderDeviceRuntime { await this.release(lease); }; + // Called through ProviderDeviceRuntime composition, not by this concrete class. + // fallow-ignore-next-line unused-class-member readonly deviceInventoryProvider: DeviceInventoryProvider = async (request) => { if (request.leaseProvider !== this.provider || !request.leaseId) return null; const session = this.sessions.get(request.leaseId); @@ -96,6 +96,8 @@ export class LimrunRuntime implements ProviderDeviceRuntime { }); } + // Called through ProviderDeviceRuntime composition, not by this concrete class. + // fallow-ignore-next-line unused-class-member ownsDevice(device: DeviceInfo): boolean { return parseLimrunDeviceId(device.id) !== undefined; } diff --git a/src/recording/overlay.ts b/src/recording/overlay.ts index 2d75241fcf..f9cd31d800 100644 --- a/src/recording/overlay.ts +++ b/src/recording/overlay.ts @@ -9,7 +9,7 @@ import { waitForPlayableVideo, waitForStableFile } from '../utils/video.ts'; import { DEFAULT_RECORDING_EXPORT_QUALITY, type RecordingExportQuality, -} from '../contracts/recording-export-quality.ts'; +} from '@agent-device/contracts/recording'; export function buildRecordingScriptPathCandidates( scriptName: string, diff --git a/src/remote/remote-config-schema.ts b/src/remote/remote-config-schema.ts index 5e25f1821b..57393092bc 100644 --- a/src/remote/remote-config-schema.ts +++ b/src/remote/remote-config-schema.ts @@ -2,10 +2,10 @@ import type { CloudProviderProfileFields, RemoteConfigMetroOptions, RemoteConnectionProfileFields, -} from '../contracts/remote-config-fields.ts'; +} from '@agent-device/contracts/remote'; // Declared in contracts/ so zones below remote/ can be stated in terms of the field vocabulary; // re-exported here because this module is where consumers already import it from. -export type { RemoteConnectionProfileFields } from '../contracts/remote-config-fields.ts'; +export type { RemoteConnectionProfileFields } from '@agent-device/contracts/remote'; import { buildPrimaryEnvVarName } from '../utils/source-value.ts'; import { PLATFORM_SELECTORS, diff --git a/src/remote/remote-connection-state.ts b/src/remote/remote-connection-state.ts index 851854807f..81bae0e3f5 100644 --- a/src/remote/remote-connection-state.ts +++ b/src/remote/remote-connection-state.ts @@ -4,7 +4,7 @@ import path from 'node:path'; import { resolveRemoteConfigPath, resolveRemoteConfigProfile } from './remote-config-core.ts'; import { AppError } from '@agent-device/kernel/errors'; import { emitDiagnostic } from '../utils/diagnostics.ts'; -import type { CliFlags } from '../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import type { LeaseBackend, SessionRuntimeHints } from '@agent-device/kernel/contracts'; import { leaseScopeFromOptions, diff --git a/src/replay/__tests__/plan-digest.test.ts b/src/replay/__tests__/plan-digest.test.ts index 0379caf11a..a543927e47 100644 --- a/src/replay/__tests__/plan-digest.test.ts +++ b/src/replay/__tests__/plan-digest.test.ts @@ -1,7 +1,7 @@ import assert from 'node:assert/strict'; import { test } from 'vitest'; import { computeReplayPlanDigest } from '../plan-digest.ts'; -import type { SessionAction } from '../../contracts/session-action.ts'; +import type { SessionAction } from '@agent-device/contracts/session'; function action(overrides: Partial = {}): SessionAction { return { diff --git a/src/replay/__tests__/script.test.ts b/src/replay/__tests__/script.test.ts index 62fe0bae52..901748712b 100644 --- a/src/replay/__tests__/script.test.ts +++ b/src/replay/__tests__/script.test.ts @@ -10,7 +10,7 @@ import { } from '../script.ts'; import { formatPortableActionLine, formatTargetAnnotationLines } from '../script-formatting.ts'; import type { TargetAnnotationV1 } from '../target-identity.ts'; -import type { SessionAction } from '../../contracts/session-action.ts'; +import type { SessionAction } from '@agent-device/contracts/session'; // `writeReplayScript` (the `--update` heal-and-rewrite serializer) was // deleted in ADR 0012 migration step 6 (`--update` retirement left it with diff --git a/src/replay/__tests__/vars.test.ts b/src/replay/__tests__/vars.test.ts index 0410ec3157..2cde1d78e3 100644 --- a/src/replay/__tests__/vars.test.ts +++ b/src/replay/__tests__/vars.test.ts @@ -9,7 +9,7 @@ import { resolveReplayString, } from '../vars.ts'; import { parseReplayScriptDetailed, readReplayScriptMetadata } from '../script.ts'; -import type { SessionAction } from '../../contracts/session-action.ts'; +import type { SessionAction } from '@agent-device/contracts/session'; const LOC = { file: 'test.ad', line: 1 }; diff --git a/src/replay/open-script.ts b/src/replay/open-script.ts index 29c87417d5..ad26facb6f 100644 --- a/src/replay/open-script.ts +++ b/src/replay/open-script.ts @@ -1,4 +1,4 @@ -import type { SessionAction } from '../contracts/session-action.ts'; +import type { SessionAction } from '@agent-device/contracts/session'; import { appendRuntimeHintFlags, formatScriptArg, diff --git a/src/replay/plan-digest.ts b/src/replay/plan-digest.ts index 4adaa42e4c..f976481579 100644 --- a/src/replay/plan-digest.ts +++ b/src/replay/plan-digest.ts @@ -1,5 +1,5 @@ import { createHash } from 'node:crypto'; -import type { SessionAction } from '../contracts/session-action.ts'; +import type { SessionAction } from '@agent-device/contracts/session'; import { canonicalJson } from '../utils/canonical-json.ts'; /** diff --git a/src/replay/script-formatting.ts b/src/replay/script-formatting.ts index 901924f9cf..dd75c90aeb 100644 --- a/src/replay/script-formatting.ts +++ b/src/replay/script-formatting.ts @@ -7,7 +7,7 @@ import { appendSnapshotActionScriptArgs, } from './script-utils.ts'; import { formatTargetAnnotationCommentLine } from './target-identity.ts'; -import type { SessionAction } from '../contracts/session-action.ts'; +import type { SessionAction } from '@agent-device/contracts/session'; export function formatPortableActionLine( action: SessionAction, diff --git a/src/replay/script-utils.ts b/src/replay/script-utils.ts index 797a1988b5..ad5b6f3b35 100644 --- a/src/replay/script-utils.ts +++ b/src/replay/script-utils.ts @@ -1,5 +1,5 @@ -import type { SessionAction } from '../contracts/session-action.ts'; -import { appendScreenshotScriptFlags } from '../contracts/screenshot.ts'; +import type { SessionAction } from '@agent-device/contracts/session'; +import { appendScreenshotScriptFlags } from '@agent-device/contracts/capture'; import { splitRefGenerationSuffix } from '@agent-device/kernel/snapshot'; /** diff --git a/src/replay/script.ts b/src/replay/script.ts index 6729b53c9d..8906c18214 100644 --- a/src/replay/script.ts +++ b/src/replay/script.ts @@ -1,11 +1,11 @@ import { AppError } from '@agent-device/kernel/errors'; -import { recordingQualityInputToExportQuality } from '../contracts/recording-export-quality.ts'; -import { describeReplayGestureArityError } from '../contracts/gesture-normalization.ts'; -import { readScreenshotScriptFlag } from '../contracts/screenshot.ts'; +import { recordingQualityInputToExportQuality } from '@agent-device/contracts/recording'; +import { describeReplayGestureArityError } from '@agent-device/contracts/interaction'; +import { readScreenshotScriptFlag } from '@agent-device/contracts/capture'; import type { DeviceTarget, PlatformSelector } from '@agent-device/kernel/device'; import { PLATFORM_SELECTORS } from '@agent-device/kernel/device'; import { parseReplayOpenFlags } from './open-script.ts'; -import type { SessionAction } from '../contracts/session-action.ts'; +import type { SessionAction } from '@agent-device/contracts/session'; import { isClickLikeCommand, parseReplaySeriesFlags, diff --git a/src/replay/target-identity.ts b/src/replay/target-identity.ts index 068586bada..14ae9254ca 100644 --- a/src/replay/target-identity.ts +++ b/src/replay/target-identity.ts @@ -26,14 +26,14 @@ export type { TargetAnnotationV1, TargetScrollRegion, TargetVerification, -} from '../contracts/target-annotation.ts'; +} from '@agent-device/contracts/replay'; import type { TargetAncestryEntry, TargetAnnotationV1, TargetRect, TargetScrollRegion, TargetVerification, -} from '../contracts/target-annotation.ts'; +} from '@agent-device/contracts/replay'; // --------------------------------------------------------------------------- // Normalization (decision 3 "Normalization"): all strings NFC; `label` fields diff --git a/src/replay/test/__tests__/reporters-default.test.ts b/src/replay/test/__tests__/reporters-default.test.ts index 62c33ffa92..247dbc3afc 100644 --- a/src/replay/test/__tests__/reporters-default.test.ts +++ b/src/replay/test/__tests__/reporters-default.test.ts @@ -1,6 +1,6 @@ import { test } from 'vitest'; import assert from 'node:assert/strict'; -import type { ReplaySuiteResult } from '../../../contracts/replay.ts'; +import type { ReplaySuiteResult } from '@agent-device/contracts/replay'; import { createDefaultReplayTestReporter } from '../reporters/default.ts'; import type { ReplayTestReporterContext } from '../reporters/types.ts'; diff --git a/src/replay/test/progress.ts b/src/replay/test/progress.ts index 7202ba647e..410f7697b9 100644 --- a/src/replay/test/progress.ts +++ b/src/replay/test/progress.ts @@ -1,12 +1,12 @@ import path from 'node:path'; import { replayTestStepLines } from './trace.ts'; -import type { ReplaySuiteTestResult } from '../../contracts/replay.ts'; +import type { ReplaySuiteTestResult } from '@agent-device/contracts/replay'; import type { ReplayTestReporterProgressEvent, ReplayTestResult, ReplayTestStep, } from './reporters/types.ts'; -import { formatCliStatusMarker } from '../../contracts/cli-status-markers.ts'; +import { formatCliStatusMarker } from '../../utils/status-markers.ts'; import { formatDurationSeconds } from '../../utils/duration-format.ts'; import { colorize, supportsColor } from '../../utils/output.ts'; diff --git a/src/replay/test/reporters/__tests__/registry.test.ts b/src/replay/test/reporters/__tests__/registry.test.ts index d5aaf302d4..ea41dc2b63 100644 --- a/src/replay/test/reporters/__tests__/registry.test.ts +++ b/src/replay/test/reporters/__tests__/registry.test.ts @@ -1,6 +1,6 @@ import assert from 'node:assert/strict'; import { test } from 'vitest'; -import type { ReplaySuiteResult } from '../../../../contracts/replay.ts'; +import type { ReplaySuiteResult } from '@agent-device/contracts/replay'; import { getReplayTestReporterExitCode, runReplayTestReporterProgress, diff --git a/src/replay/test/reporters/default.ts b/src/replay/test/reporters/default.ts index 56eee66328..69dfb1d08c 100644 --- a/src/replay/test/reporters/default.ts +++ b/src/replay/test/reporters/default.ts @@ -1,4 +1,4 @@ -import type { ReplaySuiteResult } from '../../../contracts/replay.ts'; +import type { ReplaySuiteResult } from '@agent-device/contracts/replay'; import { replayTestFailureStepLines } from '../trace.ts'; import { createReplayTestProgressRenderer, diff --git a/src/replay/test/reporters/format.ts b/src/replay/test/reporters/format.ts index 29c298b48c..c9efac2e92 100644 --- a/src/replay/test/reporters/format.ts +++ b/src/replay/test/reporters/format.ts @@ -1,5 +1,5 @@ import path from 'node:path'; -import type { ReplaySuiteTestResult } from '../../../contracts/replay.ts'; +import type { ReplaySuiteTestResult } from '@agent-device/contracts/replay'; export type PassedReplayTestResult = Extract; export type FailedReplayTestResult = Extract; diff --git a/src/replay/test/reporters/junit.ts b/src/replay/test/reporters/junit.ts index a03fc6f257..8b96cdc51d 100644 --- a/src/replay/test/reporters/junit.ts +++ b/src/replay/test/reporters/junit.ts @@ -1,6 +1,6 @@ import fs from 'node:fs'; import path from 'node:path'; -import type { ReplaySuiteResult, ReplaySuiteTestResult } from '../../../contracts/replay.ts'; +import type { ReplaySuiteResult, ReplaySuiteTestResult } from '@agent-device/contracts/replay'; import { AppError } from '@agent-device/kernel/errors'; import type { ReplayTestReporter } from './types.ts'; import { diff --git a/src/replay/test/reporters/registry.ts b/src/replay/test/reporters/registry.ts index 159a4fea89..564feb182a 100644 --- a/src/replay/test/reporters/registry.ts +++ b/src/replay/test/reporters/registry.ts @@ -1,4 +1,4 @@ -import type { ReplaySuiteResult } from '../../../contracts/replay.ts'; +import type { ReplaySuiteResult } from '@agent-device/contracts/replay'; import type { RequestProgressEvent } from '../../../request/progress.ts'; import { createCustomReplayTestReporter } from './custom.ts'; import { createDefaultReplayTestReporter } from './default.ts'; diff --git a/src/replay/test/reporters/types.ts b/src/replay/test/reporters/types.ts index 09d26d62f5..970c60ccd7 100644 --- a/src/replay/test/reporters/types.ts +++ b/src/replay/test/reporters/types.ts @@ -1,4 +1,4 @@ -import type { ReplaySuiteResult } from '../../../contracts/replay.ts'; +import type { ReplaySuiteResult } from '@agent-device/contracts/replay'; export type ReplayTestReporterContext = { debug?: boolean; diff --git a/src/replay/test/reporting.ts b/src/replay/test/reporting.ts index f6417a0c1e..6ab915b67b 100644 --- a/src/replay/test/reporting.ts +++ b/src/replay/test/reporting.ts @@ -1,5 +1,5 @@ import type { RequestProgressEvent } from '../../request/progress.ts'; -import type { ReplaySuiteResult } from '../../contracts/replay.ts'; +import type { ReplaySuiteResult } from '@agent-device/contracts/replay'; import { getReplayTestReporterExitCode, resolveReplayTestReporters, diff --git a/src/replay/test/trace.ts b/src/replay/test/trace.ts index 427cbce8fc..392d936d54 100644 --- a/src/replay/test/trace.ts +++ b/src/replay/test/trace.ts @@ -1,6 +1,6 @@ import fs from 'node:fs'; import path from 'node:path'; -import type { ReplaySuiteTestResult } from '../../contracts/replay.ts'; +import type { ReplaySuiteTestResult } from '@agent-device/contracts/replay'; import { formatDurationSeconds } from '../../utils/duration-format.ts'; type ReplayActionStartTrace = { diff --git a/src/replay/vars.ts b/src/replay/vars.ts index ef54ad5519..1bb915fb01 100644 --- a/src/replay/vars.ts +++ b/src/replay/vars.ts @@ -1,5 +1,5 @@ import { AppError } from '@agent-device/kernel/errors'; -import type { SessionAction } from '../contracts/session-action.ts'; +import type { SessionAction } from '@agent-device/contracts/session'; export type ReplayVarScope = { values: Readonly>; diff --git a/src/selectors/__tests__/is-argument-surface-parity.test.ts b/src/selectors/__tests__/is-argument-surface-parity.test.ts index f7d03364e3..477ee63112 100644 --- a/src/selectors/__tests__/is-argument-surface-parity.test.ts +++ b/src/selectors/__tests__/is-argument-surface-parity.test.ts @@ -4,7 +4,7 @@ import { AppError } from '@agent-device/kernel/errors'; import { checkIsArgs } from '../arguments.ts'; import { checkIsPredicate, IS_PREDICATE_USAGE_HINT } from '../predicates.ts'; import { readInputFromCli } from '../../commands/cli-grammar.ts'; -import type { CliFlags } from '../../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; // Parity gate for the `is` argument contract across every surface that admits one. // diff --git a/src/selectors/resolve.ts b/src/selectors/resolve.ts index 2bdc341226..903e17ab73 100644 --- a/src/selectors/resolve.ts +++ b/src/selectors/resolve.ts @@ -1,5 +1,5 @@ import type { Platform, PublicPlatform } from '@agent-device/kernel/device'; -import type { DisambiguationTiebreak } from '../contracts/interaction.ts'; +import type { DisambiguationTiebreak } from '@agent-device/contracts/interaction'; import type { SnapshotNode, SnapshotState } from '@agent-device/kernel/snapshot'; import { isNodeVisibleOnScreen } from '../snapshot/mobile-snapshot-semantics.ts'; import { buildSnapshotNodeMap } from '../snapshot/snapshot-tree.ts'; diff --git a/src/snapshot/android-input-method-overlays.ts b/src/snapshot/android-input-method-overlays.ts index 5f2e63cd19..401f2cfed0 100644 --- a/src/snapshot/android-input-method-overlays.ts +++ b/src/snapshot/android-input-method-overlays.ts @@ -1,4 +1,4 @@ -import { classifyAndroidInputOwnership } from '../contracts/android-input-ownership.ts'; +import { classifyAndroidInputOwnership } from '@agent-device/contracts/platform'; import type { RawSnapshotNode } from '@agent-device/kernel/snapshot'; export function isAndroidInputMethodSnapshotNode( diff --git a/src/snapshot/snapshot-diff.ts b/src/snapshot/snapshot-diff.ts index 6508f43c04..cd79607a85 100644 --- a/src/snapshot/snapshot-diff.ts +++ b/src/snapshot/snapshot-diff.ts @@ -1,3 +1,4 @@ +import type { SnapshotDiffLine, SnapshotDiffSummary } from '@agent-device/contracts/capture'; import type { SnapshotNode } from '@agent-device/kernel/snapshot'; import { buildSnapshotDisplayLines, @@ -6,23 +7,7 @@ import { formatSnapshotLine, } from './snapshot-lines.ts'; -export type SnapshotDiffLine = { - kind: 'added' | 'removed' | 'unchanged'; - text: string; - /** - * Plain ref body (`e12`) of the CURRENT-tree node behind an added line. - * Only populated with `withRefs` (interaction `--settle`, #1101) so the - * `diff` command's wire shape stays byte-identical. Removed/unchanged lines - * never carry it: a removed line's ref names a node of the replaced tree. - */ - ref?: string; -}; - -export type SnapshotDiffSummary = { - additions: number; - removals: number; - unchanged: number; -}; +export type { SnapshotDiffLine, SnapshotDiffSummary } from '@agent-device/contracts/capture'; export type SnapshotDiffResult = { summary: SnapshotDiffSummary; diff --git a/src/utils/__tests__/interactors.test.ts b/src/utils/__tests__/interactors.test.ts index c07a72b617..14a7236058 100644 --- a/src/utils/__tests__/interactors.test.ts +++ b/src/utils/__tests__/interactors.test.ts @@ -3,11 +3,9 @@ import assert from 'node:assert/strict'; import type { RunnerCommand } from '../../platforms/apple/core/runner/runner-client.ts'; import type { DeviceInfo } from '@agent-device/kernel/device'; import { AppError } from '@agent-device/kernel/errors'; -import type { Interactor, RunnerContext } from '../../contracts/interactor-types.ts'; -import { - setActiveProviderDeviceRuntimes, - type ProviderDeviceRuntime, -} from '../../provider-device-runtime.ts'; +import type { Interactor, RunnerContext } from '@agent-device/contracts/interaction'; +import { setActiveProviderDeviceRuntimes } from '../../provider-device-runtime.ts'; +import type { ProviderDeviceRuntime } from '@agent-device/contracts/device'; vi.mock('../../platforms/apple/core/runner/runner-client.ts', async (importOriginal) => { const actual = diff --git a/src/utils/ax-digest.ts b/src/utils/ax-digest.ts index 4f0d5731ef..4453b00b5f 100644 --- a/src/utils/ax-digest.ts +++ b/src/utils/ax-digest.ts @@ -87,7 +87,7 @@ export type AxEvidenceSummary = { /** * Summarizes one capture into the pieces `evidence` needs (see - * src/contracts/interaction.ts: `InteractionEvidence`), without ever requiring + * packages/contracts/src/interaction.ts: `InteractionEvidence`), without ever requiring * the caller to serialize the node array itself. `interactiveNodeCount` counts * nodes the platform did not mark `hittable: false` within the given capture — * cheap since it's a filter over nodes already in hand, no extra signal needed. diff --git a/src/contracts/doctor-output.ts b/src/utils/doctor-output.ts similarity index 97% rename from src/contracts/doctor-output.ts rename to src/utils/doctor-output.ts index 46f0fcaf25..8ce650d032 100644 --- a/src/contracts/doctor-output.ts +++ b/src/utils/doctor-output.ts @@ -1,4 +1,4 @@ -import { formatCliStatusMarker, type CliStatusMarkerStatus } from './cli-status-markers.ts'; +import { formatCliStatusMarker, type CliStatusMarkerStatus } from './status-markers.ts'; export type DoctorLineCheck = { id?: unknown; diff --git a/src/contracts/cli-doctor-output.ts b/src/utils/doctor-progress.ts similarity index 100% rename from src/contracts/cli-doctor-output.ts rename to src/utils/doctor-progress.ts diff --git a/src/contracts/result-serialization.test.ts b/src/utils/result-serialization.test.ts similarity index 100% rename from src/contracts/result-serialization.test.ts rename to src/utils/result-serialization.test.ts diff --git a/src/contracts/result-serialization.ts b/src/utils/result-serialization.ts similarity index 94% rename from src/contracts/result-serialization.ts rename to src/utils/result-serialization.ts index 07e2240749..92abef77b4 100644 --- a/src/contracts/result-serialization.ts +++ b/src/utils/result-serialization.ts @@ -1,23 +1,21 @@ +import { + publicSnapshotCaptureAnnotations, + type SnapshotCaptureAnnotations, +} from '@agent-device/contracts/capture'; import type { + AgentDeviceDevice, + AgentDeviceIdentifiers, + AgentDeviceSession, + AgentDeviceSessionDevice, AppCloseResult, AppDeployResult, AppInstallFromSourceResult, AppOpenResult, -} from './client-app.ts'; -import type { CaptureSnapshotResult } from './client-capture.ts'; -import type { AgentDeviceIdentifiers } from './client-connection.ts'; -import type { - AgentDeviceDevice, - AgentDeviceSession, - AgentDeviceSessionDevice, -} from './client-device-view.ts'; -import type { SessionCloseResult } from './client-session.ts'; -import { - publicSnapshotCaptureAnnotations, - type SnapshotCaptureAnnotations, -} from './snapshot-capture-annotations.ts'; + CaptureSnapshotResult, + SessionCloseResult, +} from '@agent-device/contracts/client'; import { isSerialAddressablePlatform, type PublicPlatform } from '@agent-device/kernel/device'; -import { successText, withSuccessText } from '../utils/success-text.ts'; +import { successText, withSuccessText } from './success-text.ts'; export function buildAppIdentifiers(params: { session?: string; diff --git a/src/utils/scroll-edge-state.ts b/src/utils/scroll-edge-state.ts index 962526d250..0022314620 100644 --- a/src/utils/scroll-edge-state.ts +++ b/src/utils/scroll-edge-state.ts @@ -4,7 +4,7 @@ import { } from '../snapshot/mobile-snapshot-semantics.ts'; import { AppError } from '@agent-device/kernel/errors'; import { isScrollableNodeLike } from './scrollable.ts'; -import type { ScrollDirection } from '../contracts/scroll-gesture.ts'; +import type { ScrollDirection } from '@agent-device/contracts/interaction'; import type { HiddenContentHint, Point, diff --git a/src/utils/session-binding.ts b/src/utils/session-binding.ts index b94ff1063a..89757bcdd5 100644 --- a/src/utils/session-binding.ts +++ b/src/utils/session-binding.ts @@ -1,5 +1,5 @@ import { AppError } from '@agent-device/kernel/errors'; -import type { CliFlags } from '../contracts/cli-flags.ts'; +import type { CliFlags } from '@agent-device/contracts/command'; import type { DaemonLockPolicy } from '@agent-device/kernel/contracts'; export type BindingSettings = { diff --git a/src/contracts/cli-status-markers.ts b/src/utils/status-markers.ts similarity index 92% rename from src/contracts/cli-status-markers.ts rename to src/utils/status-markers.ts index c6624dc6bb..a4691386ba 100644 --- a/src/contracts/cli-status-markers.ts +++ b/src/utils/status-markers.ts @@ -1,4 +1,4 @@ -import { colorize, supportsColor } from '../utils/output.ts'; +import { colorize, supportsColor } from './output.ts'; export type CliStatusMarkerStatus = 'pass' | 'fail' | 'warn' | 'skip'; diff --git a/src/utils/string-enum.ts b/src/utils/string-enum.ts index d8d7a1bed8..8afeae73fe 100644 --- a/src/utils/string-enum.ts +++ b/src/utils/string-enum.ts @@ -37,21 +37,3 @@ export function parseStringMember( message ?? `Invalid value: ${value}. Use ${values.join('|')}.`, ); } - -export function defineStringEnum( - values: T, - options: { - normalize?: (raw: string) => string; - message?: string | ((raw: string | undefined) => string); - } = {}, -): { - readonly values: T; - is(value: string): value is T[number]; - parse(value: string | undefined): T[number]; -} { - return { - values, - is: (value): value is T[number] => isStringMember(values, value), - parse: (value): T[number] => parseStringMember(values, value, options), - }; -} diff --git a/test/integration/android-emulator-e2e/live-form-scenario.ts b/test/integration/android-emulator-e2e/live-form-scenario.ts index 8edce3c0c1..c3f84c1539 100644 --- a/test/integration/android-emulator-e2e/live-form-scenario.ts +++ b/test/integration/android-emulator-e2e/live-form-scenario.ts @@ -2,6 +2,8 @@ import assert from 'node:assert/strict'; import path from 'node:path'; import { PUBLIC_COMMANDS } from '../../../src/command-catalog.ts'; +import { parseRect } from '../../../src/utils/parsing.ts'; +import type { CliJsonResult } from '../cli-json.ts'; import { assertElementText, assertFilesDiffer, @@ -15,6 +17,8 @@ import { type LiveContext, runStep, verifyBehavior, verifyCommand } from './live const C = PUBLIC_COMMANDS; const ANDROID_TEST_IME_PACKAGE = 'com.callstack.agentdevice.imehelper'; const ANDROID_TEST_IME_SERVICE = `${ANDROID_TEST_IME_PACKAGE}/.TestInputMethodService`; +const KEYBOARD_VISIBILITY_TIMEOUT_MS = 10_000; +const KEYBOARD_VISIBILITY_POLL_MS = 250; export async function assertFormInput(context: LiveContext): Promise { const keyboardStatus = await runStep(context, 'verify deterministic test IME active', [ @@ -86,15 +90,18 @@ export async function assertFormInput(context: LiveContext): Promise { } export async function assertKeyboardIme(context: LiveContext): Promise { - await runStep(context, 'focus email with the emulator keyboard', [ - 'click', + const email = await runStep(context, 'resolve email from the prepared form snapshot', [ + 'get', + 'attrs', 'id="field-email"', - '--settle', ]); - const keyboardStatus = await runStep(context, 'verify Android keyboard visible', [ - 'keyboard', - 'status', + const emailRect = requireResultNodeRect(email, 'field-email'); + await runStep(context, 'focus email with the emulator keyboard', [ + 'focus', + String(emailRect.x + emailRect.width / 2), + String(emailRect.y + emailRect.height / 2), ]); + const keyboardStatus = await waitForKeyboardVisible(context); assert.equal(keyboardStatus.json?.data?.visible, true, JSON.stringify(keyboardStatus.json)); assert.equal( typeof keyboardStatus.json?.data?.inputMethodPackage, @@ -145,3 +152,29 @@ export async function assertKeyboardIme(context: LiveContext): Promise { `visible and dismissed keyboard used ${String(keyboardStatus.json?.data?.inputMethodPackage)}`, ); } + +function requireResultNodeRect(result: CliJsonResult, label: string) { + const node: unknown = result.json?.data?.node; + assert.ok(typeof node === 'object' && node !== null, `${label} result has no node`); + const rect = parseRect((node as { rect?: unknown }).rect); + assert.ok(rect, `${label} result has an invalid rect`); + return rect; +} + +async function waitForKeyboardVisible(context: LiveContext): Promise { + const deadline = Date.now() + KEYBOARD_VISIBILITY_TIMEOUT_MS; + let attempt = 0; + let status: CliJsonResult; + do { + attempt += 1; + status = await runStep(context, `inspect Android keyboard visibility (${attempt})`, [ + 'keyboard', + 'status', + ]); + if (status.json?.data?.visible === true) return status; + await new Promise((resolve) => setTimeout(resolve, KEYBOARD_VISIBILITY_POLL_MS)); + } while (Date.now() < deadline); + assert.fail( + `Android keyboard did not become visible within ${KEYBOARD_VISIBILITY_TIMEOUT_MS}ms: ${JSON.stringify(status.json)}`, + ); +} diff --git a/test/integration/client-api-doc-snippets.test.ts b/test/integration/client-api-doc-snippets.test.ts index b4069a7dee..1fd046c4a9 100644 --- a/test/integration/client-api-doc-snippets.test.ts +++ b/test/integration/client-api-doc-snippets.test.ts @@ -119,9 +119,10 @@ function runTsc(tmpDir: string): string { function findKnownFreeNamesByFile(tscOutput: string): Map> { const freeNamesByFile = new Map>(); for (const line of tscOutput.split('\n')) { - const match = /^(snippet-\d+\.ts)\(\d+,\d+\): error TS2304: Cannot find name '([^']+)'/.exec( - line, - ); + const match = + /^(?:.*[/\\])?(snippet-\d+\.ts)\(\d+,\d+\): error TS2304: Cannot find name '([^']+)'/.exec( + line, + ); const name = match?.[2]; if (match?.[1] && name && name in KNOWN_FREE_NAME_STUB_TYPES) { const names = freeNamesByFile.get(match[1]) ?? new Set(); @@ -161,6 +162,13 @@ function compileDocSnippets(snippets: string[]): string[] { } } +test('recognizes known free names when TypeScript prints a relative snippet path', () => { + const freeNames = findKnownFreeNamesByFile( + "../../../../tmp/client-api-doc-snippets/snippet-3.ts(2,7): error TS2304: Cannot find name 'client'.", + ); + assert.deepEqual([...(freeNames.get('snippet-3.ts') ?? [])], ['client']); +}); + test("every fenced ```ts snippet in client-api.md compiles against agent-device's real exports", () => { const snippets = extractTsSnippets(fs.readFileSync(CLIENT_API_DOC_PATH, 'utf8')); assert.ok( diff --git a/test/integration/interaction-contract/coordinate.contract.test.ts b/test/integration/interaction-contract/coordinate.contract.test.ts index 519394fb5c..c37a3fd192 100644 --- a/test/integration/interaction-contract/coordinate.contract.test.ts +++ b/test/integration/interaction-contract/coordinate.contract.test.ts @@ -1,6 +1,6 @@ import assert from 'node:assert/strict'; import { test } from 'vitest'; -import type { InteractionGuarantee } from '../../../src/contracts/interaction-guarantees.ts'; +import type { InteractionGuarantee } from '@agent-device/contracts/interaction'; import { makeSnapshotState } from '../../../src/__tests__/test-utils/index.ts'; import { assertRpcError, assertRpcOk } from '../provider-scenarios/assertions.ts'; import { scenarioName } from './coverage-manifest.ts'; diff --git a/test/integration/interaction-contract/coverage-manifest.ts b/test/integration/interaction-contract/coverage-manifest.ts index d0570e735e..bbde7b3991 100644 --- a/test/integration/interaction-contract/coverage-manifest.ts +++ b/test/integration/interaction-contract/coverage-manifest.ts @@ -1,7 +1,4 @@ -import type { - InteractionGuarantee, - InteractionPathId, -} from '../../../src/contracts/interaction-guarantees.ts'; +import type { InteractionGuarantee, InteractionPathId } from '@agent-device/contracts/interaction'; /** * ADR 0011 Layer 3: the machine-readable claim of which interaction guarantee @@ -9,7 +6,7 @@ import type { * sibling `.coverage.ts` exporting one of these manifests (kept out of * the test file so the coverage gate can import it without re-registering the * scenarios), and `index.ts` aggregates them statically for the gate test in - * `src/contracts/__tests__/interaction-contract-coverage.test.ts`. + * `src/__tests__/contracts/interaction-contract-coverage.test.ts`. * * Scenario strings double as the vitest test titles — the test files derive * their titles from the manifest (via `scenarioName`/`scenarioNames`), so a diff --git a/test/integration/interaction-contract/direct-ios-selector.contract.test.ts b/test/integration/interaction-contract/direct-ios-selector.contract.test.ts index 1d427a3300..166a9a99f6 100644 --- a/test/integration/interaction-contract/direct-ios-selector.contract.test.ts +++ b/test/integration/interaction-contract/direct-ios-selector.contract.test.ts @@ -1,6 +1,6 @@ import assert from 'node:assert/strict'; import { test } from 'vitest'; -import type { InteractionGuarantee } from '../../../src/contracts/interaction-guarantees.ts'; +import type { InteractionGuarantee } from '@agent-device/contracts/interaction'; import { AppError } from '@agent-device/kernel/errors'; import { assertRpcError, assertRpcOk } from '../provider-scenarios/assertions.ts'; import { PARALLEL_PROVIDER_SCENARIO_TIMEOUT_MS } from '../provider-scenarios/test-timeouts.ts'; diff --git a/test/integration/interaction-contract/index.ts b/test/integration/interaction-contract/index.ts index b80b28bf6e..d3bd57a37f 100644 --- a/test/integration/interaction-contract/index.ts +++ b/test/integration/interaction-contract/index.ts @@ -9,7 +9,7 @@ import { RUNTIME_SELECTOR_COVERAGE } from './runtime-selector.coverage.ts'; /** * Static aggregation of every scenario file's coverage manifest (no dynamic * globbing — a new scenario file must be added here, and the coverage gate in - * src/contracts/__tests__/interaction-contract-coverage.test.ts fails when an + * src/__tests__/contracts/interaction-contract-coverage.test.ts fails when an * enforced matrix cell has no entry). */ export const CONTRACT_COVERAGE: readonly ContractCoverageEntry[] = [ diff --git a/test/integration/interaction-contract/maestro-fallback.contract.test.ts b/test/integration/interaction-contract/maestro-fallback.contract.test.ts index 844fa9f0cb..f3b905e1ef 100644 --- a/test/integration/interaction-contract/maestro-fallback.contract.test.ts +++ b/test/integration/interaction-contract/maestro-fallback.contract.test.ts @@ -1,6 +1,6 @@ import assert from 'node:assert/strict'; import { test } from 'vitest'; -import type { InteractionGuarantee } from '../../../src/contracts/interaction-guarantees.ts'; +import type { InteractionGuarantee } from '@agent-device/contracts/interaction'; import { AppError } from '@agent-device/kernel/errors'; import { assertRpcError, assertRpcOk } from '../provider-scenarios/assertions.ts'; import { PARALLEL_PROVIDER_SCENARIO_TIMEOUT_MS } from '../provider-scenarios/test-timeouts.ts'; diff --git a/test/integration/interaction-contract/native-ref.contract.test.ts b/test/integration/interaction-contract/native-ref.contract.test.ts index 854739ec0e..46d234185c 100644 --- a/test/integration/interaction-contract/native-ref.contract.test.ts +++ b/test/integration/interaction-contract/native-ref.contract.test.ts @@ -1,6 +1,6 @@ import assert from 'node:assert/strict'; import { test } from 'vitest'; -import type { InteractionGuarantee } from '../../../src/contracts/interaction-guarantees.ts'; +import type { InteractionGuarantee } from '@agent-device/contracts/interaction'; import type { SnapshotState } from '@agent-device/kernel/snapshot'; import { ref } from '../../../src/commands/interaction/runtime/selector-read-utils.ts'; import { scenarioName } from './coverage-manifest.ts'; diff --git a/test/integration/interaction-contract/runtime-ref.contract.test.ts b/test/integration/interaction-contract/runtime-ref.contract.test.ts index 7737c066bf..a10b19d92d 100644 --- a/test/integration/interaction-contract/runtime-ref.contract.test.ts +++ b/test/integration/interaction-contract/runtime-ref.contract.test.ts @@ -1,6 +1,6 @@ import assert from 'node:assert/strict'; import { test } from 'vitest'; -import type { InteractionGuarantee } from '../../../src/contracts/interaction-guarantees.ts'; +import type { InteractionGuarantee } from '@agent-device/contracts/interaction'; import type { Point } from '@agent-device/kernel/snapshot'; import { ref } from '../../../src/commands/interaction/runtime/selector-read-utils.ts'; import { assertRpcOk } from '../provider-scenarios/assertions.ts'; diff --git a/test/integration/interaction-contract/runtime-selector.contract.test.ts b/test/integration/interaction-contract/runtime-selector.contract.test.ts index f88ecfcbb8..90223de0f7 100644 --- a/test/integration/interaction-contract/runtime-selector.contract.test.ts +++ b/test/integration/interaction-contract/runtime-selector.contract.test.ts @@ -1,6 +1,6 @@ import assert from 'node:assert/strict'; import { test } from 'vitest'; -import type { InteractionGuarantee } from '../../../src/contracts/interaction-guarantees.ts'; +import type { InteractionGuarantee } from '@agent-device/contracts/interaction'; import type { Point } from '@agent-device/kernel/snapshot'; import { selector } from '../../../src/commands/interaction/runtime/selector-read-utils.ts'; import { assertRpcOk } from '../provider-scenarios/assertions.ts'; diff --git a/test/integration/provider-scenarios/cloud-webdriver-provider-adapters.test.ts b/test/integration/provider-scenarios/cloud-webdriver-provider-adapters.test.ts index 516203bae3..ab3778bfb3 100644 --- a/test/integration/provider-scenarios/cloud-webdriver-provider-adapters.test.ts +++ b/test/integration/provider-scenarios/cloud-webdriver-provider-adapters.test.ts @@ -17,8 +17,8 @@ import { listBrowserStackCloudArtifacts, uploadBrowserStackApp, } from '../../../src/cloud-webdriver/browserstack.ts'; -import type { CloudArtifactsResult } from '../../../src/contracts/cloud-artifacts.ts'; -import type { DeviceLease } from '../../../src/contracts/device-provider.ts'; +import type { CloudArtifactsResult } from '@agent-device/contracts/observability'; +import type { DeviceLease } from '@agent-device/contracts/device'; import { withCommandExecutorOverride } from '../../../src/utils/exec.ts'; import { withProviderScenarioResource, withProviderScenarioTempDir } from './harness.ts'; import { diff --git a/test/integration/provider-scenarios/cloud-webdriver-runtime.test.ts b/test/integration/provider-scenarios/cloud-webdriver-runtime.test.ts index 5115b17c58..59a4e9cec2 100644 --- a/test/integration/provider-scenarios/cloud-webdriver-runtime.test.ts +++ b/test/integration/provider-scenarios/cloud-webdriver-runtime.test.ts @@ -7,10 +7,10 @@ import { createDefaultCloudWebDriverProviderRuntimes } from '../../../src/cloud- import { scrollFrameFromWebDriverSource } from '../../../src/cloud-webdriver/webdriver-scroll-frame.ts'; import { parseWebDriverSource } from '../../../src/cloud-webdriver/webdriver-source.ts'; import { CLOUD_WEBDRIVER_PROVIDERS } from '../../../src/cloud-webdriver/providers.ts'; -import type { CloudArtifact } from '../../../src/contracts/cloud-artifacts.ts'; +import type { CloudArtifact } from '@agent-device/contracts/observability'; import { createProviderDeviceRuntimeRequestProviders } from '../../../src/provider-device-runtime.ts'; import { createExpiredProviderLeaseReleaser } from '../../../src/daemon/provider-lease-expiry.ts'; -import type { DeviceLease } from '../../../src/contracts/device-provider.ts'; +import type { DeviceLease } from '@agent-device/contracts/device'; import type { DaemonRequest } from '../../../src/daemon/types.ts'; import { assertRpcError, assertRpcOk } from './assertions.ts'; import { diff --git a/test/integration/provider-scenarios/harness.ts b/test/integration/provider-scenarios/harness.ts index aa49c6b58f..a71076b8b9 100644 --- a/test/integration/provider-scenarios/harness.ts +++ b/test/integration/provider-scenarios/harness.ts @@ -3,7 +3,7 @@ import fs from 'node:fs'; import os from 'node:os'; import path from 'node:path'; import { createAgentDeviceClient } from '../../../src/agent-device-client.ts'; -import type { AgentDeviceDaemonTransport } from '../../../src/contracts/client-connection.ts'; +import type { AgentDeviceDaemonTransport } from '@agent-device/contracts/client'; import type { AgentDeviceClient } from '../../../src/client/client-types.ts'; import { createRequestHandler, diff --git a/test/integration/provider-scenarios/ios-world.ts b/test/integration/provider-scenarios/ios-world.ts index 8809718b0c..54d5a5822f 100644 --- a/test/integration/provider-scenarios/ios-world.ts +++ b/test/integration/provider-scenarios/ios-world.ts @@ -1,7 +1,7 @@ import fs from 'node:fs'; import path from 'node:path'; import type { DeviceInventoryRequest } from '../../../src/core/dispatch-resolve.ts'; -import { buildGesturePlan } from '../../../src/contracts/gesture-plan.ts'; +import { buildGesturePlan } from '@agent-device/contracts/interaction'; import type { RawSnapshotNode } from '@agent-device/kernel/snapshot'; import type { ProviderScenarioTranscript } from './transcript.ts'; import { diff --git a/test/integration/provider-scenarios/provider-device-runtime.test.ts b/test/integration/provider-scenarios/provider-device-runtime.test.ts index 7334c77915..cab4bab8d3 100644 --- a/test/integration/provider-scenarios/provider-device-runtime.test.ts +++ b/test/integration/provider-scenarios/provider-device-runtime.test.ts @@ -2,17 +2,15 @@ import assert from 'node:assert/strict'; import fs from 'node:fs'; import path from 'node:path'; import { test } from 'vitest'; -import { - createProviderDeviceRuntimeRequestProviders, - type ProviderDeviceRuntime, - type ProviderPortReverseOptions, -} from '../../../src/provider-device-runtime.ts'; +import { createProviderDeviceRuntimeRequestProviders } from '../../../src/provider-device-runtime.ts'; import type { DeviceInventoryProvider, DeviceLease, LeaseLifecycleProvider, -} from '../../../src/contracts/device-provider.ts'; -import type { Interactor, SnapshotResult } from '../../../src/contracts/interactor-types.ts'; + ProviderDeviceRuntime, + ProviderPortReverseOptions, +} from '@agent-device/contracts/device'; +import type { Interactor, SnapshotResult } from '@agent-device/contracts/interaction'; import type { DaemonRequest } from '../../../src/daemon/types.ts'; import type { DeviceInfo } from '@agent-device/kernel/device'; import { assertRpcError, assertRpcOk } from './assertions.ts'; diff --git a/test/integration/provider-scenarios/provider-ios-runner-transport.test.ts b/test/integration/provider-scenarios/provider-ios-runner-transport.test.ts index 7d48908963..61989eaa9c 100644 --- a/test/integration/provider-scenarios/provider-ios-runner-transport.test.ts +++ b/test/integration/provider-scenarios/provider-ios-runner-transport.test.ts @@ -1,15 +1,13 @@ import assert from 'node:assert/strict'; import { test } from 'vitest'; -import { - createProviderDeviceRuntimeRequestProviders, - type ProviderDeviceRuntime, -} from '../../../src/provider-device-runtime.ts'; +import { createProviderDeviceRuntimeRequestProviders } from '../../../src/provider-device-runtime.ts'; import type { DeviceInventoryProvider, DeviceLease, LeaseLifecycleProvider, -} from '../../../src/contracts/device-provider.ts'; -import type { Interactor, RunnerContext } from '../../../src/contracts/interactor-types.ts'; + ProviderDeviceRuntime, +} from '@agent-device/contracts/device'; +import type { Interactor, RunnerContext } from '@agent-device/contracts/interaction'; import type { DaemonRequest } from '../../../src/daemon/types.ts'; import type { DeviceInfo } from '@agent-device/kernel/device'; import { createAppleInteractor } from '../../../src/platforms/apple/interactor.ts'; diff --git a/test/integration/provider-scenarios/provider-ios-selector-runtime.test.ts b/test/integration/provider-scenarios/provider-ios-selector-runtime.test.ts index 1a6dfae445..8a939271d0 100644 --- a/test/integration/provider-scenarios/provider-ios-selector-runtime.test.ts +++ b/test/integration/provider-scenarios/provider-ios-selector-runtime.test.ts @@ -1,15 +1,13 @@ import assert from 'node:assert/strict'; import { test } from 'vitest'; -import { - createProviderDeviceRuntimeRequestProviders, - type ProviderDeviceRuntime, -} from '../../../src/provider-device-runtime.ts'; +import { createProviderDeviceRuntimeRequestProviders } from '../../../src/provider-device-runtime.ts'; import type { DeviceInventoryProvider, DeviceLease, LeaseLifecycleProvider, -} from '../../../src/contracts/device-provider.ts'; -import type { Interactor, SnapshotResult } from '../../../src/contracts/interactor-types.ts'; + ProviderDeviceRuntime, +} from '@agent-device/contracts/device'; +import type { Interactor, SnapshotResult } from '@agent-device/contracts/interaction'; import type { DaemonRequest } from '../../../src/daemon/types.ts'; import type { DeviceInfo } from '@agent-device/kernel/device'; import { assertRpcOk } from './assertions.ts'; diff --git a/test/integration/provider-scenarios/vega-tv-remote.test.ts b/test/integration/provider-scenarios/vega-tv-remote.test.ts index e2086afefa..d50c3d2e5b 100644 --- a/test/integration/provider-scenarios/vega-tv-remote.test.ts +++ b/test/integration/provider-scenarios/vega-tv-remote.test.ts @@ -1,6 +1,6 @@ import assert from 'node:assert/strict'; import { test } from 'vitest'; -import type { VegaTvRemoteKey } from '../../../src/contracts/tv-remote.ts'; +import type { VegaTvRemoteKey } from '@agent-device/contracts/interaction'; import type { DeviceInfo } from '@agent-device/kernel/device'; import type { VegaToolProvider } from '../../../src/platforms/vega/tool-provider.ts'; import { assertRpcOk } from './assertions.ts'; diff --git a/test/integration/smoke-ios-simulator-coverage.test.ts b/test/integration/smoke-ios-simulator-coverage.test.ts index 33cecc3c6c..b573d5e51b 100644 --- a/test/integration/smoke-ios-simulator-coverage.test.ts +++ b/test/integration/smoke-ios-simulator-coverage.test.ts @@ -3,14 +3,14 @@ import fs from 'node:fs'; import path from 'node:path'; import test from 'node:test'; -import { PUBLIC_COMMANDS } from '../../src/command-catalog.ts'; import { + buildGesturePlan, gesturePayloadFromPositionals, normalizePublicGesture, normalizePublicSwipeMotion, swipePayloadFromPositionals, -} from '../../src/contracts/gesture-normalization.ts'; -import { buildGesturePlan } from '../../src/contracts/gesture-plan.ts'; +} from '@agent-device/contracts/interaction'; +import { PUBLIC_COMMANDS } from '../../src/command-catalog.ts'; import { isCommandSupportedOnDevice } from '../../src/core/capabilities.ts'; import { parseReplayScriptDetailed } from '../../src/replay/script.ts'; import { IOS_SIMULATOR_BEHAVIOR_COVERAGE } from './ios-simulator-e2e/behavior-coverage.ts'; diff --git a/test/output-economy/fixtures.ts b/test/output-economy/fixtures.ts index f12197d3da..e2b62f9fea 100644 --- a/test/output-economy/fixtures.ts +++ b/test/output-economy/fixtures.ts @@ -1,8 +1,7 @@ -import type { CaptureSnapshotResult } from '../../src/contracts/client-capture.ts'; -import type { CommandRequestResult } from '../../src/contracts/client-request.ts'; -import type { DaemonResponseData } from '../../src/daemon/types.ts'; +import type { CaptureSnapshotResult, CommandRequestResult } from '@agent-device/contracts/client'; import { AppError } from '@agent-device/kernel/errors'; import { attachRefs, type RawSnapshotNode } from '@agent-device/kernel/snapshot'; +import type { DaemonResponseData } from '../../src/daemon/types.ts'; const SNAPSHOT_NODES: RawSnapshotNode[] = [ { diff --git a/test/output-economy/routine-workflow.ts b/test/output-economy/routine-workflow.ts index 1213fcd09c..a4b8fa5b80 100644 --- a/test/output-economy/routine-workflow.ts +++ b/test/output-economy/routine-workflow.ts @@ -1,4 +1,4 @@ -import type { CommandRequestResult } from '../../src/contracts/client-request.ts'; +import type { CommandRequestResult } from '@agent-device/contracts/client'; import type { AgentDeviceClient } from '../../src/client/client-types.ts'; import { AppError, normalizeError, type NormalizedError } from '@agent-device/kernel/errors'; import { snapshotCliOutput } from '../../src/commands/capture/output.ts'; diff --git a/test/output-economy/selection-fixtures.ts b/test/output-economy/selection-fixtures.ts index d0f868a002..eeb4388e95 100644 --- a/test/output-economy/selection-fixtures.ts +++ b/test/output-economy/selection-fixtures.ts @@ -1,4 +1,4 @@ -import type { DebugSymbolsResult } from '../../src/contracts/debug-symbols.ts'; +import type { DebugSymbolsResult } from '@agent-device/contracts/observability'; import type { DaemonResponseData } from '../../src/daemon/types.ts'; const requestBody = JSON.stringify({