@run-cloud/sdk 0.19.0 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -117,6 +117,27 @@ invalid-image failures retain the same correlation fields with stable
117
117
  `screenshot_*` codes. `isSimulatorCapacityError(error)` narrows a failed create
118
118
  to the typed, retry-safe `simulator_capacity_unavailable` 503 response.
119
119
 
120
+ ## Accessibility trees
121
+
122
+ Read the current nested accessibility hierarchy from either active platform:
123
+
124
+ ```ts
125
+ const tree = await cloud.ios.accessibilityTree(ios.id);
126
+ for (const root of tree.roots) {
127
+ console.log(root.role, root.label, root.states, root.children.length);
128
+ }
129
+ ```
130
+
131
+ `SimulatorAccessibilitySnapshot` has a versioned cross-platform role, label,
132
+ value, state, bounds, identifier, and child schema, plus discriminated iOS and
133
+ Android `native` fields. iOS coordinates use points; Android coordinates use
134
+ physical display pixels. Secure text values are always `null`.
135
+
136
+ Options accept `timeoutMs` (20 seconds by default) and `signal`. Reads are
137
+ scoped to the authenticated active session. Released, expired, wrong-platform,
138
+ and inaccessible sessions fail with a typed `RunCloudError` instead of reading
139
+ another device.
140
+
120
141
  ## Simulator recordings
121
142
 
122
143
  Both platform clients expose `startRecording`, `listRecordings`,
@@ -242,6 +263,7 @@ Provider-shaped migration adapters ship in this same package:
242
263
  | Cloudflare Sandbox | `@run-cloud/sdk/compat/cloudflare` |
243
264
  | CodeSandbox | `@run-cloud/sdk/compat/codesandbox` |
244
265
  | Fly Machines | `@run-cloud/sdk/compat/fly` |
266
+ | Remotion Lambda | `@run-cloud/sdk/compat/remotion-lambda` |
245
267
 
246
268
  ```ts
247
269
  // import { Sandbox } from "@vercel/sandbox";
@@ -259,6 +281,118 @@ Provider-specific features that do not have a public run.cloud equivalent throw
259
281
  `UnsupportedCompatibilityFeatureError` with a migration hint. In particular,
260
282
  public port capabilities and filesystem mutation are not silently emulated.
261
283
 
284
+ ## Remotion renders with customer-owned S3
285
+
286
+ run.cloud can replace the Lambda compute used for a Remotion render without
287
+ owning the output bucket. Supply a presigned S3-compatible PUT URL; the sandbox
288
+ renders the video, uploads it directly to that URL, and is destroyed when
289
+ `render()` returns.
290
+
291
+ ```ts
292
+ import { Client } from "@run-cloud/sdk";
293
+
294
+ const cloud = new Client();
295
+ const result = await cloud.remotion.render({
296
+ serveUrl: "https://example.com/remotion-bundle",
297
+ composition: "ProductDemo",
298
+ remotionVersion: "4.0.507",
299
+ inputProps: { customer: "Acme" },
300
+ codec: "h264",
301
+ output: {
302
+ uploadUrl: presignedPutUrl,
303
+ downloadUrl: finalObjectUrl,
304
+ contentType: "video/mp4",
305
+ },
306
+ });
307
+
308
+ console.log(result.outputFile);
309
+ ```
310
+
311
+ `remotionVersion` selects Remotion's matching public, versioned renderer image;
312
+ all Remotion packages in a project should use that exact version. You can pass
313
+ `image` instead to use a custom compatible runtime. Signed URLs are written to
314
+ a private guest file and are not included in command logs.
315
+
316
+ For a smaller migration from `@remotion/lambda/client`, switch the import and
317
+ add `s3Output`; existing `region` and `functionName` fields may remain while
318
+ compute moves to run.cloud:
319
+
320
+ ```ts
321
+ import {
322
+ getRenderProgress,
323
+ renderMediaOnLambda,
324
+ } from "@run-cloud/sdk/compat/remotion-lambda";
325
+
326
+ const render = await renderMediaOnLambda({
327
+ region: "us-east-1",
328
+ functionName: "remotion-render-4-0-507-mem2048mb-disk2048mb-240sec",
329
+ serveUrl: "https://example.com/remotion-bundle",
330
+ composition: "ProductDemo",
331
+ codec: "h264",
332
+ s3Output: {
333
+ bucketName: "customer-video-output",
334
+ uploadUrl: presignedPutUrl,
335
+ downloadUrl: finalObjectUrl,
336
+ },
337
+ });
338
+
339
+ const progress = await getRenderProgress({ renderId: render.renderId });
340
+ ```
341
+
342
+ The adapter derives the exact Remotion image version from the standard Lambda
343
+ function name. By default, `concurrencyPerLambda` controls Remotion workers
344
+ inside one sandbox.
345
+
346
+ To split one video across multiple sandboxes, add a customer-owned temporary
347
+ chunk location. `concurrency` chooses the target maximum sandbox count, while
348
+ `framesPerLambda` can derive it after the SDK selects the composition. The
349
+ first sandbox renders the first frame range and then combines all chunks. For a
350
+ normal video, `concurrency: 8` creates eight sandboxes:
351
+
352
+ ```ts
353
+ const render = await renderMediaOnLambda({
354
+ functionName: "remotion-render-4-0-507-mem2048mb-disk2048mb-240sec",
355
+ serveUrl: "https://example.com/remotion-bundle",
356
+ composition: "ProductDemo",
357
+ codec: "h264",
358
+ concurrency: 8,
359
+ concurrencyPerLambda: 1,
360
+ s3Output: {
361
+ bucketName: "customer-video-output",
362
+ uploadUrl: finalPresignedPutUrl,
363
+ downloadUrl: finalObjectUrl,
364
+ },
365
+ runCloud: {
366
+ distributed: {
367
+ createChunkOutput: async ({ renderId, index }) => {
368
+ const prefix = `remotion-chunks/${renderId}/${index}`;
369
+ return {
370
+ video: await presignTemporaryObject(`${prefix}.ts`),
371
+ audio: await presignTemporaryObject(`${prefix}.aac`),
372
+ };
373
+ },
374
+ },
375
+ },
376
+ });
377
+
378
+ console.log(render.sandboxCount); // exact number actually allocated
379
+ ```
380
+
381
+ `presignTemporaryObject()` returns `{uploadUrl, downloadUrl, headers?,
382
+ contentType?}`. Both URLs point to the same temporary object. The SDK stores
383
+ signed URLs only in mode-0600 guest files, uploads each frame-range chunk to
384
+ customer S3, downloads them in the coordinator, calls Remotion's
385
+ `combineChunks()`, and uploads the final artifact. Configure an S3 lifecycle
386
+ rule for the temporary prefix.
387
+
388
+ Chunks must be equal-sized except for the last one, so very short or awkwardly
389
+ divisible compositions can use fewer sandboxes than the target. run.cloud still
390
+ does not create or host an S3 bucket, deploy the Remotion site,
391
+ store render metadata, or add a queue/webhook layer. `render.sandboxCount` and
392
+ `progress.runCloud.sandboxCount` report the exact fan-out. `deleteRender()` or
393
+ `cloud.remotion.cancel()` destroys every sandbox recorded in the render
394
+ manifest; finite sandbox timeouts remain the cleanup backstop.
395
+
262
396
  `cloud.assets.upload(blob, options)` verifies the uploaded size and MD5 before
263
397
  returning a ready asset. Re-uploading the same bytes reuses the verified object.
264
398
  For multipart archives, `cloud.assets.uploadBatch(parts, { uploadBatchId,
@@ -0,0 +1,81 @@
1
+ import type { RemotionCodec, RemotionDistributedOptions, RemotionRenderOptions, RemotionRenderProgress, RemotionS3Output } from "../remotion.js";
2
+ import { type CompatibilityClientOptions } from "./common.js";
3
+ export interface LambdaCompatibleS3Output extends RemotionS3Output {
4
+ /** Returned as bucketName for code that persists the Lambda render handle. */
5
+ bucketName: string;
6
+ }
7
+ export interface RenderMediaOnLambdaInput extends CompatibilityClientOptions {
8
+ /** Accepted for source compatibility. Compute runs in run.cloud, not this AWS region. */
9
+ region?: string;
10
+ /** Accepted for source compatibility. No Lambda function is invoked. */
11
+ functionName?: string;
12
+ serveUrl: string;
13
+ composition: string;
14
+ inputProps?: Record<string, unknown>;
15
+ codec: RemotionCodec;
16
+ /** Target maximum run.cloud sandbox count when runCloud.distributed is configured. */
17
+ concurrency?: number;
18
+ /** Frames rendered by each sandbox when runCloud.distributed is configured. */
19
+ framesPerLambda?: number;
20
+ /** Maps to @remotion/renderer concurrency inside the run.cloud sandbox. */
21
+ concurrencyPerLambda?: number | `${number}%`;
22
+ /** The signed S3 output determines object privacy instead. */
23
+ privacy?: "public" | "private" | "no-acl";
24
+ /** Accepted for source compatibility; this thin adapter does not orchestrate retries. */
25
+ maxRetries?: number;
26
+ envVariables?: Record<string, string>;
27
+ crf?: number;
28
+ imageFormat?: "png" | "jpeg" | "none";
29
+ pixelFormat?: string;
30
+ scale?: number;
31
+ muted?: boolean;
32
+ audioCodec?: string;
33
+ metadata?: Record<string, string>;
34
+ /**
35
+ * The only required migration addition: customer-owned S3-compatible signed
36
+ * upload and download locations. run.cloud never owns the bucket.
37
+ */
38
+ s3Output: LambdaCompatibleS3Output;
39
+ runCloud?: Pick<RemotionRenderOptions, "image" | "remotionVersion" | "cpu" | "memory" | "disk" | "timeoutSeconds" | "startupTimeoutSeconds" | "region" | "name" | "idempotencyKey"> & {
40
+ /**
41
+ * Enables multi-sandbox rendering. createChunkOutput presigns temporary
42
+ * video/audio objects in the customer's own S3 bucket.
43
+ */
44
+ distributed?: Omit<RemotionDistributedOptions, "sandboxCount" | "framesPerSandbox"> & {
45
+ sandboxCount?: number;
46
+ framesPerSandbox?: number;
47
+ };
48
+ };
49
+ }
50
+ export interface RenderMediaOnLambdaOutput {
51
+ renderId: string;
52
+ bucketName: string;
53
+ sandboxCount: number;
54
+ }
55
+ export declare function renderMediaOnLambda(input: RenderMediaOnLambdaInput): Promise<RenderMediaOnLambdaOutput>;
56
+ export interface GetRenderProgressInput extends CompatibilityClientOptions {
57
+ renderId: string;
58
+ /** Retained because existing Lambda integrations commonly persist this alongside renderId. */
59
+ bucketName?: string;
60
+ region?: string;
61
+ functionName?: string;
62
+ }
63
+ export interface LambdaCompatibleRenderProgress {
64
+ done: boolean;
65
+ overallProgress: number;
66
+ outputFile: string | null;
67
+ outputSizeInBytes: number | null;
68
+ errors: RemotionRenderProgress["errors"];
69
+ fatalErrorEncountered: boolean;
70
+ currentTime: number;
71
+ renderSize: number;
72
+ runCloud: RemotionRenderProgress;
73
+ }
74
+ export declare function getRenderProgress(input: GetRenderProgressInput): Promise<LambdaCompatibleRenderProgress>;
75
+ export interface DeleteRenderInput extends CompatibilityClientOptions {
76
+ renderId: string;
77
+ bucketName?: string;
78
+ region?: string;
79
+ }
80
+ export declare function deleteRender(input: DeleteRenderInput): Promise<void>;
81
+ export declare function remotionVersionFromFunctionName(functionName: string | undefined): string;
@@ -0,0 +1,65 @@
1
+ import { compatibilityClient, } from "./common.js";
2
+ export async function renderMediaOnLambda(input) {
3
+ const client = compatibilityClient(input);
4
+ const runCloud = input.runCloud ?? {};
5
+ const distributed = runCloud.distributed
6
+ ? {
7
+ ...runCloud.distributed,
8
+ sandboxCount: runCloud.distributed.sandboxCount ?? input.concurrency,
9
+ framesPerSandbox: runCloud.distributed.framesPerSandbox ??
10
+ (runCloud.distributed.sandboxCount === undefined && input.concurrency === undefined
11
+ ? input.framesPerLambda
12
+ : undefined),
13
+ }
14
+ : undefined;
15
+ const handle = await client.remotion.start({
16
+ serveUrl: input.serveUrl,
17
+ composition: input.composition,
18
+ inputProps: input.inputProps,
19
+ codec: input.codec,
20
+ output: input.s3Output,
21
+ concurrency: input.concurrencyPerLambda,
22
+ envVariables: input.envVariables,
23
+ crf: input.crf,
24
+ imageFormat: input.imageFormat,
25
+ pixelFormat: input.pixelFormat,
26
+ scale: input.scale,
27
+ muted: input.muted,
28
+ audioCodec: input.audioCodec,
29
+ metadata: input.metadata,
30
+ ...runCloud,
31
+ distributed,
32
+ remotionVersion: runCloud.remotionVersion ??
33
+ (runCloud.image ? undefined : remotionVersionFromFunctionName(input.functionName)),
34
+ });
35
+ return {
36
+ renderId: handle.renderId,
37
+ bucketName: input.s3Output.bucketName,
38
+ sandboxCount: handle.sandboxCount,
39
+ };
40
+ }
41
+ export async function getRenderProgress(input) {
42
+ const progress = await compatibilityClient(input).remotion.getProgress(input.renderId);
43
+ return {
44
+ done: progress.done,
45
+ overallProgress: progress.progress,
46
+ outputFile: progress.outputFile,
47
+ outputSizeInBytes: progress.outputSizeInBytes,
48
+ errors: progress.errors,
49
+ fatalErrorEncountered: progress.fatalErrorEncountered,
50
+ currentTime: Date.parse(progress.updatedAt),
51
+ renderSize: progress.outputSizeInBytes ?? 0,
52
+ runCloud: progress,
53
+ };
54
+ }
55
+ export async function deleteRender(input) {
56
+ await compatibilityClient(input).remotion.cancel(input.renderId);
57
+ }
58
+ export function remotionVersionFromFunctionName(functionName) {
59
+ const match = functionName?.match(/^remotion-render-(\d+)-(\d+)-(\d+)(?:-|$)/);
60
+ if (!match) {
61
+ throw new TypeError("functionName must use Remotion's naming convention, or runCloud.remotionVersion/image must be supplied");
62
+ }
63
+ return `${match[1]}.${match[2]}.${match[3]}`;
64
+ }
65
+ //# sourceMappingURL=remotion-lambda.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remotion-lambda.js","sourceRoot":"","sources":["../../src/compat/remotion-lambda.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,mBAAmB,GAEpB,MAAM,aAAa,CAAC;AAqErB,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,KAA+B;IAE/B,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;IAC1C,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC;IACtC,MAAM,WAAW,GAAG,QAAQ,CAAC,WAAW;QACtC,CAAC,CAAC;YACE,GAAG,QAAQ,CAAC,WAAW;YACvB,YAAY,EAAE,QAAQ,CAAC,WAAW,CAAC,YAAY,IAAI,KAAK,CAAC,WAAW;YACpE,gBAAgB,EAAE,QAAQ,CAAC,WAAW,CAAC,gBAAgB;gBACrD,CAAC,QAAQ,CAAC,WAAW,CAAC,YAAY,KAAK,SAAS,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS;oBACjF,CAAC,CAAC,KAAK,CAAC,eAAe;oBACvB,CAAC,CAAC,SAAS,CAAC;SACjB;QACH,CAAC,CAAC,SAAS,CAAC;IACd,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QACzC,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,MAAM,EAAE,KAAK,CAAC,QAAQ;QACtB,WAAW,EAAE,KAAK,CAAC,oBAAoB;QACvC,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,GAAG,QAAQ;QACX,WAAW;QACX,eAAe,EACb,QAAQ,CAAC,eAAe;YACxB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,+BAA+B,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;KACrF,CAAC,CAAC;IACH,OAAO;QACL,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,UAAU;QACrC,YAAY,EAAE,MAAM,CAAC,YAAY;KAClC,CAAC;AACJ,CAAC;AAsBD,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,KAA6B;IAE7B,MAAM,QAAQ,GAAG,MAAM,mBAAmB,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACvF,OAAO;QACL,IAAI,EAAE,QAAQ,CAAC,IAAI;QACnB,eAAe,EAAE,QAAQ,CAAC,QAAQ;QAClC,UAAU,EAAE,QAAQ,CAAC,UAAU;QAC/B,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB;QAC7C,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,qBAAqB,EAAE,QAAQ,CAAC,qBAAqB;QACrD,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC3C,UAAU,EAAE,QAAQ,CAAC,iBAAiB,IAAI,CAAC;QAC3C,QAAQ,EAAE,QAAQ;KACnB,CAAC;AACJ,CAAC;AAQD,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,KAAwB;IACzD,MAAM,mBAAmB,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;AACnE,CAAC;AAED,MAAM,UAAU,+BAA+B,CAAC,YAAgC;IAC9E,MAAM,KAAK,GAAG,YAAY,EAAE,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC/E,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,SAAS,CACjB,wGAAwG,CACzG,CAAC;IACJ,CAAC;IACD,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AAC/C,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  import WebSocket from "ws";
2
+ import { RemotionClient } from "./remotion.js";
3
+ export * from "./remotion.js";
2
4
  export type SimulatorPlatform = "ios" | "android";
3
5
  export interface SimulatorPoint {
4
6
  /** Normalized display-space coordinate, inclusive from 0 (left) to 1 (right). */
@@ -68,7 +70,7 @@ export type SimulatorInteraction = {
68
70
  enabled: boolean;
69
71
  };
70
72
  export type SimulatorInteractionAction = SimulatorInteraction["action"];
71
- export type SimulatorOperation = SimulatorInteractionAction | "screenshot" | "open-url";
73
+ export type SimulatorOperation = SimulatorInteractionAction | "screenshot" | "accessibility" | "open-url";
72
74
  export declare const SIMULATOR_SESSION_ERROR_CODES: readonly ["simulator_capacity_unavailable"];
73
75
  export type SimulatorSessionErrorCode = (typeof SIMULATOR_SESSION_ERROR_CODES)[number];
74
76
  export declare const SIMULATOR_OPEN_URL_ERROR_CODES: readonly ["invalid_url", "active_session_not_found", "open_url_scope_required", "simulator_session_ended", "ios_url_handler_not_found", "android_url_handler_not_found", "simulator_unavailable", "open_url_timeout", "ios_open_url_failed", "android_open_url_failed", "open_url_transport_error", "open_url_invalid_response", "open_url_failed"];
@@ -77,6 +79,73 @@ export declare const SIMULATOR_INTERACTION_ERROR_CODES: readonly ["invalid_inter
77
79
  export type SimulatorInteractionErrorCode = (typeof SIMULATOR_INTERACTION_ERROR_CODES)[number];
78
80
  export declare const SIMULATOR_SCREENSHOT_ERROR_CODES: readonly ["invalid_screenshot_request", "active_session_not_found", "simulator_capacity_unavailable", "screenshot_cancelled", "screenshot_timeout", "screenshot_transport_error", "screenshot_invalid_response", "screenshot_failed"];
79
81
  export type SimulatorScreenshotErrorCode = (typeof SIMULATOR_SCREENSHOT_ERROR_CODES)[number];
82
+ export declare const SIMULATOR_ACCESSIBILITY_ERROR_CODES: readonly ["active_session_not_found", "simulator_capacity_unavailable", "simulator_session_ended", "accessibility_unavailable", "accessibility_cancelled", "accessibility_timeout", "accessibility_transport_error", "accessibility_invalid_response"];
83
+ export type SimulatorAccessibilityErrorCode = (typeof SIMULATOR_ACCESSIBILITY_ERROR_CODES)[number];
84
+ export type SimulatorAccessibilityRole = "application" | "window" | "dialog" | "alert" | "group" | "scroll-view" | "list" | "list-item" | "text" | "heading" | "button" | "link" | "image" | "text-field" | "checkbox" | "switch" | "radio-button" | "slider" | "progress-indicator" | "tab" | "tab-bar" | "toolbar" | "menu" | "menu-item" | "web-view" | "keyboard" | "other";
85
+ export interface SimulatorAccessibilityBounds {
86
+ x: number;
87
+ y: number;
88
+ width: number;
89
+ height: number;
90
+ }
91
+ export interface SimulatorAccessibilityStates {
92
+ enabled: boolean;
93
+ focused: boolean | null;
94
+ selected: boolean | null;
95
+ checked: boolean | "mixed" | null;
96
+ expanded: boolean | null;
97
+ focusable: boolean | null;
98
+ clickable: boolean | null;
99
+ scrollable: boolean | null;
100
+ editable: boolean;
101
+ secure: boolean;
102
+ }
103
+ export interface IosSimulatorAccessibilityNative {
104
+ platform: "ios";
105
+ type: string | null;
106
+ roleDescription: string | null;
107
+ subrole: string | null;
108
+ title: string | null;
109
+ help: string | null;
110
+ }
111
+ export interface AndroidSimulatorAccessibilityNative {
112
+ platform: "android";
113
+ className: string | null;
114
+ packageName: string | null;
115
+ resourceId: string | null;
116
+ contentDescription: string | null;
117
+ checkable: boolean;
118
+ longClickable: boolean;
119
+ password: boolean;
120
+ }
121
+ export type SimulatorAccessibilityNative = IosSimulatorAccessibilityNative | AndroidSimulatorAccessibilityNative;
122
+ export interface SimulatorAccessibilityNode {
123
+ id: string;
124
+ path: string;
125
+ role: SimulatorAccessibilityRole;
126
+ label: string | null;
127
+ /** Current accessible value. Always null for secure text fields. */
128
+ value: string | null;
129
+ identifier: string | null;
130
+ bounds: SimulatorAccessibilityBounds | null;
131
+ states: SimulatorAccessibilityStates;
132
+ native: SimulatorAccessibilityNative;
133
+ children: SimulatorAccessibilityNode[];
134
+ }
135
+ export interface SimulatorAccessibilitySnapshot {
136
+ schemaVersion: 1;
137
+ platform: SimulatorPlatform;
138
+ capturedAt: string;
139
+ /** iOS dimensions use points; Android dimensions use physical display pixels. */
140
+ screen: {
141
+ width: number;
142
+ height: number;
143
+ unit: "points" | "pixels";
144
+ };
145
+ nodeCount: number;
146
+ truncated: boolean;
147
+ roots: SimulatorAccessibilityNode[];
148
+ }
80
149
  export interface SimulatorInteractionOptions {
81
150
  /** Correlates this request with logs and the returned acknowledgement. */
82
151
  requestId?: string;
@@ -166,6 +235,11 @@ export interface SimulatorScreenshotOptions {
166
235
  /** Maximum time to wait for image capture. Defaults to 15 seconds. */
167
236
  timeoutMs?: number;
168
237
  }
238
+ export interface SimulatorAccessibilityOptions {
239
+ signal?: AbortSignal;
240
+ /** Maximum time to wait for hierarchy capture. Defaults to 20 seconds. */
241
+ timeoutMs?: number;
242
+ }
169
243
  export interface SimulatorRecordingStartOptions {
170
244
  /** Reuse this value when retrying a start request to receive the original recording. */
171
245
  idempotencyKey?: string;
@@ -199,6 +273,9 @@ export interface AggregateSimulatorPressButtonOptions extends SimulatorPressButt
199
273
  export interface AggregateSimulatorScreenshotOptions extends SimulatorScreenshotOptions {
200
274
  platform?: SimulatorPlatform;
201
275
  }
276
+ export interface AggregateSimulatorAccessibilityOptions extends SimulatorAccessibilityOptions {
277
+ platform?: SimulatorPlatform;
278
+ }
202
279
  export interface AggregateSimulatorRecordingStartOptions extends SimulatorRecordingStartOptions {
203
280
  platform?: SimulatorPlatform;
204
281
  }
@@ -206,7 +283,10 @@ export interface AggregateSimulatorRecordingRequestOptions extends SimulatorReco
206
283
  platform?: SimulatorPlatform;
207
284
  }
208
285
  export declare const DEFAULT_SIMULATOR_INTERACTION_TIMEOUT_MS = 15000;
286
+ export declare const DEFAULT_SIMULATOR_ACCESSIBILITY_TIMEOUT_MS = 20000;
209
287
  export declare function validateSimulatorInteraction(interaction: SimulatorInteraction, timeoutMs?: number): void;
288
+ /** Validate an API response and remove any secure value defensively. */
289
+ export declare function validateSimulatorAccessibilitySnapshot(value: unknown, expectedPlatform: SimulatorPlatform): SimulatorAccessibilitySnapshot;
210
290
  interface RequestAbortOptions {
211
291
  signal?: AbortSignal;
212
292
  timeoutMs?: number;
@@ -735,6 +815,7 @@ export declare class Client {
735
815
  readonly secrets: SecretsClient;
736
816
  readonly ci: CiClient;
737
817
  readonly images: ImageClient;
818
+ readonly remotion: RemotionClient;
738
819
  private readonly apiKey;
739
820
  private readonly apiUrl;
740
821
  private readonly fetchImpl;
@@ -812,6 +893,7 @@ export declare class SimulatorClient {
812
893
  simulateMemoryWarning(id: string, options?: SimulatorInteractionOptions): Promise<SimulatorInteractionResult<"simulateMemoryWarning">>;
813
894
  rotateDigitalCrown(id: string, delta: number, options?: SimulatorInteractionOptions): Promise<SimulatorInteractionResult<"rotateDigitalCrown">>;
814
895
  setRenderDebug(id: string, option: SimulatorRenderDebugOption, enabled: boolean, options?: SimulatorInteractionOptions): Promise<SimulatorInteractionResult<"setRenderDebug">>;
896
+ accessibilityTree(id: string, options?: SimulatorAccessibilityOptions): Promise<SimulatorAccessibilitySnapshot>;
815
897
  screenshot(id: string, options?: SimulatorScreenshotOptions): Promise<Uint8Array>;
816
898
  startRecording(id: string, options?: SimulatorRecordingStartOptions): Promise<SimulatorRecording>;
817
899
  listRecordings(id: string, options?: SimulatorRecordingRequestOptions): Promise<SimulatorRecording[]>;
@@ -879,6 +961,7 @@ export declare class SimulatorsClient {
879
961
  rotateDigitalCrown(id: string, delta: number, options?: AggregateSimulatorInteractionOptions): Promise<SimulatorInteractionResult<"rotateDigitalCrown">>;
880
962
  setRenderDebug(id: string, option: SimulatorRenderDebugOption, enabled: boolean, options?: AggregateSimulatorInteractionOptions): Promise<SimulatorInteractionResult<"setRenderDebug">>;
881
963
  screenshot(id: string, options?: AggregateSimulatorScreenshotOptions): Promise<Uint8Array>;
964
+ accessibilityTree(id: string, options?: AggregateSimulatorAccessibilityOptions): Promise<SimulatorAccessibilitySnapshot>;
882
965
  startRecording(id: string, options?: AggregateSimulatorRecordingStartOptions): Promise<SimulatorRecording>;
883
966
  listRecordings(id: string, options?: AggregateSimulatorRecordingRequestOptions): Promise<SimulatorRecording[]>;
884
967
  getRecording(id: string, recordingId: string, options?: AggregateSimulatorRecordingRequestOptions): Promise<SimulatorRecordingDetails>;
@@ -1188,4 +1271,3 @@ export declare class AssetsClient {
1188
1271
  deleted: boolean;
1189
1272
  }>;
1190
1273
  }
1191
- export {};