Skip to content
Merged
3 changes: 2 additions & 1 deletion src/alert-contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ export const ALERT_POLL_INTERVAL_MS = 300;
export const DEFAULT_ALERT_TIMEOUT_MS = 10_000;
export const ALERT_ACTION_RETRY_MS = 2_000;

export type AlertAction = 'get' | 'accept' | 'dismiss' | 'wait';
export const ALERT_ACTIONS = ['get', 'accept', 'dismiss', 'wait'] as const;
export type AlertAction = (typeof ALERT_ACTIONS)[number];

export type AlertPlatform = 'android' | 'ios' | 'macos';

Expand Down
39 changes: 19 additions & 20 deletions src/backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,16 @@ import type {
SnapshotOptions,
SnapshotState,
} from './utils/snapshot.ts';
import type { NetworkIncludeMode } from './contracts.ts';
import type { DeviceTarget, Platform, PlatformSelector } from './utils/device.ts';
import type { BackMode } from './core/back-mode.ts';
import type { RepeatedInput } from './commands/command-input.ts';
import type { ClickButton } from './core/click-button.ts';
import type { DeviceRotation } from './core/device-rotation.ts';
import type { ScrollDirection } from './core/scroll-gesture.ts';
import type { SessionSurface } from './core/session-surface.ts';

export type AgentDeviceBackendPlatform = 'ios' | 'android' | 'macos' | 'linux';
export type AgentDeviceBackendPlatform = Platform;

export const BACKEND_CAPABILITY_NAMES = [
'android.shell',
Expand Down Expand Up @@ -71,7 +79,7 @@ export type BackendScreenshotOptions = {
fullscreen?: boolean;
overlayRefs?: boolean;
stabilize?: boolean;
surface?: 'app' | 'frontmost-app' | 'desktop' | 'menubar';
surface?: SessionSurface;
};

export type BackendScreenshotResult = {
Expand All @@ -81,22 +89,18 @@ export type BackendScreenshotResult = {

export type BackendActionResult = Record<string, unknown> | void;

export type BackendDeviceOrientation =
| 'portrait'
| 'portrait-upside-down'
| 'landscape-left'
| 'landscape-right';
export type BackendDeviceOrientation = DeviceRotation;

export type BackendBackOptions = {
mode?: 'in-app' | 'system';
mode?: BackMode;
};

export type BackendKeyboardOptions = {
action: 'status' | 'get' | 'dismiss' | 'enter' | 'return';
};

export type BackendKeyboardResult = {
platform?: 'android' | 'ios' | 'macos' | 'linux';
platform?: Platform;
action?: BackendKeyboardOptions['action'];
visible?: boolean;
inputType?: string | null;
Expand Down Expand Up @@ -133,13 +137,8 @@ export type BackendAlertResult =
timedOut?: boolean;
};

export type BackendTapOptions = {
button?: 'primary' | 'secondary' | 'middle';
count?: number;
intervalMs?: number;
holdMs?: number;
jitterPx?: number;
doubleTap?: boolean;
export type BackendTapOptions = RepeatedInput & {
button?: ClickButton;
};

export type BackendFillOptions = {
Expand All @@ -164,7 +163,7 @@ export type BackendScrollTarget =
};

export type BackendScrollOptions = {
direction: 'up' | 'down' | 'left' | 'right';
direction: ScrollDirection;
amount?: number;
pixels?: number;
};
Expand Down Expand Up @@ -234,8 +233,8 @@ export type BackendAppEvent = {
};

export type BackendDeviceFilter = {
platform?: AgentDeviceBackendPlatform | 'apple';
target?: 'mobile' | 'tv' | 'desktop';
platform?: PlatformSelector;
target?: DeviceTarget;
kind?: 'simulator' | 'emulator' | 'device' | 'desktop';
};

Expand Down Expand Up @@ -340,7 +339,7 @@ export type BackendReadLogsResult = {
notes?: readonly string[];
};

export type BackendNetworkIncludeMode = 'summary' | 'headers' | 'body' | 'all';
export type BackendNetworkIncludeMode = NetworkIncludeMode;

export type BackendNetworkEntry = {
timestamp?: string;
Expand Down
72 changes: 38 additions & 34 deletions src/client-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,26 @@ import type {
DaemonLockPolicy,
DaemonRequest,
DaemonResponse,
DaemonServerMode,
DaemonTransportPreference,
LeaseBackend,
NetworkIncludeMode,
SessionIsolationMode,
SessionRuntimeHints,
} from './contracts.ts';
import type { DeviceKind, DeviceTarget, Platform, PlatformSelector } from './utils/device.ts';
import type { BackMode } from './core/back-mode.ts';
import type { ClickButton } from './core/click-button.ts';
import type { DeviceRotation } from './core/device-rotation.ts';
import type {
ScrollDirection,
SwipePattern,
SwipePreset,
TransformGestureParams,
} from './core/scroll-gesture.ts';
import type { ScrollInputDirection } from './commands/interaction-gestures.ts';
import type { LogAction } from './commands/log-command-contract.ts';
import type { SessionSurface } from './core/session-surface.ts';
import type { FindLocator } from './utils/finders.ts';
import type { AndroidSnapshotBackendMetadata } from './platforms/android/snapshot-types.ts';
import type {
Expand All @@ -26,17 +42,13 @@ import type { AppsFilter } from './commands/app-inventory-contract.ts';
import type { ScreenshotRequestFlags } from './commands/capture-screenshot-options.ts';
import type { PerfAction, PerfArea } from './commands/perf-command-contract.ts';
import type { DaemonBatchStep } from './core/batch.ts';
import type { AlertInfo } from './alert-contract.ts';
import type { AlertAction, AlertInfo } from './alert-contract.ts';

export type { FindLocator } from './utils/finders.ts';
export type { CompanionTunnelScope, MetroBridgeScope } from './client-companion-tunnel-contract.ts';
export type { AppsFilter } from './commands/app-inventory-contract.ts';
export type { AlertAction, AlertInfo, AlertPlatform, AlertSource } from './alert-contract.ts';

type DaemonTransportMode = 'auto' | 'socket' | 'http';
type DaemonServerMode = 'socket' | 'http' | 'dual';
type SessionIsolationMode = 'none' | 'tenant';

export type AgentDeviceDaemonTransport = (
req: Omit<DaemonRequest, 'token'>,
) => Promise<DaemonResponse>;
Expand All @@ -49,7 +61,7 @@ export type AgentDeviceClientConfig = {
stateDir?: string;
daemonBaseUrl?: string;
daemonAuthToken?: string;
daemonTransport?: DaemonTransportMode;
daemonTransport?: DaemonTransportPreference;
daemonServerMode?: DaemonServerMode;
tenant?: string;
sessionIsolation?: SessionIsolationMode;
Expand Down Expand Up @@ -175,7 +187,7 @@ export type AppOpenOptions = AgentDeviceRequestOverrides &
AgentDeviceSelectionOptions & {
app?: string;
url?: string;
surface?: 'app' | 'frontmost-app' | 'desktop' | 'menubar';
surface?: SessionSurface;
activity?: string;
launchConsole?: string;
launchArgs?: string[];
Expand Down Expand Up @@ -333,7 +345,7 @@ export type CaptureScreenshotOptions = AgentDeviceRequestOverrides & {
fullscreen?: boolean;
maxSize?: number;
stabilize?: boolean;
surface?: 'app' | 'frontmost-app' | 'desktop' | 'menubar';
surface?: SessionSurface;
};

export type CaptureScreenshotResult = {
Expand Down Expand Up @@ -379,20 +391,20 @@ type WaitCommandTarget =
export type WaitCommandOptions = DeviceCommandBaseOptions & WaitCommandTarget;

export type AlertCommandOptions = DeviceCommandBaseOptions & {
action?: 'get' | 'accept' | 'dismiss' | 'wait';
action?: AlertAction;
timeoutMs?: number;
};

export type AppStateCommandOptions = DeviceCommandBaseOptions;

export type BackCommandOptions = DeviceCommandBaseOptions & {
mode?: 'in-app' | 'system';
mode?: BackMode;
};

export type HomeCommandOptions = DeviceCommandBaseOptions;

export type RotateCommandOptions = DeviceCommandBaseOptions & {
orientation: 'portrait' | 'portrait-upside-down' | 'landscape-left' | 'landscape-right';
orientation: DeviceRotation;
};

export type AppSwitcherCommandOptions = DeviceCommandBaseOptions;
Expand Down Expand Up @@ -441,11 +453,11 @@ export type AppStateCommandResult = DaemonResponseData & {
package?: string;
activity?: string;
source?: 'session';
surface?: 'app' | 'frontmost-app' | 'desktop' | 'menubar';
surface?: SessionSurface;
};

export type BackCommandResult = CommandActionResult<'back'> & {
mode?: 'in-app' | 'system';
mode?: BackMode;
};

export type HomeCommandResult = CommandActionResult<'home'>;
Expand Down Expand Up @@ -569,7 +581,7 @@ export type ClickOptions = ClientCommandBaseOptions &
SelectorSnapshotCommandOptions &
InteractionTarget &
RepeatedPressOptions & {
button?: 'primary' | 'secondary' | 'middle';
button?: ClickButton;
};

export type PressOptions = ClientCommandBaseOptions &
Expand All @@ -589,7 +601,7 @@ export type SwipeOptions = ClientCommandBaseOptions & {
durationMs?: number;
count?: number;
pauseMs?: number;
pattern?: 'one-way' | 'ping-pong';
pattern?: SwipePattern;
};

export type PanOptions = ClientCommandBaseOptions & {
Expand All @@ -601,15 +613,15 @@ export type PanOptions = ClientCommandBaseOptions & {
};

export type FlingOptions = ClientCommandBaseOptions & {
direction: 'up' | 'down' | 'left' | 'right';
direction: ScrollDirection;
x: number;
y: number;
distance?: number;
durationMs?: number;
};

export type SwipeGestureOptions = ClientCommandBaseOptions & {
preset: 'left' | 'right' | 'left-edge' | 'right-edge';
preset: SwipePreset;
durationMs?: number;
};

Expand All @@ -631,7 +643,7 @@ export type FillOptions = ClientCommandBaseOptions &
};

export type ScrollOptions = ClientCommandBaseOptions & {
direction: 'up' | 'down' | 'left' | 'right' | 'top' | 'bottom';
direction: ScrollInputDirection;
amount?: number;
pixels?: number;
};
Expand All @@ -649,15 +661,7 @@ export type RotateGestureOptions = ClientCommandBaseOptions & {
velocity?: number;
};

export type TransformGestureOptions = ClientCommandBaseOptions & {
x: number;
y: number;
dx: number;
dy: number;
scale: number;
degrees: number;
durationMs?: number;
};
export type TransformGestureOptions = ClientCommandBaseOptions & TransformGestureParams;

export type GetOptions = ClientCommandBaseOptions &
SelectorSnapshotCommandOptions &
Expand Down Expand Up @@ -742,15 +746,15 @@ export type PerfOptions = ClientCommandBaseOptions & {
};

export type LogsOptions = AgentDeviceRequestOverrides & {
action?: 'path' | 'start' | 'stop' | 'doctor' | 'mark' | 'clear';
action?: LogAction;
message?: string;
restart?: boolean;
};

export type NetworkOptions = AgentDeviceRequestOverrides & {
action?: 'dump' | 'log';
limit?: number;
include?: 'summary' | 'headers' | 'body' | 'all';
include?: NetworkIncludeMode;
};

type RecordingQuality = 5 | 6 | 7 | 8 | 9 | 10;
Expand Down Expand Up @@ -844,9 +848,9 @@ type CommandExecutionOptions = Partial<ScreenshotRequestFlags> & {
jitterPx?: number;
pixels?: number;
doubleTap?: boolean;
clickButton?: 'primary' | 'secondary' | 'middle';
clickButton?: ClickButton;
pauseMs?: number;
pattern?: 'one-way' | 'ping-pong';
pattern?: SwipePattern;
headless?: boolean;
restart?: boolean;
replayUpdate?: boolean;
Expand All @@ -863,7 +867,7 @@ type CommandExecutionOptions = Partial<ScreenshotRequestFlags> & {
shardSplit?: number;
findFirst?: boolean;
findLast?: boolean;
networkInclude?: 'summary' | 'headers' | 'body' | 'all';
networkInclude?: NetworkIncludeMode;
batchOnError?: 'stop';
batchMaxSteps?: number;
batchSteps?: DaemonBatchStep[];
Expand All @@ -874,15 +878,15 @@ export type InternalRequestOptions = AgentDeviceClientConfig &
CommandExecutionOptions & {
runtime?: SessionRuntimeHints;
overlayRefs?: boolean;
surface?: 'app' | 'frontmost-app' | 'desktop' | 'menubar';
surface?: SessionSurface;
activity?: string;
launchConsole?: string;
launchArgs?: string[];
relaunch?: boolean;
shutdown?: boolean;
saveScript?: boolean | string;
noRecord?: boolean;
backMode?: 'in-app' | 'system';
backMode?: BackMode;
metroHost?: string;
metroPort?: number;
bundleUrl?: string;
Expand Down
5 changes: 3 additions & 2 deletions src/command-catalog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@ const LOCAL_CLI_COMMANDS = {
session: 'session',
} as const;

const GESTURE_SUBCOMMANDS = ['pan', 'fling', 'swipe', 'pinch', 'rotate', 'transform'] as const;
export const GESTURE_SUBCOMMAND_ERROR = `gesture requires one of: ${GESTURE_SUBCOMMANDS.join(', ')}`;
export const GESTURE_KINDS = ['pan', 'fling', 'swipe', 'pinch', 'rotate', 'transform'] as const;
export type GestureKind = (typeof GESTURE_KINDS)[number];
export const GESTURE_SUBCOMMAND_ERROR = `gesture requires one of: ${GESTURE_KINDS.join(', ')}`;

export type PublicCommandName = (typeof PUBLIC_COMMANDS)[keyof typeof PUBLIC_COMMANDS];
export type LocalCliCommandName = (typeof LOCAL_CLI_COMMANDS)[keyof typeof LOCAL_CLI_COMMANDS];
Expand Down
19 changes: 7 additions & 12 deletions src/commands/admin.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type {
BackendActionResult,
BackendCommandContext,
BackendDeviceFilter,
BackendDeviceInfo,
Expand All @@ -10,7 +9,11 @@ import type {
import type { AgentDeviceRuntime, CommandContext } from '../runtime-contract.ts';
import { AppError } from '../utils/errors.ts';
import { successText } from '../utils/success-text.ts';
import type { RuntimeCommand } from './runtime-types.ts';
import {
toBackendResult,
type BackendResultEnvelope,
type RuntimeCommand,
} from './runtime-types.ts';
import { resolveCommandInput } from './io-policy.ts';
import { toBackendContext } from './selector-read-utils.ts';
import { normalizeOptionalText, requireText } from './text.ts';
Expand All @@ -31,9 +34,7 @@ export type AdminBootCommandOptions = CommandContext & {
export type AdminBootCommandResult = {
kind: 'deviceBooted';
target?: BackendDeviceTarget;
backendResult?: Record<string, unknown>;
message?: string;
};
} & BackendResultEnvelope;

export type AdminInstallCommandOptions = CommandContext & {
app: string;
Expand All @@ -58,9 +59,7 @@ export type AdminInstallCommandResult = {
launchTarget?: string;
installablePath?: string;
archivePath?: string;
backendResult?: Record<string, unknown>;
message?: string;
};
} & BackendResultEnvelope;

export const devicesCommand: RuntimeCommand<
AdminDevicesCommandOptions | undefined,
Expand Down Expand Up @@ -283,7 +282,3 @@ function formatSource(source: BackendInstallSource): string {
if (source.kind === 'uploadedArtifact') return source.id;
return source.url;
}

function toBackendResult(result: BackendActionResult): Record<string, unknown> | undefined {
return result && typeof result === 'object' ? result : undefined;
}
Loading
Loading