doc-detective 4.24.0 → 4.25.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.
Files changed (30) hide show
  1. package/dist/common/src/schemas/schemas.json +2272 -242
  2. package/dist/common/src/types/generated/record_v3.d.ts +38 -5
  3. package/dist/common/src/types/generated/record_v3.d.ts.map +1 -1
  4. package/dist/common/src/types/generated/step_v3.d.ts +106 -73
  5. package/dist/common/src/types/generated/step_v3.d.ts.map +1 -1
  6. package/dist/common/src/types/generated/test_v3.d.ts +266 -200
  7. package/dist/common/src/types/generated/test_v3.d.ts.map +1 -1
  8. package/dist/core/tests/appSurface.d.ts.map +1 -1
  9. package/dist/core/tests/appSurface.js +52 -13
  10. package/dist/core/tests/appSurface.js.map +1 -1
  11. package/dist/core/tests/ffmpegRecorder.d.ts +29 -2
  12. package/dist/core/tests/ffmpegRecorder.d.ts.map +1 -1
  13. package/dist/core/tests/ffmpegRecorder.js +154 -8
  14. package/dist/core/tests/ffmpegRecorder.js.map +1 -1
  15. package/dist/core/tests/startRecording.d.ts +9 -1
  16. package/dist/core/tests/startRecording.d.ts.map +1 -1
  17. package/dist/core/tests/startRecording.js +187 -19
  18. package/dist/core/tests/startRecording.js.map +1 -1
  19. package/dist/core/tests/stopRecording.d.ts +8 -1
  20. package/dist/core/tests/stopRecording.d.ts.map +1 -1
  21. package/dist/core/tests/stopRecording.js +108 -3
  22. package/dist/core/tests/stopRecording.js.map +1 -1
  23. package/dist/core/tests.d.ts.map +1 -1
  24. package/dist/core/tests.js +39 -6
  25. package/dist/core/tests.js.map +1 -1
  26. package/dist/hints/hints.d.ts.map +1 -1
  27. package/dist/hints/hints.js +7 -2
  28. package/dist/hints/hints.js.map +1 -1
  29. package/dist/index.cjs +2597 -275
  30. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -34176,7 +34176,7 @@ var init_schemas = __esm({
34176
34176
  record: {
34177
34177
  $schema: "http://json-schema.org/draft-07/schema#",
34178
34178
  title: "record",
34179
- description: "Start recording. Must be followed by a `stopRecord` step. The `browser` engine captures the Chrome viewport (works under concurrency); the `ffmpeg` engine captures the screen and supports any application. Supported extensions: [ '.mp4', '.webm', '.gif' ]",
34179
+ description: "Start recording. Must be followed by a `stopRecord` step. The `browser` engine captures the Chrome viewport (works under concurrency); the `ffmpeg` engine captures the screen and supports any application. On Android/iOS contexts, recording captures the device screen through the device itself \u2014 `engine` doesn't apply. Supported extensions: [ '.mp4', '.webm', '.gif' ]",
34180
34180
  anyOf: [
34181
34181
  {
34182
34182
  title: "Record (simple)",
@@ -34191,7 +34191,7 @@ var init_schemas = __esm({
34191
34191
  type: "object",
34192
34192
  properties: {
34193
34193
  surface: {
34194
- description: "The browser window/tab to record. Omit to record the active tab. The targeted tab stays focused afterward.",
34194
+ description: 'The browser window/tab or app window to record. Omit to record the active surface. The targeted surface stays focused afterward. App surfaces use the object form ({ "app": \u2026 }) and are captured via the `ffmpeg` engine, cropped to the app window by default.',
34195
34195
  anyOf: [
34196
34196
  {
34197
34197
  title: "Surface (by browser engine)",
@@ -34341,6 +34341,72 @@ var init_schemas = __esm({
34341
34341
  ]
34342
34342
  }
34343
34343
  }
34344
+ },
34345
+ {
34346
+ title: "App surface",
34347
+ type: "object",
34348
+ additionalProperties: false,
34349
+ required: [
34350
+ "app"
34351
+ ],
34352
+ properties: {
34353
+ app: {
34354
+ type: "string",
34355
+ minLength: 1,
34356
+ pattern: "\\S",
34357
+ transform: [
34358
+ "trim"
34359
+ ],
34360
+ description: "Name of an app surface opened by `startSurface` (its `name`, or the default derived from the app identifier)."
34361
+ },
34362
+ window: {
34363
+ description: "Which app window to act on. Omit to use the active window. Apps have windows, no tabs.",
34364
+ title: "App window selector",
34365
+ anyOf: [
34366
+ {
34367
+ title: "By index",
34368
+ type: "integer",
34369
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest (e.g. a dialog the app just opened)."
34370
+ },
34371
+ {
34372
+ title: "By name",
34373
+ type: "string",
34374
+ minLength: 1,
34375
+ pattern: "\\S",
34376
+ transform: [
34377
+ "trim"
34378
+ ],
34379
+ description: "Assigned window name. The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
34380
+ },
34381
+ {
34382
+ title: "By criteria",
34383
+ type: "object",
34384
+ additionalProperties: false,
34385
+ minProperties: 1,
34386
+ properties: {
34387
+ name: {
34388
+ type: "string",
34389
+ minLength: 1,
34390
+ pattern: "\\S",
34391
+ transform: [
34392
+ "trim"
34393
+ ],
34394
+ description: "Assigned window name."
34395
+ },
34396
+ index: {
34397
+ type: "integer",
34398
+ description: "Index in creation order. Negative counts from the end."
34399
+ },
34400
+ title: {
34401
+ type: "string",
34402
+ minLength: 1,
34403
+ description: "Window title to match. Substring, or /regex/."
34404
+ }
34405
+ }
34406
+ }
34407
+ ]
34408
+ }
34409
+ }
34344
34410
  }
34345
34411
  ]
34346
34412
  },
@@ -34406,13 +34472,12 @@ var init_schemas = __esm({
34406
34472
  },
34407
34473
  target: {
34408
34474
  type: "string",
34409
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
34475
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
34410
34476
  enum: [
34411
34477
  "display",
34412
34478
  "window",
34413
34479
  "viewport"
34414
- ],
34415
- default: "display"
34480
+ ]
34416
34481
  },
34417
34482
  fps: {
34418
34483
  type: "integer",
@@ -34430,7 +34495,7 @@ var init_schemas = __esm({
34430
34495
  {
34431
34496
  type: "boolean",
34432
34497
  title: "Record (boolean)",
34433
- description: "If `true`, starts recording \u2014 auto-selecting the `browser` engine for a visible Chrome context and the `ffmpeg` engine otherwise. If `false`, doesn't record."
34498
+ description: "If `true`, starts recording \u2014 auto-selecting the `browser` engine for a visible Chrome context, the device screen on Android/iOS contexts, and the `ffmpeg` engine otherwise. If `false`, doesn't record."
34434
34499
  }
34435
34500
  ],
34436
34501
  components: {
@@ -34448,7 +34513,7 @@ var init_schemas = __esm({
34448
34513
  type: "object",
34449
34514
  properties: {
34450
34515
  surface: {
34451
- description: "The browser window/tab to record. Omit to record the active tab. The targeted tab stays focused afterward.",
34516
+ description: 'The browser window/tab or app window to record. Omit to record the active surface. The targeted surface stays focused afterward. App surfaces use the object form ({ "app": \u2026 }) and are captured via the `ffmpeg` engine, cropped to the app window by default.',
34452
34517
  anyOf: [
34453
34518
  {
34454
34519
  title: "Surface (by browser engine)",
@@ -34598,6 +34663,72 @@ var init_schemas = __esm({
34598
34663
  ]
34599
34664
  }
34600
34665
  }
34666
+ },
34667
+ {
34668
+ title: "App surface",
34669
+ type: "object",
34670
+ additionalProperties: false,
34671
+ required: [
34672
+ "app"
34673
+ ],
34674
+ properties: {
34675
+ app: {
34676
+ type: "string",
34677
+ minLength: 1,
34678
+ pattern: "\\S",
34679
+ transform: [
34680
+ "trim"
34681
+ ],
34682
+ description: "Name of an app surface opened by `startSurface` (its `name`, or the default derived from the app identifier)."
34683
+ },
34684
+ window: {
34685
+ description: "Which app window to act on. Omit to use the active window. Apps have windows, no tabs.",
34686
+ title: "App window selector",
34687
+ anyOf: [
34688
+ {
34689
+ title: "By index",
34690
+ type: "integer",
34691
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest (e.g. a dialog the app just opened)."
34692
+ },
34693
+ {
34694
+ title: "By name",
34695
+ type: "string",
34696
+ minLength: 1,
34697
+ pattern: "\\S",
34698
+ transform: [
34699
+ "trim"
34700
+ ],
34701
+ description: "Assigned window name. The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
34702
+ },
34703
+ {
34704
+ title: "By criteria",
34705
+ type: "object",
34706
+ additionalProperties: false,
34707
+ minProperties: 1,
34708
+ properties: {
34709
+ name: {
34710
+ type: "string",
34711
+ minLength: 1,
34712
+ pattern: "\\S",
34713
+ transform: [
34714
+ "trim"
34715
+ ],
34716
+ description: "Assigned window name."
34717
+ },
34718
+ index: {
34719
+ type: "integer",
34720
+ description: "Index in creation order. Negative counts from the end."
34721
+ },
34722
+ title: {
34723
+ type: "string",
34724
+ minLength: 1,
34725
+ description: "Window title to match. Substring, or /regex/."
34726
+ }
34727
+ }
34728
+ }
34729
+ ]
34730
+ }
34731
+ }
34601
34732
  }
34602
34733
  ]
34603
34734
  },
@@ -34663,13 +34794,12 @@ var init_schemas = __esm({
34663
34794
  },
34664
34795
  target: {
34665
34796
  type: "string",
34666
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
34797
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
34667
34798
  enum: [
34668
34799
  "display",
34669
34800
  "window",
34670
34801
  "viewport"
34671
- ],
34672
- default: "display"
34802
+ ]
34673
34803
  },
34674
34804
  fps: {
34675
34805
  type: "integer",
@@ -34715,13 +34845,12 @@ var init_schemas = __esm({
34715
34845
  },
34716
34846
  target: {
34717
34847
  type: "string",
34718
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
34848
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
34719
34849
  enum: [
34720
34850
  "display",
34721
34851
  "window",
34722
34852
  "viewport"
34723
- ],
34724
- default: "display"
34853
+ ]
34725
34854
  },
34726
34855
  fps: {
34727
34856
  type: "integer",
@@ -34754,6 +34883,22 @@ var init_schemas = __esm({
34754
34883
  target: "window",
34755
34884
  fps: 60
34756
34885
  }
34886
+ },
34887
+ {
34888
+ path: "notepad.mp4",
34889
+ surface: {
34890
+ app: "notepad"
34891
+ }
34892
+ },
34893
+ {
34894
+ path: "full-screen.mp4",
34895
+ surface: {
34896
+ app: "notepad"
34897
+ },
34898
+ engine: {
34899
+ name: "ffmpeg",
34900
+ target: "display"
34901
+ }
34757
34902
  }
34758
34903
  ]
34759
34904
  }
@@ -78758,7 +78903,7 @@ var init_schemas = __esm({
78758
78903
  record: {
78759
78904
  $schema: "http://json-schema.org/draft-07/schema#",
78760
78905
  title: "record",
78761
- description: "Start recording. Must be followed by a `stopRecord` step. The `browser` engine captures the Chrome viewport (works under concurrency); the `ffmpeg` engine captures the screen and supports any application. Supported extensions: [ '.mp4', '.webm', '.gif' ]",
78906
+ description: "Start recording. Must be followed by a `stopRecord` step. The `browser` engine captures the Chrome viewport (works under concurrency); the `ffmpeg` engine captures the screen and supports any application. On Android/iOS contexts, recording captures the device screen through the device itself \u2014 `engine` doesn't apply. Supported extensions: [ '.mp4', '.webm', '.gif' ]",
78762
78907
  anyOf: [
78763
78908
  {
78764
78909
  title: "Record (simple)",
@@ -78773,7 +78918,7 @@ var init_schemas = __esm({
78773
78918
  type: "object",
78774
78919
  properties: {
78775
78920
  surface: {
78776
- description: "The browser window/tab to record. Omit to record the active tab. The targeted tab stays focused afterward.",
78921
+ description: 'The browser window/tab or app window to record. Omit to record the active surface. The targeted surface stays focused afterward. App surfaces use the object form ({ "app": \u2026 }) and are captured via the `ffmpeg` engine, cropped to the app window by default.',
78777
78922
  anyOf: [
78778
78923
  {
78779
78924
  title: "Surface (by browser engine)",
@@ -78923,6 +79068,72 @@ var init_schemas = __esm({
78923
79068
  ]
78924
79069
  }
78925
79070
  }
79071
+ },
79072
+ {
79073
+ title: "App surface",
79074
+ type: "object",
79075
+ additionalProperties: false,
79076
+ required: [
79077
+ "app"
79078
+ ],
79079
+ properties: {
79080
+ app: {
79081
+ type: "string",
79082
+ minLength: 1,
79083
+ pattern: "\\S",
79084
+ transform: [
79085
+ "trim"
79086
+ ],
79087
+ description: "Name of an app surface opened by `startSurface` (its `name`, or the default derived from the app identifier)."
79088
+ },
79089
+ window: {
79090
+ description: "Which app window to act on. Omit to use the active window. Apps have windows, no tabs.",
79091
+ title: "App window selector",
79092
+ anyOf: [
79093
+ {
79094
+ title: "By index",
79095
+ type: "integer",
79096
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest (e.g. a dialog the app just opened)."
79097
+ },
79098
+ {
79099
+ title: "By name",
79100
+ type: "string",
79101
+ minLength: 1,
79102
+ pattern: "\\S",
79103
+ transform: [
79104
+ "trim"
79105
+ ],
79106
+ description: "Assigned window name. The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
79107
+ },
79108
+ {
79109
+ title: "By criteria",
79110
+ type: "object",
79111
+ additionalProperties: false,
79112
+ minProperties: 1,
79113
+ properties: {
79114
+ name: {
79115
+ type: "string",
79116
+ minLength: 1,
79117
+ pattern: "\\S",
79118
+ transform: [
79119
+ "trim"
79120
+ ],
79121
+ description: "Assigned window name."
79122
+ },
79123
+ index: {
79124
+ type: "integer",
79125
+ description: "Index in creation order. Negative counts from the end."
79126
+ },
79127
+ title: {
79128
+ type: "string",
79129
+ minLength: 1,
79130
+ description: "Window title to match. Substring, or /regex/."
79131
+ }
79132
+ }
79133
+ }
79134
+ ]
79135
+ }
79136
+ }
78926
79137
  }
78927
79138
  ]
78928
79139
  },
@@ -78988,13 +79199,12 @@ var init_schemas = __esm({
78988
79199
  },
78989
79200
  target: {
78990
79201
  type: "string",
78991
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
79202
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
78992
79203
  enum: [
78993
79204
  "display",
78994
79205
  "window",
78995
79206
  "viewport"
78996
- ],
78997
- default: "display"
79207
+ ]
78998
79208
  },
78999
79209
  fps: {
79000
79210
  type: "integer",
@@ -79012,7 +79222,7 @@ var init_schemas = __esm({
79012
79222
  {
79013
79223
  type: "boolean",
79014
79224
  title: "Record (boolean)",
79015
- description: "If `true`, starts recording \u2014 auto-selecting the `browser` engine for a visible Chrome context and the `ffmpeg` engine otherwise. If `false`, doesn't record."
79225
+ description: "If `true`, starts recording \u2014 auto-selecting the `browser` engine for a visible Chrome context, the device screen on Android/iOS contexts, and the `ffmpeg` engine otherwise. If `false`, doesn't record."
79016
79226
  }
79017
79227
  ],
79018
79228
  components: {
@@ -79030,7 +79240,7 @@ var init_schemas = __esm({
79030
79240
  type: "object",
79031
79241
  properties: {
79032
79242
  surface: {
79033
- description: "The browser window/tab to record. Omit to record the active tab. The targeted tab stays focused afterward.",
79243
+ description: 'The browser window/tab or app window to record. Omit to record the active surface. The targeted surface stays focused afterward. App surfaces use the object form ({ "app": \u2026 }) and are captured via the `ffmpeg` engine, cropped to the app window by default.',
79034
79244
  anyOf: [
79035
79245
  {
79036
79246
  title: "Surface (by browser engine)",
@@ -79180,6 +79390,72 @@ var init_schemas = __esm({
79180
79390
  ]
79181
79391
  }
79182
79392
  }
79393
+ },
79394
+ {
79395
+ title: "App surface",
79396
+ type: "object",
79397
+ additionalProperties: false,
79398
+ required: [
79399
+ "app"
79400
+ ],
79401
+ properties: {
79402
+ app: {
79403
+ type: "string",
79404
+ minLength: 1,
79405
+ pattern: "\\S",
79406
+ transform: [
79407
+ "trim"
79408
+ ],
79409
+ description: "Name of an app surface opened by `startSurface` (its `name`, or the default derived from the app identifier)."
79410
+ },
79411
+ window: {
79412
+ description: "Which app window to act on. Omit to use the active window. Apps have windows, no tabs.",
79413
+ title: "App window selector",
79414
+ anyOf: [
79415
+ {
79416
+ title: "By index",
79417
+ type: "integer",
79418
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest (e.g. a dialog the app just opened)."
79419
+ },
79420
+ {
79421
+ title: "By name",
79422
+ type: "string",
79423
+ minLength: 1,
79424
+ pattern: "\\S",
79425
+ transform: [
79426
+ "trim"
79427
+ ],
79428
+ description: "Assigned window name. The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
79429
+ },
79430
+ {
79431
+ title: "By criteria",
79432
+ type: "object",
79433
+ additionalProperties: false,
79434
+ minProperties: 1,
79435
+ properties: {
79436
+ name: {
79437
+ type: "string",
79438
+ minLength: 1,
79439
+ pattern: "\\S",
79440
+ transform: [
79441
+ "trim"
79442
+ ],
79443
+ description: "Assigned window name."
79444
+ },
79445
+ index: {
79446
+ type: "integer",
79447
+ description: "Index in creation order. Negative counts from the end."
79448
+ },
79449
+ title: {
79450
+ type: "string",
79451
+ minLength: 1,
79452
+ description: "Window title to match. Substring, or /regex/."
79453
+ }
79454
+ }
79455
+ }
79456
+ ]
79457
+ }
79458
+ }
79183
79459
  }
79184
79460
  ]
79185
79461
  },
@@ -79245,13 +79521,12 @@ var init_schemas = __esm({
79245
79521
  },
79246
79522
  target: {
79247
79523
  type: "string",
79248
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
79524
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
79249
79525
  enum: [
79250
79526
  "display",
79251
79527
  "window",
79252
79528
  "viewport"
79253
- ],
79254
- default: "display"
79529
+ ]
79255
79530
  },
79256
79531
  fps: {
79257
79532
  type: "integer",
@@ -79297,13 +79572,12 @@ var init_schemas = __esm({
79297
79572
  },
79298
79573
  target: {
79299
79574
  type: "string",
79300
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
79575
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
79301
79576
  enum: [
79302
79577
  "display",
79303
79578
  "window",
79304
79579
  "viewport"
79305
- ],
79306
- default: "display"
79580
+ ]
79307
79581
  },
79308
79582
  fps: {
79309
79583
  type: "integer",
@@ -79336,6 +79610,22 @@ var init_schemas = __esm({
79336
79610
  target: "window",
79337
79611
  fps: 60
79338
79612
  }
79613
+ },
79614
+ {
79615
+ path: "notepad.mp4",
79616
+ surface: {
79617
+ app: "notepad"
79618
+ }
79619
+ },
79620
+ {
79621
+ path: "full-screen.mp4",
79622
+ surface: {
79623
+ app: "notepad"
79624
+ },
79625
+ engine: {
79626
+ name: "ffmpeg",
79627
+ target: "display"
79628
+ }
79339
79629
  }
79340
79630
  ]
79341
79631
  }
@@ -104055,7 +104345,7 @@ var init_schemas = __esm({
104055
104345
  record_v3: {
104056
104346
  $schema: "http://json-schema.org/draft-07/schema#",
104057
104347
  title: "record",
104058
- description: "Start recording. Must be followed by a `stopRecord` step. The `browser` engine captures the Chrome viewport (works under concurrency); the `ffmpeg` engine captures the screen and supports any application. Supported extensions: [ '.mp4', '.webm', '.gif' ]",
104348
+ description: "Start recording. Must be followed by a `stopRecord` step. The `browser` engine captures the Chrome viewport (works under concurrency); the `ffmpeg` engine captures the screen and supports any application. On Android/iOS contexts, recording captures the device screen through the device itself \u2014 `engine` doesn't apply. Supported extensions: [ '.mp4', '.webm', '.gif' ]",
104059
104349
  anyOf: [
104060
104350
  {
104061
104351
  title: "Record (simple)",
@@ -104070,7 +104360,7 @@ var init_schemas = __esm({
104070
104360
  type: "object",
104071
104361
  properties: {
104072
104362
  surface: {
104073
- description: "The browser window/tab to record. Omit to record the active tab. The targeted tab stays focused afterward.",
104363
+ description: 'The browser window/tab or app window to record. Omit to record the active surface. The targeted surface stays focused afterward. App surfaces use the object form ({ "app": \u2026 }) and are captured via the `ffmpeg` engine, cropped to the app window by default.',
104074
104364
  anyOf: [
104075
104365
  {
104076
104366
  title: "Surface (by browser engine)",
@@ -104220,6 +104510,72 @@ var init_schemas = __esm({
104220
104510
  ]
104221
104511
  }
104222
104512
  }
104513
+ },
104514
+ {
104515
+ title: "App surface",
104516
+ type: "object",
104517
+ additionalProperties: false,
104518
+ required: [
104519
+ "app"
104520
+ ],
104521
+ properties: {
104522
+ app: {
104523
+ type: "string",
104524
+ minLength: 1,
104525
+ pattern: "\\S",
104526
+ transform: [
104527
+ "trim"
104528
+ ],
104529
+ description: "Name of an app surface opened by `startSurface` (its `name`, or the default derived from the app identifier)."
104530
+ },
104531
+ window: {
104532
+ description: "Which app window to act on. Omit to use the active window. Apps have windows, no tabs.",
104533
+ title: "App window selector",
104534
+ anyOf: [
104535
+ {
104536
+ title: "By index",
104537
+ type: "integer",
104538
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest (e.g. a dialog the app just opened)."
104539
+ },
104540
+ {
104541
+ title: "By name",
104542
+ type: "string",
104543
+ minLength: 1,
104544
+ pattern: "\\S",
104545
+ transform: [
104546
+ "trim"
104547
+ ],
104548
+ description: "Assigned window name. The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
104549
+ },
104550
+ {
104551
+ title: "By criteria",
104552
+ type: "object",
104553
+ additionalProperties: false,
104554
+ minProperties: 1,
104555
+ properties: {
104556
+ name: {
104557
+ type: "string",
104558
+ minLength: 1,
104559
+ pattern: "\\S",
104560
+ transform: [
104561
+ "trim"
104562
+ ],
104563
+ description: "Assigned window name."
104564
+ },
104565
+ index: {
104566
+ type: "integer",
104567
+ description: "Index in creation order. Negative counts from the end."
104568
+ },
104569
+ title: {
104570
+ type: "string",
104571
+ minLength: 1,
104572
+ description: "Window title to match. Substring, or /regex/."
104573
+ }
104574
+ }
104575
+ }
104576
+ ]
104577
+ }
104578
+ }
104223
104579
  }
104224
104580
  ]
104225
104581
  },
@@ -104285,13 +104641,12 @@ var init_schemas = __esm({
104285
104641
  },
104286
104642
  target: {
104287
104643
  type: "string",
104288
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
104644
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
104289
104645
  enum: [
104290
104646
  "display",
104291
104647
  "window",
104292
104648
  "viewport"
104293
- ],
104294
- default: "display"
104649
+ ]
104295
104650
  },
104296
104651
  fps: {
104297
104652
  type: "integer",
@@ -104309,7 +104664,7 @@ var init_schemas = __esm({
104309
104664
  {
104310
104665
  type: "boolean",
104311
104666
  title: "Record (boolean)",
104312
- description: "If `true`, starts recording \u2014 auto-selecting the `browser` engine for a visible Chrome context and the `ffmpeg` engine otherwise. If `false`, doesn't record."
104667
+ description: "If `true`, starts recording \u2014 auto-selecting the `browser` engine for a visible Chrome context, the device screen on Android/iOS contexts, and the `ffmpeg` engine otherwise. If `false`, doesn't record."
104313
104668
  }
104314
104669
  ],
104315
104670
  components: {
@@ -104327,7 +104682,7 @@ var init_schemas = __esm({
104327
104682
  type: "object",
104328
104683
  properties: {
104329
104684
  surface: {
104330
- description: "The browser window/tab to record. Omit to record the active tab. The targeted tab stays focused afterward.",
104685
+ description: 'The browser window/tab or app window to record. Omit to record the active surface. The targeted surface stays focused afterward. App surfaces use the object form ({ "app": \u2026 }) and are captured via the `ffmpeg` engine, cropped to the app window by default.',
104331
104686
  anyOf: [
104332
104687
  {
104333
104688
  title: "Surface (by browser engine)",
@@ -104477,6 +104832,72 @@ var init_schemas = __esm({
104477
104832
  ]
104478
104833
  }
104479
104834
  }
104835
+ },
104836
+ {
104837
+ title: "App surface",
104838
+ type: "object",
104839
+ additionalProperties: false,
104840
+ required: [
104841
+ "app"
104842
+ ],
104843
+ properties: {
104844
+ app: {
104845
+ type: "string",
104846
+ minLength: 1,
104847
+ pattern: "\\S",
104848
+ transform: [
104849
+ "trim"
104850
+ ],
104851
+ description: "Name of an app surface opened by `startSurface` (its `name`, or the default derived from the app identifier)."
104852
+ },
104853
+ window: {
104854
+ description: "Which app window to act on. Omit to use the active window. Apps have windows, no tabs.",
104855
+ title: "App window selector",
104856
+ anyOf: [
104857
+ {
104858
+ title: "By index",
104859
+ type: "integer",
104860
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest (e.g. a dialog the app just opened)."
104861
+ },
104862
+ {
104863
+ title: "By name",
104864
+ type: "string",
104865
+ minLength: 1,
104866
+ pattern: "\\S",
104867
+ transform: [
104868
+ "trim"
104869
+ ],
104870
+ description: "Assigned window name. The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
104871
+ },
104872
+ {
104873
+ title: "By criteria",
104874
+ type: "object",
104875
+ additionalProperties: false,
104876
+ minProperties: 1,
104877
+ properties: {
104878
+ name: {
104879
+ type: "string",
104880
+ minLength: 1,
104881
+ pattern: "\\S",
104882
+ transform: [
104883
+ "trim"
104884
+ ],
104885
+ description: "Assigned window name."
104886
+ },
104887
+ index: {
104888
+ type: "integer",
104889
+ description: "Index in creation order. Negative counts from the end."
104890
+ },
104891
+ title: {
104892
+ type: "string",
104893
+ minLength: 1,
104894
+ description: "Window title to match. Substring, or /regex/."
104895
+ }
104896
+ }
104897
+ }
104898
+ ]
104899
+ }
104900
+ }
104480
104901
  }
104481
104902
  ]
104482
104903
  },
@@ -104542,13 +104963,12 @@ var init_schemas = __esm({
104542
104963
  },
104543
104964
  target: {
104544
104965
  type: "string",
104545
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
104966
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
104546
104967
  enum: [
104547
104968
  "display",
104548
104969
  "window",
104549
104970
  "viewport"
104550
- ],
104551
- default: "display"
104971
+ ]
104552
104972
  },
104553
104973
  fps: {
104554
104974
  type: "integer",
@@ -104594,13 +105014,12 @@ var init_schemas = __esm({
104594
105014
  },
104595
105015
  target: {
104596
105016
  type: "string",
104597
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
105017
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
104598
105018
  enum: [
104599
105019
  "display",
104600
105020
  "window",
104601
105021
  "viewport"
104602
- ],
104603
- default: "display"
105022
+ ]
104604
105023
  },
104605
105024
  fps: {
104606
105025
  type: "integer",
@@ -104633,6 +105052,22 @@ var init_schemas = __esm({
104633
105052
  target: "window",
104634
105053
  fps: 60
104635
105054
  }
105055
+ },
105056
+ {
105057
+ path: "notepad.mp4",
105058
+ surface: {
105059
+ app: "notepad"
105060
+ }
105061
+ },
105062
+ {
105063
+ path: "full-screen.mp4",
105064
+ surface: {
105065
+ app: "notepad"
105066
+ },
105067
+ engine: {
105068
+ name: "ffmpeg",
105069
+ target: "display"
105070
+ }
104636
105071
  }
104637
105072
  ]
104638
105073
  },
@@ -136500,7 +136935,7 @@ var init_schemas = __esm({
136500
136935
  record: {
136501
136936
  $schema: "http://json-schema.org/draft-07/schema#",
136502
136937
  title: "record",
136503
- description: "Start recording. Must be followed by a `stopRecord` step. The `browser` engine captures the Chrome viewport (works under concurrency); the `ffmpeg` engine captures the screen and supports any application. Supported extensions: [ '.mp4', '.webm', '.gif' ]",
136938
+ description: "Start recording. Must be followed by a `stopRecord` step. The `browser` engine captures the Chrome viewport (works under concurrency); the `ffmpeg` engine captures the screen and supports any application. On Android/iOS contexts, recording captures the device screen through the device itself \u2014 `engine` doesn't apply. Supported extensions: [ '.mp4', '.webm', '.gif' ]",
136504
136939
  anyOf: [
136505
136940
  {
136506
136941
  title: "Record (simple)",
@@ -136515,7 +136950,7 @@ var init_schemas = __esm({
136515
136950
  type: "object",
136516
136951
  properties: {
136517
136952
  surface: {
136518
- description: "The browser window/tab to record. Omit to record the active tab. The targeted tab stays focused afterward.",
136953
+ description: 'The browser window/tab or app window to record. Omit to record the active surface. The targeted surface stays focused afterward. App surfaces use the object form ({ "app": \u2026 }) and are captured via the `ffmpeg` engine, cropped to the app window by default.',
136519
136954
  anyOf: [
136520
136955
  {
136521
136956
  title: "Surface (by browser engine)",
@@ -136665,6 +137100,72 @@ var init_schemas = __esm({
136665
137100
  ]
136666
137101
  }
136667
137102
  }
137103
+ },
137104
+ {
137105
+ title: "App surface",
137106
+ type: "object",
137107
+ additionalProperties: false,
137108
+ required: [
137109
+ "app"
137110
+ ],
137111
+ properties: {
137112
+ app: {
137113
+ type: "string",
137114
+ minLength: 1,
137115
+ pattern: "\\S",
137116
+ transform: [
137117
+ "trim"
137118
+ ],
137119
+ description: "Name of an app surface opened by `startSurface` (its `name`, or the default derived from the app identifier)."
137120
+ },
137121
+ window: {
137122
+ description: "Which app window to act on. Omit to use the active window. Apps have windows, no tabs.",
137123
+ title: "App window selector",
137124
+ anyOf: [
137125
+ {
137126
+ title: "By index",
137127
+ type: "integer",
137128
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest (e.g. a dialog the app just opened)."
137129
+ },
137130
+ {
137131
+ title: "By name",
137132
+ type: "string",
137133
+ minLength: 1,
137134
+ pattern: "\\S",
137135
+ transform: [
137136
+ "trim"
137137
+ ],
137138
+ description: "Assigned window name. The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
137139
+ },
137140
+ {
137141
+ title: "By criteria",
137142
+ type: "object",
137143
+ additionalProperties: false,
137144
+ minProperties: 1,
137145
+ properties: {
137146
+ name: {
137147
+ type: "string",
137148
+ minLength: 1,
137149
+ pattern: "\\S",
137150
+ transform: [
137151
+ "trim"
137152
+ ],
137153
+ description: "Assigned window name."
137154
+ },
137155
+ index: {
137156
+ type: "integer",
137157
+ description: "Index in creation order. Negative counts from the end."
137158
+ },
137159
+ title: {
137160
+ type: "string",
137161
+ minLength: 1,
137162
+ description: "Window title to match. Substring, or /regex/."
137163
+ }
137164
+ }
137165
+ }
137166
+ ]
137167
+ }
137168
+ }
136668
137169
  }
136669
137170
  ]
136670
137171
  },
@@ -136730,13 +137231,12 @@ var init_schemas = __esm({
136730
137231
  },
136731
137232
  target: {
136732
137233
  type: "string",
136733
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
137234
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
136734
137235
  enum: [
136735
137236
  "display",
136736
137237
  "window",
136737
137238
  "viewport"
136738
- ],
136739
- default: "display"
137239
+ ]
136740
137240
  },
136741
137241
  fps: {
136742
137242
  type: "integer",
@@ -136754,7 +137254,7 @@ var init_schemas = __esm({
136754
137254
  {
136755
137255
  type: "boolean",
136756
137256
  title: "Record (boolean)",
136757
- description: "If `true`, starts recording \u2014 auto-selecting the `browser` engine for a visible Chrome context and the `ffmpeg` engine otherwise. If `false`, doesn't record."
137257
+ description: "If `true`, starts recording \u2014 auto-selecting the `browser` engine for a visible Chrome context, the device screen on Android/iOS contexts, and the `ffmpeg` engine otherwise. If `false`, doesn't record."
136758
137258
  }
136759
137259
  ],
136760
137260
  components: {
@@ -136772,7 +137272,7 @@ var init_schemas = __esm({
136772
137272
  type: "object",
136773
137273
  properties: {
136774
137274
  surface: {
136775
- description: "The browser window/tab to record. Omit to record the active tab. The targeted tab stays focused afterward.",
137275
+ description: 'The browser window/tab or app window to record. Omit to record the active surface. The targeted surface stays focused afterward. App surfaces use the object form ({ "app": \u2026 }) and are captured via the `ffmpeg` engine, cropped to the app window by default.',
136776
137276
  anyOf: [
136777
137277
  {
136778
137278
  title: "Surface (by browser engine)",
@@ -136922,6 +137422,72 @@ var init_schemas = __esm({
136922
137422
  ]
136923
137423
  }
136924
137424
  }
137425
+ },
137426
+ {
137427
+ title: "App surface",
137428
+ type: "object",
137429
+ additionalProperties: false,
137430
+ required: [
137431
+ "app"
137432
+ ],
137433
+ properties: {
137434
+ app: {
137435
+ type: "string",
137436
+ minLength: 1,
137437
+ pattern: "\\S",
137438
+ transform: [
137439
+ "trim"
137440
+ ],
137441
+ description: "Name of an app surface opened by `startSurface` (its `name`, or the default derived from the app identifier)."
137442
+ },
137443
+ window: {
137444
+ description: "Which app window to act on. Omit to use the active window. Apps have windows, no tabs.",
137445
+ title: "App window selector",
137446
+ anyOf: [
137447
+ {
137448
+ title: "By index",
137449
+ type: "integer",
137450
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest (e.g. a dialog the app just opened)."
137451
+ },
137452
+ {
137453
+ title: "By name",
137454
+ type: "string",
137455
+ minLength: 1,
137456
+ pattern: "\\S",
137457
+ transform: [
137458
+ "trim"
137459
+ ],
137460
+ description: "Assigned window name. The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
137461
+ },
137462
+ {
137463
+ title: "By criteria",
137464
+ type: "object",
137465
+ additionalProperties: false,
137466
+ minProperties: 1,
137467
+ properties: {
137468
+ name: {
137469
+ type: "string",
137470
+ minLength: 1,
137471
+ pattern: "\\S",
137472
+ transform: [
137473
+ "trim"
137474
+ ],
137475
+ description: "Assigned window name."
137476
+ },
137477
+ index: {
137478
+ type: "integer",
137479
+ description: "Index in creation order. Negative counts from the end."
137480
+ },
137481
+ title: {
137482
+ type: "string",
137483
+ minLength: 1,
137484
+ description: "Window title to match. Substring, or /regex/."
137485
+ }
137486
+ }
137487
+ }
137488
+ ]
137489
+ }
137490
+ }
136925
137491
  }
136926
137492
  ]
136927
137493
  },
@@ -136987,13 +137553,12 @@ var init_schemas = __esm({
136987
137553
  },
136988
137554
  target: {
136989
137555
  type: "string",
136990
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
137556
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
136991
137557
  enum: [
136992
137558
  "display",
136993
137559
  "window",
136994
137560
  "viewport"
136995
- ],
136996
- default: "display"
137561
+ ]
136997
137562
  },
136998
137563
  fps: {
136999
137564
  type: "integer",
@@ -137039,13 +137604,12 @@ var init_schemas = __esm({
137039
137604
  },
137040
137605
  target: {
137041
137606
  type: "string",
137042
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
137607
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
137043
137608
  enum: [
137044
137609
  "display",
137045
137610
  "window",
137046
137611
  "viewport"
137047
- ],
137048
- default: "display"
137612
+ ]
137049
137613
  },
137050
137614
  fps: {
137051
137615
  type: "integer",
@@ -137078,6 +137642,22 @@ var init_schemas = __esm({
137078
137642
  target: "window",
137079
137643
  fps: 60
137080
137644
  }
137645
+ },
137646
+ {
137647
+ path: "notepad.mp4",
137648
+ surface: {
137649
+ app: "notepad"
137650
+ }
137651
+ },
137652
+ {
137653
+ path: "full-screen.mp4",
137654
+ surface: {
137655
+ app: "notepad"
137656
+ },
137657
+ engine: {
137658
+ name: "ffmpeg",
137659
+ target: "display"
137660
+ }
137081
137661
  }
137082
137662
  ]
137083
137663
  }
@@ -181082,7 +181662,7 @@ var init_schemas = __esm({
181082
181662
  record: {
181083
181663
  $schema: "http://json-schema.org/draft-07/schema#",
181084
181664
  title: "record",
181085
- description: "Start recording. Must be followed by a `stopRecord` step. The `browser` engine captures the Chrome viewport (works under concurrency); the `ffmpeg` engine captures the screen and supports any application. Supported extensions: [ '.mp4', '.webm', '.gif' ]",
181665
+ description: "Start recording. Must be followed by a `stopRecord` step. The `browser` engine captures the Chrome viewport (works under concurrency); the `ffmpeg` engine captures the screen and supports any application. On Android/iOS contexts, recording captures the device screen through the device itself \u2014 `engine` doesn't apply. Supported extensions: [ '.mp4', '.webm', '.gif' ]",
181086
181666
  anyOf: [
181087
181667
  {
181088
181668
  title: "Record (simple)",
@@ -181097,7 +181677,7 @@ var init_schemas = __esm({
181097
181677
  type: "object",
181098
181678
  properties: {
181099
181679
  surface: {
181100
- description: "The browser window/tab to record. Omit to record the active tab. The targeted tab stays focused afterward.",
181680
+ description: 'The browser window/tab or app window to record. Omit to record the active surface. The targeted surface stays focused afterward. App surfaces use the object form ({ "app": \u2026 }) and are captured via the `ffmpeg` engine, cropped to the app window by default.',
181101
181681
  anyOf: [
181102
181682
  {
181103
181683
  title: "Surface (by browser engine)",
@@ -181247,6 +181827,72 @@ var init_schemas = __esm({
181247
181827
  ]
181248
181828
  }
181249
181829
  }
181830
+ },
181831
+ {
181832
+ title: "App surface",
181833
+ type: "object",
181834
+ additionalProperties: false,
181835
+ required: [
181836
+ "app"
181837
+ ],
181838
+ properties: {
181839
+ app: {
181840
+ type: "string",
181841
+ minLength: 1,
181842
+ pattern: "\\S",
181843
+ transform: [
181844
+ "trim"
181845
+ ],
181846
+ description: "Name of an app surface opened by `startSurface` (its `name`, or the default derived from the app identifier)."
181847
+ },
181848
+ window: {
181849
+ description: "Which app window to act on. Omit to use the active window. Apps have windows, no tabs.",
181850
+ title: "App window selector",
181851
+ anyOf: [
181852
+ {
181853
+ title: "By index",
181854
+ type: "integer",
181855
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest (e.g. a dialog the app just opened)."
181856
+ },
181857
+ {
181858
+ title: "By name",
181859
+ type: "string",
181860
+ minLength: 1,
181861
+ pattern: "\\S",
181862
+ transform: [
181863
+ "trim"
181864
+ ],
181865
+ description: "Assigned window name. The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
181866
+ },
181867
+ {
181868
+ title: "By criteria",
181869
+ type: "object",
181870
+ additionalProperties: false,
181871
+ minProperties: 1,
181872
+ properties: {
181873
+ name: {
181874
+ type: "string",
181875
+ minLength: 1,
181876
+ pattern: "\\S",
181877
+ transform: [
181878
+ "trim"
181879
+ ],
181880
+ description: "Assigned window name."
181881
+ },
181882
+ index: {
181883
+ type: "integer",
181884
+ description: "Index in creation order. Negative counts from the end."
181885
+ },
181886
+ title: {
181887
+ type: "string",
181888
+ minLength: 1,
181889
+ description: "Window title to match. Substring, or /regex/."
181890
+ }
181891
+ }
181892
+ }
181893
+ ]
181894
+ }
181895
+ }
181250
181896
  }
181251
181897
  ]
181252
181898
  },
@@ -181312,13 +181958,12 @@ var init_schemas = __esm({
181312
181958
  },
181313
181959
  target: {
181314
181960
  type: "string",
181315
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
181961
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
181316
181962
  enum: [
181317
181963
  "display",
181318
181964
  "window",
181319
181965
  "viewport"
181320
- ],
181321
- default: "display"
181966
+ ]
181322
181967
  },
181323
181968
  fps: {
181324
181969
  type: "integer",
@@ -181336,7 +181981,7 @@ var init_schemas = __esm({
181336
181981
  {
181337
181982
  type: "boolean",
181338
181983
  title: "Record (boolean)",
181339
- description: "If `true`, starts recording \u2014 auto-selecting the `browser` engine for a visible Chrome context and the `ffmpeg` engine otherwise. If `false`, doesn't record."
181984
+ description: "If `true`, starts recording \u2014 auto-selecting the `browser` engine for a visible Chrome context, the device screen on Android/iOS contexts, and the `ffmpeg` engine otherwise. If `false`, doesn't record."
181340
181985
  }
181341
181986
  ],
181342
181987
  components: {
@@ -181354,7 +181999,7 @@ var init_schemas = __esm({
181354
181999
  type: "object",
181355
182000
  properties: {
181356
182001
  surface: {
181357
- description: "The browser window/tab to record. Omit to record the active tab. The targeted tab stays focused afterward.",
182002
+ description: 'The browser window/tab or app window to record. Omit to record the active surface. The targeted surface stays focused afterward. App surfaces use the object form ({ "app": \u2026 }) and are captured via the `ffmpeg` engine, cropped to the app window by default.',
181358
182003
  anyOf: [
181359
182004
  {
181360
182005
  title: "Surface (by browser engine)",
@@ -181451,14 +182096,85 @@ var init_schemas = __esm({
181451
182096
  }
181452
182097
  ]
181453
182098
  },
181454
- tab: {
181455
- description: "Which tab to act on. Omit to use the active tab. Without `window`, the selector searches every tab in creation order \u2014 including tabs the page opened itself.",
181456
- title: "Window/tab selector",
182099
+ tab: {
182100
+ description: "Which tab to act on. Omit to use the active tab. Without `window`, the selector searches every tab in creation order \u2014 including tabs the page opened itself.",
182101
+ title: "Window/tab selector",
182102
+ anyOf: [
182103
+ {
182104
+ title: "By index",
182105
+ type: "integer",
182106
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest."
182107
+ },
182108
+ {
182109
+ title: "By name",
182110
+ type: "string",
182111
+ minLength: 1,
182112
+ pattern: "\\S",
182113
+ transform: [
182114
+ "trim"
182115
+ ],
182116
+ description: "Name assigned when the window/tab was opened (goTo `newTab`/`newWindow`). The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
182117
+ },
182118
+ {
182119
+ title: "By criteria",
182120
+ type: "object",
182121
+ additionalProperties: false,
182122
+ minProperties: 1,
182123
+ properties: {
182124
+ name: {
182125
+ type: "string",
182126
+ minLength: 1,
182127
+ pattern: "\\S",
182128
+ transform: [
182129
+ "trim"
182130
+ ],
182131
+ description: "Name assigned when the window/tab was opened."
182132
+ },
182133
+ index: {
182134
+ type: "integer",
182135
+ description: "Index in creation order. Negative counts from the end."
182136
+ },
182137
+ title: {
182138
+ type: "string",
182139
+ minLength: 1,
182140
+ description: "Page title to match. Substring, or /regex/."
182141
+ },
182142
+ url: {
182143
+ type: "string",
182144
+ minLength: 1,
182145
+ description: "Page URL to match. Substring, or /regex/."
182146
+ }
182147
+ }
182148
+ }
182149
+ ]
182150
+ }
182151
+ }
182152
+ },
182153
+ {
182154
+ title: "App surface",
182155
+ type: "object",
182156
+ additionalProperties: false,
182157
+ required: [
182158
+ "app"
182159
+ ],
182160
+ properties: {
182161
+ app: {
182162
+ type: "string",
182163
+ minLength: 1,
182164
+ pattern: "\\S",
182165
+ transform: [
182166
+ "trim"
182167
+ ],
182168
+ description: "Name of an app surface opened by `startSurface` (its `name`, or the default derived from the app identifier)."
182169
+ },
182170
+ window: {
182171
+ description: "Which app window to act on. Omit to use the active window. Apps have windows, no tabs.",
182172
+ title: "App window selector",
181457
182173
  anyOf: [
181458
182174
  {
181459
182175
  title: "By index",
181460
182176
  type: "integer",
181461
- description: "Index in creation order. Negative counts from the end; `-1` is the newest."
182177
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest (e.g. a dialog the app just opened)."
181462
182178
  },
181463
182179
  {
181464
182180
  title: "By name",
@@ -181468,7 +182184,7 @@ var init_schemas = __esm({
181468
182184
  transform: [
181469
182185
  "trim"
181470
182186
  ],
181471
- description: "Name assigned when the window/tab was opened (goTo `newTab`/`newWindow`). The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
182187
+ description: "Assigned window name. The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
181472
182188
  },
181473
182189
  {
181474
182190
  title: "By criteria",
@@ -181483,7 +182199,7 @@ var init_schemas = __esm({
181483
182199
  transform: [
181484
182200
  "trim"
181485
182201
  ],
181486
- description: "Name assigned when the window/tab was opened."
182202
+ description: "Assigned window name."
181487
182203
  },
181488
182204
  index: {
181489
182205
  type: "integer",
@@ -181492,12 +182208,7 @@ var init_schemas = __esm({
181492
182208
  title: {
181493
182209
  type: "string",
181494
182210
  minLength: 1,
181495
- description: "Page title to match. Substring, or /regex/."
181496
- },
181497
- url: {
181498
- type: "string",
181499
- minLength: 1,
181500
- description: "Page URL to match. Substring, or /regex/."
182211
+ description: "Window title to match. Substring, or /regex/."
181501
182212
  }
181502
182213
  }
181503
182214
  }
@@ -181569,13 +182280,12 @@ var init_schemas = __esm({
181569
182280
  },
181570
182281
  target: {
181571
182282
  type: "string",
181572
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
182283
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
181573
182284
  enum: [
181574
182285
  "display",
181575
182286
  "window",
181576
182287
  "viewport"
181577
- ],
181578
- default: "display"
182288
+ ]
181579
182289
  },
181580
182290
  fps: {
181581
182291
  type: "integer",
@@ -181621,13 +182331,12 @@ var init_schemas = __esm({
181621
182331
  },
181622
182332
  target: {
181623
182333
  type: "string",
181624
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
182334
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
181625
182335
  enum: [
181626
182336
  "display",
181627
182337
  "window",
181628
182338
  "viewport"
181629
- ],
181630
- default: "display"
182339
+ ]
181631
182340
  },
181632
182341
  fps: {
181633
182342
  type: "integer",
@@ -181660,6 +182369,22 @@ var init_schemas = __esm({
181660
182369
  target: "window",
181661
182370
  fps: 60
181662
182371
  }
182372
+ },
182373
+ {
182374
+ path: "notepad.mp4",
182375
+ surface: {
182376
+ app: "notepad"
182377
+ }
182378
+ },
182379
+ {
182380
+ path: "full-screen.mp4",
182381
+ surface: {
182382
+ app: "notepad"
182383
+ },
182384
+ engine: {
182385
+ name: "ffmpeg",
182386
+ target: "display"
182387
+ }
181663
182388
  }
181664
182389
  ]
181665
182390
  }
@@ -227437,7 +228162,7 @@ var init_schemas = __esm({
227437
228162
  record: {
227438
228163
  $schema: "http://json-schema.org/draft-07/schema#",
227439
228164
  title: "record",
227440
- description: "Start recording. Must be followed by a `stopRecord` step. The `browser` engine captures the Chrome viewport (works under concurrency); the `ffmpeg` engine captures the screen and supports any application. Supported extensions: [ '.mp4', '.webm', '.gif' ]",
228165
+ description: "Start recording. Must be followed by a `stopRecord` step. The `browser` engine captures the Chrome viewport (works under concurrency); the `ffmpeg` engine captures the screen and supports any application. On Android/iOS contexts, recording captures the device screen through the device itself \u2014 `engine` doesn't apply. Supported extensions: [ '.mp4', '.webm', '.gif' ]",
227441
228166
  anyOf: [
227442
228167
  {
227443
228168
  title: "Record (simple)",
@@ -227452,7 +228177,7 @@ var init_schemas = __esm({
227452
228177
  type: "object",
227453
228178
  properties: {
227454
228179
  surface: {
227455
- description: "The browser window/tab to record. Omit to record the active tab. The targeted tab stays focused afterward.",
228180
+ description: 'The browser window/tab or app window to record. Omit to record the active surface. The targeted surface stays focused afterward. App surfaces use the object form ({ "app": \u2026 }) and are captured via the `ffmpeg` engine, cropped to the app window by default.',
227456
228181
  anyOf: [
227457
228182
  {
227458
228183
  title: "Surface (by browser engine)",
@@ -227602,6 +228327,72 @@ var init_schemas = __esm({
227602
228327
  ]
227603
228328
  }
227604
228329
  }
228330
+ },
228331
+ {
228332
+ title: "App surface",
228333
+ type: "object",
228334
+ additionalProperties: false,
228335
+ required: [
228336
+ "app"
228337
+ ],
228338
+ properties: {
228339
+ app: {
228340
+ type: "string",
228341
+ minLength: 1,
228342
+ pattern: "\\S",
228343
+ transform: [
228344
+ "trim"
228345
+ ],
228346
+ description: "Name of an app surface opened by `startSurface` (its `name`, or the default derived from the app identifier)."
228347
+ },
228348
+ window: {
228349
+ description: "Which app window to act on. Omit to use the active window. Apps have windows, no tabs.",
228350
+ title: "App window selector",
228351
+ anyOf: [
228352
+ {
228353
+ title: "By index",
228354
+ type: "integer",
228355
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest (e.g. a dialog the app just opened)."
228356
+ },
228357
+ {
228358
+ title: "By name",
228359
+ type: "string",
228360
+ minLength: 1,
228361
+ pattern: "\\S",
228362
+ transform: [
228363
+ "trim"
228364
+ ],
228365
+ description: "Assigned window name. The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
228366
+ },
228367
+ {
228368
+ title: "By criteria",
228369
+ type: "object",
228370
+ additionalProperties: false,
228371
+ minProperties: 1,
228372
+ properties: {
228373
+ name: {
228374
+ type: "string",
228375
+ minLength: 1,
228376
+ pattern: "\\S",
228377
+ transform: [
228378
+ "trim"
228379
+ ],
228380
+ description: "Assigned window name."
228381
+ },
228382
+ index: {
228383
+ type: "integer",
228384
+ description: "Index in creation order. Negative counts from the end."
228385
+ },
228386
+ title: {
228387
+ type: "string",
228388
+ minLength: 1,
228389
+ description: "Window title to match. Substring, or /regex/."
228390
+ }
228391
+ }
228392
+ }
228393
+ ]
228394
+ }
228395
+ }
227605
228396
  }
227606
228397
  ]
227607
228398
  },
@@ -227667,13 +228458,12 @@ var init_schemas = __esm({
227667
228458
  },
227668
228459
  target: {
227669
228460
  type: "string",
227670
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
228461
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
227671
228462
  enum: [
227672
228463
  "display",
227673
228464
  "window",
227674
228465
  "viewport"
227675
- ],
227676
- default: "display"
228466
+ ]
227677
228467
  },
227678
228468
  fps: {
227679
228469
  type: "integer",
@@ -227691,7 +228481,7 @@ var init_schemas = __esm({
227691
228481
  {
227692
228482
  type: "boolean",
227693
228483
  title: "Record (boolean)",
227694
- description: "If `true`, starts recording \u2014 auto-selecting the `browser` engine for a visible Chrome context and the `ffmpeg` engine otherwise. If `false`, doesn't record."
228484
+ description: "If `true`, starts recording \u2014 auto-selecting the `browser` engine for a visible Chrome context, the device screen on Android/iOS contexts, and the `ffmpeg` engine otherwise. If `false`, doesn't record."
227695
228485
  }
227696
228486
  ],
227697
228487
  components: {
@@ -227709,7 +228499,7 @@ var init_schemas = __esm({
227709
228499
  type: "object",
227710
228500
  properties: {
227711
228501
  surface: {
227712
- description: "The browser window/tab to record. Omit to record the active tab. The targeted tab stays focused afterward.",
228502
+ description: 'The browser window/tab or app window to record. Omit to record the active surface. The targeted surface stays focused afterward. App surfaces use the object form ({ "app": \u2026 }) and are captured via the `ffmpeg` engine, cropped to the app window by default.',
227713
228503
  anyOf: [
227714
228504
  {
227715
228505
  title: "Surface (by browser engine)",
@@ -227859,6 +228649,72 @@ var init_schemas = __esm({
227859
228649
  ]
227860
228650
  }
227861
228651
  }
228652
+ },
228653
+ {
228654
+ title: "App surface",
228655
+ type: "object",
228656
+ additionalProperties: false,
228657
+ required: [
228658
+ "app"
228659
+ ],
228660
+ properties: {
228661
+ app: {
228662
+ type: "string",
228663
+ minLength: 1,
228664
+ pattern: "\\S",
228665
+ transform: [
228666
+ "trim"
228667
+ ],
228668
+ description: "Name of an app surface opened by `startSurface` (its `name`, or the default derived from the app identifier)."
228669
+ },
228670
+ window: {
228671
+ description: "Which app window to act on. Omit to use the active window. Apps have windows, no tabs.",
228672
+ title: "App window selector",
228673
+ anyOf: [
228674
+ {
228675
+ title: "By index",
228676
+ type: "integer",
228677
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest (e.g. a dialog the app just opened)."
228678
+ },
228679
+ {
228680
+ title: "By name",
228681
+ type: "string",
228682
+ minLength: 1,
228683
+ pattern: "\\S",
228684
+ transform: [
228685
+ "trim"
228686
+ ],
228687
+ description: "Assigned window name. The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
228688
+ },
228689
+ {
228690
+ title: "By criteria",
228691
+ type: "object",
228692
+ additionalProperties: false,
228693
+ minProperties: 1,
228694
+ properties: {
228695
+ name: {
228696
+ type: "string",
228697
+ minLength: 1,
228698
+ pattern: "\\S",
228699
+ transform: [
228700
+ "trim"
228701
+ ],
228702
+ description: "Assigned window name."
228703
+ },
228704
+ index: {
228705
+ type: "integer",
228706
+ description: "Index in creation order. Negative counts from the end."
228707
+ },
228708
+ title: {
228709
+ type: "string",
228710
+ minLength: 1,
228711
+ description: "Window title to match. Substring, or /regex/."
228712
+ }
228713
+ }
228714
+ }
228715
+ ]
228716
+ }
228717
+ }
227862
228718
  }
227863
228719
  ]
227864
228720
  },
@@ -227924,13 +228780,12 @@ var init_schemas = __esm({
227924
228780
  },
227925
228781
  target: {
227926
228782
  type: "string",
227927
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
228783
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
227928
228784
  enum: [
227929
228785
  "display",
227930
228786
  "window",
227931
228787
  "viewport"
227932
- ],
227933
- default: "display"
228788
+ ]
227934
228789
  },
227935
228790
  fps: {
227936
228791
  type: "integer",
@@ -227976,13 +228831,12 @@ var init_schemas = __esm({
227976
228831
  },
227977
228832
  target: {
227978
228833
  type: "string",
227979
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
228834
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
227980
228835
  enum: [
227981
228836
  "display",
227982
228837
  "window",
227983
228838
  "viewport"
227984
- ],
227985
- default: "display"
228839
+ ]
227986
228840
  },
227987
228841
  fps: {
227988
228842
  type: "integer",
@@ -228015,6 +228869,22 @@ var init_schemas = __esm({
228015
228869
  target: "window",
228016
228870
  fps: 60
228017
228871
  }
228872
+ },
228873
+ {
228874
+ path: "notepad.mp4",
228875
+ surface: {
228876
+ app: "notepad"
228877
+ }
228878
+ },
228879
+ {
228880
+ path: "full-screen.mp4",
228881
+ surface: {
228882
+ app: "notepad"
228883
+ },
228884
+ engine: {
228885
+ name: "ffmpeg",
228886
+ target: "display"
228887
+ }
228018
228888
  }
228019
228889
  ]
228020
228890
  }
@@ -271318,7 +272188,7 @@ var init_schemas = __esm({
271318
272188
  record: {
271319
272189
  $schema: "http://json-schema.org/draft-07/schema#",
271320
272190
  title: "record",
271321
- description: "Start recording. Must be followed by a `stopRecord` step. The `browser` engine captures the Chrome viewport (works under concurrency); the `ffmpeg` engine captures the screen and supports any application. Supported extensions: [ '.mp4', '.webm', '.gif' ]",
272191
+ description: "Start recording. Must be followed by a `stopRecord` step. The `browser` engine captures the Chrome viewport (works under concurrency); the `ffmpeg` engine captures the screen and supports any application. On Android/iOS contexts, recording captures the device screen through the device itself \u2014 `engine` doesn't apply. Supported extensions: [ '.mp4', '.webm', '.gif' ]",
271322
272192
  anyOf: [
271323
272193
  {
271324
272194
  title: "Record (simple)",
@@ -271333,7 +272203,7 @@ var init_schemas = __esm({
271333
272203
  type: "object",
271334
272204
  properties: {
271335
272205
  surface: {
271336
- description: "The browser window/tab to record. Omit to record the active tab. The targeted tab stays focused afterward.",
272206
+ description: 'The browser window/tab or app window to record. Omit to record the active surface. The targeted surface stays focused afterward. App surfaces use the object form ({ "app": \u2026 }) and are captured via the `ffmpeg` engine, cropped to the app window by default.',
271337
272207
  anyOf: [
271338
272208
  {
271339
272209
  title: "Surface (by browser engine)",
@@ -271430,14 +272300,85 @@ var init_schemas = __esm({
271430
272300
  }
271431
272301
  ]
271432
272302
  },
271433
- tab: {
271434
- description: "Which tab to act on. Omit to use the active tab. Without `window`, the selector searches every tab in creation order \u2014 including tabs the page opened itself.",
271435
- title: "Window/tab selector",
272303
+ tab: {
272304
+ description: "Which tab to act on. Omit to use the active tab. Without `window`, the selector searches every tab in creation order \u2014 including tabs the page opened itself.",
272305
+ title: "Window/tab selector",
272306
+ anyOf: [
272307
+ {
272308
+ title: "By index",
272309
+ type: "integer",
272310
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest."
272311
+ },
272312
+ {
272313
+ title: "By name",
272314
+ type: "string",
272315
+ minLength: 1,
272316
+ pattern: "\\S",
272317
+ transform: [
272318
+ "trim"
272319
+ ],
272320
+ description: "Name assigned when the window/tab was opened (goTo `newTab`/`newWindow`). The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
272321
+ },
272322
+ {
272323
+ title: "By criteria",
272324
+ type: "object",
272325
+ additionalProperties: false,
272326
+ minProperties: 1,
272327
+ properties: {
272328
+ name: {
272329
+ type: "string",
272330
+ minLength: 1,
272331
+ pattern: "\\S",
272332
+ transform: [
272333
+ "trim"
272334
+ ],
272335
+ description: "Name assigned when the window/tab was opened."
272336
+ },
272337
+ index: {
272338
+ type: "integer",
272339
+ description: "Index in creation order. Negative counts from the end."
272340
+ },
272341
+ title: {
272342
+ type: "string",
272343
+ minLength: 1,
272344
+ description: "Page title to match. Substring, or /regex/."
272345
+ },
272346
+ url: {
272347
+ type: "string",
272348
+ minLength: 1,
272349
+ description: "Page URL to match. Substring, or /regex/."
272350
+ }
272351
+ }
272352
+ }
272353
+ ]
272354
+ }
272355
+ }
272356
+ },
272357
+ {
272358
+ title: "App surface",
272359
+ type: "object",
272360
+ additionalProperties: false,
272361
+ required: [
272362
+ "app"
272363
+ ],
272364
+ properties: {
272365
+ app: {
272366
+ type: "string",
272367
+ minLength: 1,
272368
+ pattern: "\\S",
272369
+ transform: [
272370
+ "trim"
272371
+ ],
272372
+ description: "Name of an app surface opened by `startSurface` (its `name`, or the default derived from the app identifier)."
272373
+ },
272374
+ window: {
272375
+ description: "Which app window to act on. Omit to use the active window. Apps have windows, no tabs.",
272376
+ title: "App window selector",
271436
272377
  anyOf: [
271437
272378
  {
271438
272379
  title: "By index",
271439
272380
  type: "integer",
271440
- description: "Index in creation order. Negative counts from the end; `-1` is the newest."
272381
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest (e.g. a dialog the app just opened)."
271441
272382
  },
271442
272383
  {
271443
272384
  title: "By name",
@@ -271447,7 +272388,7 @@ var init_schemas = __esm({
271447
272388
  transform: [
271448
272389
  "trim"
271449
272390
  ],
271450
- description: "Name assigned when the window/tab was opened (goTo `newTab`/`newWindow`). The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
272391
+ description: "Assigned window name. The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
271451
272392
  },
271452
272393
  {
271453
272394
  title: "By criteria",
@@ -271462,7 +272403,7 @@ var init_schemas = __esm({
271462
272403
  transform: [
271463
272404
  "trim"
271464
272405
  ],
271465
- description: "Name assigned when the window/tab was opened."
272406
+ description: "Assigned window name."
271466
272407
  },
271467
272408
  index: {
271468
272409
  type: "integer",
@@ -271471,12 +272412,7 @@ var init_schemas = __esm({
271471
272412
  title: {
271472
272413
  type: "string",
271473
272414
  minLength: 1,
271474
- description: "Page title to match. Substring, or /regex/."
271475
- },
271476
- url: {
271477
- type: "string",
271478
- minLength: 1,
271479
- description: "Page URL to match. Substring, or /regex/."
272415
+ description: "Window title to match. Substring, or /regex/."
271480
272416
  }
271481
272417
  }
271482
272418
  }
@@ -271548,13 +272484,12 @@ var init_schemas = __esm({
271548
272484
  },
271549
272485
  target: {
271550
272486
  type: "string",
271551
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
272487
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
271552
272488
  enum: [
271553
272489
  "display",
271554
272490
  "window",
271555
272491
  "viewport"
271556
- ],
271557
- default: "display"
272492
+ ]
271558
272493
  },
271559
272494
  fps: {
271560
272495
  type: "integer",
@@ -271572,7 +272507,7 @@ var init_schemas = __esm({
271572
272507
  {
271573
272508
  type: "boolean",
271574
272509
  title: "Record (boolean)",
271575
- description: "If `true`, starts recording \u2014 auto-selecting the `browser` engine for a visible Chrome context and the `ffmpeg` engine otherwise. If `false`, doesn't record."
272510
+ description: "If `true`, starts recording \u2014 auto-selecting the `browser` engine for a visible Chrome context, the device screen on Android/iOS contexts, and the `ffmpeg` engine otherwise. If `false`, doesn't record."
271576
272511
  }
271577
272512
  ],
271578
272513
  components: {
@@ -271590,7 +272525,7 @@ var init_schemas = __esm({
271590
272525
  type: "object",
271591
272526
  properties: {
271592
272527
  surface: {
271593
- description: "The browser window/tab to record. Omit to record the active tab. The targeted tab stays focused afterward.",
272528
+ description: 'The browser window/tab or app window to record. Omit to record the active surface. The targeted surface stays focused afterward. App surfaces use the object form ({ "app": \u2026 }) and are captured via the `ffmpeg` engine, cropped to the app window by default.',
271594
272529
  anyOf: [
271595
272530
  {
271596
272531
  title: "Surface (by browser engine)",
@@ -271740,6 +272675,72 @@ var init_schemas = __esm({
271740
272675
  ]
271741
272676
  }
271742
272677
  }
272678
+ },
272679
+ {
272680
+ title: "App surface",
272681
+ type: "object",
272682
+ additionalProperties: false,
272683
+ required: [
272684
+ "app"
272685
+ ],
272686
+ properties: {
272687
+ app: {
272688
+ type: "string",
272689
+ minLength: 1,
272690
+ pattern: "\\S",
272691
+ transform: [
272692
+ "trim"
272693
+ ],
272694
+ description: "Name of an app surface opened by `startSurface` (its `name`, or the default derived from the app identifier)."
272695
+ },
272696
+ window: {
272697
+ description: "Which app window to act on. Omit to use the active window. Apps have windows, no tabs.",
272698
+ title: "App window selector",
272699
+ anyOf: [
272700
+ {
272701
+ title: "By index",
272702
+ type: "integer",
272703
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest (e.g. a dialog the app just opened)."
272704
+ },
272705
+ {
272706
+ title: "By name",
272707
+ type: "string",
272708
+ minLength: 1,
272709
+ pattern: "\\S",
272710
+ transform: [
272711
+ "trim"
272712
+ ],
272713
+ description: "Assigned window name. The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
272714
+ },
272715
+ {
272716
+ title: "By criteria",
272717
+ type: "object",
272718
+ additionalProperties: false,
272719
+ minProperties: 1,
272720
+ properties: {
272721
+ name: {
272722
+ type: "string",
272723
+ minLength: 1,
272724
+ pattern: "\\S",
272725
+ transform: [
272726
+ "trim"
272727
+ ],
272728
+ description: "Assigned window name."
272729
+ },
272730
+ index: {
272731
+ type: "integer",
272732
+ description: "Index in creation order. Negative counts from the end."
272733
+ },
272734
+ title: {
272735
+ type: "string",
272736
+ minLength: 1,
272737
+ description: "Window title to match. Substring, or /regex/."
272738
+ }
272739
+ }
272740
+ }
272741
+ ]
272742
+ }
272743
+ }
271743
272744
  }
271744
272745
  ]
271745
272746
  },
@@ -271805,13 +272806,12 @@ var init_schemas = __esm({
271805
272806
  },
271806
272807
  target: {
271807
272808
  type: "string",
271808
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
272809
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
271809
272810
  enum: [
271810
272811
  "display",
271811
272812
  "window",
271812
272813
  "viewport"
271813
- ],
271814
- default: "display"
272814
+ ]
271815
272815
  },
271816
272816
  fps: {
271817
272817
  type: "integer",
@@ -271857,13 +272857,12 @@ var init_schemas = __esm({
271857
272857
  },
271858
272858
  target: {
271859
272859
  type: "string",
271860
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
272860
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
271861
272861
  enum: [
271862
272862
  "display",
271863
272863
  "window",
271864
272864
  "viewport"
271865
- ],
271866
- default: "display"
272865
+ ]
271867
272866
  },
271868
272867
  fps: {
271869
272868
  type: "integer",
@@ -271896,6 +272895,22 @@ var init_schemas = __esm({
271896
272895
  target: "window",
271897
272896
  fps: 60
271898
272897
  }
272898
+ },
272899
+ {
272900
+ path: "notepad.mp4",
272901
+ surface: {
272902
+ app: "notepad"
272903
+ }
272904
+ },
272905
+ {
272906
+ path: "full-screen.mp4",
272907
+ surface: {
272908
+ app: "notepad"
272909
+ },
272910
+ engine: {
272911
+ name: "ffmpeg",
272912
+ target: "display"
272913
+ }
271899
272914
  }
271900
272915
  ]
271901
272916
  }
@@ -318160,7 +319175,7 @@ var init_schemas = __esm({
318160
319175
  record: {
318161
319176
  $schema: "http://json-schema.org/draft-07/schema#",
318162
319177
  title: "record",
318163
- description: "Start recording. Must be followed by a `stopRecord` step. The `browser` engine captures the Chrome viewport (works under concurrency); the `ffmpeg` engine captures the screen and supports any application. Supported extensions: [ '.mp4', '.webm', '.gif' ]",
319178
+ description: "Start recording. Must be followed by a `stopRecord` step. The `browser` engine captures the Chrome viewport (works under concurrency); the `ffmpeg` engine captures the screen and supports any application. On Android/iOS contexts, recording captures the device screen through the device itself \u2014 `engine` doesn't apply. Supported extensions: [ '.mp4', '.webm', '.gif' ]",
318164
319179
  anyOf: [
318165
319180
  {
318166
319181
  title: "Record (simple)",
@@ -318175,7 +319190,7 @@ var init_schemas = __esm({
318175
319190
  type: "object",
318176
319191
  properties: {
318177
319192
  surface: {
318178
- description: "The browser window/tab to record. Omit to record the active tab. The targeted tab stays focused afterward.",
319193
+ description: 'The browser window/tab or app window to record. Omit to record the active surface. The targeted surface stays focused afterward. App surfaces use the object form ({ "app": \u2026 }) and are captured via the `ffmpeg` engine, cropped to the app window by default.',
318179
319194
  anyOf: [
318180
319195
  {
318181
319196
  title: "Surface (by browser engine)",
@@ -318325,6 +319340,72 @@ var init_schemas = __esm({
318325
319340
  ]
318326
319341
  }
318327
319342
  }
319343
+ },
319344
+ {
319345
+ title: "App surface",
319346
+ type: "object",
319347
+ additionalProperties: false,
319348
+ required: [
319349
+ "app"
319350
+ ],
319351
+ properties: {
319352
+ app: {
319353
+ type: "string",
319354
+ minLength: 1,
319355
+ pattern: "\\S",
319356
+ transform: [
319357
+ "trim"
319358
+ ],
319359
+ description: "Name of an app surface opened by `startSurface` (its `name`, or the default derived from the app identifier)."
319360
+ },
319361
+ window: {
319362
+ description: "Which app window to act on. Omit to use the active window. Apps have windows, no tabs.",
319363
+ title: "App window selector",
319364
+ anyOf: [
319365
+ {
319366
+ title: "By index",
319367
+ type: "integer",
319368
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest (e.g. a dialog the app just opened)."
319369
+ },
319370
+ {
319371
+ title: "By name",
319372
+ type: "string",
319373
+ minLength: 1,
319374
+ pattern: "\\S",
319375
+ transform: [
319376
+ "trim"
319377
+ ],
319378
+ description: "Assigned window name. The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
319379
+ },
319380
+ {
319381
+ title: "By criteria",
319382
+ type: "object",
319383
+ additionalProperties: false,
319384
+ minProperties: 1,
319385
+ properties: {
319386
+ name: {
319387
+ type: "string",
319388
+ minLength: 1,
319389
+ pattern: "\\S",
319390
+ transform: [
319391
+ "trim"
319392
+ ],
319393
+ description: "Assigned window name."
319394
+ },
319395
+ index: {
319396
+ type: "integer",
319397
+ description: "Index in creation order. Negative counts from the end."
319398
+ },
319399
+ title: {
319400
+ type: "string",
319401
+ minLength: 1,
319402
+ description: "Window title to match. Substring, or /regex/."
319403
+ }
319404
+ }
319405
+ }
319406
+ ]
319407
+ }
319408
+ }
318328
319409
  }
318329
319410
  ]
318330
319411
  },
@@ -318390,13 +319471,12 @@ var init_schemas = __esm({
318390
319471
  },
318391
319472
  target: {
318392
319473
  type: "string",
318393
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
319474
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
318394
319475
  enum: [
318395
319476
  "display",
318396
319477
  "window",
318397
319478
  "viewport"
318398
- ],
318399
- default: "display"
319479
+ ]
318400
319480
  },
318401
319481
  fps: {
318402
319482
  type: "integer",
@@ -318414,7 +319494,7 @@ var init_schemas = __esm({
318414
319494
  {
318415
319495
  type: "boolean",
318416
319496
  title: "Record (boolean)",
318417
- description: "If `true`, starts recording \u2014 auto-selecting the `browser` engine for a visible Chrome context and the `ffmpeg` engine otherwise. If `false`, doesn't record."
319497
+ description: "If `true`, starts recording \u2014 auto-selecting the `browser` engine for a visible Chrome context, the device screen on Android/iOS contexts, and the `ffmpeg` engine otherwise. If `false`, doesn't record."
318418
319498
  }
318419
319499
  ],
318420
319500
  components: {
@@ -318432,7 +319512,7 @@ var init_schemas = __esm({
318432
319512
  type: "object",
318433
319513
  properties: {
318434
319514
  surface: {
318435
- description: "The browser window/tab to record. Omit to record the active tab. The targeted tab stays focused afterward.",
319515
+ description: 'The browser window/tab or app window to record. Omit to record the active surface. The targeted surface stays focused afterward. App surfaces use the object form ({ "app": \u2026 }) and are captured via the `ffmpeg` engine, cropped to the app window by default.',
318436
319516
  anyOf: [
318437
319517
  {
318438
319518
  title: "Surface (by browser engine)",
@@ -318582,6 +319662,72 @@ var init_schemas = __esm({
318582
319662
  ]
318583
319663
  }
318584
319664
  }
319665
+ },
319666
+ {
319667
+ title: "App surface",
319668
+ type: "object",
319669
+ additionalProperties: false,
319670
+ required: [
319671
+ "app"
319672
+ ],
319673
+ properties: {
319674
+ app: {
319675
+ type: "string",
319676
+ minLength: 1,
319677
+ pattern: "\\S",
319678
+ transform: [
319679
+ "trim"
319680
+ ],
319681
+ description: "Name of an app surface opened by `startSurface` (its `name`, or the default derived from the app identifier)."
319682
+ },
319683
+ window: {
319684
+ description: "Which app window to act on. Omit to use the active window. Apps have windows, no tabs.",
319685
+ title: "App window selector",
319686
+ anyOf: [
319687
+ {
319688
+ title: "By index",
319689
+ type: "integer",
319690
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest (e.g. a dialog the app just opened)."
319691
+ },
319692
+ {
319693
+ title: "By name",
319694
+ type: "string",
319695
+ minLength: 1,
319696
+ pattern: "\\S",
319697
+ transform: [
319698
+ "trim"
319699
+ ],
319700
+ description: "Assigned window name. The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
319701
+ },
319702
+ {
319703
+ title: "By criteria",
319704
+ type: "object",
319705
+ additionalProperties: false,
319706
+ minProperties: 1,
319707
+ properties: {
319708
+ name: {
319709
+ type: "string",
319710
+ minLength: 1,
319711
+ pattern: "\\S",
319712
+ transform: [
319713
+ "trim"
319714
+ ],
319715
+ description: "Assigned window name."
319716
+ },
319717
+ index: {
319718
+ type: "integer",
319719
+ description: "Index in creation order. Negative counts from the end."
319720
+ },
319721
+ title: {
319722
+ type: "string",
319723
+ minLength: 1,
319724
+ description: "Window title to match. Substring, or /regex/."
319725
+ }
319726
+ }
319727
+ }
319728
+ ]
319729
+ }
319730
+ }
318585
319731
  }
318586
319732
  ]
318587
319733
  },
@@ -318647,13 +319793,12 @@ var init_schemas = __esm({
318647
319793
  },
318648
319794
  target: {
318649
319795
  type: "string",
318650
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
319796
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
318651
319797
  enum: [
318652
319798
  "display",
318653
319799
  "window",
318654
319800
  "viewport"
318655
- ],
318656
- default: "display"
319801
+ ]
318657
319802
  },
318658
319803
  fps: {
318659
319804
  type: "integer",
@@ -318699,13 +319844,12 @@ var init_schemas = __esm({
318699
319844
  },
318700
319845
  target: {
318701
319846
  type: "string",
318702
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
319847
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
318703
319848
  enum: [
318704
319849
  "display",
318705
319850
  "window",
318706
319851
  "viewport"
318707
- ],
318708
- default: "display"
319852
+ ]
318709
319853
  },
318710
319854
  fps: {
318711
319855
  type: "integer",
@@ -318738,6 +319882,22 @@ var init_schemas = __esm({
318738
319882
  target: "window",
318739
319883
  fps: 60
318740
319884
  }
319885
+ },
319886
+ {
319887
+ path: "notepad.mp4",
319888
+ surface: {
319889
+ app: "notepad"
319890
+ }
319891
+ },
319892
+ {
319893
+ path: "full-screen.mp4",
319894
+ surface: {
319895
+ app: "notepad"
319896
+ },
319897
+ engine: {
319898
+ name: "ffmpeg",
319899
+ target: "display"
319900
+ }
318741
319901
  }
318742
319902
  ]
318743
319903
  }
@@ -362041,7 +363201,7 @@ var init_schemas = __esm({
362041
363201
  record: {
362042
363202
  $schema: "http://json-schema.org/draft-07/schema#",
362043
363203
  title: "record",
362044
- description: "Start recording. Must be followed by a `stopRecord` step. The `browser` engine captures the Chrome viewport (works under concurrency); the `ffmpeg` engine captures the screen and supports any application. Supported extensions: [ '.mp4', '.webm', '.gif' ]",
363204
+ description: "Start recording. Must be followed by a `stopRecord` step. The `browser` engine captures the Chrome viewport (works under concurrency); the `ffmpeg` engine captures the screen and supports any application. On Android/iOS contexts, recording captures the device screen through the device itself \u2014 `engine` doesn't apply. Supported extensions: [ '.mp4', '.webm', '.gif' ]",
362045
363205
  anyOf: [
362046
363206
  {
362047
363207
  title: "Record (simple)",
@@ -362056,7 +363216,7 @@ var init_schemas = __esm({
362056
363216
  type: "object",
362057
363217
  properties: {
362058
363218
  surface: {
362059
- description: "The browser window/tab to record. Omit to record the active tab. The targeted tab stays focused afterward.",
363219
+ description: 'The browser window/tab or app window to record. Omit to record the active surface. The targeted surface stays focused afterward. App surfaces use the object form ({ "app": \u2026 }) and are captured via the `ffmpeg` engine, cropped to the app window by default.',
362060
363220
  anyOf: [
362061
363221
  {
362062
363222
  title: "Surface (by browser engine)",
@@ -362206,6 +363366,72 @@ var init_schemas = __esm({
362206
363366
  ]
362207
363367
  }
362208
363368
  }
363369
+ },
363370
+ {
363371
+ title: "App surface",
363372
+ type: "object",
363373
+ additionalProperties: false,
363374
+ required: [
363375
+ "app"
363376
+ ],
363377
+ properties: {
363378
+ app: {
363379
+ type: "string",
363380
+ minLength: 1,
363381
+ pattern: "\\S",
363382
+ transform: [
363383
+ "trim"
363384
+ ],
363385
+ description: "Name of an app surface opened by `startSurface` (its `name`, or the default derived from the app identifier)."
363386
+ },
363387
+ window: {
363388
+ description: "Which app window to act on. Omit to use the active window. Apps have windows, no tabs.",
363389
+ title: "App window selector",
363390
+ anyOf: [
363391
+ {
363392
+ title: "By index",
363393
+ type: "integer",
363394
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest (e.g. a dialog the app just opened)."
363395
+ },
363396
+ {
363397
+ title: "By name",
363398
+ type: "string",
363399
+ minLength: 1,
363400
+ pattern: "\\S",
363401
+ transform: [
363402
+ "trim"
363403
+ ],
363404
+ description: "Assigned window name. The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
363405
+ },
363406
+ {
363407
+ title: "By criteria",
363408
+ type: "object",
363409
+ additionalProperties: false,
363410
+ minProperties: 1,
363411
+ properties: {
363412
+ name: {
363413
+ type: "string",
363414
+ minLength: 1,
363415
+ pattern: "\\S",
363416
+ transform: [
363417
+ "trim"
363418
+ ],
363419
+ description: "Assigned window name."
363420
+ },
363421
+ index: {
363422
+ type: "integer",
363423
+ description: "Index in creation order. Negative counts from the end."
363424
+ },
363425
+ title: {
363426
+ type: "string",
363427
+ minLength: 1,
363428
+ description: "Window title to match. Substring, or /regex/."
363429
+ }
363430
+ }
363431
+ }
363432
+ ]
363433
+ }
363434
+ }
362209
363435
  }
362210
363436
  ]
362211
363437
  },
@@ -362271,13 +363497,12 @@ var init_schemas = __esm({
362271
363497
  },
362272
363498
  target: {
362273
363499
  type: "string",
362274
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
363500
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
362275
363501
  enum: [
362276
363502
  "display",
362277
363503
  "window",
362278
363504
  "viewport"
362279
- ],
362280
- default: "display"
363505
+ ]
362281
363506
  },
362282
363507
  fps: {
362283
363508
  type: "integer",
@@ -362295,7 +363520,7 @@ var init_schemas = __esm({
362295
363520
  {
362296
363521
  type: "boolean",
362297
363522
  title: "Record (boolean)",
362298
- description: "If `true`, starts recording \u2014 auto-selecting the `browser` engine for a visible Chrome context and the `ffmpeg` engine otherwise. If `false`, doesn't record."
363523
+ description: "If `true`, starts recording \u2014 auto-selecting the `browser` engine for a visible Chrome context, the device screen on Android/iOS contexts, and the `ffmpeg` engine otherwise. If `false`, doesn't record."
362299
363524
  }
362300
363525
  ],
362301
363526
  components: {
@@ -362313,7 +363538,7 @@ var init_schemas = __esm({
362313
363538
  type: "object",
362314
363539
  properties: {
362315
363540
  surface: {
362316
- description: "The browser window/tab to record. Omit to record the active tab. The targeted tab stays focused afterward.",
363541
+ description: 'The browser window/tab or app window to record. Omit to record the active surface. The targeted surface stays focused afterward. App surfaces use the object form ({ "app": \u2026 }) and are captured via the `ffmpeg` engine, cropped to the app window by default.',
362317
363542
  anyOf: [
362318
363543
  {
362319
363544
  title: "Surface (by browser engine)",
@@ -362463,6 +363688,72 @@ var init_schemas = __esm({
362463
363688
  ]
362464
363689
  }
362465
363690
  }
363691
+ },
363692
+ {
363693
+ title: "App surface",
363694
+ type: "object",
363695
+ additionalProperties: false,
363696
+ required: [
363697
+ "app"
363698
+ ],
363699
+ properties: {
363700
+ app: {
363701
+ type: "string",
363702
+ minLength: 1,
363703
+ pattern: "\\S",
363704
+ transform: [
363705
+ "trim"
363706
+ ],
363707
+ description: "Name of an app surface opened by `startSurface` (its `name`, or the default derived from the app identifier)."
363708
+ },
363709
+ window: {
363710
+ description: "Which app window to act on. Omit to use the active window. Apps have windows, no tabs.",
363711
+ title: "App window selector",
363712
+ anyOf: [
363713
+ {
363714
+ title: "By index",
363715
+ type: "integer",
363716
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest (e.g. a dialog the app just opened)."
363717
+ },
363718
+ {
363719
+ title: "By name",
363720
+ type: "string",
363721
+ minLength: 1,
363722
+ pattern: "\\S",
363723
+ transform: [
363724
+ "trim"
363725
+ ],
363726
+ description: "Assigned window name. The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
363727
+ },
363728
+ {
363729
+ title: "By criteria",
363730
+ type: "object",
363731
+ additionalProperties: false,
363732
+ minProperties: 1,
363733
+ properties: {
363734
+ name: {
363735
+ type: "string",
363736
+ minLength: 1,
363737
+ pattern: "\\S",
363738
+ transform: [
363739
+ "trim"
363740
+ ],
363741
+ description: "Assigned window name."
363742
+ },
363743
+ index: {
363744
+ type: "integer",
363745
+ description: "Index in creation order. Negative counts from the end."
363746
+ },
363747
+ title: {
363748
+ type: "string",
363749
+ minLength: 1,
363750
+ description: "Window title to match. Substring, or /regex/."
363751
+ }
363752
+ }
363753
+ }
363754
+ ]
363755
+ }
363756
+ }
362466
363757
  }
362467
363758
  ]
362468
363759
  },
@@ -362528,13 +363819,12 @@ var init_schemas = __esm({
362528
363819
  },
362529
363820
  target: {
362530
363821
  type: "string",
362531
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
363822
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
362532
363823
  enum: [
362533
363824
  "display",
362534
363825
  "window",
362535
363826
  "viewport"
362536
- ],
362537
- default: "display"
363827
+ ]
362538
363828
  },
362539
363829
  fps: {
362540
363830
  type: "integer",
@@ -362580,13 +363870,12 @@ var init_schemas = __esm({
362580
363870
  },
362581
363871
  target: {
362582
363872
  type: "string",
362583
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
363873
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
362584
363874
  enum: [
362585
363875
  "display",
362586
363876
  "window",
362587
363877
  "viewport"
362588
- ],
362589
- default: "display"
363878
+ ]
362590
363879
  },
362591
363880
  fps: {
362592
363881
  type: "integer",
@@ -362619,6 +363908,22 @@ var init_schemas = __esm({
362619
363908
  target: "window",
362620
363909
  fps: 60
362621
363910
  }
363911
+ },
363912
+ {
363913
+ path: "notepad.mp4",
363914
+ surface: {
363915
+ app: "notepad"
363916
+ }
363917
+ },
363918
+ {
363919
+ path: "full-screen.mp4",
363920
+ surface: {
363921
+ app: "notepad"
363922
+ },
363923
+ engine: {
363924
+ name: "ffmpeg",
363925
+ target: "display"
363926
+ }
362622
363927
  }
362623
363928
  ]
362624
363929
  }
@@ -412096,7 +413401,7 @@ var init_schemas = __esm({
412096
413401
  record: {
412097
413402
  $schema: "http://json-schema.org/draft-07/schema#",
412098
413403
  title: "record",
412099
- description: "Start recording. Must be followed by a `stopRecord` step. The `browser` engine captures the Chrome viewport (works under concurrency); the `ffmpeg` engine captures the screen and supports any application. Supported extensions: [ '.mp4', '.webm', '.gif' ]",
413404
+ description: "Start recording. Must be followed by a `stopRecord` step. The `browser` engine captures the Chrome viewport (works under concurrency); the `ffmpeg` engine captures the screen and supports any application. On Android/iOS contexts, recording captures the device screen through the device itself \u2014 `engine` doesn't apply. Supported extensions: [ '.mp4', '.webm', '.gif' ]",
412100
413405
  anyOf: [
412101
413406
  {
412102
413407
  title: "Record (simple)",
@@ -412111,7 +413416,7 @@ var init_schemas = __esm({
412111
413416
  type: "object",
412112
413417
  properties: {
412113
413418
  surface: {
412114
- description: "The browser window/tab to record. Omit to record the active tab. The targeted tab stays focused afterward.",
413419
+ description: 'The browser window/tab or app window to record. Omit to record the active surface. The targeted surface stays focused afterward. App surfaces use the object form ({ "app": \u2026 }) and are captured via the `ffmpeg` engine, cropped to the app window by default.',
412115
413420
  anyOf: [
412116
413421
  {
412117
413422
  title: "Surface (by browser engine)",
@@ -412261,6 +413566,72 @@ var init_schemas = __esm({
412261
413566
  ]
412262
413567
  }
412263
413568
  }
413569
+ },
413570
+ {
413571
+ title: "App surface",
413572
+ type: "object",
413573
+ additionalProperties: false,
413574
+ required: [
413575
+ "app"
413576
+ ],
413577
+ properties: {
413578
+ app: {
413579
+ type: "string",
413580
+ minLength: 1,
413581
+ pattern: "\\S",
413582
+ transform: [
413583
+ "trim"
413584
+ ],
413585
+ description: "Name of an app surface opened by `startSurface` (its `name`, or the default derived from the app identifier)."
413586
+ },
413587
+ window: {
413588
+ description: "Which app window to act on. Omit to use the active window. Apps have windows, no tabs.",
413589
+ title: "App window selector",
413590
+ anyOf: [
413591
+ {
413592
+ title: "By index",
413593
+ type: "integer",
413594
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest (e.g. a dialog the app just opened)."
413595
+ },
413596
+ {
413597
+ title: "By name",
413598
+ type: "string",
413599
+ minLength: 1,
413600
+ pattern: "\\S",
413601
+ transform: [
413602
+ "trim"
413603
+ ],
413604
+ description: "Assigned window name. The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
413605
+ },
413606
+ {
413607
+ title: "By criteria",
413608
+ type: "object",
413609
+ additionalProperties: false,
413610
+ minProperties: 1,
413611
+ properties: {
413612
+ name: {
413613
+ type: "string",
413614
+ minLength: 1,
413615
+ pattern: "\\S",
413616
+ transform: [
413617
+ "trim"
413618
+ ],
413619
+ description: "Assigned window name."
413620
+ },
413621
+ index: {
413622
+ type: "integer",
413623
+ description: "Index in creation order. Negative counts from the end."
413624
+ },
413625
+ title: {
413626
+ type: "string",
413627
+ minLength: 1,
413628
+ description: "Window title to match. Substring, or /regex/."
413629
+ }
413630
+ }
413631
+ }
413632
+ ]
413633
+ }
413634
+ }
412264
413635
  }
412265
413636
  ]
412266
413637
  },
@@ -412326,13 +413697,12 @@ var init_schemas = __esm({
412326
413697
  },
412327
413698
  target: {
412328
413699
  type: "string",
412329
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
413700
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
412330
413701
  enum: [
412331
413702
  "display",
412332
413703
  "window",
412333
413704
  "viewport"
412334
- ],
412335
- default: "display"
413705
+ ]
412336
413706
  },
412337
413707
  fps: {
412338
413708
  type: "integer",
@@ -412350,7 +413720,7 @@ var init_schemas = __esm({
412350
413720
  {
412351
413721
  type: "boolean",
412352
413722
  title: "Record (boolean)",
412353
- description: "If `true`, starts recording \u2014 auto-selecting the `browser` engine for a visible Chrome context and the `ffmpeg` engine otherwise. If `false`, doesn't record."
413723
+ description: "If `true`, starts recording \u2014 auto-selecting the `browser` engine for a visible Chrome context, the device screen on Android/iOS contexts, and the `ffmpeg` engine otherwise. If `false`, doesn't record."
412354
413724
  }
412355
413725
  ],
412356
413726
  components: {
@@ -412368,7 +413738,7 @@ var init_schemas = __esm({
412368
413738
  type: "object",
412369
413739
  properties: {
412370
413740
  surface: {
412371
- description: "The browser window/tab to record. Omit to record the active tab. The targeted tab stays focused afterward.",
413741
+ description: 'The browser window/tab or app window to record. Omit to record the active surface. The targeted surface stays focused afterward. App surfaces use the object form ({ "app": \u2026 }) and are captured via the `ffmpeg` engine, cropped to the app window by default.',
412372
413742
  anyOf: [
412373
413743
  {
412374
413744
  title: "Surface (by browser engine)",
@@ -412465,14 +413835,85 @@ var init_schemas = __esm({
412465
413835
  }
412466
413836
  ]
412467
413837
  },
412468
- tab: {
412469
- description: "Which tab to act on. Omit to use the active tab. Without `window`, the selector searches every tab in creation order \u2014 including tabs the page opened itself.",
412470
- title: "Window/tab selector",
413838
+ tab: {
413839
+ description: "Which tab to act on. Omit to use the active tab. Without `window`, the selector searches every tab in creation order \u2014 including tabs the page opened itself.",
413840
+ title: "Window/tab selector",
413841
+ anyOf: [
413842
+ {
413843
+ title: "By index",
413844
+ type: "integer",
413845
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest."
413846
+ },
413847
+ {
413848
+ title: "By name",
413849
+ type: "string",
413850
+ minLength: 1,
413851
+ pattern: "\\S",
413852
+ transform: [
413853
+ "trim"
413854
+ ],
413855
+ description: "Name assigned when the window/tab was opened (goTo `newTab`/`newWindow`). The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
413856
+ },
413857
+ {
413858
+ title: "By criteria",
413859
+ type: "object",
413860
+ additionalProperties: false,
413861
+ minProperties: 1,
413862
+ properties: {
413863
+ name: {
413864
+ type: "string",
413865
+ minLength: 1,
413866
+ pattern: "\\S",
413867
+ transform: [
413868
+ "trim"
413869
+ ],
413870
+ description: "Name assigned when the window/tab was opened."
413871
+ },
413872
+ index: {
413873
+ type: "integer",
413874
+ description: "Index in creation order. Negative counts from the end."
413875
+ },
413876
+ title: {
413877
+ type: "string",
413878
+ minLength: 1,
413879
+ description: "Page title to match. Substring, or /regex/."
413880
+ },
413881
+ url: {
413882
+ type: "string",
413883
+ minLength: 1,
413884
+ description: "Page URL to match. Substring, or /regex/."
413885
+ }
413886
+ }
413887
+ }
413888
+ ]
413889
+ }
413890
+ }
413891
+ },
413892
+ {
413893
+ title: "App surface",
413894
+ type: "object",
413895
+ additionalProperties: false,
413896
+ required: [
413897
+ "app"
413898
+ ],
413899
+ properties: {
413900
+ app: {
413901
+ type: "string",
413902
+ minLength: 1,
413903
+ pattern: "\\S",
413904
+ transform: [
413905
+ "trim"
413906
+ ],
413907
+ description: "Name of an app surface opened by `startSurface` (its `name`, or the default derived from the app identifier)."
413908
+ },
413909
+ window: {
413910
+ description: "Which app window to act on. Omit to use the active window. Apps have windows, no tabs.",
413911
+ title: "App window selector",
412471
413912
  anyOf: [
412472
413913
  {
412473
413914
  title: "By index",
412474
413915
  type: "integer",
412475
- description: "Index in creation order. Negative counts from the end; `-1` is the newest."
413916
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest (e.g. a dialog the app just opened)."
412476
413917
  },
412477
413918
  {
412478
413919
  title: "By name",
@@ -412482,7 +413923,7 @@ var init_schemas = __esm({
412482
413923
  transform: [
412483
413924
  "trim"
412484
413925
  ],
412485
- description: "Name assigned when the window/tab was opened (goTo `newTab`/`newWindow`). The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
413926
+ description: "Assigned window name. The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
412486
413927
  },
412487
413928
  {
412488
413929
  title: "By criteria",
@@ -412497,7 +413938,7 @@ var init_schemas = __esm({
412497
413938
  transform: [
412498
413939
  "trim"
412499
413940
  ],
412500
- description: "Name assigned when the window/tab was opened."
413941
+ description: "Assigned window name."
412501
413942
  },
412502
413943
  index: {
412503
413944
  type: "integer",
@@ -412506,12 +413947,7 @@ var init_schemas = __esm({
412506
413947
  title: {
412507
413948
  type: "string",
412508
413949
  minLength: 1,
412509
- description: "Page title to match. Substring, or /regex/."
412510
- },
412511
- url: {
412512
- type: "string",
412513
- minLength: 1,
412514
- description: "Page URL to match. Substring, or /regex/."
413950
+ description: "Window title to match. Substring, or /regex/."
412515
413951
  }
412516
413952
  }
412517
413953
  }
@@ -412583,13 +414019,12 @@ var init_schemas = __esm({
412583
414019
  },
412584
414020
  target: {
412585
414021
  type: "string",
412586
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
414022
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
412587
414023
  enum: [
412588
414024
  "display",
412589
414025
  "window",
412590
414026
  "viewport"
412591
- ],
412592
- default: "display"
414027
+ ]
412593
414028
  },
412594
414029
  fps: {
412595
414030
  type: "integer",
@@ -412635,13 +414070,12 @@ var init_schemas = __esm({
412635
414070
  },
412636
414071
  target: {
412637
414072
  type: "string",
412638
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
414073
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
412639
414074
  enum: [
412640
414075
  "display",
412641
414076
  "window",
412642
414077
  "viewport"
412643
- ],
412644
- default: "display"
414078
+ ]
412645
414079
  },
412646
414080
  fps: {
412647
414081
  type: "integer",
@@ -412674,6 +414108,22 @@ var init_schemas = __esm({
412674
414108
  target: "window",
412675
414109
  fps: 60
412676
414110
  }
414111
+ },
414112
+ {
414113
+ path: "notepad.mp4",
414114
+ surface: {
414115
+ app: "notepad"
414116
+ }
414117
+ },
414118
+ {
414119
+ path: "full-screen.mp4",
414120
+ surface: {
414121
+ app: "notepad"
414122
+ },
414123
+ engine: {
414124
+ name: "ffmpeg",
414125
+ target: "display"
414126
+ }
412677
414127
  }
412678
414128
  ]
412679
414129
  }
@@ -455977,7 +457427,7 @@ var init_schemas = __esm({
455977
457427
  record: {
455978
457428
  $schema: "http://json-schema.org/draft-07/schema#",
455979
457429
  title: "record",
455980
- description: "Start recording. Must be followed by a `stopRecord` step. The `browser` engine captures the Chrome viewport (works under concurrency); the `ffmpeg` engine captures the screen and supports any application. Supported extensions: [ '.mp4', '.webm', '.gif' ]",
457430
+ description: "Start recording. Must be followed by a `stopRecord` step. The `browser` engine captures the Chrome viewport (works under concurrency); the `ffmpeg` engine captures the screen and supports any application. On Android/iOS contexts, recording captures the device screen through the device itself \u2014 `engine` doesn't apply. Supported extensions: [ '.mp4', '.webm', '.gif' ]",
455981
457431
  anyOf: [
455982
457432
  {
455983
457433
  title: "Record (simple)",
@@ -455992,7 +457442,7 @@ var init_schemas = __esm({
455992
457442
  type: "object",
455993
457443
  properties: {
455994
457444
  surface: {
455995
- description: "The browser window/tab to record. Omit to record the active tab. The targeted tab stays focused afterward.",
457445
+ description: 'The browser window/tab or app window to record. Omit to record the active surface. The targeted surface stays focused afterward. App surfaces use the object form ({ "app": \u2026 }) and are captured via the `ffmpeg` engine, cropped to the app window by default.',
455996
457446
  anyOf: [
455997
457447
  {
455998
457448
  title: "Surface (by browser engine)",
@@ -456142,6 +457592,72 @@ var init_schemas = __esm({
456142
457592
  ]
456143
457593
  }
456144
457594
  }
457595
+ },
457596
+ {
457597
+ title: "App surface",
457598
+ type: "object",
457599
+ additionalProperties: false,
457600
+ required: [
457601
+ "app"
457602
+ ],
457603
+ properties: {
457604
+ app: {
457605
+ type: "string",
457606
+ minLength: 1,
457607
+ pattern: "\\S",
457608
+ transform: [
457609
+ "trim"
457610
+ ],
457611
+ description: "Name of an app surface opened by `startSurface` (its `name`, or the default derived from the app identifier)."
457612
+ },
457613
+ window: {
457614
+ description: "Which app window to act on. Omit to use the active window. Apps have windows, no tabs.",
457615
+ title: "App window selector",
457616
+ anyOf: [
457617
+ {
457618
+ title: "By index",
457619
+ type: "integer",
457620
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest (e.g. a dialog the app just opened)."
457621
+ },
457622
+ {
457623
+ title: "By name",
457624
+ type: "string",
457625
+ minLength: 1,
457626
+ pattern: "\\S",
457627
+ transform: [
457628
+ "trim"
457629
+ ],
457630
+ description: "Assigned window name. The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
457631
+ },
457632
+ {
457633
+ title: "By criteria",
457634
+ type: "object",
457635
+ additionalProperties: false,
457636
+ minProperties: 1,
457637
+ properties: {
457638
+ name: {
457639
+ type: "string",
457640
+ minLength: 1,
457641
+ pattern: "\\S",
457642
+ transform: [
457643
+ "trim"
457644
+ ],
457645
+ description: "Assigned window name."
457646
+ },
457647
+ index: {
457648
+ type: "integer",
457649
+ description: "Index in creation order. Negative counts from the end."
457650
+ },
457651
+ title: {
457652
+ type: "string",
457653
+ minLength: 1,
457654
+ description: "Window title to match. Substring, or /regex/."
457655
+ }
457656
+ }
457657
+ }
457658
+ ]
457659
+ }
457660
+ }
456145
457661
  }
456146
457662
  ]
456147
457663
  },
@@ -456207,13 +457723,12 @@ var init_schemas = __esm({
456207
457723
  },
456208
457724
  target: {
456209
457725
  type: "string",
456210
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
457726
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
456211
457727
  enum: [
456212
457728
  "display",
456213
457729
  "window",
456214
457730
  "viewport"
456215
- ],
456216
- default: "display"
457731
+ ]
456217
457732
  },
456218
457733
  fps: {
456219
457734
  type: "integer",
@@ -456231,7 +457746,7 @@ var init_schemas = __esm({
456231
457746
  {
456232
457747
  type: "boolean",
456233
457748
  title: "Record (boolean)",
456234
- description: "If `true`, starts recording \u2014 auto-selecting the `browser` engine for a visible Chrome context and the `ffmpeg` engine otherwise. If `false`, doesn't record."
457749
+ description: "If `true`, starts recording \u2014 auto-selecting the `browser` engine for a visible Chrome context, the device screen on Android/iOS contexts, and the `ffmpeg` engine otherwise. If `false`, doesn't record."
456235
457750
  }
456236
457751
  ],
456237
457752
  components: {
@@ -456249,7 +457764,7 @@ var init_schemas = __esm({
456249
457764
  type: "object",
456250
457765
  properties: {
456251
457766
  surface: {
456252
- description: "The browser window/tab to record. Omit to record the active tab. The targeted tab stays focused afterward.",
457767
+ description: 'The browser window/tab or app window to record. Omit to record the active surface. The targeted surface stays focused afterward. App surfaces use the object form ({ "app": \u2026 }) and are captured via the `ffmpeg` engine, cropped to the app window by default.',
456253
457768
  anyOf: [
456254
457769
  {
456255
457770
  title: "Surface (by browser engine)",
@@ -456399,6 +457914,72 @@ var init_schemas = __esm({
456399
457914
  ]
456400
457915
  }
456401
457916
  }
457917
+ },
457918
+ {
457919
+ title: "App surface",
457920
+ type: "object",
457921
+ additionalProperties: false,
457922
+ required: [
457923
+ "app"
457924
+ ],
457925
+ properties: {
457926
+ app: {
457927
+ type: "string",
457928
+ minLength: 1,
457929
+ pattern: "\\S",
457930
+ transform: [
457931
+ "trim"
457932
+ ],
457933
+ description: "Name of an app surface opened by `startSurface` (its `name`, or the default derived from the app identifier)."
457934
+ },
457935
+ window: {
457936
+ description: "Which app window to act on. Omit to use the active window. Apps have windows, no tabs.",
457937
+ title: "App window selector",
457938
+ anyOf: [
457939
+ {
457940
+ title: "By index",
457941
+ type: "integer",
457942
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest (e.g. a dialog the app just opened)."
457943
+ },
457944
+ {
457945
+ title: "By name",
457946
+ type: "string",
457947
+ minLength: 1,
457948
+ pattern: "\\S",
457949
+ transform: [
457950
+ "trim"
457951
+ ],
457952
+ description: "Assigned window name. The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
457953
+ },
457954
+ {
457955
+ title: "By criteria",
457956
+ type: "object",
457957
+ additionalProperties: false,
457958
+ minProperties: 1,
457959
+ properties: {
457960
+ name: {
457961
+ type: "string",
457962
+ minLength: 1,
457963
+ pattern: "\\S",
457964
+ transform: [
457965
+ "trim"
457966
+ ],
457967
+ description: "Assigned window name."
457968
+ },
457969
+ index: {
457970
+ type: "integer",
457971
+ description: "Index in creation order. Negative counts from the end."
457972
+ },
457973
+ title: {
457974
+ type: "string",
457975
+ minLength: 1,
457976
+ description: "Window title to match. Substring, or /regex/."
457977
+ }
457978
+ }
457979
+ }
457980
+ ]
457981
+ }
457982
+ }
456402
457983
  }
456403
457984
  ]
456404
457985
  },
@@ -456464,13 +458045,12 @@ var init_schemas = __esm({
456464
458045
  },
456465
458046
  target: {
456466
458047
  type: "string",
456467
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
458048
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
456468
458049
  enum: [
456469
458050
  "display",
456470
458051
  "window",
456471
458052
  "viewport"
456472
- ],
456473
- default: "display"
458053
+ ]
456474
458054
  },
456475
458055
  fps: {
456476
458056
  type: "integer",
@@ -456516,13 +458096,12 @@ var init_schemas = __esm({
456516
458096
  },
456517
458097
  target: {
456518
458098
  type: "string",
456519
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
458099
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
456520
458100
  enum: [
456521
458101
  "display",
456522
458102
  "window",
456523
458103
  "viewport"
456524
- ],
456525
- default: "display"
458104
+ ]
456526
458105
  },
456527
458106
  fps: {
456528
458107
  type: "integer",
@@ -456555,6 +458134,22 @@ var init_schemas = __esm({
456555
458134
  target: "window",
456556
458135
  fps: 60
456557
458136
  }
458137
+ },
458138
+ {
458139
+ path: "notepad.mp4",
458140
+ surface: {
458141
+ app: "notepad"
458142
+ }
458143
+ },
458144
+ {
458145
+ path: "full-screen.mp4",
458146
+ surface: {
458147
+ app: "notepad"
458148
+ },
458149
+ engine: {
458150
+ name: "ffmpeg",
458151
+ target: "display"
458152
+ }
456558
458153
  }
456559
458154
  ]
456560
458155
  }
@@ -500744,7 +502339,7 @@ var init_schemas = __esm({
500744
502339
  record: {
500745
502340
  $schema: "http://json-schema.org/draft-07/schema#",
500746
502341
  title: "record",
500747
- description: "Start recording. Must be followed by a `stopRecord` step. The `browser` engine captures the Chrome viewport (works under concurrency); the `ffmpeg` engine captures the screen and supports any application. Supported extensions: [ '.mp4', '.webm', '.gif' ]",
502342
+ description: "Start recording. Must be followed by a `stopRecord` step. The `browser` engine captures the Chrome viewport (works under concurrency); the `ffmpeg` engine captures the screen and supports any application. On Android/iOS contexts, recording captures the device screen through the device itself \u2014 `engine` doesn't apply. Supported extensions: [ '.mp4', '.webm', '.gif' ]",
500748
502343
  anyOf: [
500749
502344
  {
500750
502345
  title: "Record (simple)",
@@ -500759,7 +502354,7 @@ var init_schemas = __esm({
500759
502354
  type: "object",
500760
502355
  properties: {
500761
502356
  surface: {
500762
- description: "The browser window/tab to record. Omit to record the active tab. The targeted tab stays focused afterward.",
502357
+ description: 'The browser window/tab or app window to record. Omit to record the active surface. The targeted surface stays focused afterward. App surfaces use the object form ({ "app": \u2026 }) and are captured via the `ffmpeg` engine, cropped to the app window by default.',
500763
502358
  anyOf: [
500764
502359
  {
500765
502360
  title: "Surface (by browser engine)",
@@ -500909,6 +502504,72 @@ var init_schemas = __esm({
500909
502504
  ]
500910
502505
  }
500911
502506
  }
502507
+ },
502508
+ {
502509
+ title: "App surface",
502510
+ type: "object",
502511
+ additionalProperties: false,
502512
+ required: [
502513
+ "app"
502514
+ ],
502515
+ properties: {
502516
+ app: {
502517
+ type: "string",
502518
+ minLength: 1,
502519
+ pattern: "\\S",
502520
+ transform: [
502521
+ "trim"
502522
+ ],
502523
+ description: "Name of an app surface opened by `startSurface` (its `name`, or the default derived from the app identifier)."
502524
+ },
502525
+ window: {
502526
+ description: "Which app window to act on. Omit to use the active window. Apps have windows, no tabs.",
502527
+ title: "App window selector",
502528
+ anyOf: [
502529
+ {
502530
+ title: "By index",
502531
+ type: "integer",
502532
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest (e.g. a dialog the app just opened)."
502533
+ },
502534
+ {
502535
+ title: "By name",
502536
+ type: "string",
502537
+ minLength: 1,
502538
+ pattern: "\\S",
502539
+ transform: [
502540
+ "trim"
502541
+ ],
502542
+ description: "Assigned window name. The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
502543
+ },
502544
+ {
502545
+ title: "By criteria",
502546
+ type: "object",
502547
+ additionalProperties: false,
502548
+ minProperties: 1,
502549
+ properties: {
502550
+ name: {
502551
+ type: "string",
502552
+ minLength: 1,
502553
+ pattern: "\\S",
502554
+ transform: [
502555
+ "trim"
502556
+ ],
502557
+ description: "Assigned window name."
502558
+ },
502559
+ index: {
502560
+ type: "integer",
502561
+ description: "Index in creation order. Negative counts from the end."
502562
+ },
502563
+ title: {
502564
+ type: "string",
502565
+ minLength: 1,
502566
+ description: "Window title to match. Substring, or /regex/."
502567
+ }
502568
+ }
502569
+ }
502570
+ ]
502571
+ }
502572
+ }
500912
502573
  }
500913
502574
  ]
500914
502575
  },
@@ -500974,13 +502635,12 @@ var init_schemas = __esm({
500974
502635
  },
500975
502636
  target: {
500976
502637
  type: "string",
500977
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
502638
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
500978
502639
  enum: [
500979
502640
  "display",
500980
502641
  "window",
500981
502642
  "viewport"
500982
- ],
500983
- default: "display"
502643
+ ]
500984
502644
  },
500985
502645
  fps: {
500986
502646
  type: "integer",
@@ -500998,7 +502658,7 @@ var init_schemas = __esm({
500998
502658
  {
500999
502659
  type: "boolean",
501000
502660
  title: "Record (boolean)",
501001
- description: "If `true`, starts recording \u2014 auto-selecting the `browser` engine for a visible Chrome context and the `ffmpeg` engine otherwise. If `false`, doesn't record."
502661
+ description: "If `true`, starts recording \u2014 auto-selecting the `browser` engine for a visible Chrome context, the device screen on Android/iOS contexts, and the `ffmpeg` engine otherwise. If `false`, doesn't record."
501002
502662
  }
501003
502663
  ],
501004
502664
  components: {
@@ -501016,7 +502676,7 @@ var init_schemas = __esm({
501016
502676
  type: "object",
501017
502677
  properties: {
501018
502678
  surface: {
501019
- description: "The browser window/tab to record. Omit to record the active tab. The targeted tab stays focused afterward.",
502679
+ description: 'The browser window/tab or app window to record. Omit to record the active surface. The targeted surface stays focused afterward. App surfaces use the object form ({ "app": \u2026 }) and are captured via the `ffmpeg` engine, cropped to the app window by default.',
501020
502680
  anyOf: [
501021
502681
  {
501022
502682
  title: "Surface (by browser engine)",
@@ -501166,6 +502826,72 @@ var init_schemas = __esm({
501166
502826
  ]
501167
502827
  }
501168
502828
  }
502829
+ },
502830
+ {
502831
+ title: "App surface",
502832
+ type: "object",
502833
+ additionalProperties: false,
502834
+ required: [
502835
+ "app"
502836
+ ],
502837
+ properties: {
502838
+ app: {
502839
+ type: "string",
502840
+ minLength: 1,
502841
+ pattern: "\\S",
502842
+ transform: [
502843
+ "trim"
502844
+ ],
502845
+ description: "Name of an app surface opened by `startSurface` (its `name`, or the default derived from the app identifier)."
502846
+ },
502847
+ window: {
502848
+ description: "Which app window to act on. Omit to use the active window. Apps have windows, no tabs.",
502849
+ title: "App window selector",
502850
+ anyOf: [
502851
+ {
502852
+ title: "By index",
502853
+ type: "integer",
502854
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest (e.g. a dialog the app just opened)."
502855
+ },
502856
+ {
502857
+ title: "By name",
502858
+ type: "string",
502859
+ minLength: 1,
502860
+ pattern: "\\S",
502861
+ transform: [
502862
+ "trim"
502863
+ ],
502864
+ description: "Assigned window name. The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
502865
+ },
502866
+ {
502867
+ title: "By criteria",
502868
+ type: "object",
502869
+ additionalProperties: false,
502870
+ minProperties: 1,
502871
+ properties: {
502872
+ name: {
502873
+ type: "string",
502874
+ minLength: 1,
502875
+ pattern: "\\S",
502876
+ transform: [
502877
+ "trim"
502878
+ ],
502879
+ description: "Assigned window name."
502880
+ },
502881
+ index: {
502882
+ type: "integer",
502883
+ description: "Index in creation order. Negative counts from the end."
502884
+ },
502885
+ title: {
502886
+ type: "string",
502887
+ minLength: 1,
502888
+ description: "Window title to match. Substring, or /regex/."
502889
+ }
502890
+ }
502891
+ }
502892
+ ]
502893
+ }
502894
+ }
501169
502895
  }
501170
502896
  ]
501171
502897
  },
@@ -501231,13 +502957,12 @@ var init_schemas = __esm({
501231
502957
  },
501232
502958
  target: {
501233
502959
  type: "string",
501234
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
502960
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
501235
502961
  enum: [
501236
502962
  "display",
501237
502963
  "window",
501238
502964
  "viewport"
501239
- ],
501240
- default: "display"
502965
+ ]
501241
502966
  },
501242
502967
  fps: {
501243
502968
  type: "integer",
@@ -501283,13 +503008,12 @@ var init_schemas = __esm({
501283
503008
  },
501284
503009
  target: {
501285
503010
  type: "string",
501286
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
503011
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
501287
503012
  enum: [
501288
503013
  "display",
501289
503014
  "window",
501290
503015
  "viewport"
501291
- ],
501292
- default: "display"
503016
+ ]
501293
503017
  },
501294
503018
  fps: {
501295
503019
  type: "integer",
@@ -501322,6 +503046,22 @@ var init_schemas = __esm({
501322
503046
  target: "window",
501323
503047
  fps: 60
501324
503048
  }
503049
+ },
503050
+ {
503051
+ path: "notepad.mp4",
503052
+ surface: {
503053
+ app: "notepad"
503054
+ }
503055
+ },
503056
+ {
503057
+ path: "full-screen.mp4",
503058
+ surface: {
503059
+ app: "notepad"
503060
+ },
503061
+ engine: {
503062
+ name: "ffmpeg",
503063
+ target: "display"
503064
+ }
501325
503065
  }
501326
503066
  ]
501327
503067
  }
@@ -547966,7 +549706,7 @@ var init_schemas = __esm({
547966
549706
  record: {
547967
549707
  $schema: "http://json-schema.org/draft-07/schema#",
547968
549708
  title: "record",
547969
- description: "Start recording. Must be followed by a `stopRecord` step. The `browser` engine captures the Chrome viewport (works under concurrency); the `ffmpeg` engine captures the screen and supports any application. Supported extensions: [ '.mp4', '.webm', '.gif' ]",
549709
+ description: "Start recording. Must be followed by a `stopRecord` step. The `browser` engine captures the Chrome viewport (works under concurrency); the `ffmpeg` engine captures the screen and supports any application. On Android/iOS contexts, recording captures the device screen through the device itself \u2014 `engine` doesn't apply. Supported extensions: [ '.mp4', '.webm', '.gif' ]",
547970
549710
  anyOf: [
547971
549711
  {
547972
549712
  title: "Record (simple)",
@@ -547981,7 +549721,7 @@ var init_schemas = __esm({
547981
549721
  type: "object",
547982
549722
  properties: {
547983
549723
  surface: {
547984
- description: "The browser window/tab to record. Omit to record the active tab. The targeted tab stays focused afterward.",
549724
+ description: 'The browser window/tab or app window to record. Omit to record the active surface. The targeted surface stays focused afterward. App surfaces use the object form ({ "app": \u2026 }) and are captured via the `ffmpeg` engine, cropped to the app window by default.',
547985
549725
  anyOf: [
547986
549726
  {
547987
549727
  title: "Surface (by browser engine)",
@@ -548131,6 +549871,72 @@ var init_schemas = __esm({
548131
549871
  ]
548132
549872
  }
548133
549873
  }
549874
+ },
549875
+ {
549876
+ title: "App surface",
549877
+ type: "object",
549878
+ additionalProperties: false,
549879
+ required: [
549880
+ "app"
549881
+ ],
549882
+ properties: {
549883
+ app: {
549884
+ type: "string",
549885
+ minLength: 1,
549886
+ pattern: "\\S",
549887
+ transform: [
549888
+ "trim"
549889
+ ],
549890
+ description: "Name of an app surface opened by `startSurface` (its `name`, or the default derived from the app identifier)."
549891
+ },
549892
+ window: {
549893
+ description: "Which app window to act on. Omit to use the active window. Apps have windows, no tabs.",
549894
+ title: "App window selector",
549895
+ anyOf: [
549896
+ {
549897
+ title: "By index",
549898
+ type: "integer",
549899
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest (e.g. a dialog the app just opened)."
549900
+ },
549901
+ {
549902
+ title: "By name",
549903
+ type: "string",
549904
+ minLength: 1,
549905
+ pattern: "\\S",
549906
+ transform: [
549907
+ "trim"
549908
+ ],
549909
+ description: "Assigned window name. The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
549910
+ },
549911
+ {
549912
+ title: "By criteria",
549913
+ type: "object",
549914
+ additionalProperties: false,
549915
+ minProperties: 1,
549916
+ properties: {
549917
+ name: {
549918
+ type: "string",
549919
+ minLength: 1,
549920
+ pattern: "\\S",
549921
+ transform: [
549922
+ "trim"
549923
+ ],
549924
+ description: "Assigned window name."
549925
+ },
549926
+ index: {
549927
+ type: "integer",
549928
+ description: "Index in creation order. Negative counts from the end."
549929
+ },
549930
+ title: {
549931
+ type: "string",
549932
+ minLength: 1,
549933
+ description: "Window title to match. Substring, or /regex/."
549934
+ }
549935
+ }
549936
+ }
549937
+ ]
549938
+ }
549939
+ }
548134
549940
  }
548135
549941
  ]
548136
549942
  },
@@ -548196,13 +550002,12 @@ var init_schemas = __esm({
548196
550002
  },
548197
550003
  target: {
548198
550004
  type: "string",
548199
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
550005
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
548200
550006
  enum: [
548201
550007
  "display",
548202
550008
  "window",
548203
550009
  "viewport"
548204
- ],
548205
- default: "display"
550010
+ ]
548206
550011
  },
548207
550012
  fps: {
548208
550013
  type: "integer",
@@ -548220,7 +550025,7 @@ var init_schemas = __esm({
548220
550025
  {
548221
550026
  type: "boolean",
548222
550027
  title: "Record (boolean)",
548223
- description: "If `true`, starts recording \u2014 auto-selecting the `browser` engine for a visible Chrome context and the `ffmpeg` engine otherwise. If `false`, doesn't record."
550028
+ description: "If `true`, starts recording \u2014 auto-selecting the `browser` engine for a visible Chrome context, the device screen on Android/iOS contexts, and the `ffmpeg` engine otherwise. If `false`, doesn't record."
548224
550029
  }
548225
550030
  ],
548226
550031
  components: {
@@ -548238,7 +550043,7 @@ var init_schemas = __esm({
548238
550043
  type: "object",
548239
550044
  properties: {
548240
550045
  surface: {
548241
- description: "The browser window/tab to record. Omit to record the active tab. The targeted tab stays focused afterward.",
550046
+ description: 'The browser window/tab or app window to record. Omit to record the active surface. The targeted surface stays focused afterward. App surfaces use the object form ({ "app": \u2026 }) and are captured via the `ffmpeg` engine, cropped to the app window by default.',
548242
550047
  anyOf: [
548243
550048
  {
548244
550049
  title: "Surface (by browser engine)",
@@ -548388,6 +550193,72 @@ var init_schemas = __esm({
548388
550193
  ]
548389
550194
  }
548390
550195
  }
550196
+ },
550197
+ {
550198
+ title: "App surface",
550199
+ type: "object",
550200
+ additionalProperties: false,
550201
+ required: [
550202
+ "app"
550203
+ ],
550204
+ properties: {
550205
+ app: {
550206
+ type: "string",
550207
+ minLength: 1,
550208
+ pattern: "\\S",
550209
+ transform: [
550210
+ "trim"
550211
+ ],
550212
+ description: "Name of an app surface opened by `startSurface` (its `name`, or the default derived from the app identifier)."
550213
+ },
550214
+ window: {
550215
+ description: "Which app window to act on. Omit to use the active window. Apps have windows, no tabs.",
550216
+ title: "App window selector",
550217
+ anyOf: [
550218
+ {
550219
+ title: "By index",
550220
+ type: "integer",
550221
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest (e.g. a dialog the app just opened)."
550222
+ },
550223
+ {
550224
+ title: "By name",
550225
+ type: "string",
550226
+ minLength: 1,
550227
+ pattern: "\\S",
550228
+ transform: [
550229
+ "trim"
550230
+ ],
550231
+ description: "Assigned window name. The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
550232
+ },
550233
+ {
550234
+ title: "By criteria",
550235
+ type: "object",
550236
+ additionalProperties: false,
550237
+ minProperties: 1,
550238
+ properties: {
550239
+ name: {
550240
+ type: "string",
550241
+ minLength: 1,
550242
+ pattern: "\\S",
550243
+ transform: [
550244
+ "trim"
550245
+ ],
550246
+ description: "Assigned window name."
550247
+ },
550248
+ index: {
550249
+ type: "integer",
550250
+ description: "Index in creation order. Negative counts from the end."
550251
+ },
550252
+ title: {
550253
+ type: "string",
550254
+ minLength: 1,
550255
+ description: "Window title to match. Substring, or /regex/."
550256
+ }
550257
+ }
550258
+ }
550259
+ ]
550260
+ }
550261
+ }
548391
550262
  }
548392
550263
  ]
548393
550264
  },
@@ -548453,13 +550324,12 @@ var init_schemas = __esm({
548453
550324
  },
548454
550325
  target: {
548455
550326
  type: "string",
548456
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
550327
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
548457
550328
  enum: [
548458
550329
  "display",
548459
550330
  "window",
548460
550331
  "viewport"
548461
- ],
548462
- default: "display"
550332
+ ]
548463
550333
  },
548464
550334
  fps: {
548465
550335
  type: "integer",
@@ -548505,13 +550375,12 @@ var init_schemas = __esm({
548505
550375
  },
548506
550376
  target: {
548507
550377
  type: "string",
548508
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
550378
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
548509
550379
  enum: [
548510
550380
  "display",
548511
550381
  "window",
548512
550382
  "viewport"
548513
- ],
548514
- default: "display"
550383
+ ]
548515
550384
  },
548516
550385
  fps: {
548517
550386
  type: "integer",
@@ -548544,6 +550413,22 @@ var init_schemas = __esm({
548544
550413
  target: "window",
548545
550414
  fps: 60
548546
550415
  }
550416
+ },
550417
+ {
550418
+ path: "notepad.mp4",
550419
+ surface: {
550420
+ app: "notepad"
550421
+ }
550422
+ },
550423
+ {
550424
+ path: "full-screen.mp4",
550425
+ surface: {
550426
+ app: "notepad"
550427
+ },
550428
+ engine: {
550429
+ name: "ffmpeg",
550430
+ target: "display"
550431
+ }
548547
550432
  }
548548
550433
  ]
548549
550434
  }
@@ -591847,7 +593732,7 @@ var init_schemas = __esm({
591847
593732
  record: {
591848
593733
  $schema: "http://json-schema.org/draft-07/schema#",
591849
593734
  title: "record",
591850
- description: "Start recording. Must be followed by a `stopRecord` step. The `browser` engine captures the Chrome viewport (works under concurrency); the `ffmpeg` engine captures the screen and supports any application. Supported extensions: [ '.mp4', '.webm', '.gif' ]",
593735
+ description: "Start recording. Must be followed by a `stopRecord` step. The `browser` engine captures the Chrome viewport (works under concurrency); the `ffmpeg` engine captures the screen and supports any application. On Android/iOS contexts, recording captures the device screen through the device itself \u2014 `engine` doesn't apply. Supported extensions: [ '.mp4', '.webm', '.gif' ]",
591851
593736
  anyOf: [
591852
593737
  {
591853
593738
  title: "Record (simple)",
@@ -591862,7 +593747,7 @@ var init_schemas = __esm({
591862
593747
  type: "object",
591863
593748
  properties: {
591864
593749
  surface: {
591865
- description: "The browser window/tab to record. Omit to record the active tab. The targeted tab stays focused afterward.",
593750
+ description: 'The browser window/tab or app window to record. Omit to record the active surface. The targeted surface stays focused afterward. App surfaces use the object form ({ "app": \u2026 }) and are captured via the `ffmpeg` engine, cropped to the app window by default.',
591866
593751
  anyOf: [
591867
593752
  {
591868
593753
  title: "Surface (by browser engine)",
@@ -591959,14 +593844,85 @@ var init_schemas = __esm({
591959
593844
  }
591960
593845
  ]
591961
593846
  },
591962
- tab: {
591963
- description: "Which tab to act on. Omit to use the active tab. Without `window`, the selector searches every tab in creation order \u2014 including tabs the page opened itself.",
591964
- title: "Window/tab selector",
593847
+ tab: {
593848
+ description: "Which tab to act on. Omit to use the active tab. Without `window`, the selector searches every tab in creation order \u2014 including tabs the page opened itself.",
593849
+ title: "Window/tab selector",
593850
+ anyOf: [
593851
+ {
593852
+ title: "By index",
593853
+ type: "integer",
593854
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest."
593855
+ },
593856
+ {
593857
+ title: "By name",
593858
+ type: "string",
593859
+ minLength: 1,
593860
+ pattern: "\\S",
593861
+ transform: [
593862
+ "trim"
593863
+ ],
593864
+ description: "Name assigned when the window/tab was opened (goTo `newTab`/`newWindow`). The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
593865
+ },
593866
+ {
593867
+ title: "By criteria",
593868
+ type: "object",
593869
+ additionalProperties: false,
593870
+ minProperties: 1,
593871
+ properties: {
593872
+ name: {
593873
+ type: "string",
593874
+ minLength: 1,
593875
+ pattern: "\\S",
593876
+ transform: [
593877
+ "trim"
593878
+ ],
593879
+ description: "Name assigned when the window/tab was opened."
593880
+ },
593881
+ index: {
593882
+ type: "integer",
593883
+ description: "Index in creation order. Negative counts from the end."
593884
+ },
593885
+ title: {
593886
+ type: "string",
593887
+ minLength: 1,
593888
+ description: "Page title to match. Substring, or /regex/."
593889
+ },
593890
+ url: {
593891
+ type: "string",
593892
+ minLength: 1,
593893
+ description: "Page URL to match. Substring, or /regex/."
593894
+ }
593895
+ }
593896
+ }
593897
+ ]
593898
+ }
593899
+ }
593900
+ },
593901
+ {
593902
+ title: "App surface",
593903
+ type: "object",
593904
+ additionalProperties: false,
593905
+ required: [
593906
+ "app"
593907
+ ],
593908
+ properties: {
593909
+ app: {
593910
+ type: "string",
593911
+ minLength: 1,
593912
+ pattern: "\\S",
593913
+ transform: [
593914
+ "trim"
593915
+ ],
593916
+ description: "Name of an app surface opened by `startSurface` (its `name`, or the default derived from the app identifier)."
593917
+ },
593918
+ window: {
593919
+ description: "Which app window to act on. Omit to use the active window. Apps have windows, no tabs.",
593920
+ title: "App window selector",
591965
593921
  anyOf: [
591966
593922
  {
591967
593923
  title: "By index",
591968
593924
  type: "integer",
591969
- description: "Index in creation order. Negative counts from the end; `-1` is the newest."
593925
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest (e.g. a dialog the app just opened)."
591970
593926
  },
591971
593927
  {
591972
593928
  title: "By name",
@@ -591976,7 +593932,7 @@ var init_schemas = __esm({
591976
593932
  transform: [
591977
593933
  "trim"
591978
593934
  ],
591979
- description: "Name assigned when the window/tab was opened (goTo `newTab`/`newWindow`). The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
593935
+ description: "Assigned window name. The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
591980
593936
  },
591981
593937
  {
591982
593938
  title: "By criteria",
@@ -591991,7 +593947,7 @@ var init_schemas = __esm({
591991
593947
  transform: [
591992
593948
  "trim"
591993
593949
  ],
591994
- description: "Name assigned when the window/tab was opened."
593950
+ description: "Assigned window name."
591995
593951
  },
591996
593952
  index: {
591997
593953
  type: "integer",
@@ -592000,12 +593956,7 @@ var init_schemas = __esm({
592000
593956
  title: {
592001
593957
  type: "string",
592002
593958
  minLength: 1,
592003
- description: "Page title to match. Substring, or /regex/."
592004
- },
592005
- url: {
592006
- type: "string",
592007
- minLength: 1,
592008
- description: "Page URL to match. Substring, or /regex/."
593959
+ description: "Window title to match. Substring, or /regex/."
592009
593960
  }
592010
593961
  }
592011
593962
  }
@@ -592077,13 +594028,12 @@ var init_schemas = __esm({
592077
594028
  },
592078
594029
  target: {
592079
594030
  type: "string",
592080
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
594031
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
592081
594032
  enum: [
592082
594033
  "display",
592083
594034
  "window",
592084
594035
  "viewport"
592085
- ],
592086
- default: "display"
594036
+ ]
592087
594037
  },
592088
594038
  fps: {
592089
594039
  type: "integer",
@@ -592101,7 +594051,7 @@ var init_schemas = __esm({
592101
594051
  {
592102
594052
  type: "boolean",
592103
594053
  title: "Record (boolean)",
592104
- description: "If `true`, starts recording \u2014 auto-selecting the `browser` engine for a visible Chrome context and the `ffmpeg` engine otherwise. If `false`, doesn't record."
594054
+ description: "If `true`, starts recording \u2014 auto-selecting the `browser` engine for a visible Chrome context, the device screen on Android/iOS contexts, and the `ffmpeg` engine otherwise. If `false`, doesn't record."
592105
594055
  }
592106
594056
  ],
592107
594057
  components: {
@@ -592119,7 +594069,7 @@ var init_schemas = __esm({
592119
594069
  type: "object",
592120
594070
  properties: {
592121
594071
  surface: {
592122
- description: "The browser window/tab to record. Omit to record the active tab. The targeted tab stays focused afterward.",
594072
+ description: 'The browser window/tab or app window to record. Omit to record the active surface. The targeted surface stays focused afterward. App surfaces use the object form ({ "app": \u2026 }) and are captured via the `ffmpeg` engine, cropped to the app window by default.',
592123
594073
  anyOf: [
592124
594074
  {
592125
594075
  title: "Surface (by browser engine)",
@@ -592269,6 +594219,72 @@ var init_schemas = __esm({
592269
594219
  ]
592270
594220
  }
592271
594221
  }
594222
+ },
594223
+ {
594224
+ title: "App surface",
594225
+ type: "object",
594226
+ additionalProperties: false,
594227
+ required: [
594228
+ "app"
594229
+ ],
594230
+ properties: {
594231
+ app: {
594232
+ type: "string",
594233
+ minLength: 1,
594234
+ pattern: "\\S",
594235
+ transform: [
594236
+ "trim"
594237
+ ],
594238
+ description: "Name of an app surface opened by `startSurface` (its `name`, or the default derived from the app identifier)."
594239
+ },
594240
+ window: {
594241
+ description: "Which app window to act on. Omit to use the active window. Apps have windows, no tabs.",
594242
+ title: "App window selector",
594243
+ anyOf: [
594244
+ {
594245
+ title: "By index",
594246
+ type: "integer",
594247
+ description: "Index in creation order. Negative counts from the end; `-1` is the newest (e.g. a dialog the app just opened)."
594248
+ },
594249
+ {
594250
+ title: "By name",
594251
+ type: "string",
594252
+ minLength: 1,
594253
+ pattern: "\\S",
594254
+ transform: [
594255
+ "trim"
594256
+ ],
594257
+ description: "Assigned window name. The integer branch is listed first because Ajv validates with coerceTypes \u2014 string-first would coerce integer indexes into name strings."
594258
+ },
594259
+ {
594260
+ title: "By criteria",
594261
+ type: "object",
594262
+ additionalProperties: false,
594263
+ minProperties: 1,
594264
+ properties: {
594265
+ name: {
594266
+ type: "string",
594267
+ minLength: 1,
594268
+ pattern: "\\S",
594269
+ transform: [
594270
+ "trim"
594271
+ ],
594272
+ description: "Assigned window name."
594273
+ },
594274
+ index: {
594275
+ type: "integer",
594276
+ description: "Index in creation order. Negative counts from the end."
594277
+ },
594278
+ title: {
594279
+ type: "string",
594280
+ minLength: 1,
594281
+ description: "Window title to match. Substring, or /regex/."
594282
+ }
594283
+ }
594284
+ }
594285
+ ]
594286
+ }
594287
+ }
592272
594288
  }
592273
594289
  ]
592274
594290
  },
@@ -592334,13 +594350,12 @@ var init_schemas = __esm({
592334
594350
  },
592335
594351
  target: {
592336
594352
  type: "string",
592337
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
594353
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
592338
594354
  enum: [
592339
594355
  "display",
592340
594356
  "window",
592341
594357
  "viewport"
592342
- ],
592343
- default: "display"
594358
+ ]
592344
594359
  },
592345
594360
  fps: {
592346
594361
  type: "integer",
@@ -592386,13 +594401,12 @@ var init_schemas = __esm({
592386
594401
  },
592387
594402
  target: {
592388
594403
  type: "string",
592389
- description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped).",
594404
+ description: "What the `ffmpeg` engine captures. `display` records the full screen, `window` the active window, `viewport` the browser content area. Ignored by the `browser` engine, which always captures its tab. `window` and `viewport` are best-effort (captured full-screen, then cropped). If unset, defaults to `window` when the recording's `surface` is an app surface and to `display` otherwise. `viewport` doesn't apply to app surfaces (they have no browser viewport).",
592390
594405
  enum: [
592391
594406
  "display",
592392
594407
  "window",
592393
594408
  "viewport"
592394
- ],
592395
- default: "display"
594409
+ ]
592396
594410
  },
592397
594411
  fps: {
592398
594412
  type: "integer",
@@ -592425,6 +594439,22 @@ var init_schemas = __esm({
592425
594439
  target: "window",
592426
594440
  fps: 60
592427
594441
  }
594442
+ },
594443
+ {
594444
+ path: "notepad.mp4",
594445
+ surface: {
594446
+ app: "notepad"
594447
+ }
594448
+ },
594449
+ {
594450
+ path: "full-screen.mp4",
594451
+ surface: {
594452
+ app: "notepad"
594453
+ },
594454
+ engine: {
594455
+ name: "ffmpeg",
594456
+ target: "display"
594457
+ }
592428
594458
  }
592429
594459
  ]
592430
594460
  }
@@ -624012,7 +626042,7 @@ var import_node_fs26 = __toESM(require("node:fs"), 1);
624012
626042
  init_loader();
624013
626043
  init_browsers();
624014
626044
  init_browserStepKeys();
624015
- var import_node_os10 = __toESM(require("node:os"), 1);
626045
+ var import_node_os11 = __toESM(require("node:os"), 1);
624016
626046
  init_utils();
624017
626047
  var import_axios6 = __toESM(require("axios"), 1);
624018
626048
 
@@ -624795,16 +626825,28 @@ function engineFields(record) {
624795
626825
  return { name: engine.name, target: engine.target, fps: engine.fps };
624796
626826
  return {};
624797
626827
  }
626828
+ function recordSurfaceApp(record) {
626829
+ const surface = record && typeof record === "object" ? record.surface : void 0;
626830
+ if (surface && typeof surface === "object" && typeof surface.app === "string" && surface.app.trim().length > 0) {
626831
+ return surface.app.trim();
626832
+ }
626833
+ return void 0;
626834
+ }
624798
626835
  function resolveRecordPlan({ step, context }) {
624799
626836
  const { name, target, fps } = engineFields(step?.record);
626837
+ const appSurface = recordSurfaceApp(step?.record);
624800
626838
  let engineName = name;
624801
626839
  if (!engineName) {
624802
- const b = context?.browser;
624803
- engineName = b?.name === "chrome" && b?.headless === false ? "browser" : "ffmpeg";
626840
+ if (isMobileTargetPlatform(context?.platform)) {
626841
+ engineName = "device";
626842
+ } else {
626843
+ const b = context?.browser;
626844
+ engineName = b?.name === "chrome" && b?.headless === false && !appSurface ? "browser" : "ffmpeg";
626845
+ }
624804
626846
  }
624805
626847
  return {
624806
626848
  name: engineName,
624807
- target: target || "display",
626849
+ target: target || (appSurface ? "window" : "display"),
624808
626850
  fps: fps ?? 30
624809
626851
  };
624810
626852
  }
@@ -624813,12 +626855,16 @@ function hasRecordStepWithoutEngine(context) {
624813
626855
  return steps.some((s) => {
624814
626856
  if (!s?.record)
624815
626857
  return false;
626858
+ if (recordSurfaceApp(s.record))
626859
+ return false;
624816
626860
  return engineFields(s.record).name === void 0;
624817
626861
  });
624818
626862
  }
624819
626863
  function coerceRecordContextBrowser({ context, availableApps }) {
624820
626864
  if (context?.browser)
624821
626865
  return null;
626866
+ if (isMobileTargetPlatform(context?.platform))
626867
+ return null;
624822
626868
  if (!hasRecordStepWithoutEngine(context))
624823
626869
  return null;
624824
626870
  const chromeAvailable = Array.isArray(availableApps) && availableApps.some((a) => a?.name === "chrome");
@@ -624907,8 +626953,66 @@ async function resolveCropGeometry({ driver, target }) {
624907
626953
  }
624908
626954
  return null;
624909
626955
  }
626956
+ async function resolveAppWindowRect(driver) {
626957
+ const r = await driver.getWindowRect();
626958
+ const finite = (v) => typeof v === "number" && Number.isFinite(v);
626959
+ if (!r || !finite(r.x) || !finite(r.y) || !finite(r.width) || !finite(r.height) || r.width <= 0 || r.height <= 0) {
626960
+ return null;
626961
+ }
626962
+ return { x: r.x, y: r.y, w: r.width, h: r.height };
626963
+ }
626964
+ function ffmpegPathEnv(ffmpegPath, baseEnv = process.env) {
626965
+ const dir = import_node_path11.default.dirname(ffmpegPath);
626966
+ const pathKey = Object.keys(baseEnv).find((k) => k.toUpperCase() === "PATH") ?? "PATH";
626967
+ const existing = baseEnv[pathKey];
626968
+ return {
626969
+ [pathKey]: existing ? `${dir}${import_node_path11.default.delimiter}${existing}` : dir
626970
+ };
626971
+ }
626972
+ function parseCaptureFrameSize(stderr) {
626973
+ const m = /Stream #\d+:\d+.*?Video:.*?\b(\d{3,5})x(\d{3,5})\b/.exec(stderr ?? "");
626974
+ if (!m)
626975
+ return null;
626976
+ return { w: Number(m[1]), h: Number(m[2]) };
626977
+ }
626978
+ function deriveCropScale({ platform, frameSize, displayPointSize }) {
626979
+ if (platform !== "darwin")
626980
+ return 1;
626981
+ if (!frameSize?.w || !displayPointSize?.w)
626982
+ return 1;
626983
+ const raw = frameSize.w / displayPointSize.w;
626984
+ if (!Number.isFinite(raw) || raw <= 0)
626985
+ return 1;
626986
+ const clamped = Math.min(4, Math.max(1, raw));
626987
+ return Math.round(clamped * 100) / 100;
626988
+ }
626989
+ async function detectDisplayPointSize() {
626990
+ if (process.platform !== "darwin")
626991
+ return null;
626992
+ return await new Promise((resolve) => {
626993
+ (0, import_node_child_process5.execFile)("osascript", [
626994
+ "-l",
626995
+ "JavaScript",
626996
+ "-e",
626997
+ "ObjC.import('AppKit'); const s = $.NSScreen.mainScreen.frame.size; JSON.stringify({w: s.width, h: s.height});"
626998
+ ], { timeout: 5e3 }, (error, stdout) => {
626999
+ if (error)
627000
+ return resolve(null);
627001
+ try {
627002
+ const parsed = JSON.parse(String(stdout).trim());
627003
+ if (typeof parsed?.w === "number" && parsed.w > 0 && typeof parsed?.h === "number" && parsed.h > 0) {
627004
+ return resolve({ w: parsed.w, h: parsed.h });
627005
+ }
627006
+ } catch {
627007
+ }
627008
+ resolve(null);
627009
+ });
627010
+ });
627011
+ }
624910
627012
  function jobIsFfmpegRecording(job) {
624911
627013
  const context = job?.context;
627014
+ if (isMobileTargetPlatform(context?.platform))
627015
+ return false;
624912
627016
  const steps = Array.isArray(context?.steps) ? context.steps : [];
624913
627017
  const activeBrowser = [];
624914
627018
  for (const s of steps) {
@@ -624978,6 +627082,8 @@ function contextHasRouting(context) {
624978
627082
  return steps.some((s) => stepHasRouting(s));
624979
627083
  }
624980
627084
  function contextHasAnyFfmpegRecordStep(context) {
627085
+ if (isMobileTargetPlatform(context?.platform))
627086
+ return false;
624981
627087
  const steps = Array.isArray(context?.steps) ? context.steps : [];
624982
627088
  let browserRecords = 0;
624983
627089
  for (const s of steps) {
@@ -625269,9 +627375,9 @@ function hostAbi(arch = process.arch) {
625269
627375
  }
625270
627376
  var JRE_FEATURE_VERSION = "17";
625271
627377
  function jreDownloadUrl(platform = process.platform, arch = process.arch) {
625272
- const os12 = platform === "win32" ? "windows" : platform === "darwin" ? "mac" : "linux";
627378
+ const os13 = platform === "win32" ? "windows" : platform === "darwin" ? "mac" : "linux";
625273
627379
  const adoptiumArch = arch === "arm64" ? "aarch64" : "x64";
625274
- return `https://api.adoptium.net/v3/binary/latest/${JRE_FEATURE_VERSION}/ga/${os12}/${adoptiumArch}/jre/hotspot/normal/eclipse`;
627380
+ return `https://api.adoptium.net/v3/binary/latest/${JRE_FEATURE_VERSION}/ga/${os13}/${adoptiumArch}/jre/hotspot/normal/eclipse`;
625275
627381
  }
625276
627382
  function jreArchiveFilename(platform = process.platform) {
625277
627383
  return platform === "win32" ? "jre.zip" : "jre.tar.gz";
@@ -627317,13 +629423,37 @@ async function startAppSurface({ config, step, appSession, platform, serverDeps
627317
629423
  deviceName
627318
629424
  });
627319
629425
  appSession.activeApp = name;
627320
- const pendingHandles = (appSession.recordingHost?.state?.recordings ?? []).filter((handle) => handle?.pendingAppWindowCrop && !handle.crop);
627321
- for (const handle of pendingHandles) {
627322
- try {
627323
- handle.crop = await resolveCropGeometry({ driver, target: "window" });
627324
- handle.pendingAppWindowCrop = false;
627325
- } catch (error) {
627326
- log(config, "warning", `Couldn't resolve the app window geometry for the active recording; it stays full-display. ${error?.message ?? error}`);
629426
+ if (!isMobileTargetPlatform(platform)) {
629427
+ const pendingHandles = (appSession.recordingHost?.state?.recordings ?? []).filter((handle) => handle?.pendingAppWindowCrop && !handle.crop && !handle.cropRect);
629428
+ for (const handle of pendingHandles) {
629429
+ try {
629430
+ const rect = await resolveAppWindowRect(driver);
629431
+ if (rect) {
629432
+ handle.cropRect = rect;
629433
+ handle.cropPendingScale = true;
629434
+ } else {
629435
+ log(config, "warning", "Couldn't resolve the app window geometry for the active recording (malformed window rect); it stays full-display.");
629436
+ }
629437
+ handle.pendingAppWindowCrop = false;
629438
+ } catch (error) {
629439
+ log(config, "warning", `Couldn't resolve the app window geometry for the active recording; it stays full-display. ${error?.message ?? error}`);
629440
+ }
629441
+ }
629442
+ } else {
629443
+ const pendingDeviceHandles = (appSession.recordingHost?.state?.recordings ?? []).filter((handle) => handle?.type === "appium-pending");
629444
+ for (const handle of pendingDeviceHandles) {
629445
+ const options = platform === "ios" ? { videoType: "h264", timeLimit: 1800 } : { timeLimit: 1800 };
629446
+ try {
629447
+ await driver.startRecordingScreen(options);
629448
+ handle.type = "appium";
629449
+ handle.driver = driver;
629450
+ } catch (error) {
629451
+ const message = `Couldn't start the pending device recording: ${error?.message ?? error}`;
629452
+ handle.startError = message;
629453
+ if (/ffmpeg.*not found/i.test(message))
629454
+ handle.startSkip = true;
629455
+ log(config, "warning", message);
629456
+ }
627327
629457
  }
627328
629458
  }
627329
629459
  log(config, "debug", `Opened app surface "${name}" (${appId}).`);
@@ -630674,7 +632804,7 @@ var import_node_crypto6 = require("node:crypto");
630674
632804
  var import_node_path16 = __toESM(require("node:path"), 1);
630675
632805
  var import_node_fs18 = __toESM(require("node:fs"), 1);
630676
632806
  var import_node_os8 = __toESM(require("node:os"), 1);
630677
- async function startRecording({ config, context, step, driver, recordingHost }) {
632807
+ async function startRecording({ config, context, step, driver, recordingHost, appSession, deps = {} }) {
630678
632808
  let result = {
630679
632809
  status: "PASS",
630680
632810
  description: "Started recording."
@@ -630691,14 +632821,35 @@ async function startRecording({ config, context, step, driver, recordingHost })
630691
632821
  result.description = "Recording is disabled (record: false).";
630692
632822
  return result;
630693
632823
  }
632824
+ let appRef = null;
630694
632825
  if (typeof step.record === "object" && step.record !== null && step.record.surface !== void 0) {
630695
- const switched = await switchToSurface(driver, step.record.surface);
630696
- if (!switched.ok) {
630697
- result.status = "FAIL";
630698
- result.description = switched.message;
630699
- return result;
632826
+ appRef = resolveAppSurfaceRef(step.record.surface, appSession);
632827
+ if (appRef) {
632828
+ if (appRef.error) {
632829
+ result.status = "FAIL";
632830
+ result.description = appRef.error;
632831
+ return result;
632832
+ }
632833
+ if (appRef.window !== void 0) {
632834
+ result.status = "SKIPPED";
632835
+ result.description = "Window selectors on app recordings land in a later part of this phase; the recording crops to the app's active window (omit `window`).";
632836
+ return result;
632837
+ }
632838
+ const switchedApp = await ensureAppForeground(appRef.entry, appSession);
632839
+ if (switchedApp.error) {
632840
+ result.status = "FAIL";
632841
+ result.description = switchedApp.error;
632842
+ return result;
632843
+ }
632844
+ } else {
632845
+ const switched = await switchToSurface(driver, step.record.surface);
632846
+ if (!switched.ok) {
632847
+ result.status = "FAIL";
632848
+ result.description = switched.message;
632849
+ return result;
632850
+ }
632851
+ driver = switched.driver ?? driver;
630700
632852
  }
630701
- driver = switched.driver ?? driver;
630702
632853
  }
630703
632854
  if (typeof step.record === "boolean") {
630704
632855
  step.record = { path: `${step.stepId}.mp4` };
@@ -630739,6 +632890,65 @@ async function startRecording({ config, context, step, driver, recordingHost })
630739
632890
  return result;
630740
632891
  }
630741
632892
  let plan = resolveRecordPlan({ step, context });
632893
+ const mobileTarget = isMobileTargetPlatform(context?.platform);
632894
+ if (mobileTarget && plan.name !== "device") {
632895
+ result.status = "SKIPPED";
632896
+ result.description = `Recordings on ${context.platform} contexts capture the device screen through the app driver; the "${plan.name}" engine doesn't apply \u2014 omit \`engine\`.`;
632897
+ return result;
632898
+ }
632899
+ if (appRef && plan.name === "browser") {
632900
+ result.status = "SKIPPED";
632901
+ result.description = "The browser engine records a Chrome tab and can't capture a native app window. Omit `engine` to record an app surface (ffmpeg, cropped to the app window).";
632902
+ return result;
632903
+ }
632904
+ if (appRef && plan.name === "ffmpeg" && plan.target === "viewport") {
632905
+ result.status = "SKIPPED";
632906
+ result.description = "The `viewport` target is the browser content area and doesn't apply to app surfaces. Use `window` (the default) or `display`.";
632907
+ return result;
632908
+ }
632909
+ if (plan.name === "device") {
632910
+ let recordingDriver = appRef?.entry?.driver ?? driver;
632911
+ if (!recordingDriver && appSession) {
632912
+ const activeEntry = appSession.activeApp ? appSession.surfaces?.get?.(appSession.activeApp) : void 0;
632913
+ recordingDriver = activeEntry?.driver;
632914
+ if (!recordingDriver && appSession.deviceSessions?.size > 0) {
632915
+ recordingDriver = appSession.deviceSessions.values().next().value?.driver;
632916
+ }
632917
+ }
632918
+ if (!recordingDriver) {
632919
+ result.recording = { type: "appium-pending", targetPath: filePath };
632920
+ result.description = "Device recording pending: it starts when the first app surface opens a device session.";
632921
+ return result;
632922
+ }
632923
+ const hasActiveDeviceRecording = Array.isArray(stateHolder?.state?.recordings) && stateHolder.state.recordings.some((r) => r?.type === "appium" && r.driver === recordingDriver);
632924
+ if (hasActiveDeviceRecording) {
632925
+ result.status = "SKIPPED";
632926
+ result.description = "A device recording is already running on this device; only one can run at a time. Stop it with stopRecord before starting another.";
632927
+ return result;
632928
+ }
632929
+ const platform = appRef?.entry?.platform ?? context?.platform;
632930
+ const options = platform === "ios" ? { videoType: "h264", timeLimit: 1800 } : { timeLimit: 1800 };
632931
+ try {
632932
+ await recordingDriver.startRecordingScreen(options);
632933
+ } catch (error) {
632934
+ const message = String(error?.message ?? error);
632935
+ if (/ffmpeg.*not found/i.test(message)) {
632936
+ result.status = "SKIPPED";
632937
+ result.description = `The device recording needs an ffmpeg binary on the Appium server's PATH and none was found; skipping the recording. ${message}`;
632938
+ return result;
632939
+ }
632940
+ result.status = "FAIL";
632941
+ result.description = `Couldn't start the device recording: ${message}`;
632942
+ log(config, "error", result.description);
632943
+ return result;
632944
+ }
632945
+ result.recording = {
632946
+ type: "appium",
632947
+ driver: recordingDriver,
632948
+ targetPath: filePath
632949
+ };
632950
+ return result;
632951
+ }
630742
632952
  const hasActiveBrowserRecording = Array.isArray(stateHolder?.state?.recordings) && stateHolder.state.recordings.some((r) => r?.type === "MediaRecorder");
630743
632953
  if (plan.name === "browser" && hasActiveBrowserRecording) {
630744
632954
  log(config, "warning", "A browser-engine recording is already active in this context; recording this one with the ffmpeg engine (viewport target) instead, since only one browser-engine recording can run at a time.");
@@ -630874,20 +633084,30 @@ async function startRecording({ config, context, step, driver, recordingHost })
630874
633084
  };
630875
633085
  return result;
630876
633086
  }
630877
- if (context.browser?.headless && !context.__display) {
633087
+ if (!appRef && context.browser?.headless && !context.__display) {
630878
633088
  result.status = "SKIPPED";
630879
633089
  result.description = `Recording isn't supported in headless mode without a virtual display (Xvfb).`;
630880
633090
  return result;
630881
633091
  }
630882
633092
  let crop = null;
630883
- if (driver && plan.target !== "display") {
633093
+ let appWindowRect = null;
633094
+ if (appRef && plan.target === "window") {
633095
+ try {
633096
+ appWindowRect = await resolveAppWindowRect(appRef.entry.driver);
633097
+ if (!appWindowRect) {
633098
+ log(config, "warning", "Couldn't resolve the app window geometry for recording (malformed window rect); capturing the full display.");
633099
+ }
633100
+ } catch (err) {
633101
+ log(config, "warning", `Couldn't resolve the app window geometry for recording; capturing the full display. ${err}`);
633102
+ }
633103
+ } else if (!appRef && driver && plan.target !== "display") {
630884
633104
  try {
630885
633105
  crop = await resolveCropGeometry({ driver, target: plan.target });
630886
633106
  } catch (err) {
630887
633107
  log(config, "warning", `Couldn't resolve ${plan.target} geometry for recording; capturing the full display. ${err}`);
630888
633108
  }
630889
633109
  }
630890
- if (driver) {
633110
+ if (driver && !appRef) {
630891
633111
  try {
630892
633112
  await instantiateCursor(driver, { position: "center" });
630893
633113
  } catch {
@@ -630899,7 +633119,9 @@ async function startRecording({ config, context, step, driver, recordingHost })
630899
633119
  const tempPath = import_node_path16.default.join(tempDir, `${safeContextId(context.contextId)}-${baseName}-${(0, import_node_crypto6.randomUUID)().slice(0, 8)}.mkv`);
630900
633120
  let ffmpegPath;
630901
633121
  try {
630902
- ffmpegPath = await getFfmpegPath({ cacheDir: config?.cacheDir });
633122
+ ffmpegPath = await (deps.getFfmpegPath ?? getFfmpegPath)({
633123
+ cacheDir: config?.cacheDir
633124
+ });
630903
633125
  } catch (err) {
630904
633126
  result.status = "FAIL";
630905
633127
  result.description = `Couldn't start recording: ${err}`;
@@ -630925,11 +633147,19 @@ async function startRecording({ config, context, step, driver, recordingHost })
630925
633147
  screenSize
630926
633148
  });
630927
633149
  log(config, "debug", `ffmpeg recording: platform=${process.platform} target=${plan.target}${screenIndex !== void 0 ? ` screen=${screenIndex}` : ""}${context.__display ? ` display=${context.__display}` : ""} -> ${tempPath}`);
630928
- const proc = (0, import_node_child_process9.spawn)(ffmpegPath, args, { stdio: ["pipe", "ignore", "pipe"] });
633150
+ const proc = (deps.spawn ?? import_node_child_process9.spawn)(ffmpegPath, args, {
633151
+ stdio: ["pipe", "ignore", "pipe"]
633152
+ });
630929
633153
  let spawnError = null;
630930
633154
  let stderrTail = "";
633155
+ const captureInfo = { frameSize: null, head: "" };
630931
633156
  proc.stderr?.on("data", (d) => {
630932
- stderrTail = (stderrTail + d.toString()).slice(-2e3);
633157
+ const text = d.toString();
633158
+ stderrTail = (stderrTail + text).slice(-2e3);
633159
+ if (!captureInfo.frameSize && captureInfo.head.length < 8192) {
633160
+ captureInfo.head = (captureInfo.head + text).slice(0, 8192);
633161
+ captureInfo.frameSize = parseCaptureFrameSize(captureInfo.head);
633162
+ }
630933
633163
  });
630934
633164
  proc.on("error", (err) => {
630935
633165
  spawnError = err;
@@ -630946,7 +633176,9 @@ async function startRecording({ config, context, step, driver, recordingHost })
630946
633176
  process: proc,
630947
633177
  tempPath,
630948
633178
  targetPath: filePath,
630949
- crop
633179
+ crop,
633180
+ captureInfo,
633181
+ ...appWindowRect ? { cropRect: appWindowRect, cropPendingScale: true } : {}
630950
633182
  };
630951
633183
  return result;
630952
633184
  }
@@ -630955,9 +633187,11 @@ async function startRecording({ config, context, step, driver, recordingHost })
630955
633187
  init_validate();
630956
633188
  init_utils();
630957
633189
  var import_node_child_process10 = require("node:child_process");
633190
+ var import_node_crypto7 = require("node:crypto");
630958
633191
  var import_node_path17 = __toESM(require("node:path"), 1);
630959
633192
  var import_node_fs19 = __toESM(require("node:fs"), 1);
630960
- async function stopRecording({ config, step, driver }) {
633193
+ var import_node_os9 = __toESM(require("node:os"), 1);
633194
+ async function stopRecording({ config, step, driver, deps = {} }) {
630961
633195
  let result = {
630962
633196
  status: "PASS",
630963
633197
  description: "Stopped recording."
@@ -631010,6 +633244,17 @@ async function stopRecording({ config, step, driver }) {
631010
633244
  if (idx !== -1)
631011
633245
  recordings.splice(idx, 1);
631012
633246
  };
633247
+ if (recording.type === "appium-pending") {
633248
+ dropHandle();
633249
+ if (recording.startError) {
633250
+ result.status = recording.startSkip ? "SKIPPED" : "FAIL";
633251
+ result.description = recording.startError;
633252
+ return result;
633253
+ }
633254
+ result.status = "SKIPPED";
633255
+ result.description = "The device recording never started (no app surface opened a device session), so there is nothing to save.";
633256
+ return result;
633257
+ }
631013
633258
  try {
631014
633259
  if (recording.type === "MediaRecorder") {
631015
633260
  let returnTab = null;
@@ -631088,14 +633333,73 @@ async function stopRecording({ config, step, driver }) {
631088
633333
  finish();
631089
633334
  });
631090
633335
  });
633336
+ let crop = recording.crop ?? null;
633337
+ if (!crop && recording.cropRect && recording.cropPendingScale) {
633338
+ const platform = deps.platform ?? process.platform;
633339
+ let scale = 1;
633340
+ try {
633341
+ const displayPointSize = platform === "darwin" ? await (deps.detectDisplayPointSize ?? detectDisplayPointSize)() : null;
633342
+ scale = deriveCropScale({
633343
+ platform,
633344
+ frameSize: recording.captureInfo?.frameSize ?? null,
633345
+ displayPointSize
633346
+ });
633347
+ } catch {
633348
+ }
633349
+ crop = {
633350
+ x: Math.round(recording.cropRect.x * scale),
633351
+ y: Math.round(recording.cropRect.y * scale),
633352
+ w: Math.round(recording.cropRect.w * scale),
633353
+ h: Math.round(recording.cropRect.h * scale)
633354
+ };
633355
+ }
631091
633356
  await transcode({
631092
633357
  config,
631093
633358
  sourcePath: recording.tempPath,
631094
633359
  targetPath: recording.targetPath,
631095
633360
  deleteSource: true,
631096
- crop: recording.crop
633361
+ crop
631097
633362
  });
631098
633363
  dropHandle();
633364
+ } else if (recording.type === "appium") {
633365
+ const b64 = await recording.driver.stopRecordingScreen();
633366
+ if (typeof b64 !== "string" || b64.length === 0) {
633367
+ result.status = "FAIL";
633368
+ result.description = "The device recording returned no data; nothing was saved.";
633369
+ dropHandle();
633370
+ return result;
633371
+ }
633372
+ let buffer;
633373
+ try {
633374
+ buffer = Buffer.from(b64, "base64");
633375
+ } catch (error) {
633376
+ result.status = "FAIL";
633377
+ result.description = `Couldn't buffer the device recording (${Math.round(b64.length / 1024 / 1024)} MB base64) \u2014 device recordings transfer in one payload, so long recordings can exhaust memory. Keep device recordings short (they cap at 30 minutes). ${error?.message ?? error}`;
633378
+ dropHandle();
633379
+ return result;
633380
+ }
633381
+ if (buffer.length === 0) {
633382
+ result.status = "FAIL";
633383
+ result.description = "The device recording decoded to an empty payload (no data); nothing was saved.";
633384
+ dropHandle();
633385
+ return result;
633386
+ }
633387
+ if (import_node_path17.default.extname(recording.targetPath) === ".mp4") {
633388
+ import_node_fs19.default.writeFileSync(recording.targetPath, buffer);
633389
+ } else {
633390
+ const tempDir = import_node_path17.default.join(import_node_os9.default.tmpdir(), "doc-detective", "recordings");
633391
+ if (!import_node_fs19.default.existsSync(tempDir))
633392
+ import_node_fs19.default.mkdirSync(tempDir, { recursive: true });
633393
+ const tempPath = import_node_path17.default.join(tempDir, `device-${(0, import_node_crypto7.randomUUID)().slice(0, 8)}.mp4`);
633394
+ import_node_fs19.default.writeFileSync(tempPath, buffer);
633395
+ await transcode({
633396
+ config,
633397
+ sourcePath: tempPath,
633398
+ targetPath: recording.targetPath,
633399
+ deleteSource: true
633400
+ });
633401
+ }
633402
+ dropHandle();
631099
633403
  }
631100
633404
  } catch (error) {
631101
633405
  result.status = "FAIL";
@@ -632107,7 +634411,7 @@ init_validate();
632107
634411
  init_utils();
632108
634412
  var import_node_fs23 = __toESM(require("node:fs"), 1);
632109
634413
  var import_node_path21 = __toESM(require("node:path"), 1);
632110
- var import_node_os9 = __toESM(require("node:os"), 1);
634414
+ var import_node_os10 = __toESM(require("node:os"), 1);
632111
634415
  function createTempScript(code, language) {
632112
634416
  let extension;
632113
634417
  switch (language) {
@@ -632130,7 +634434,7 @@ function createTempScript(code, language) {
632130
634434
  default:
632131
634435
  extension = "";
632132
634436
  }
632133
- const tmpDir = import_node_os9.default.tmpdir();
634437
+ const tmpDir = import_node_os10.default.tmpdir();
632134
634438
  const tmpFile = import_node_path21.default.join(tmpDir, `doc-detective-${Date.now()}${extension}`);
632135
634439
  try {
632136
634440
  import_node_fs23.default.writeFileSync(tmpFile, code);
@@ -632197,7 +634501,7 @@ async function runCode({ config, step, driver, processRegistry }) {
632197
634501
  result.description = `Command ${command} is unavailable. Make sure it's installed and in your PATH.`;
632198
634502
  return result;
632199
634503
  }
632200
- if (import_node_os9.default.platform() === "win32" && command === "bash") {
634504
+ if (import_node_os10.default.platform() === "win32" && command === "bash") {
632201
634505
  result.status = "FAIL";
632202
634506
  result.description = `runCode currently doesn't support bash on Windows. Use a different command, a different language, or a runShell step.`;
632203
634507
  return result;
@@ -633120,7 +635424,7 @@ async function dragAndDropElement({ config, step, driver }) {
633120
635424
  // dist/core/tests.js
633121
635425
  var import_node_path24 = __toESM(require("node:path"), 1);
633122
635426
  var import_node_child_process12 = require("node:child_process");
633123
- var import_node_crypto7 = require("node:crypto");
635427
+ var import_node_crypto8 = require("node:crypto");
633124
635428
  init_appium();
633125
635429
  init_config();
633126
635430
 
@@ -633399,7 +635703,7 @@ function getDriverCapabilities({ runnerDetails, name, options }) {
633399
635703
  prefs: {
633400
635704
  // Per-context download dir keeps concurrent recordings from
633401
635705
  // colliding on the same .webm filename in a shared temp dir.
633402
- "download.default_directory": options.downloadDir || import_node_os10.default.tmpdir(),
635706
+ "download.default_directory": options.downloadDir || import_node_os11.default.tmpdir(),
633403
635707
  "download.prompt_for_download": false,
633404
635708
  "download.directory_upgrade": true
633405
635709
  },
@@ -634679,7 +636983,14 @@ function buildAutoRecordStep({ config, spec, test, context }) {
634679
636983
  const contextSegment = capPathSegment(sanitizeFilesystemName(String(context.contextId ?? ""), "context"));
634680
636984
  const recordPath = import_node_path24.default.join(runDir, "specs", capPathSegment(sanitizeFilesystemName(String(spec.specId ?? ""), "spec")), "tests", capPathSegment(sanitizeFilesystemName(String(test.testId ?? ""), "test")), "contexts", contextSegment, "recordings", `${contextSegment}.mp4`);
634681
636985
  return {
634682
- record: { path: recordPath, overwrite: "true", engine: "ffmpeg" },
636986
+ // Mobile-target contexts record the device screen through the app driver
636987
+ // (the internal device plan, resolved from the platform) — pinning ffmpeg
636988
+ // there would host-capture the emulator window, or nothing when headless.
636989
+ record: {
636990
+ path: recordPath,
636991
+ overwrite: "true",
636992
+ ...isMobileTargetPlatform(context?.platform) ? {} : { engine: "ffmpeg" }
636993
+ },
634683
636994
  description: "Automatic full-context recording",
634684
636995
  stepId: `${sanitizeFilesystemName(String(test.testId ?? ""), "test")}~autorecord`,
634685
636996
  // Internal marker — the runStep record dispatch flags the started handle as
@@ -634690,7 +637001,7 @@ function buildAutoRecordStep({ config, spec, test, context }) {
634690
637001
  function capPathSegment(segment, max = 32) {
634691
637002
  if (segment.length <= max)
634692
637003
  return segment;
634693
- const hash = (0, import_node_crypto7.createHash)("sha1").update(segment).digest("hex").slice(0, 8);
637004
+ const hash = (0, import_node_crypto8.createHash)("sha1").update(segment).digest("hex").slice(0, 8);
634694
637005
  const tail = segment.slice(segment.length - (max - hash.length - 1));
634695
637006
  return `${hash}-${tail}`;
634696
637007
  }
@@ -635141,7 +637452,7 @@ ${JSON.stringify(context, null, 2)}`);
635141
637452
  const usedStepIds = new Set(context.steps.map((s) => s.stepId).filter(Boolean));
635142
637453
  for (const step of context.steps) {
635143
637454
  if (!step.stepId) {
635144
- const baseId = sanitizeFilesystemName(`${test.testId}~s${contentHash(step)}`, `step-${(0, import_node_crypto7.randomUUID)()}`);
637455
+ const baseId = sanitizeFilesystemName(`${test.testId}~s${contentHash(step)}`, `step-${(0, import_node_crypto8.randomUUID)()}`);
635145
637456
  let stepId = baseId;
635146
637457
  let suffix = 2;
635147
637458
  while (usedStepIds.has(stepId)) {
@@ -635439,7 +637750,7 @@ async function stopAllRecordings({ config, context, driver, contextReport }) {
635439
637750
  stopRecord: true,
635440
637751
  __stopAny: true,
635441
637752
  description: "Stopping recording",
635442
- stepId: (0, import_node_crypto7.randomUUID)()
637753
+ stepId: (0, import_node_crypto8.randomUUID)()
635443
637754
  };
635444
637755
  try {
635445
637756
  const stepResult = await runStep({
@@ -635522,7 +637833,8 @@ async function runStep({ config = {}, context = {}, step, driver, metaValues = {
635522
637833
  context,
635523
637834
  step,
635524
637835
  driver,
635525
- recordingHost
637836
+ recordingHost,
637837
+ appSession
635526
637838
  });
635527
637839
  if (actionResult.recording && !recordingHost) {
635528
637840
  try {
@@ -635536,12 +637848,13 @@ async function runStep({ config = {}, context = {}, step, driver, metaValues = {
635536
637848
  if (!Array.isArray(recordingHost.state.recordings))
635537
637849
  recordingHost.state.recordings = [];
635538
637850
  const handle = actionResult.recording;
635539
- handle.id = handle.id ?? (0, import_node_crypto7.randomUUID)();
637851
+ handle.id = handle.id ?? (0, import_node_crypto8.randomUUID)();
635540
637852
  handle.name = handle.name ?? recordStepName(step.record);
635541
637853
  if (step.__autoRecord) {
635542
637854
  handle.synthetic = true;
635543
- if (!driver && appSession)
637855
+ if (!driver && appSession && !isMobileTargetPlatform(context?.platform)) {
635544
637856
  handle.pendingAppWindowCrop = true;
637857
+ }
635545
637858
  }
635546
637859
  recordingHost.state.recordings.push(handle);
635547
637860
  }
@@ -635576,6 +637889,15 @@ async function runStep({ config = {}, context = {}, step, driver, metaValues = {
635576
637889
  env.ANDROID_HOME = appSession.androidSdkRoot;
635577
637890
  env.ANDROID_SDK_ROOT = appSession.androidSdkRoot;
635578
637891
  }
637892
+ if (isMobileTargetPlatform(context?.platform) === "ios") {
637893
+ try {
637894
+ const ffmpegPath = await getFfmpegPath({
637895
+ cacheDir: config?.cacheDir
637896
+ });
637897
+ Object.assign(env, ffmpegPathEnv(ffmpegPath));
637898
+ } catch {
637899
+ }
637900
+ }
635579
637901
  const server = await startAppiumServer(appiumEntry, config, void 0, env);
635580
637902
  return { port: server.port, process: server.process };
635581
637903
  },
@@ -635878,7 +638200,7 @@ async function getRunner(options = {}) {
635878
638200
  }
635879
638201
 
635880
638202
  // dist/core/telem.js
635881
- var import_node_os11 = __toESM(require("node:os"), 1);
638203
+ var import_node_os12 = __toESM(require("node:os"), 1);
635882
638204
  init_utils();
635883
638205
  var import_posthog_node = require("posthog-node");
635884
638206
  var import_node_module2 = require("node:module");
@@ -635904,11 +638226,11 @@ function sendTelemetry(config, command, results) {
635904
638226
  telemetryData.dist_interface = telemetryData.dist_interface || "package";
635905
638227
  telemetryData.core_version = pkg.version;
635906
638228
  telemetryData.dist_version = telemetryData.dist_version || telemetryData.core_version;
635907
- telemetryData.core_platform = platformMap2[import_node_os11.default.platform()] || import_node_os11.default.platform();
638229
+ telemetryData.core_platform = platformMap2[import_node_os12.default.platform()] || import_node_os12.default.platform();
635908
638230
  telemetryData.dist_platform = telemetryData.dist_platform || telemetryData.core_platform;
635909
- telemetryData.core_platform_version = import_node_os11.default.release();
638231
+ telemetryData.core_platform_version = import_node_os12.default.release();
635910
638232
  telemetryData.dist_platform_version = telemetryData.dist_platform_version || telemetryData.core_platform_version;
635911
- telemetryData.core_platform_arch = import_node_os11.default.arch();
638233
+ telemetryData.core_platform_arch = import_node_os12.default.arch();
635912
638234
  telemetryData.dist_platform_arch = telemetryData.dist_platform_arch || telemetryData.core_platform_arch;
635913
638235
  telemetryData.core_deployment = telemetryData.core_deployment || "node";
635914
638236
  telemetryData.dist_deployment = telemetryData.dist_deployment || telemetryData.core_deployment;