From 0ceddf409cf4e89c5a2e0606405868eda3feccc6 Mon Sep 17 00:00:00 2001 From: PJ Date: Sat, 6 Jun 2026 23:20:03 +0530 Subject: [PATCH] feat(ioscompanion): add transport companion interface --- .../ioscompanion/transport/transport.go | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 internal/driver/ioscompanion/transport/transport.go diff --git a/internal/driver/ioscompanion/transport/transport.go b/internal/driver/ioscompanion/transport/transport.go new file mode 100644 index 0000000..6191130 --- /dev/null +++ b/internal/driver/ioscompanion/transport/transport.go @@ -0,0 +1,75 @@ +// Package transport is the only layer that touches the generated companion +// gRPC stubs. Everything above it speaks the brand-free Companion interface, +// so the companion binary stays swappable behind this boundary. +package transport + +import ( + "context" + + pb "github.com/priyanshujain/sanderling/internal/driver/ioscompanion/companionpb" +) + +// Companion drives a single booted iOS simulator through the companion. +// Callers own per-call deadlines by passing a context. +type Companion interface { + // AccessibilityInfo returns the describe-all accessibility tree as the + // raw flat-format JSON string the companion emits. + AccessibilityInfo(ctx context.Context) (string, error) + + // SendHID opens the HID stream, sends every event in order, then closes. + SendHID(ctx context.Context, events ...HIDEvent) error + + // Screenshot captures the current screen, returning the encoded image + // bytes and the image format string the companion reports. + Screenshot(ctx context.Context) (imageData []byte, imageFormat string, err error) + + // Launch brings the app to the foreground, starting it if needed. + Launch(ctx context.Context, bundleID string, foregroundIfRunning bool) error + + // Terminate stops the running app with the given bundle identifier. + Terminate(ctx context.Context, bundleID string) error + + // ListApps reports every installed app and its current process state. + ListApps(ctx context.Context) ([]InstalledApp, error) + + // Install installs a .app bundle directory by streaming it to the + // companion. + Install(ctx context.Context, appPath string) error + + // Uninstall removes the app with the given bundle identifier. + Uninstall(ctx context.Context, bundleID string) error + + // Close releases the underlying connection. + Close() error +} + +// ProcessState mirrors the companion's notion of whether an app is running. +type ProcessState int + +const ( + ProcessStateUnknown ProcessState = iota + ProcessStateNotRunning + ProcessStateRunning +) + +// InstalledApp describes one installed app. ProcessState and ProcessIdentifier +// together answer whether the app is currently running and in the foreground. +type InstalledApp struct { + BundleID string + Name string + InstallType string + ProcessState ProcessState + Debuggable bool + ProcessIdentifier uint64 +} + +func processStateFromProto(s pb.InstalledAppInfo_AppProcessState) ProcessState { + switch s { + case pb.InstalledAppInfo_RUNNING: + return ProcessStateRunning + case pb.InstalledAppInfo_NOT_RUNNING: + return ProcessStateNotRunning + default: + return ProcessStateUnknown + } +}