@oniroproject/oniro-app 0.12.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -45,8 +45,8 @@ Once a device or emulator is connected you can inspect and drive it:
45
45
  ```bash
46
46
  oniro-app devices --json
47
47
  oniro-app screenshot -o shot.jpeg
48
- oniro-app dump layout --json
49
- oniro-app input --type click --x 200 --y 400
48
+ oniro-app dump layout --flat
49
+ oniro-app input --type click --target "Sign in"
50
50
  oniro-app watch --log 'error|fault' --for 5000 --json
51
51
  ```
52
52
 
@@ -214,7 +214,7 @@ These commands target a connected device or emulator over `hdc`. Most accept `--
214
214
 
215
215
  #### `wait` — wait for a device condition
216
216
 
217
- Specify exactly one of `--log`, `--boot`, or `--bundle`.
217
+ Specify exactly one of `--log`, `--boot`, `--bundle`, or an element selector (`--target` / `--target-id` / `--target-type`).
218
218
 
219
219
  | Flag | Description |
220
220
  | --- | --- |
@@ -223,9 +223,13 @@ Specify exactly one of `--log`, `--boot`, or `--bundle`.
223
223
  | `--bundle <bundle>` | With `--log`: filter to this bundle. Alone: wait until this bundle is running. |
224
224
  | `--pid-of <name>` | With `--boot`: also require this process to have a pid. |
225
225
  | `--domain <domain>` | With `--log`: hilog domain filter (e.g. `0xD003900`). |
226
+ | `--target <text>` | Resolve when an uncovered element whose text, description, or placeholder matches is on screen (case-insensitive; exact matches win, else substring). |
227
+ | `--target-id <id>` / `--target-type <type>` | Match the element by id/key, or restrict it to a component type (e.g. `Button`). |
228
+ | `--gone` | With a selector: resolve when no uncovered element matches any more. |
229
+ | `--interval <ms>` | With a selector: poll interval (default `500`; each poll is a layout dump). |
226
230
  | `--timeout <ms>` | Max wait (default `30000`). |
227
231
  | `--device <serial>` | Target device serial. |
228
- | `--json` | With `--log`: emit the matched entry as JSON. |
232
+ | `--json` | With `--log` or a selector: emit the matched entry or element as JSON. |
229
233
 
230
234
  #### `watch` — collect matching hilog lines for a fixed duration
231
235
 
@@ -241,50 +245,82 @@ Specify exactly one of `--log`, `--boot`, or `--bundle`.
241
245
 
242
246
  #### `screenshot` — capture the screen as a JPEG
243
247
 
244
- Default: writes the full-resolution raw JPEG. `--grid` reproduces the old MCP screenshot (downscaled + grid overlay). `--contact-sheet` captures a burst (default 8 frames) into one tiled sheet and prints per-frame diffs (0..1) on stdout — one image instead of N, pointing you at the frame where something changed.
248
+ Default: writes the full-resolution raw JPEG. `--grid` reproduces the old MCP screenshot (downscaled + grid overlay). `--crop` / `--target` write a full-resolution crop of one region or element — detail where it is needed without the cost of a full-resolution screenshot. `--contact-sheet` captures a burst (default 8 frames) into one tiled sheet and prints per-frame diffs (0..1) on stdout — one image instead of N, pointing you at the frame where something changed.
245
249
 
246
250
  | Flag | Description |
247
251
  | --- | --- |
248
252
  | `-o, --output <file>` | Output path (default `screenshot.jpeg`). |
249
253
  | `--grid` | Downscale to `--max-dim` and overlay a 10x10 grid (axes 0.0–1.0) for picking tap coordinates. |
250
- | `--max-dim <px>` | Longest-side cap for `--grid` / `--contact-sheet` (256–4096, default `1024`). On its own, downscales without a grid. |
254
+ | `--max-dim <px>` | Longest-side cap for `--grid` / `--crop` / `--target` / `--contact-sheet` (256–4096, default `1024`). On its own, downscales without a grid. |
255
+ | `--crop <x1,y1,x2,y2>` | Crop to this region, given as 0–1 fractions of the screen (as in `dump layout` and the grid). |
256
+ | `--target <text>` | Crop to the element whose text, description, or placeholder matches, plus a small margin. Also `--target-id`, `--target-type`, `--target-index`. |
251
257
  | `--contact-sheet` | Capture a burst and composite it into one tiled image with per-frame change diffs. |
252
258
  | `--burst <count>` | Capture N frames; writes `<base>-<i><ext>` (or sets the `--contact-sheet` frame count). |
253
259
  | `--interval <ms>` | Delay between burst frames (default `50`). |
254
260
  | `--json` | With `--contact-sheet`, emit the full result object as JSON on stdout. |
255
261
  | `--device <serial>` | Target device serial. |
256
262
 
257
- #### `dump` — dump device state as JSON
263
+ #### `dump` — dump device state
258
264
 
259
265
  | Command | Description |
260
266
  | --- | --- |
261
- | `dump [layout]` | Dump the on-screen UI layout (the default and currently only target) as a pruned, 0–1-normalized tree to stdout. |
267
+ | `dump [layout]` | Dump the on-screen UI layout (the default and currently only target) to stdout: a pruned, 0–1-normalized JSON tree, or one line per element with `--flat`. |
262
268
 
263
269
  | Flag | Description |
264
270
  | --- | --- |
265
271
  | `--bundle <bundle>` | Filter the layout to a single window/bundle. |
266
- | `--raw` | Return the unpruned tree. |
272
+ | `--flat` | One line per labelled or interactive element, grouped by window: type, label, `#id`, center `c=x,y` (0–1 fractions), and flags (`click`, `focus`, `disabled`, `covered`, …). The soft keyboard collapses to one `[keyboard …]` line. |
273
+ | `--raw` | Return the unpruned tree (no keyboard detection; not combinable with `--flat`). |
267
274
  | `--device <serial>` | Target device serial. |
268
275
 
276
+ The pruned output marks elements as `covered` when a later layer with a visible background (a dialog scrim, an overlay, the keyboard) paints over their center, so a tap there would land on that layer instead. A fully transparent layer that only intercepts touches is not detected. Placeholder text is reported as `hint`, and disabled components as `disabled`. The JSON result also carries `keyboard: { shown, bundle, b }`.
277
+
278
+ ```text
279
+ $ oniro-app dump layout --flat
280
+ # display 1080x2400; c = element center as 0-1 fractions (input --fx/--fy), or act by label with input --target "<text>"
281
+ [window com.example.app]
282
+ Text "Sign in" c=0.500,0.180
283
+ TextInput hint="you@example.com" c=0.500,0.320 click focus
284
+ Button "Sign in" c=0.500,0.520 click
285
+ [keyboard dev.patrickgold.florisboard] up — dismiss with input --type hideKeyboard
286
+ ```
287
+
269
288
  #### `input` / `gesture` — inject UI input
270
289
 
271
- `input` injects a single event in **pixel** coordinates via `uitest uiInput`:
290
+ `input` injects a single event via `uitest uiInput`. Give the start point one way: an on-screen element (`--target`), 0–1 fractions of the display (`--fx`/`--fy`, as read from `dump layout` or the screenshot grid), or pixels (`--x`/`--y`).
272
291
 
273
292
  | Flag | Description |
274
293
  | --- | --- |
275
- | `--type <type>` | **Required.** One of `click`, `doubleClick`, `longClick`, `swipe`, `drag`, `fling`, `keyEvent`, `inputText`. |
276
- | `--x <px>` / `--y <px>` | Start coordinate (click / swipe start). |
277
- | `--x2 <px>` / `--y2 <px>` | End coordinate (swipe / drag / fling). |
294
+ | `--type <type>` | **Required.** One of `click`, `doubleClick`, `longClick`, `swipe`, `drag`, `fling`, `keyEvent`, `inputText`, `clearText`, `hideKeyboard`. |
295
+ | `--target <text>` | Act on the center of the element whose text, description, or placeholder matches (case-insensitive; exact matches win, else substring). Covered elements and soft-keyboard keys are skipped and clickable ones preferred; if the keyboard hides the element, it is dismissed first. |
296
+ | `--target-id <id>` / `--target-type <type>` | Match by id/key, or restrict to a component type (e.g. `Button`, `TextInput`). |
297
+ | `--target-index <n>` | Pick the n-th (0-based) of several matching elements; without it, an ambiguous match fails and lists the candidates. |
298
+ | `--fx <fraction>` / `--fy <fraction>` | Start point as 0–1 fractions of the display. |
299
+ | `--fx2 <fraction>` / `--fy2 <fraction>` | End point as fractions (swipe / drag / fling). |
300
+ | `--x <px>` / `--y <px>` | Start point in pixels. |
301
+ | `--x2 <px>` / `--y2 <px>` | End point in pixels (swipe / drag / fling). |
278
302
  | `--speed <px-per-s>` | Velocity for swipe / drag / fling. |
279
- | `--key <key>` | Key id or symbolic name (`Back` / `Home` / `Power`) for `keyEvent`. |
303
+ | `--key <key>` | For `keyEvent`: `Back` / `Home` / `Power`, a name (`Delete`, `Enter`, `Tab`, `Escape`, `MoveHome`, `MoveEnd`, `ForwardDelete`, …), a letter, a KeyCode id, or a combo of up to three keys like `Ctrl+A`. |
280
304
  | `--text <text>` | Text for `inputText`. |
305
+ | `--clear` | `inputText`: clear the field (Ctrl+A, Delete) before typing. |
306
+ | `--hide-keyboard` | Dismiss the soft keyboard afterwards, if it is up. |
281
307
  | `--device <serial>` | Target device serial. |
282
308
 
309
+ `clearText` taps the field, then sends Ctrl+A and Delete. `hideKeyboard` presses Back only when the soft keyboard is on screen, so it never navigates away.
310
+
311
+ ```bash
312
+ oniro-app input --type inputText --target "you@example.com" --text 'me@example.com'
313
+ oniro-app input --type inputText --target-id password --clear --text 'secret' --hide-keyboard
314
+ oniro-app input --type click --target "Sign in" --target-type Button
315
+ oniro-app input --type swipe --fx 0.5 --fy 0.8 --fx2 0.5 --fy2 0.3
316
+ ```
317
+
283
318
  `gesture` injects a multi-waypoint path:
284
319
 
285
320
  | Flag | Description |
286
321
  | --- | --- |
287
322
  | `--waypoints <json>` | **Required.** JSON array of pixel waypoints `[{"x":..,"y":..,"t":..}]` (`t` = ms from start). |
323
+ | `--fractions` | Waypoint `x`/`y` are 0–1 fractions of the display instead of pixels. |
288
324
  | `--hold-start <ms>` / `--hold-end <ms>` | Hold at the first/last point before moving/lifting (routes via `uinput`). |
289
325
  | `--device <serial>` | Target device serial. |
290
326
 
@@ -294,7 +330,7 @@ oniro-app gesture --waypoints '[{"x":200,"y":600,"t":0},{"x":200,"y":200,"t":400
294
330
 
295
331
  ## Output & exit codes
296
332
 
297
- - **Results → stdout.** Plain text by default; `--json` (where supported) writes `JSON.stringify(..., null, 2)`. Read/observe commands (`sdk list`, `cmdtools status`, `templates list`, `devices`, `wait --log`, `watch`, `lint`, `app apply`, `build`) accept `--json` (and `screenshot` with `--contact-sheet`); `dump` always emits JSON; action-only commands do not.
333
+ - **Results → stdout.** Plain text by default; `--json` (where supported) writes `JSON.stringify(..., null, 2)`. Read/observe commands (`sdk list`, `cmdtools status`, `templates list`, `devices`, `wait --log` / `--target`, `watch`, `lint`, `app apply`, `build`) accept `--json` (and `screenshot` with `--contact-sheet`); `dump` emits JSON unless `--flat`; action-only commands do not.
298
334
  - **Progress & logs → stderr.** stdout stays clean for machine consumers, so `oniro-app create … > path.txt` or `oniro-app devices --json | jq` work cleanly.
299
335
  - **Exit code.** `0` on success, non-zero on failure (the error message is written to stderr). Set `ONIRO_DEBUG=1` to also print full stack traces.
300
336
 
package/dist/oniro-app.js CHANGED
@@ -614,11 +614,40 @@ function registerRebootCommand(program) {
614
614
  }
615
615
 
616
616
  // src/commands/wait.ts
617
- import { waitForLog, waitForBoot, waitForBundle } from "@oniroproject/core";
617
+ import { waitForLog, waitForBoot, waitForBundle, waitForTarget, describeLayoutNode } from "@oniroproject/core";
618
+
619
+ // src/lib/target.ts
620
+ function addTargetOptions(cmd, verb, opts = {}) {
621
+ cmd.option(
622
+ "--target <text>",
623
+ `${verb} the element whose text, description, or placeholder matches (case-insensitive; exact matches win, else substring). Covered elements are skipped.`
624
+ ).option("--target-id <id>", "Match the element by its id or key.").option("--target-type <type>", "Restrict the match to a component type (e.g. Button, TextInput).");
625
+ if (opts.index !== false) {
626
+ cmd.option("--target-index <n>", "Pick the n-th (0-based) of several matching elements.");
627
+ }
628
+ return cmd;
629
+ }
630
+ function selectorFrom(opts) {
631
+ if (opts.target === void 0 && opts.targetId === void 0 && opts.targetType === void 0) return void 0;
632
+ return { text: opts.target, id: opts.targetId, type: opts.targetType };
633
+ }
634
+ function targetIndexFrom(opts) {
635
+ if (opts.targetIndex === void 0) return void 0;
636
+ const n = Number(opts.targetIndex);
637
+ if (!Number.isInteger(n) || n < 0) throw new Error(`--target-index must be a non-negative integer; got ${opts.targetIndex}.`);
638
+ return n;
639
+ }
640
+
641
+ // src/commands/wait.ts
618
642
  function registerWaitCommand(program) {
619
- program.command("wait").description("Wait for a device condition: a log line (--log), boot (--boot), or a bundle to start (--bundle).").option("--log <pattern>", "Resolve when a hilog line (tag: message) matches this regex.").option("--boot", "Resolve when the device is reachable (optionally also --pid-of).").option("--bundle <bundle>", "With --log: filter to this bundle. Alone: wait until this bundle is running.").option("--pid-of <name>", "With --boot: also require this process to have a pid.").option("--domain <domain>", "With --log: hilog domain filter (e.g. 0xD003900).").option("--timeout <ms>", "Max wait, ms.", "30000").option("--device <serial>", "Target device serial.").option("--json", "With --log: emit the matched entry as JSON.").action(async (opts) => {
643
+ const wait = program.command("wait").description(
644
+ "Wait for a device condition: a log line (--log), boot (--boot), a bundle to start (--bundle), or an on-screen element (--target / --target-id / --target-type)."
645
+ ).option("--log <pattern>", "Resolve when a hilog line (tag: message) matches this regex.").option("--boot", "Resolve when the device is reachable (optionally also --pid-of).").option("--bundle <bundle>", "With --log: filter to this bundle. Alone: wait until this bundle is running.").option("--pid-of <name>", "With --boot: also require this process to have a pid.").option("--domain <domain>", "With --log: hilog domain filter (e.g. 0xD003900).");
646
+ addTargetOptions(wait, "Resolve when", { index: false });
647
+ wait.option("--gone", "With --target*: resolve when no uncovered element matches any more.").option("--interval <ms>", "With --target*: poll interval, ms (each poll is a layout dump).", "500").option("--timeout <ms>", "Max wait, ms.", "30000").option("--device <serial>", "Target device serial.").option("--json", "With --log or --target*: emit the matched entry/element as JSON.").action(async (opts) => {
620
648
  const { config, logger } = getRuntime();
621
649
  const timeoutMs = Number(opts.timeout);
650
+ const selector = selectorFrom(opts);
622
651
  if (opts.log) {
623
652
  const entry = await waitForLog({
624
653
  config,
@@ -639,12 +668,31 @@ function registerWaitCommand(program) {
639
668
  logger.info("Device booted.");
640
669
  return;
641
670
  }
671
+ if (selector) {
672
+ const node = await waitForTarget({
673
+ config,
674
+ selector,
675
+ gone: opts.gone,
676
+ timeoutMs,
677
+ pollMs: Number(opts.interval) || 500,
678
+ deviceSerial: opts.device,
679
+ logger
680
+ });
681
+ if (!node) {
682
+ logger.info("Element is gone.");
683
+ return;
684
+ }
685
+ if (opts.json) process.stdout.write(`${JSON.stringify(node, null, 2)}
686
+ `);
687
+ else logger.info(`found: ${describeLayoutNode(node)}`);
688
+ return;
689
+ }
642
690
  if (opts.bundle) {
643
691
  await waitForBundle({ config, bundle: opts.bundle, timeoutMs, deviceSerial: opts.device, logger });
644
692
  logger.info(`Bundle ${opts.bundle} is running.`);
645
693
  return;
646
694
  }
647
- throw new Error("Specify one of --log <pattern>, --boot, or --bundle <bundle>.");
695
+ throw new Error("Specify one of --log <pattern>, --boot, --bundle <bundle>, or --target <text> (or --target-id / --target-type).");
648
696
  });
649
697
  }
650
698
 
@@ -677,7 +725,7 @@ function registerWatchCommand(program) {
677
725
  // src/commands/screenshot.ts
678
726
  import * as fs3 from "fs";
679
727
  import * as path7 from "path";
680
- import { takeScreenshot, captureBurst } from "@oniroproject/core";
728
+ import { takeScreenshot, captureBurst, locateTarget, describeLayoutNode as describeLayoutNode2 } from "@oniroproject/core";
681
729
 
682
730
  // src/lib/screenshotImage.ts
683
731
  import sharp from "sharp";
@@ -732,6 +780,32 @@ async function renderWithGrid(jpeg, opts) {
732
780
  const buf = await sharp(resized).composite([{ input: Buffer.from(svg) }]).jpeg({ quality: 80 }).toBuffer();
733
781
  return { buf, width, height, originalWidth, originalHeight };
734
782
  }
783
+ function parseCropRect(spec) {
784
+ const parts = spec.split(",").map((s) => Number(s.trim()));
785
+ if (parts.length !== 4 || parts.some((n) => !Number.isFinite(n) || n < 0 || n > 1)) {
786
+ throw new Error(`--crop expects four 0-1 fractions "x1,y1,x2,y2"; got "${spec}".`);
787
+ }
788
+ const [x1, y1, x2, y2] = parts;
789
+ if (!(x2 > x1 && y2 > y1)) throw new Error(`--crop needs x1 < x2 and y1 < y2; got "${spec}".`);
790
+ return [x1, y1, x2, y2];
791
+ }
792
+ function padCropRect(r, pad) {
793
+ return [Math.max(0, r[0] - pad), Math.max(0, r[1] - pad), Math.min(1, r[2] + pad), Math.min(1, r[3] + pad)];
794
+ }
795
+ async function cropImage(jpeg, rect, opts) {
796
+ const meta = await sharp(jpeg).metadata();
797
+ const w = meta.width ?? 1;
798
+ const h = meta.height ?? 1;
799
+ const left = Math.min(w - 1, Math.floor(rect[0] * w));
800
+ const top = Math.min(h - 1, Math.floor(rect[1] * h));
801
+ const cropWidth = Math.max(1, Math.min(w, Math.ceil(rect[2] * w)) - left);
802
+ const cropHeight = Math.max(1, Math.min(h, Math.ceil(rect[3] * h)) - top);
803
+ const scale = Math.min(1, opts.maxDim / Math.max(cropWidth, cropHeight));
804
+ const width = Math.max(1, Math.round(cropWidth * scale));
805
+ const height = Math.max(1, Math.round(cropHeight * scale));
806
+ const buf = await sharp(jpeg).extract({ left, top, width: cropWidth, height: cropHeight }).resize(width, height).jpeg({ quality: 85 }).toBuffer();
807
+ return { buf, width, height, left, top, cropWidth, cropHeight };
808
+ }
735
809
  function buildTileLabelSvg(width, height, idx, diff) {
736
810
  const fontSize = Math.max(12, Math.round(Math.min(width, height) / 16));
737
811
  const pad = Math.round(fontSize * 0.4);
@@ -796,18 +870,53 @@ async function frameDiffs(frames, opts = {}) {
796
870
 
797
871
  // src/commands/screenshot.ts
798
872
  var DEFAULT_CONTACT_SHEET_FRAMES = 8;
873
+ var TARGET_CROP_PAD = 0.02;
799
874
  function clampMaxDim(raw) {
800
875
  const n = Number(raw);
801
876
  if (!Number.isFinite(n)) return 1024;
802
877
  return Math.max(256, Math.min(4096, Math.round(n)));
803
878
  }
804
879
  function registerScreenshotCommand(program) {
805
- program.command("screenshot").description(
806
- "Capture the screen. Default: full-resolution raw JPEG. --grid: downscaled JPEG with a 10x10 grid (axes 0.0-1.0) for picking tap coordinates. --contact-sheet: capture a burst and tile it into one image with per-frame change diffs."
807
- ).option("-o, --output <file>", "Output file path.", "screenshot.jpeg").option("--grid", "Downscale (to --max-dim) and overlay a 10x10 coordinate grid.").option("--max-dim <px>", "Longest-side cap for --grid / --contact-sheet (256-4096).", "1024").option("--contact-sheet", "Capture a burst and composite it into one tiled contact sheet.").option("--burst <count>", "Capture N frames; writes <base>-<i><ext> (or feeds --contact-sheet).").option("--interval <ms>", "Delay between burst frames, ms.", "50").option("--json", "Emit the full result object as JSON on stdout (with --contact-sheet).").option("--device <serial>", "Target device serial.").action(async (opts, command) => {
880
+ const screenshot = program.command("screenshot").description(
881
+ "Capture the screen. Default: full-resolution raw JPEG. --grid: downscaled JPEG with a 10x10 grid (axes 0.0-1.0) for picking tap coordinates. --crop / --target: a full-resolution crop of one region or element, for checking detail cheaply. --contact-sheet: capture a burst and tile it into one image with per-frame change diffs."
882
+ ).option("-o, --output <file>", "Output file path.", "screenshot.jpeg").option("--grid", "Downscale (to --max-dim) and overlay a 10x10 coordinate grid.").option("--max-dim <px>", "Longest-side cap for --grid / --crop / --target / --contact-sheet (256-4096).", "1024").option("--crop <x1,y1,x2,y2>", "Crop to this region, given as 0-1 fractions of the screen.");
883
+ addTargetOptions(screenshot, "Crop to");
884
+ screenshot.option("--contact-sheet", "Capture a burst and composite it into one tiled contact sheet.").option("--burst <count>", "Capture N frames; writes <base>-<i><ext> (or feeds --contact-sheet).").option("--interval <ms>", "Delay between burst frames, ms.", "50").option("--json", "Emit the full result object as JSON on stdout (with --contact-sheet).").option("--device <serial>", "Target device serial.").action(async (opts, command) => {
808
885
  const { config, logger } = getRuntime();
809
886
  const maxDim = clampMaxDim(opts.maxDim);
810
887
  const intervalMs = Number(opts.interval) || 50;
888
+ const selector = selectorFrom(opts);
889
+ if (opts.crop !== void 0 || selector) {
890
+ if (opts.crop !== void 0 && selector) throw new Error("Use either --crop or --target*, not both.");
891
+ if (opts.grid || opts.contactSheet || opts.burst) {
892
+ throw new Error("--crop / --target cannot be combined with --grid, --contact-sheet, or --burst.");
893
+ }
894
+ let rect;
895
+ let label;
896
+ if (selector) {
897
+ const located = await locateTarget({
898
+ config,
899
+ selector,
900
+ index: targetIndexFrom(opts),
901
+ hideKeyboard: false,
902
+ deviceSerial: opts.device,
903
+ logger
904
+ });
905
+ if (!located.node.b) throw new Error(`${describeLayoutNode2(located.node)} has no bounds to crop to.`);
906
+ rect = padCropRect(located.node.b, TARGET_CROP_PAD);
907
+ label = describeLayoutNode2(located.node);
908
+ } else {
909
+ rect = parseCropRect(opts.crop);
910
+ label = rect.map((n) => n.toFixed(3)).join(",");
911
+ }
912
+ const shot2 = await takeScreenshot({ config, deviceSerial: opts.device, logger });
913
+ const cropped = await cropImage(shot2.pixels, rect, { maxDim });
914
+ fs3.writeFileSync(opts.output, cropped.buf);
915
+ logger.info(
916
+ `Wrote ${opts.output} (${cropped.width}x${cropped.height} from a ${cropped.cropWidth}x${cropped.cropHeight} crop at ${cropped.left},${cropped.top}: ${label}).`
917
+ );
918
+ return;
919
+ }
811
920
  if (opts.contactSheet) {
812
921
  const count = opts.burst ? Math.max(1, Number(opts.burst)) : DEFAULT_CONTACT_SHEET_FRAMES;
813
922
  const frames = await captureBurst({ config, count, intervalMs, deviceSerial: opts.device, logger });
@@ -879,19 +988,84 @@ function registerScreenshotCommand(program) {
879
988
 
880
989
  // src/commands/dump.ts
881
990
  import { dumpLayout } from "@oniroproject/core";
991
+
992
+ // src/lib/layoutText.ts
993
+ import { flattenLayout } from "@oniroproject/core";
994
+ var MAX_TEXT = 80;
995
+ function quote(s) {
996
+ return JSON.stringify(s.length > MAX_TEXT ? `${s.slice(0, MAX_TEXT - 1)}\u2026` : s);
997
+ }
998
+ function flags(n) {
999
+ const out = [];
1000
+ if (n.click) out.push("click");
1001
+ if (n.longClick) out.push("longClick");
1002
+ if (n.scroll) out.push("scroll");
1003
+ if (n.checked) out.push("checked");
1004
+ else if (n.check) out.push("checkable");
1005
+ if (n.sel) out.push("selected");
1006
+ if (n.focus) out.push("focus");
1007
+ if (n.disabled) out.push("disabled");
1008
+ if (n.covered) out.push("covered");
1009
+ return out;
1010
+ }
1011
+ function formatLayoutLine(n) {
1012
+ const parts = [n.type ?? "node"];
1013
+ if (n.text !== void 0) parts.push(quote(n.text));
1014
+ if (n.desc !== void 0) parts.push(`desc=${quote(n.desc)}`);
1015
+ if (n.hint !== void 0) parts.push(`hint=${quote(n.hint)}`);
1016
+ if (n.id !== void 0) parts.push(`#${n.id}`);
1017
+ if (n.key !== void 0) parts.push(`key=${n.key}`);
1018
+ if (n.c) parts.push(`c=${n.c[0].toFixed(3)},${n.c[1].toFixed(3)}`);
1019
+ parts.push(...flags(n));
1020
+ return parts.join(" ");
1021
+ }
1022
+ function isListed(n) {
1023
+ const labelled = n.text !== void 0 || n.desc !== void 0 || n.hint !== void 0;
1024
+ return labelled || !!(n.click || n.longClick || n.scroll || n.check || n.focus);
1025
+ }
1026
+ function formatFlatLayout(result) {
1027
+ const lines = [];
1028
+ const d = result.display;
1029
+ lines.push(
1030
+ `# display ${d ? `${d.width}x${d.height}` : "unknown"}; c = element center as 0-1 fractions (input --fx/--fy), or act by label with input --target "<text>"`
1031
+ );
1032
+ const keyboardBundle = result.keyboard?.shown ? result.keyboard.bundle : void 0;
1033
+ let window;
1034
+ for (const n of flattenLayout(result.tree)) {
1035
+ if (n.window !== window) {
1036
+ window = n.window;
1037
+ if (window !== void 0 && window === keyboardBundle) {
1038
+ lines.push(`[keyboard ${window}] up \u2014 dismiss with input --type hideKeyboard`);
1039
+ } else if (window !== void 0) {
1040
+ lines.push(`[window ${window}]`);
1041
+ }
1042
+ }
1043
+ if (window !== void 0 && window === keyboardBundle) continue;
1044
+ if (n.bundle !== void 0 && n.text === void 0 && !n.click) continue;
1045
+ if (isListed(n)) lines.push(formatLayoutLine(n));
1046
+ }
1047
+ return `${lines.join("\n")}
1048
+ `;
1049
+ }
1050
+
1051
+ // src/commands/dump.ts
882
1052
  function registerDumpCommand(program) {
883
- program.command("dump [target]").description("Dump device state as JSON. Currently supports `dump layout` (the default target).").option("--bundle <bundle>", "Filter the layout to a single window/bundle.").option("--raw", "Return the unpruned layout tree.").option("--device <serial>", "Target device serial.").action(async (target, opts) => {
1053
+ program.command("dump [target]").description(
1054
+ "Dump device state. Currently supports `dump layout` (the default target): JSON by default, or one line per element with --flat."
1055
+ ).option("--bundle <bundle>", "Filter the layout to a single window/bundle.").option("--raw", "Return the unpruned layout tree.").option("--flat", "One line per element (type, label, center as 0-1 fractions, flags) instead of a JSON tree.").option("--device <serial>", "Target device serial.").action(async (target, opts) => {
884
1056
  const { config, logger } = getRuntime();
885
1057
  const what = target ?? "layout";
886
1058
  if (what !== "layout") throw new Error(`Unknown dump target "${what}". Supported: layout.`);
1059
+ if (opts.raw && opts.flat) throw new Error("--raw and --flat cannot be combined.");
887
1060
  const result = await dumpLayout({
888
1061
  config,
889
1062
  bundleName: opts.bundle,
890
1063
  prune: !opts.raw,
1064
+ detectKeyboard: !opts.raw,
891
1065
  deviceSerial: opts.device,
892
1066
  logger
893
1067
  });
894
- process.stdout.write(`${JSON.stringify(result, null, 2)}
1068
+ process.stdout.write(opts.flat ? formatFlatLayout(result) : `${JSON.stringify(result, null, 2)}
895
1069
  `);
896
1070
  });
897
1071
  }
@@ -958,15 +1132,44 @@ function registerLintCommand(program) {
958
1132
 
959
1133
  // src/commands/input.ts
960
1134
  import { Option as Option3 } from "commander";
961
- import { sendInput, sendGesture } from "@oniroproject/core";
962
- var INPUT_TYPES = ["click", "doubleClick", "longClick", "swipe", "drag", "fling", "keyEvent", "inputText"];
1135
+ import {
1136
+ performInput,
1137
+ sendGesture,
1138
+ getDisplaySize,
1139
+ describeLayoutNode as describeLayoutNode3
1140
+ } from "@oniroproject/core";
1141
+ var INPUT_TYPES = [
1142
+ "click",
1143
+ "doubleClick",
1144
+ "longClick",
1145
+ "swipe",
1146
+ "drag",
1147
+ "fling",
1148
+ "keyEvent",
1149
+ "inputText",
1150
+ "clearText",
1151
+ "hideKeyboard"
1152
+ ];
963
1153
  var num = (v) => v === void 0 ? void 0 : Number(v);
964
1154
  function registerInputCommand(program) {
965
- program.command("input").description("Inject a UI input event (pixel coordinates) via uitest uiInput.").addOption(new Option3("--type <type>", "Input type.").choices(INPUT_TYPES).makeOptionMandatory()).option("--x <px>", "X pixel (click/swipe start).").option("--y <px>", "Y pixel (click/swipe start).").option("--x2 <px>", "End X pixel (swipe/drag/fling).").option("--y2 <px>", "End Y pixel (swipe/drag/fling).").option("--speed <px-per-s>", "Velocity for swipe/drag/fling.").option("--key <key>", "Key id or symbolic name (Back/Home/Power) for keyEvent.").option("--text <text>", "Text for inputText.").option("--device <serial>", "Target device serial.").action(async (opts) => {
1155
+ const input = program.command("input").description(
1156
+ "Inject a UI input event via uitest uiInput. Position it with --target (an on-screen element), --fx/--fy (0-1 fractions of the display, as in `dump layout` and the screenshot grid), or --x/--y (pixels)."
1157
+ ).addOption(new Option3("--type <type>", "Input type.").choices(INPUT_TYPES).makeOptionMandatory());
1158
+ addTargetOptions(input, "Act on");
1159
+ input.option("--fx <fraction>", "Start X as a 0-1 fraction of the display width.").option("--fy <fraction>", "Start Y as a 0-1 fraction of the display height.").option("--fx2 <fraction>", "End X fraction (swipe/drag/fling).").option("--fy2 <fraction>", "End Y fraction (swipe/drag/fling).").option("--x <px>", "X pixel (click/swipe start).").option("--y <px>", "Y pixel (click/swipe start).").option("--x2 <px>", "End X pixel (swipe/drag/fling).").option("--y2 <px>", "End Y pixel (swipe/drag/fling).").option("--speed <px-per-s>", "Velocity for swipe/drag/fling.").option(
1160
+ "--key <key>",
1161
+ "Key for keyEvent: Back/Home/Power, a name (Delete, Enter, Tab, Escape, MoveHome, MoveEnd, \u2026), a letter, a KeyCode id, or a combo like Ctrl+A."
1162
+ ).option("--text <text>", "Text for inputText.").option("--clear", "inputText: clear the field (Ctrl+A, Delete) before typing.").option("--hide-keyboard", "Dismiss the soft keyboard afterwards, if it is up.").option("--device <serial>", "Target device serial.").action(async (opts) => {
966
1163
  const { config, logger } = getRuntime();
967
- await sendInput({
1164
+ const result = await performInput({
968
1165
  config,
969
1166
  type: opts.type,
1167
+ target: selectorFrom(opts),
1168
+ targetIndex: targetIndexFrom(opts),
1169
+ fx: num(opts.fx),
1170
+ fy: num(opts.fy),
1171
+ fx2: num(opts.fx2),
1172
+ fy2: num(opts.fy2),
970
1173
  pxX: num(opts.x),
971
1174
  pxY: num(opts.y),
972
1175
  pxX2: num(opts.x2),
@@ -974,14 +1177,31 @@ function registerInputCommand(program) {
974
1177
  speed: num(opts.speed),
975
1178
  key: opts.key,
976
1179
  text: opts.text,
1180
+ clear: opts.clear,
1181
+ hideKeyboard: opts.hideKeyboard,
977
1182
  deviceSerial: opts.device,
978
1183
  logger
979
1184
  });
980
- logger.info(`Sent ${opts.type}.`);
1185
+ if (opts.type === "hideKeyboard") {
1186
+ logger.info(result.keyboardHidden ? "Dismissed the keyboard." : "The keyboard was not shown.");
1187
+ return;
1188
+ }
1189
+ const at = result.x !== void 0 ? ` at ${result.x},${result.y}` : "";
1190
+ const on = result.target ? ` on ${describeLayoutNode3(result.target)}` : "";
1191
+ const kb = result.keyboardHidden ? " (dismissed the keyboard)" : "";
1192
+ logger.info(`Sent ${opts.type}${at}${on}${kb}.`);
981
1193
  });
982
- program.command("gesture").description('Inject a multi-waypoint gesture. Waypoints are pixel JSON: [{"x":..,"y":..,"t":..}].').requiredOption("--waypoints <json>", "JSON array of {x,y,t} pixel waypoints (t = ms from start).").option("--hold-start <ms>", "Leading press-hold before moving (best-effort: uses `uitest drag`).").option("--hold-end <ms>", "Trailing hold before lifting (no uitest equivalent; ignored).").option("--device <serial>", "Target device serial.").action(async (opts) => {
1194
+ program.command("gesture").description('Inject a multi-waypoint gesture. Waypoints are JSON: [{"x":..,"y":..,"t":..}] in pixels (or fractions with --fractions).').requiredOption("--waypoints <json>", "JSON array of {x,y,t} waypoints (t = ms from start).").option("--fractions", "Waypoint x/y are 0-1 fractions of the display instead of pixels.").option("--hold-start <ms>", "Leading press-hold before moving (best-effort: uses `uitest drag`).").option("--hold-end <ms>", "Trailing hold before lifting (no uitest equivalent; ignored).").option("--device <serial>", "Target device serial.").action(async (opts) => {
983
1195
  const { config, logger } = getRuntime();
984
- const waypoints = JSON.parse(opts.waypoints);
1196
+ let waypoints = JSON.parse(opts.waypoints);
1197
+ if (opts.fractions) {
1198
+ const bad = waypoints.find((w) => !(w.x >= 0 && w.x <= 1 && w.y >= 0 && w.y <= 1));
1199
+ if (bad) throw new Error(`With --fractions, waypoint x and y must be 0-1; got ${bad.x},${bad.y}.`);
1200
+ const display = await getDisplaySize(config, { deviceSerial: opts.device, logger });
1201
+ if (!display) throw new Error("Could not read the display size to convert fractions to pixels.");
1202
+ const px = (f, size) => Math.min(size - 1, Math.round(f * size));
1203
+ waypoints = waypoints.map((w) => ({ ...w, x: px(w.x, display.width), y: px(w.y, display.height) }));
1204
+ }
985
1205
  await sendGesture({
986
1206
  config,
987
1207
  waypoints,
@@ -995,7 +1215,7 @@ function registerInputCommand(program) {
995
1215
  }
996
1216
 
997
1217
  // src/bin/oniro-app.ts
998
- var CLI_VERSION = "0.12.0";
1218
+ var CLI_VERSION = "0.13.0";
999
1219
  function buildProgram() {
1000
1220
  const program = new Command4().name("oniro-app").description(
1001
1221
  "Cross-platform CLI for Oniro/OpenHarmony app development.\n\nDesigned for non-interactive use (CI, scripts, agents): every command\ntakes explicit flags, results go to stdout, progress/logs go to stderr,\nand a non-zero exit code indicates failure."
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/bin/oniro-app.ts","../src/commands/sdk.ts","../src/adapters/logger.ts","../src/adapters/progress.ts","../src/adapters/config.ts","../src/lib/runtime.ts","../src/commands/cmdtools.ts","../src/commands/emulator.ts","../src/commands/build.ts","../src/commands/sign.ts","../src/commands/auth.ts","../src/commands/app.ts","../src/commands/create.ts","../src/lib/templateRoot.ts","../src/commands/templates.ts","../src/commands/reboot.ts","../src/commands/wait.ts","../src/commands/watch.ts","../src/commands/screenshot.ts","../src/lib/screenshotImage.ts","../src/commands/dump.ts","../src/commands/devices.ts","../src/commands/file.ts","../src/commands/lint.ts","../src/commands/input.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { OniroError } from '@oniroproject/core';\nimport { registerSdkCommand } from '../commands/sdk.js';\nimport { registerCmdToolsCommand } from '../commands/cmdtools.js';\nimport { registerEmulatorCommand } from '../commands/emulator.js';\nimport { registerBuildCommand } from '../commands/build.js';\nimport { registerSignCommand } from '../commands/sign.js';\nimport { registerAuthCommand } from '../commands/auth.js';\nimport { registerAppCommand } from '../commands/app.js';\nimport { registerCreateCommand } from '../commands/create.js';\nimport { registerTemplatesCommand } from '../commands/templates.js';\nimport { registerRebootCommand } from '../commands/reboot.js';\nimport { registerWaitCommand } from '../commands/wait.js';\nimport { registerWatchCommand } from '../commands/watch.js';\nimport { registerScreenshotCommand } from '../commands/screenshot.js';\nimport { registerDumpCommand } from '../commands/dump.js';\nimport { registerDevicesCommand } from '../commands/devices.js';\nimport { registerFileCommand } from '../commands/file.js';\nimport { registerLintCommand } from '../commands/lint.js';\nimport { registerInputCommand } from '../commands/input.js';\n\ndeclare const __CLI_VERSION__: string;\nconst CLI_VERSION = __CLI_VERSION__;\n\nfunction buildProgram(): Command {\n const program = new Command()\n .name('oniro-app')\n .description(\n 'Cross-platform CLI for Oniro/OpenHarmony app development.\\n\\n' +\n 'Designed for non-interactive use (CI, scripts, agents): every command\\n' +\n 'takes explicit flags, results go to stdout, progress/logs go to stderr,\\n' +\n 'and a non-zero exit code indicates failure.',\n )\n .version(CLI_VERSION)\n .showHelpAfterError();\n\n registerSdkCommand(program);\n registerCmdToolsCommand(program);\n registerEmulatorCommand(program);\n registerBuildCommand(program);\n registerSignCommand(program);\n registerAuthCommand(program);\n registerAppCommand(program);\n registerCreateCommand(program);\n registerTemplatesCommand(program);\n registerRebootCommand(program);\n registerWaitCommand(program);\n registerWatchCommand(program);\n registerScreenshotCommand(program);\n registerDumpCommand(program);\n registerDevicesCommand(program);\n registerFileCommand(program);\n registerLintCommand(program);\n registerInputCommand(program);\n\n return program;\n}\n\nasync function main(): Promise<void> {\n const program = buildProgram();\n try {\n await program.parseAsync(process.argv);\n } catch (err) {\n const message = err instanceof OniroError ? err.message : err instanceof Error ? err.message : String(err);\n process.stderr.write(`[error] ${message}\\n`);\n if (process.env.ONIRO_DEBUG === '1' && err instanceof Error && err.stack) {\n process.stderr.write(`${err.stack}\\n`);\n }\n process.exit(1);\n }\n}\n\nvoid main();\n","import { Command } from 'commander';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport {\n ALL_SDKS,\n downloadAndInstallSdk,\n getOsFolder,\n getSdkRootDir,\n getSupportedSdksForUi,\n removeSdk,\n} from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\n\nexport function registerSdkCommand(program: Command): void {\n const sdk = program.command('sdk').description('Manage OpenHarmony SDK installs.');\n\n sdk\n .command('install <version>')\n .description('Download and install an OpenHarmony SDK. Skips if already installed.')\n .option('--force', 'Reinstall even if the SDK is already present.')\n .option(\n '--tmp-dir <path>',\n 'Directory for download/extract temporaries (default: ONIRO_TMP_DIR, else .oniro-tmp next to ' +\n 'the install target). Use this when that filesystem is short on space.',\n )\n .action(async (version: string, opts: { force?: boolean; tmpDir?: string }) => {\n const { config, logger, progress } = getRuntime();\n const release = ALL_SDKS.find((s) => s.version === version);\n if (!release) {\n throw new Error(\n `Unknown SDK version \"${version}\". Known: ${ALL_SDKS.map((s) => s.version).join(', ')}`,\n );\n }\n const sdkInstallDir = path.join(getSdkRootDir(config), getOsFolder(), release.api);\n if (fs.existsSync(sdkInstallDir) && !opts.force) {\n logger.info(\n `SDK ${release.version} (api ${release.api}) already installed at ${sdkInstallDir}; pass --force to reinstall.`,\n );\n return;\n }\n logger.info(`Installing OpenHarmony SDK ${release.version} (api ${release.api})...`);\n await downloadAndInstallSdk({\n config,\n version: release.version,\n api: release.api,\n progress,\n logger,\n tmpDir: opts.tmpDir,\n });\n logger.info('SDK installed.');\n });\n\n sdk\n .command('list')\n .description('List known SDK versions and whether they are installed on this machine.')\n .option('--json', 'Emit machine-readable JSON instead of a table.')\n .action((opts: { json?: boolean }) => {\n const { config } = getRuntime();\n const sdks = getSupportedSdksForUi(config);\n if (opts.json) {\n process.stdout.write(`${JSON.stringify(sdks, null, 2)}\\n`);\n return;\n }\n const rows = sdks.map((s) => `${s.installed ? '*' : ' '} ${s.version.padEnd(8)} api ${s.api}`);\n process.stdout.write(`${rows.join('\\n')}\\n`);\n });\n\n sdk\n .command('remove <api>')\n .description('Remove an installed SDK by API level (e.g. 18, 20).')\n .action((api: string) => {\n const { config, logger } = getRuntime();\n const removed = removeSdk(config, api);\n if (!removed) {\n logger.warn(`No SDK with api ${api} found under the configured SDK root.`);\n process.exit(1);\n }\n logger.info(`Removed SDK api ${api}.`);\n });\n}\n","import type { Logger } from '@oniroproject/core';\n\n/**\n * Stderr-only logger. All diagnostic output goes to stderr so command stdout\n * stays clean for machine consumers (json results, paths, etc.).\n *\n * Debug lines are suppressed unless `ONIRO_DEBUG=1`.\n */\nexport function createCliLogger(): Logger {\n const debugEnabled = process.env.ONIRO_DEBUG === '1' || process.env.ONIRO_DEBUG === 'true';\n return {\n debug(m) {\n if (debugEnabled) process.stderr.write(`[debug] ${m}\\n`);\n },\n info(m) {\n process.stderr.write(`${m}\\n`);\n },\n warn(m) {\n process.stderr.write(`[warn] ${m}\\n`);\n },\n error(m) {\n process.stderr.write(`[error] ${m}\\n`);\n },\n };\n}\n","import type { ProgressReporter } from '@oniroproject/core';\n\n/**\n * Line-per-update progress reporter, designed for machine consumers and log scrapers.\n * Format: `[progress NN%] message` (or `[progress] message` if no percent is known).\n * Updates that don't change the percent and don't carry a message are suppressed\n * to keep output volume reasonable on chatty downloads.\n */\nexport function createCliProgress(): ProgressReporter {\n let total = 0;\n let lastEmitted = -1;\n let lastMessage = '';\n return {\n report({ message, increment }) {\n if (typeof increment === 'number') total = Math.min(100, total + increment);\n const pct = total > 0 ? Math.round(total) : null;\n const msg = message ?? lastMessage;\n // Drop redundant updates: same message, same percent.\n if (pct === lastEmitted && msg === lastMessage) return;\n const prefix = pct === null ? '[progress]' : `[progress ${pct}%]`;\n process.stderr.write(`${prefix} ${msg}\\n`);\n lastEmitted = pct ?? lastEmitted;\n if (message) lastMessage = message;\n },\n };\n}\n","import * as os from 'node:os';\nimport type { ConfigKey, ConfigProvider } from '@oniroproject/core';\n\n/**\n * Maps a core ConfigKey to its environment variable name.\n * Convention: ONIRO_<UPPER_SNAKE>.\n */\nconst ENV_VAR_BY_KEY: Record<ConfigKey, string> = {\n sdkRootDir: 'ONIRO_SDK_ROOT_DIR',\n cmdToolsPath: 'ONIRO_CMD_TOOLS_PATH',\n hdcPath: 'ONIRO_HDC',\n emulatorDir: 'ONIRO_EMULATOR_DIR',\n hapPath: 'ONIRO_HAP_PATH',\n cmdToolsUrlLinux: 'ONIRO_CMD_TOOLS_URL_LINUX',\n cmdToolsUrlWindows: 'ONIRO_CMD_TOOLS_URL_WINDOWS',\n cmdToolsUrlMac: 'ONIRO_CMD_TOOLS_URL_MAC',\n emulatorUrl: 'ONIRO_EMULATOR_URL',\n tmpDir: 'ONIRO_TMP_DIR',\n sdkUrlBase: 'ONIRO_SDK_URL_BASE',\n applicationCertPath: 'ONIRO_APPLICATION_CERT_PATH',\n harmonyosSdkPath: 'ONIRO_HARMONYOS_SDK_PATH',\n harmonyosAuthDir: 'ONIRO_HARMONYOS_AUTH_DIR',\n harmonyosSigningDir: 'ONIRO_HARMONYOS_SIGNING_DIR',\n};\n\n/**\n * Reads configuration from environment variables (ONIRO_*). Returns the fallback\n * when the variable is unset or empty. Expands `${userHome}` to the user's home\n * directory for parity with the VS Code extension's `${userHome}` expansion.\n */\nexport function createEnvConfig(env: NodeJS.ProcessEnv = process.env): ConfigProvider {\n return {\n get<T extends string | number | boolean>(key: ConfigKey, fallback: T): T {\n const envName = ENV_VAR_BY_KEY[key];\n const raw = env[envName];\n if (raw === undefined || raw === '') return fallback;\n const expanded = raw.includes('${userHome}')\n ? raw.replace(/\\$\\{userHome\\}/g, os.homedir())\n : raw;\n return expanded as unknown as T;\n },\n };\n}\n","import type { ConfigProvider, Logger, ProgressReporter } from '@oniroproject/core';\nimport { createCliLogger } from '../adapters/logger.js';\nimport { createCliProgress } from '../adapters/progress.js';\nimport { createEnvConfig } from '../adapters/config.js';\n\nexport interface CliRuntime {\n logger: Logger;\n config: ConfigProvider;\n progress: ProgressReporter;\n}\n\nlet cached: CliRuntime | null = null;\n\n/**\n * Build (and cache) the per-process runtime used by every command. Tests can\n * override the cached runtime via `setRuntime` to inject mocks.\n */\nexport function getRuntime(): CliRuntime {\n if (!cached) {\n cached = {\n logger: createCliLogger(),\n config: createEnvConfig(),\n progress: createCliProgress(),\n };\n }\n return cached;\n}\n\nexport function setRuntime(runtime: CliRuntime | null): void {\n cached = runtime;\n}\n","import { Command } from 'commander';\nimport { getCmdToolsStatus, installCmdTools, isCmdToolsInstalled, removeCmdTools } from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\n\nexport function registerCmdToolsCommand(program: Command): void {\n const cmdtools = program.command('cmdtools').description('Manage OpenHarmony command-line tools.');\n\n cmdtools\n .command('install')\n .description('Install the OpenHarmony command-line tools (hvigorw, ohpm, hdc). Skips if already installed.')\n .option('--from-zip <path>', 'Install from a local ZIP instead of downloading.')\n .option('--force', 'Reinstall even if the tools are already present.')\n .option(\n '--tmp-dir <path>',\n 'Directory for download/extract temporaries (default: ONIRO_TMP_DIR, else .oniro-tmp next to ' +\n 'the install target). Use this when that filesystem is short on space.',\n )\n .action(async (opts: { fromZip?: string; force?: boolean; tmpDir?: string }) => {\n const { config, logger, progress } = getRuntime();\n if (isCmdToolsInstalled(config) && !opts.force) {\n logger.info('Command-line tools already installed; pass --force to reinstall.');\n return;\n }\n logger.info('Installing OpenHarmony command-line tools...');\n await installCmdTools({ config, progress, logger, localZipPath: opts.fromZip, tmpDir: opts.tmpDir });\n logger.info('Command-line tools installed.');\n });\n\n cmdtools\n .command('status')\n .description('Report whether the command-line tools are installed and their version.')\n .option('--json', 'Emit machine-readable JSON.')\n .action((opts: { json?: boolean }) => {\n const { config } = getRuntime();\n const status = getCmdToolsStatus(config);\n if (opts.json) {\n process.stdout.write(`${JSON.stringify(status, null, 2)}\\n`);\n return;\n }\n process.stdout.write(`${status.status}\\n`);\n if (!status.installed) process.exit(1);\n });\n\n cmdtools\n .command('remove')\n .description('Delete the configured command-line tools directory.')\n .action(() => {\n const { config, logger } = getRuntime();\n removeCmdTools(config);\n logger.info('Command-line tools removed.');\n });\n}\n","import { Command } from 'commander';\nimport {\n attemptHdcConnection,\n installEmulator,\n isEmulatorInstalled,\n removeEmulator,\n startEmulator,\n stopEmulator,\n} from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\n\nexport function registerEmulatorCommand(program: Command): void {\n const emu = program.command('emulator').description('Manage the Oniro emulator.');\n\n emu\n .command('install')\n .description('Download and install the Oniro emulator (QEMU-based). Skips if already installed.')\n .option('--force', 'Reinstall even if the emulator is already present.')\n .option(\n '--tmp-dir <path>',\n 'Directory for the downloaded ZIP (default: ONIRO_TMP_DIR, else .oniro-tmp next to the ' +\n 'install target). Use this when that filesystem is short on space.',\n )\n .action(async (opts: { force?: boolean; tmpDir?: string }) => {\n const { config, logger, progress } = getRuntime();\n if (isEmulatorInstalled(config) && !opts.force) {\n logger.info('Emulator already installed; pass --force to reinstall.');\n return;\n }\n logger.info('Installing Oniro emulator...');\n await installEmulator({ config, progress, logger, tmpDir: opts.tmpDir });\n logger.info('Emulator installed.');\n });\n\n emu\n .command('start')\n .description('Start the Oniro emulator via the bundled launcher (run.sh / run.bat). Detaches so the CLI can exit while the emulator keeps running.')\n .option('--headless', 'Launch headless (VNC + telnet serial, no local window). Required in CI.')\n .option('--log <path>', 'Redirect launcher stdout/stderr to this file. Defaults to discarding output.')\n .option('--wait-for-hdc <seconds>', 'Wait up to N seconds for hdc to connect. 0 = do not wait.', (v) => parseInt(v, 10), 0)\n .option('--connect <host:port>', 'Override the launcher\\'s hdc port-forward bind address. Pass 0.0.0.0:55555 on hosts where QEMU refuses to bind 127.0.0.1 (some CI runners).')\n .action(async (opts: { headless?: boolean; log?: string; waitForHdc: number; connect?: string }) => {\n const { config, logger } = getRuntime();\n await startEmulator({\n config,\n logger,\n headless: opts.headless === true,\n logFile: opts.log,\n waitForHdcSeconds: opts.waitForHdc,\n connect: opts.connect,\n });\n logger.info('Emulator start command complete.');\n });\n\n emu\n .command('stop')\n .description('Kill running emulator processes.')\n .action(async () => {\n const { logger } = getRuntime();\n await stopEmulator(logger);\n logger.info('Emulator stopped.');\n });\n\n emu\n .command('connect')\n .description('Attempt to connect hdc to the emulator.')\n .option('--address <addr>', 'hdc address to connect to', '127.0.0.1:55555')\n .action(async (opts: { address: string }) => {\n const { config, logger } = getRuntime();\n const ok = await attemptHdcConnection(config, opts.address, logger);\n if (!ok) {\n logger.error(`Could not connect hdc to ${opts.address}.`);\n process.exit(1);\n }\n logger.info(`hdc connected to ${opts.address}.`);\n });\n\n emu\n .command('remove')\n .description('Delete the configured emulator directory.')\n .action(() => {\n const { config, logger } = getRuntime();\n removeEmulator(config);\n logger.info('Emulator removed.');\n });\n}\n","import { Command } from 'commander';\nimport * as path from 'node:path';\nimport { buildHap } from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\n\ninterface BuildOpts {\n product: string;\n module?: string;\n mode?: string;\n task: string;\n deps: boolean;\n parallel: boolean;\n json?: boolean;\n}\n\nexport function registerBuildCommand(program: Command): void {\n program\n .command('build [project-dir]')\n .description(\n 'Build an OpenHarmony or HarmonyOS app via hvigorw. Defaults to the current directory. ' +\n 'Projects declaring runtimeOS \"HarmonyOS\" build against the HarmonyOS SDK (ONIRO_HARMONYOS_SDK_PATH or an installed DevEco Studio).',\n )\n .option('--product <product>', 'hvigor product name', 'default')\n .option('--module <module>', 'restrict the build to a specific module')\n .option('--mode <mode>', 'hvigor build mode (e.g. release, debug)')\n .option('--task <task>', 'hvigor task to run', 'assembleHap')\n .option('--no-deps', 'skip the automatic `ohpm install --all` when oh_modules/ is missing')\n .option('--no-parallel', 'build modules serially (default: parallel)')\n .option('--json', 'emit the build result (discovered HAPs, warnings) as JSON')\n .action(async (projectDir: string | undefined, opts: BuildOpts) => {\n const { config, logger } = getRuntime();\n const dir = path.resolve(projectDir ?? process.cwd());\n logger.info(`Building project at ${dir}...`);\n const result = await buildHap({\n config,\n projectDir: dir,\n product: opts.product,\n module: opts.module,\n mode: opts.mode,\n task: opts.task,\n autoInstallDeps: opts.deps,\n parallel: opts.parallel,\n logger,\n // The logger already echoes spawn output; this hook is for streaming to other UIs.\n onOutput: () => {},\n });\n for (const w of result.warnings) logger.warn(w);\n if (opts.json) {\n process.stdout.write(`${JSON.stringify(result, null, 2)}\\n`);\n }\n logger.info('Build complete.');\n });\n}\n","import { Command, Option } from 'commander';\nimport * as path from 'node:path';\nimport {\n APL_VALUES,\n APP_FEATURE_VALUES,\n OniroError,\n createHarmonyOsSession,\n detectRuntimeOs,\n generateSigningConfigs,\n harmonyOsAutoSign,\n prepareSigning,\n getOhosBaseSdkHome,\n type Apl,\n type AppFeature,\n type SigningPasswords,\n} from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\n\nfunction parseAclsList(value: string): string[] {\n return value\n .split(',')\n .map((s) => s.trim())\n .filter((s) => s.length > 0);\n}\n\nexport function registerSignCommand(program: Command): void {\n program\n .command('sign [project-dir]')\n .description(\n [\n 'Generate signing keys, certificates, and signingConfigs for an OpenHarmony project.',\n 'Requires java on PATH. The generated profile uses the SDK\\'s built-in development',\n 'cert (issuer=pki_internal) and its bundled validity window — dev/local builds only.',\n 'Overwrites the `signingConfigs` block in build-profile.json5 (other keys preserved).',\n 'HarmonyOS projects need --harmonyos instead, which has AppGallery Connect issue the',\n 'certificate and profile for a signed-in Huawei account (`oniro-app auth login`).',\n ].join(' '),\n )\n .addOption(\n new Option(\n '--apl <level>',\n 'Ability Privilege Level written into the profile. Apps that request permissions above `normal` (e.g. ohos.permission.GET_WIFI_INFO_INTERNAL) need system_basic or system_core, which also switches the HAP-signing key to \"OpenHarmony Application Release\".',\n )\n .choices([...APL_VALUES])\n .default('normal'),\n )\n .addOption(\n new Option(\n '--app-feature <feature>',\n 'App feature written into the profile. Defaults: hos_normal_app for apl=normal; hos_system_app for apl=system_basic/system_core.',\n ).choices([...APP_FEATURE_VALUES]),\n )\n .addOption(\n new Option(\n '--acls <list>',\n 'Comma-separated permission names to write into the profile\\'s acls.allowed-acls. Required for apps that request permissions above their apl (e.g. a system_basic app requesting ohos.permission.CAPTURE_SCREEN). Example: --acls ohos.permission.REBOOT,ohos.permission.INJECT_INPUT_EVENT',\n ).argParser(parseAclsList),\n )\n .option(\n '--harmonyos',\n 'Sign a HarmonyOS project through AppGallery Connect. Needs `oniro-app auth login`, and a connected device unless the team already has devices registered.',\n )\n .option('--team-id <id>', 'With --harmonyos: the AGC team to sign under. Default: the account\\'s own (`oniro-app auth team list`).')\n .option('--product <name>', 'With --harmonyos: the product to sign. Default `default`.')\n .option('--force', 'With --harmonyos: regenerate the certificate and profile even when they are still valid.')\n .option('--bootstrap', 'No-op if signing material is already present; otherwise generate it.')\n .option('--store-password <pwd>', 'Keystore store password (default 123456 — the SDK keystore password).')\n .option('--key-password <pwd>', 'Keystore key password (default 123456 — the SDK keystore password).')\n .action(\n async (\n projectDir: string | undefined,\n opts: {\n apl: Apl;\n appFeature?: AppFeature;\n acls?: string[];\n bootstrap?: boolean;\n storePassword?: string;\n keyPassword?: string;\n harmonyos?: boolean;\n teamId?: string;\n product?: string;\n force?: boolean;\n },\n ) => {\n const { config, logger } = getRuntime();\n const dir = path.resolve(projectDir ?? process.cwd());\n\n if (opts.harmonyos) {\n const result = await harmonyOsAutoSign({\n config,\n session: createHarmonyOsSession({ config, logger }),\n projectDir: dir,\n productName: opts.product,\n teamId: opts.teamId,\n force: opts.force,\n logger,\n });\n logger.info(`Signing configs ready for ${result.bundleName} (profile names ${result.deviceIds.length} device(s)).`);\n return;\n }\n // The OpenHarmony development certificate cannot sign for a HarmonyOS device.\n if (detectRuntimeOs(dir, opts.product) === 'HarmonyOS') {\n throw new OniroError(\n `${dir} targets HarmonyOS, which needs a certificate from AppGallery Connect: run \\`oniro-app auth login\\` once, then \\`oniro-app sign --harmonyos\\`.`,\n );\n }\n const passwords: SigningPasswords | undefined =\n opts.storePassword || opts.keyPassword\n ? { store: opts.storePassword ?? '123456', key: opts.keyPassword ?? '123456' }\n : undefined;\n\n if (opts.bootstrap) {\n const result = prepareSigning({\n config,\n projectDir: dir,\n apl: opts.apl,\n appFeature: opts.appFeature,\n acls: opts.acls,\n passwords,\n logger,\n });\n logger.info(result.source === 'present' ? 'Signing material already present.' : 'Signing configs generated.');\n return;\n }\n\n const sdkHome = getOhosBaseSdkHome(config);\n logger.info(`Generating signing configs in ${dir} using SDK at ${sdkHome}...`);\n generateSigningConfigs({\n projectDir: dir,\n sdkHome,\n apl: opts.apl,\n appFeature: opts.appFeature,\n acls: opts.acls,\n passwords,\n logger,\n });\n logger.info('Signing configs generated.');\n },\n );\n}\n","import { Command } from 'commander';\nimport { HUAWEI_SITES, createHarmonyOsSession, type HarmonyOsSession } from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\n\n/** A session bound to the CLI runtime. The sign-in URL goes to stderr for headless hosts. */\nfunction session(): HarmonyOsSession {\n const { config, logger } = getRuntime();\n return createHarmonyOsSession({\n config,\n logger,\n onLoginUrl: (url) => process.stderr.write(`Opening the Huawei sign-in page. If no browser opens, visit:\\n ${url}\\n`),\n });\n}\n\nexport function registerAuthCommand(program: Command): void {\n const auth = program\n .command('auth')\n .description(\n 'Sign in to a Huawei developer account, which HarmonyOS signing (`oniro-app sign --harmonyos`) needs. ' +\n 'OpenHarmony signing needs no account. The token is stored encrypted under ONIRO_HARMONYOS_AUTH_DIR ' +\n '(default ~/.oniro/harmonyos).',\n );\n\n auth\n .command('login')\n .description('Sign in through the browser, which redirects back to a loopback port on this machine.')\n .option('--timeout <seconds>', 'How long to wait for the browser sign-in. Default 600.', (v) => Number(v))\n .action(async (opts: { timeout?: number }) => {\n const user = await session().login(opts.timeout ? { timeoutMs: Math.max(1, opts.timeout) * 1000 } : undefined);\n process.stdout.write(`${user.userName || user.userId}\\n`);\n });\n\n auth\n .command('logout')\n .description('Sign out and delete the stored token.')\n .action(async () => {\n const signedOut = await session().logout();\n getRuntime().logger.info(signedOut ? 'Signed out.' : 'Not signed in; nothing to do.');\n });\n\n auth\n .command('status')\n .description('Show the signed-in account. Exits non-zero when not signed in.')\n .option('--json', 'Emit the account details as JSON.')\n .action(async (opts: { json?: boolean }) => {\n const s = session();\n // Refreshed: a stale access token makes the agreement check fail.\n const user = await s.getUserInfo({ refresh: true });\n if (!user) {\n process.stderr.write('Not signed in. Run `oniro-app auth login`.\\n');\n process.exitCode = 1;\n return;\n }\n // Without real-name verification, the developer agreement is what allows signing.\n const agreement = user.isRealName ? null : await s.getDeveloperAgreement(user);\n if (opts.json) {\n const { userId, userName, countryCode, siteCode, isRealName } = user;\n const agcBaseUrl = HUAWEI_SITES[siteCode].agcBaseUrl;\n const status = { userId, userName, countryCode, site: siteCode, agcBaseUrl, isRealName, developerAgreement: agreement, tokenPath: s.tokenPath };\n process.stdout.write(`${JSON.stringify(status, null, 2)}\\n`);\n return;\n }\n process.stdout.write(`${user.userName || user.userId} (${user.userId}) [${user.siteCode}]\\n`);\n if (agreement && !(agreement.signed && agreement.latest)) {\n process.stderr.write(\n '[warn] This account has neither real-name verification nor the current HUAWEI Developer Basic Service Agreement accepted, so AppGallery Connect will not issue signing material. Accept the agreement in AppGallery Connect or DevEco Studio.\\n',\n );\n }\n });\n\n auth\n .command('team')\n .description('AGC teams this account belongs to.')\n .command('list')\n .description('List the AGC teams this account belongs to, for `oniro-app sign --harmonyos --team-id <id>`.')\n .option('--json', 'Emit the team list as JSON.')\n .action(async (opts: { json?: boolean }) => {\n const teams = await session().listTeams();\n if (opts.json) {\n process.stdout.write(`${JSON.stringify(teams, null, 2)}\\n`);\n return;\n }\n for (const t of teams) process.stdout.write(`${t.id}\\t${t.name}\\n`);\n });\n}\n","import { Command } from 'commander';\nimport * as path from 'node:path';\nimport { installApp, launchApp, uninstallApp, forceStop, applyChanges, getBundleName } from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\n\ninterface ApplyOpts {\n bundle?: string;\n module?: string;\n hap?: string;\n installedHap?: string;\n system?: boolean;\n allowUninstall?: boolean;\n device?: string;\n json?: boolean;\n}\n\nexport function registerAppCommand(program: Command): void {\n const app = program.command('app').description('Install, launch, and manage built apps on a connected device/emulator.');\n\n app\n .command('install [project-dir]')\n .description('Install the signed .hap on the connected device/emulator via hdc.')\n .option('--hap <path>', 'Override the .hap path (relative to project-dir or absolute).')\n .option('--device <serial>', 'Target device serial.')\n .action(async (projectDir: string | undefined, opts: { hap?: string; device?: string }) => {\n const { config, logger } = getRuntime();\n const dir = path.resolve(projectDir ?? process.cwd());\n logger.info(`Installing app from ${dir}...`);\n await installApp({ config, projectDir: dir, hapPath: opts.hap, deviceSerial: opts.device, logger });\n logger.info('App installed.');\n });\n\n app\n .command('launch [project-dir]')\n .description(\n 'Launch an app on the connected device/emulator. Project mode (default): resolves ' +\n 'bundle + main ability from the project. Bundle mode (--bundle): launch an ' +\n 'already-installed app by bundle name, no project needed.',\n )\n .option('--bundle <bundle>', 'Launch an already-installed app by bundle name (no project needed).')\n .option('--module <module>', 'Module folder name (project mode).', 'entry')\n .option('--ability <name>', 'Explicit ability to launch (defaults to the module mainElement in project mode, or the installed bundle main ability in --bundle mode).')\n .option('--device <serial>', 'Target device serial.')\n .action(async (projectDir: string | undefined, opts: { bundle?: string; module: string; ability?: string; device?: string }) => {\n const { config, logger } = getRuntime();\n if (opts.bundle) {\n logger.info(`Launching installed bundle ${opts.bundle}...`);\n await launchApp({ config, bundleName: opts.bundle, abilityName: opts.ability, deviceSerial: opts.device, logger });\n } else {\n const dir = path.resolve(projectDir ?? process.cwd());\n logger.info(`Launching app from ${dir}...`);\n await launchApp({ config, projectDir: dir, moduleName: opts.module, abilityName: opts.ability, deviceSerial: opts.device, logger });\n }\n logger.info('App launched.');\n });\n\n app\n .command('apply [project-dir]')\n .description(\n 'Install a HAP and verify the running process took the change. Handles sign-info mismatch, ' +\n 'asset-cache invalidation, and persistent-bundle restart.',\n )\n .option('--bundle <bundle>', 'Bundle name to apply changes to. Defaults to the bundleName in the project AppScope/app.json5.')\n .option('--module <module>', 'Module to resolve the HAP from (multi-module projects).')\n .option('--hap <path>', 'Explicit .hap path (relative to project-dir or absolute).')\n .option('--installed-hap <path>', 'Local path to the currently-installed HAP, to enable the asset-cache reboot.')\n .option('--system', 'Treat as a persistent/system bundle (refuses uninstall on sign-info mismatch).')\n .option('--allow-uninstall', 'Permit uninstalling a system bundle on sign-info mismatch (dangerous).')\n .option('--device <serial>', 'Target device serial.')\n .option('--json', 'Emit the result as JSON.')\n .action(async (projectDir: string | undefined, opts: ApplyOpts) => {\n const { config, logger } = getRuntime();\n const dir = path.resolve(projectDir ?? process.cwd());\n const bundle = opts.bundle ?? getBundleName(dir);\n const result = await applyChanges({\n config,\n bundle,\n hapPath: opts.hap,\n projectDir: dir,\n module: opts.module,\n installedHapPath: opts.installedHap,\n isSystemBundle: opts.system,\n allowUninstall: opts.allowUninstall,\n deviceSerial: opts.device,\n logger,\n });\n if (opts.json) {\n process.stdout.write(`${JSON.stringify(result, null, 2)}\\n`);\n } else {\n logger.info(\n `apply: method=${result.method} pid ${result.preInstallPid ?? '-'} -> ${result.postInstallPid ?? '-'}` +\n `${result.cacheCleared ? ' (cache cleared)' : ''}`,\n );\n }\n });\n\n app\n .command('uninstall <bundle>')\n .description('Uninstall an app by bundle name.')\n .option('--device <serial>', 'Target device serial.')\n .action(async (bundle: string, opts: { device?: string }) => {\n const { config, logger } = getRuntime();\n await uninstallApp({ config, bundle, deviceSerial: opts.device, logger });\n logger.info(`Uninstalled ${bundle}.`);\n });\n\n app\n .command('stop <bundle>')\n .description('Force-stop an app by bundle name.')\n .option('--device <serial>', 'Target device serial.')\n .action(async (bundle: string, opts: { device?: string }) => {\n const { config, logger } = getRuntime();\n await forceStop({ config, bundle, deviceSerial: opts.device, logger });\n logger.info(`Stopped ${bundle}.`);\n });\n}\n","import { Command } from 'commander';\nimport * as path from 'node:path';\nimport {\n ALL_SDKS,\n createScaffold,\n isValidBundleName,\n isValidProjectName,\n} from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\nimport { getBundledTemplateRoot } from '../lib/templateRoot.js';\n\ninterface CreateOpts {\n name: string;\n bundle: string;\n location: string;\n sdk: string;\n template: string;\n module?: string;\n overwrite?: boolean;\n}\n\nexport function registerCreateCommand(program: Command): void {\n program\n .command('create')\n .description('Scaffold a new Oniro/OpenHarmony or HarmonyOS app from a template. All flags are required (non-interactive).')\n .requiredOption('--name <name>', 'Project folder name (letters, digits, ._- only)')\n .requiredOption('--bundle <bundleName>', 'Bundle name in reverse-DNS form, e.g. com.example.myapp')\n .requiredOption('--location <dir>', 'Parent directory where the new project folder will be created')\n .requiredOption('--sdk <api>', 'Target SDK API level (e.g. 18, 20)')\n .option('--template <id>', 'Template id', 'EmptyAbility')\n .option('--module <name>', 'Module folder name (defaults to the template default, usually `entry`)')\n .option('--overwrite', 'Replace the destination if it already exists')\n .action(async (opts: CreateOpts) => {\n const { config, logger } = getRuntime();\n\n if (!isValidProjectName(opts.name)) {\n throw new Error(`Invalid --name '${opts.name}'. Use letters/numbers/._- and no slashes.`);\n }\n if (!isValidBundleName(opts.bundle)) {\n throw new Error(`Invalid --bundle '${opts.bundle}'. Example: com.example.myapp`);\n }\n const sdkApi = Number(opts.sdk);\n if (!Number.isFinite(sdkApi)) {\n throw new Error(`--sdk must be a numeric api level. Known: ${ALL_SDKS.map((s) => s.api).join(', ')}`);\n }\n\n const templateRoot = getBundledTemplateRoot();\n const result = await createScaffold({\n config,\n templateId: opts.template,\n projectName: opts.name,\n bundleName: opts.bundle,\n location: path.resolve(opts.location),\n sdkApi,\n moduleName: opts.module,\n templateRoot,\n overwrite: opts.overwrite,\n logger,\n });\n\n logger.info(`Project created at ${result.projectDir}`);\n process.stdout.write(`${result.projectDir}\\n`);\n });\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n/**\n * Resolve the bundled `templates/` directory shipped inside this CLI package.\n *\n * The CLI's `dist/oniro-app.js` lives at `<pkg>/dist/oniro-app.js` after build\n * and the templates ship at `<pkg>/templates/`. During development the entrypoint\n * lives at `<pkg>/src/bin/oniro-app.ts` so we also try `../../templates` from there.\n */\nexport function getBundledTemplateRoot(): string {\n const here = path.dirname(fileURLToPath(import.meta.url));\n const candidates = [\n path.resolve(here, '../templates'), // dist/oniro-app.js → ../templates\n path.resolve(here, '../../templates'), // src/bin/oniro-app.ts → ../../templates\n ];\n for (const c of candidates) {\n if (fs.existsSync(c)) return c;\n }\n // Return the most likely path even if it doesn't exist yet; createScaffold will\n // surface a clear error from there.\n return candidates[0]!;\n}\n","import { Command } from 'commander';\nimport { listTemplates } from '@oniroproject/core';\nimport { getBundledTemplateRoot } from '../lib/templateRoot.js';\n\nexport function registerTemplatesCommand(program: Command): void {\n const templates = program.command('templates').description('Inspect the templates bundled with this CLI.');\n\n templates\n .command('list')\n .description('List available project templates.')\n .option('--json', 'Emit machine-readable JSON.')\n .action((opts: { json?: boolean }) => {\n const root = getBundledTemplateRoot();\n const list = listTemplates(root);\n if (opts.json) {\n process.stdout.write(`${JSON.stringify(list, null, 2)}\\n`);\n return;\n }\n if (list.length === 0) {\n process.stdout.write('No templates available.\\n');\n return;\n }\n const rows = list.map((t) => `${t.id.padEnd(20)} ${t.label.padEnd(24)} ${t.description}`);\n process.stdout.write(`${rows.join('\\n')}\\n`);\n });\n}\n","import { Command, Option } from 'commander';\nimport { reboot } from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\n\nexport function registerRebootCommand(program: Command): void {\n program\n .command('reboot')\n .description('Reboot the connected device/emulator.')\n .addOption(\n new Option('--mode <mode>', 'Reboot target.').choices(['system', 'bootloader', 'recovery']).default('system'),\n )\n .option('--wait-bundle <bundle>', 'After a system reboot, wait until this bundle is running again.')\n .option('--timeout <ms>', 'Max time to wait for the bundle, ms.', '180000')\n .option('--device <serial>', 'Target device serial.')\n .action(\n async (opts: {\n mode: 'system' | 'bootloader' | 'recovery';\n waitBundle?: string;\n timeout: string;\n device?: string;\n }) => {\n const { config, logger } = getRuntime();\n logger.info(`Rebooting device (${opts.mode})...`);\n await reboot({\n config,\n mode: opts.mode,\n waitForBundle: opts.waitBundle,\n timeoutMs: Number(opts.timeout),\n deviceSerial: opts.device,\n logger,\n });\n logger.info('Reboot complete.');\n },\n );\n}\n","import { Command } from 'commander';\nimport { waitForLog, waitForBoot, waitForBundle } from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\n\ninterface WaitOpts {\n log?: string;\n boot?: boolean;\n bundle?: string;\n pidOf?: string;\n domain?: string;\n timeout: string;\n device?: string;\n json?: boolean;\n}\n\nexport function registerWaitCommand(program: Command): void {\n program\n .command('wait')\n .description('Wait for a device condition: a log line (--log), boot (--boot), or a bundle to start (--bundle).')\n .option('--log <pattern>', 'Resolve when a hilog line (tag: message) matches this regex.')\n .option('--boot', 'Resolve when the device is reachable (optionally also --pid-of).')\n .option('--bundle <bundle>', 'With --log: filter to this bundle. Alone: wait until this bundle is running.')\n .option('--pid-of <name>', 'With --boot: also require this process to have a pid.')\n .option('--domain <domain>', 'With --log: hilog domain filter (e.g. 0xD003900).')\n .option('--timeout <ms>', 'Max wait, ms.', '30000')\n .option('--device <serial>', 'Target device serial.')\n .option('--json', 'With --log: emit the matched entry as JSON.')\n .action(async (opts: WaitOpts) => {\n const { config, logger } = getRuntime();\n const timeoutMs = Number(opts.timeout);\n\n if (opts.log) {\n const entry = await waitForLog({\n config,\n pattern: new RegExp(opts.log),\n timeoutMs,\n bundle: opts.bundle,\n domain: opts.domain,\n deviceSerial: opts.device,\n logger,\n });\n if (opts.json) process.stdout.write(`${JSON.stringify(entry, null, 2)}\\n`);\n else logger.info(`matched: ${entry.tag}: ${entry.message}`);\n return;\n }\n if (opts.boot) {\n await waitForBoot({ config, untilPidOf: opts.pidOf, timeoutMs, deviceSerial: opts.device, logger });\n logger.info('Device booted.');\n return;\n }\n if (opts.bundle) {\n await waitForBundle({ config, bundle: opts.bundle, timeoutMs, deviceSerial: opts.device, logger });\n logger.info(`Bundle ${opts.bundle} is running.`);\n return;\n }\n throw new Error('Specify one of --log <pattern>, --boot, or --bundle <bundle>.');\n });\n}\n","import { Command } from 'commander';\nimport { watchLog } from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\n\ninterface WatchOpts {\n log?: string;\n for: string;\n bundle?: string;\n domain?: string;\n dedup: boolean;\n device?: string;\n json?: boolean;\n}\n\nexport function registerWatchCommand(program: Command): void {\n program\n .command('watch')\n .description('Collect hilog lines matching a pattern for a fixed duration.')\n .option('--log <pattern>', 'Regex tested against each line (tag: message).')\n .option('--for <ms>', 'Duration to watch, ms.', '10000')\n .option('--bundle <bundle>', 'Filter to this bundle.')\n .option('--domain <domain>', 'hilog domain filter (e.g. 0xD003900).')\n .option('--no-dedup', 'Do not collapse consecutive duplicate lines.')\n .option('--device <serial>', 'Target device serial.')\n .option('--json', 'Emit the entries as JSON.')\n .action(async (opts: WatchOpts) => {\n const { config, logger } = getRuntime();\n if (!opts.log) throw new Error('watch requires --log <pattern>.');\n const entries = await watchLog({\n config,\n pattern: new RegExp(opts.log),\n durationMs: Number(opts.for),\n bundle: opts.bundle,\n domain: opts.domain,\n dedup: opts.dedup,\n deviceSerial: opts.device,\n logger,\n });\n if (opts.json) {\n process.stdout.write(`${JSON.stringify(entries, null, 2)}\\n`);\n } else {\n for (const e of entries) process.stdout.write(`${e.time} ${e.level} ${e.tag}: ${e.message}\\n`);\n }\n });\n}\n","import { Command } from 'commander';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { takeScreenshot, captureBurst } from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\nimport { renderWithGrid, buildContactSheet, frameDiffs } from '../lib/screenshotImage.js';\n\ninterface ScreenshotOpts {\n output: string;\n grid?: boolean;\n maxDim: string;\n contactSheet?: boolean;\n burst?: string;\n interval: string;\n json?: boolean;\n device?: string;\n}\n\nconst DEFAULT_CONTACT_SHEET_FRAMES = 8;\n\nfunction clampMaxDim(raw: string): number {\n const n = Number(raw);\n if (!Number.isFinite(n)) return 1024;\n return Math.max(256, Math.min(4096, Math.round(n)));\n}\n\nexport function registerScreenshotCommand(program: Command): void {\n program\n .command('screenshot')\n .description(\n 'Capture the screen. Default: full-resolution raw JPEG. ' +\n '--grid: downscaled JPEG with a 10x10 grid (axes 0.0-1.0) for picking tap coordinates. ' +\n '--contact-sheet: capture a burst and tile it into one image with per-frame change diffs.',\n )\n .option('-o, --output <file>', 'Output file path.', 'screenshot.jpeg')\n .option('--grid', 'Downscale (to --max-dim) and overlay a 10x10 coordinate grid.')\n .option('--max-dim <px>', 'Longest-side cap for --grid / --contact-sheet (256-4096).', '1024')\n .option('--contact-sheet', 'Capture a burst and composite it into one tiled contact sheet.')\n .option('--burst <count>', 'Capture N frames; writes <base>-<i><ext> (or feeds --contact-sheet).')\n .option('--interval <ms>', 'Delay between burst frames, ms.', '50')\n .option('--json', 'Emit the full result object as JSON on stdout (with --contact-sheet).')\n .option('--device <serial>', 'Target device serial.')\n .action(async (opts: ScreenshotOpts, command: Command) => {\n const { config, logger } = getRuntime();\n const maxDim = clampMaxDim(opts.maxDim);\n const intervalMs = Number(opts.interval) || 50;\n\n // --- Contact sheet: burst -> one tiled image + per-frame diffs ---\n if (opts.contactSheet) {\n const count = opts.burst ? Math.max(1, Number(opts.burst)) : DEFAULT_CONTACT_SHEET_FRAMES;\n const frames = await captureBurst({ config, count, intervalMs, deviceSerial: opts.device, logger });\n const diffs = await frameDiffs(frames);\n const sheet = await buildContactSheet(frames, { maxDim, diffs });\n fs.writeFileSync(opts.output, sheet.buf);\n\n // Only fan out the individual raw frames when --burst was also requested.\n if (opts.burst) {\n const ext = path.extname(opts.output) || '.jpeg';\n const base = opts.output.slice(0, opts.output.length - ext.length);\n frames.forEach((frame, i) => fs.writeFileSync(`${base}-${i}${ext}`, frame));\n }\n\n const perFrame = frames.map((_, i) => ({ idx: i, t_ms: i * intervalMs, diffVsPrev: diffs[i] ?? 0 }));\n if (opts.json) {\n process.stdout.write(\n `${JSON.stringify(\n {\n sheet: opts.output,\n frameCount: frames.length,\n cols: sheet.cols,\n rows: sheet.rows,\n intervalMs,\n note: 't_ms is nominal (idx*interval); diffVsPrev is 0..1 mean greyscale diff vs the previous frame.',\n frames: perFrame,\n },\n null,\n 2,\n )}\\n`,\n );\n } else {\n process.stdout.write(`${JSON.stringify(perFrame)}\\n`);\n }\n\n let peak = 0;\n for (let i = 1; i < diffs.length; i++) if ((diffs[i] ?? 0) > (diffs[peak] ?? 0)) peak = i;\n logger.info(\n `Wrote contact sheet ${opts.output} (${sheet.cols}x${sheet.rows}, ${frames.length} frames). ` +\n `Biggest change at frame ${peak} (Δ${(diffs[peak] ?? 0).toFixed(2)}).`,\n );\n return;\n }\n\n // --- Burst (raw frames) — unchanged behaviour ---\n if (opts.burst) {\n const frames = await captureBurst({\n config,\n count: Number(opts.burst),\n intervalMs,\n deviceSerial: opts.device,\n logger,\n });\n const ext = path.extname(opts.output) || '.jpeg';\n const base = opts.output.slice(0, opts.output.length - ext.length);\n frames.forEach((frame, i) => fs.writeFileSync(`${base}-${i}${ext}`, frame));\n logger.info(`Wrote ${frames.length} frames to ${base}-<0..${frames.length - 1}>${ext}.`);\n return;\n }\n\n // --- Single shot ---\n const shot = await takeScreenshot({ config, deviceSerial: opts.device, logger });\n const maxDimProvided = command.getOptionValueSource('maxDim') === 'cli';\n if (opts.grid || maxDimProvided) {\n const rendered = await renderWithGrid(shot.pixels, { maxDim, grid: !!opts.grid });\n fs.writeFileSync(opts.output, rendered.buf);\n logger.info(\n `Wrote ${opts.output} (${rendered.width}x${rendered.height} from ` +\n `${rendered.originalWidth}x${rendered.originalHeight}${opts.grid ? ', 10x10 grid' : ''}).`,\n );\n return;\n }\n fs.writeFileSync(opts.output, shot.pixels);\n logger.info(`Wrote ${opts.output} (${shot.width}x${shot.height}).`);\n });\n}\n","import sharp from 'sharp';\n\n/**\n * Agent-facing screenshot image processing for the CLI.\n *\n * `@oniroproject/core` deliberately ships no image dependency — it returns raw\n * JPEG buffers. The grid overlay / downscale and the burst contact-sheet live\n * here (the CLI is the affordance layer), so `oniro-app screenshot` can produce\n * exactly what the ohos-hdc MCP used to. The grid drawing is ported verbatim\n * from that MCP so the output is equivalent.\n */\n\nexport interface RenderResult {\n /** Encoded JPEG. */\n buf: Buffer;\n /** Rendered (post-downscale) dimensions. */\n width: number;\n height: number;\n /** Source dimensions, before downscale. */\n originalWidth: number;\n originalHeight: number;\n}\n\nexport interface RenderWithGridOptions {\n /** Longest-side cap in pixels. The image is downscaled (never upscaled) to fit. */\n maxDim: number;\n /** Overlay the 10x10 grid with 0.0–1.0 axis labels after downscaling. */\n grid?: boolean;\n}\n\n/**\n * Build an SVG overlay: a 10x10 grid with X/Y axis labels (0.0–1.0) sized to the\n * given image dimensions. Ported verbatim from the ohos-hdc MCP so the gridded\n * output matches what agents are used to.\n */\nexport function buildGridSvg(width: number, height: number): string {\n const lineColor = 'rgba(255,80,80,0.55)';\n const labelBg = 'rgba(0,0,0,0.7)';\n const labelFg = '#fff';\n const fontSize = Math.max(10, Math.round(Math.min(width, height) / 60));\n const padding = Math.round(fontSize * 0.4);\n const labels: string[] = [];\n const lines: string[] = [];\n for (let i = 0; i <= 10; i++) {\n const f = i / 10;\n const x = Math.round(f * (width - 1));\n const y = Math.round(f * (height - 1));\n // grid lines (skip 0 and 10 — those are the image edges)\n if (i > 0 && i < 10) {\n lines.push(`<line x1=\"${x}\" y1=\"0\" x2=\"${x}\" y2=\"${height}\" stroke=\"${lineColor}\" stroke-width=\"1\"/>`);\n lines.push(`<line x1=\"0\" y1=\"${y}\" x2=\"${width}\" y2=\"${y}\" stroke=\"${lineColor}\" stroke-width=\"1\"/>`);\n }\n const tag = f.toFixed(1);\n // X-axis labels along the top\n const tx = i === 0 ? padding : i === 10 ? width - padding : x;\n const anchorX = i === 0 ? 'start' : i === 10 ? 'end' : 'middle';\n labels.push(\n `<text x=\"${tx}\" y=\"${fontSize + padding}\" font-family=\"monospace\" font-size=\"${fontSize}\" font-weight=\"bold\" fill=\"${labelFg}\" stroke=\"${labelBg}\" stroke-width=\"3\" paint-order=\"stroke\" text-anchor=\"${anchorX}\">${tag}</text>`,\n );\n // Y-axis labels along the left\n const ty = i === 0 ? fontSize + padding : i === 10 ? height - padding : y + fontSize / 3;\n labels.push(\n `<text x=\"${padding}\" y=\"${ty}\" font-family=\"monospace\" font-size=\"${fontSize}\" font-weight=\"bold\" fill=\"${labelFg}\" stroke=\"${labelBg}\" stroke-width=\"3\" paint-order=\"stroke\" text-anchor=\"start\">${tag}</text>`,\n );\n }\n // Axis title markers in the corners\n labels.push(\n `<text x=\"${width / 2}\" y=\"${fontSize * 2.4 + padding}\" font-family=\"monospace\" font-size=\"${fontSize}\" font-weight=\"bold\" fill=\"${labelFg}\" stroke=\"${labelBg}\" stroke-width=\"3\" paint-order=\"stroke\" text-anchor=\"middle\">X →</text>`,\n );\n labels.push(\n `<text x=\"${padding}\" y=\"${fontSize * 2.6 + padding}\" font-family=\"monospace\" font-size=\"${fontSize}\" font-weight=\"bold\" fill=\"${labelFg}\" stroke=\"${labelBg}\" stroke-width=\"3\" paint-order=\"stroke\" text-anchor=\"start\">Y ↓</text>`,\n );\n return `<svg width=\"${width}\" height=\"${height}\" xmlns=\"http://www.w3.org/2000/svg\">${lines.join('')}${labels.join('')}</svg>`;\n}\n\n/**\n * Downscale a JPEG so its longest side is <= `maxDim` (never upscaling) and,\n * when `grid` is set, overlay the coordinate grid. Returns the encoded JPEG plus\n * rendered and original dimensions.\n */\nexport async function renderWithGrid(jpeg: Buffer, opts: RenderWithGridOptions): Promise<RenderResult> {\n const meta = await sharp(jpeg).metadata();\n const originalWidth = meta.width ?? 0;\n const originalHeight = meta.height ?? 0;\n const longest = Math.max(originalWidth, originalHeight) || 1;\n const scale = Math.min(1, opts.maxDim / longest);\n const width = Math.max(1, Math.round(originalWidth * scale));\n const height = Math.max(1, Math.round(originalHeight * scale));\n const resized = await sharp(jpeg).resize(width, height).jpeg({ quality: 80 }).toBuffer();\n if (!opts.grid) {\n return { buf: resized, width, height, originalWidth, originalHeight };\n }\n const svg = buildGridSvg(width, height);\n const buf = await sharp(resized)\n .composite([{ input: Buffer.from(svg) }])\n .jpeg({ quality: 80 })\n .toBuffer();\n return { buf, width, height, originalWidth, originalHeight };\n}\n\nexport interface ContactSheetOptions {\n /** Longest-side cap for the whole sheet; per-tile size derives from this. */\n maxDim: number;\n /** Tiles per row. Defaults to ceil(sqrt(N)). */\n cols?: number;\n /** Per-frame diff (0..1), index-aligned with `frames`; printed on each tile. */\n diffs?: number[];\n /** Gap between tiles, px. */\n gap?: number;\n}\n\nexport interface ContactSheetResult {\n buf: Buffer;\n width: number;\n height: number;\n cols: number;\n rows: number;\n tileWidth: number;\n tileHeight: number;\n count: number;\n}\n\nfunction buildTileLabelSvg(width: number, height: number, idx: number, diff?: number): string {\n const fontSize = Math.max(12, Math.round(Math.min(width, height) / 16));\n const pad = Math.round(fontSize * 0.4);\n let label = `#${idx}`;\n if (typeof diff === 'number') label += ` Δ${diff.toFixed(2)}`;\n const boxW = Math.round(label.length * fontSize * 0.62) + pad * 2;\n const boxH = fontSize + pad * 2;\n return (\n `<svg width=\"${width}\" height=\"${height}\" xmlns=\"http://www.w3.org/2000/svg\">` +\n `<rect x=\"0\" y=\"0\" width=\"${boxW}\" height=\"${boxH}\" fill=\"rgba(0,0,0,0.6)\"/>` +\n `<text x=\"${pad}\" y=\"${fontSize + pad - 1}\" font-family=\"monospace\" font-size=\"${fontSize}\" font-weight=\"bold\" fill=\"#fff\" stroke=\"rgba(0,0,0,0.85)\" stroke-width=\"3\" paint-order=\"stroke\" text-anchor=\"start\">${label}</text>` +\n `</svg>`\n );\n}\n\n/**\n * Composite a burst of JPEG frames into a single tiled contact sheet, each tile\n * labelled with its frame index (and per-frame diff when provided). One image\n * replaces N — a large token saving when verifying transient UI.\n */\nexport async function buildContactSheet(frames: Buffer[], opts: ContactSheetOptions): Promise<ContactSheetResult> {\n if (frames.length === 0) throw new Error('buildContactSheet: no frames');\n const count = frames.length;\n const cols = Math.max(1, opts.cols ?? Math.ceil(Math.sqrt(count)));\n const rows = Math.ceil(count / cols);\n const gap = opts.gap ?? 8;\n\n const meta0 = await sharp(frames[0]).metadata();\n const fw = meta0.width ?? 1;\n const fh = meta0.height ?? 1;\n const longest = Math.max(fw, fh) || 1;\n const tileScale = Math.min(1, opts.maxDim / cols / longest);\n const tileWidth = Math.max(1, Math.round(fw * tileScale));\n const tileHeight = Math.max(1, Math.round(fh * tileScale));\n\n const tiles = await Promise.all(\n frames.map((frame, i) => {\n const label = Buffer.from(buildTileLabelSvg(tileWidth, tileHeight, i, opts.diffs?.[i]));\n return sharp(frame)\n .resize(tileWidth, tileHeight, { fit: 'fill' })\n .composite([{ input: label, top: 0, left: 0 }])\n .png()\n .toBuffer();\n }),\n );\n\n const width = cols * tileWidth + (cols + 1) * gap;\n const height = rows * tileHeight + (rows + 1) * gap;\n const placements = tiles.map((input, i) => {\n const r = Math.floor(i / cols);\n const c = i % cols;\n return { input, left: gap + c * (tileWidth + gap), top: gap + r * (tileHeight + gap) };\n });\n\n const buf = await sharp({\n create: { width, height, channels: 3, background: { r: 20, g: 20, b: 20 } },\n })\n .composite(placements)\n .jpeg({ quality: 80 })\n .toBuffer();\n\n return { buf, width, height, cols, rows, tileWidth, tileHeight, count };\n}\n\n/**\n * Per-frame change metric: mean absolute difference of a downscaled greyscale\n * thumbnail vs. the previous frame, normalised to 0..1. Frame 0 is 0 (no\n * predecessor). Cheap, deterministic, and device-free.\n */\nexport async function frameDiffs(frames: Buffer[], opts: { sample?: number } = {}): Promise<number[]> {\n if (frames.length === 0) return [];\n const sample = opts.sample ?? 32;\n const thumbs = await Promise.all(\n frames.map((f) => sharp(f).greyscale().resize(sample, sample, { fit: 'fill' }).raw().toBuffer()),\n );\n const out: number[] = [0];\n for (let i = 1; i < thumbs.length; i++) {\n const a = thumbs[i - 1];\n const b = thumbs[i];\n if (!a || !b) {\n out.push(0);\n continue;\n }\n const n = Math.min(a.length, b.length) || 1;\n let s = 0;\n for (let k = 0; k < n; k++) s += Math.abs((a[k] ?? 0) - (b[k] ?? 0));\n out.push(+(s / n / 255).toFixed(4));\n }\n return out;\n}\n","import { Command } from 'commander';\nimport { dumpLayout } from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\n\ninterface DumpOpts {\n bundle?: string;\n raw?: boolean;\n device?: string;\n}\n\nexport function registerDumpCommand(program: Command): void {\n program\n .command('dump [target]')\n .description('Dump device state as JSON. Currently supports `dump layout` (the default target).')\n .option('--bundle <bundle>', 'Filter the layout to a single window/bundle.')\n .option('--raw', 'Return the unpruned layout tree.')\n .option('--device <serial>', 'Target device serial.')\n .action(async (target: string | undefined, opts: DumpOpts) => {\n const { config, logger } = getRuntime();\n const what = target ?? 'layout';\n if (what !== 'layout') throw new Error(`Unknown dump target \"${what}\". Supported: layout.`);\n const result = await dumpLayout({\n config,\n bundleName: opts.bundle,\n prune: !opts.raw,\n deviceSerial: opts.device,\n logger,\n });\n process.stdout.write(`${JSON.stringify(result, null, 2)}\\n`);\n });\n}\n","import { Command } from 'commander';\nimport { listDevices } from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\n\nexport function registerDevicesCommand(program: Command): void {\n program\n .command('devices')\n .description('List connected hdc devices.')\n .option('--json', 'Emit machine-readable JSON.')\n .action(async (opts: { json?: boolean }) => {\n const { config } = getRuntime();\n const devices = await listDevices(config);\n if (opts.json) {\n process.stdout.write(`${JSON.stringify(devices, null, 2)}\\n`);\n return;\n }\n if (devices.length === 0) {\n process.stdout.write('(no devices)\\n');\n return;\n }\n for (const d of devices) {\n process.stdout.write(`${d.serial}\\t${d.connection ?? ''}\\t${d.status}\\n`);\n }\n });\n}\n","import { Command } from 'commander';\nimport { sendFile, recvFile } from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\n\nexport function registerFileCommand(program: Command): void {\n const file = program.command('file').description('Transfer files to/from the device (hdc file send/recv).');\n\n file\n .command('send <local> <remote>')\n .description('Push a local file to the device.')\n .option('--device <serial>', 'Target device serial.')\n .action(async (local: string, remote: string, opts: { device?: string }) => {\n const { config, logger } = getRuntime();\n await sendFile({ config, local, remote, deviceSerial: opts.device, logger });\n logger.info(`Sent ${local} -> ${remote}.`);\n });\n\n file\n .command('recv <remote> <local>')\n .description('Pull a file from the device.')\n .option('--device <serial>', 'Target device serial.')\n .action(async (remote: string, local: string, opts: { device?: string }) => {\n const { config, logger } = getRuntime();\n await recvFile({ config, remote, local, deviceSerial: opts.device, logger });\n logger.info(`Received ${remote} -> ${local}.`);\n });\n}\n","import { Command } from 'commander';\nimport * as path from 'node:path';\nimport { runCodelinter } from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\n\ninterface LintOpts {\n files?: string[];\n json?: boolean;\n}\n\nexport function registerLintCommand(program: Command): void {\n program\n .command('lint [project-dir]')\n .description('Run the OpenHarmony codelinter on a project. Defaults to the current directory.')\n .option('--files <globs...>', 'Specific files/globs to lint (default: the whole project).')\n .option('--json', 'Emit findings as JSON.')\n .action(async (projectDir: string | undefined, opts: LintOpts) => {\n const { config, logger } = getRuntime();\n const dir = path.resolve(projectDir ?? process.cwd());\n const result = await runCodelinter({ config, projectDir: dir, files: opts.files, logger });\n if (opts.json) {\n process.stdout.write(`${JSON.stringify(result, null, 2)}\\n`);\n } else {\n for (const f of result.findings) {\n process.stdout.write(`${f.file}:${f.line} ${f.severity} ${f.message}${f.code ? ` [${f.code}]` : ''}\\n`);\n }\n if (result.findings.length === 0) process.stdout.write('No findings.\\n');\n }\n // Surface a non-zero codelinter exit to the caller (CI), but let output flush.\n if (result.code !== 0) process.exitCode = result.code;\n });\n}\n","import { Command, Option } from 'commander';\nimport { sendInput, sendGesture, type InputType, type Waypoint } from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\n\nconst INPUT_TYPES: InputType[] = ['click', 'doubleClick', 'longClick', 'swipe', 'drag', 'fling', 'keyEvent', 'inputText'];\n\nconst num = (v: string | undefined): number | undefined => (v === undefined ? undefined : Number(v));\n\ninterface InputOpts {\n type: InputType;\n x?: string;\n y?: string;\n x2?: string;\n y2?: string;\n speed?: string;\n key?: string;\n text?: string;\n device?: string;\n}\n\ninterface GestureOpts {\n waypoints: string;\n holdStart?: string;\n holdEnd?: string;\n device?: string;\n}\n\nexport function registerInputCommand(program: Command): void {\n program\n .command('input')\n .description('Inject a UI input event (pixel coordinates) via uitest uiInput.')\n .addOption(new Option('--type <type>', 'Input type.').choices(INPUT_TYPES).makeOptionMandatory())\n .option('--x <px>', 'X pixel (click/swipe start).')\n .option('--y <px>', 'Y pixel (click/swipe start).')\n .option('--x2 <px>', 'End X pixel (swipe/drag/fling).')\n .option('--y2 <px>', 'End Y pixel (swipe/drag/fling).')\n .option('--speed <px-per-s>', 'Velocity for swipe/drag/fling.')\n .option('--key <key>', 'Key id or symbolic name (Back/Home/Power) for keyEvent.')\n .option('--text <text>', 'Text for inputText.')\n .option('--device <serial>', 'Target device serial.')\n .action(async (opts: InputOpts) => {\n const { config, logger } = getRuntime();\n await sendInput({\n config,\n type: opts.type,\n pxX: num(opts.x),\n pxY: num(opts.y),\n pxX2: num(opts.x2),\n pxY2: num(opts.y2),\n speed: num(opts.speed),\n key: opts.key,\n text: opts.text,\n deviceSerial: opts.device,\n logger,\n });\n logger.info(`Sent ${opts.type}.`);\n });\n\n program\n .command('gesture')\n .description('Inject a multi-waypoint gesture. Waypoints are pixel JSON: [{\"x\":..,\"y\":..,\"t\":..}].')\n .requiredOption('--waypoints <json>', 'JSON array of {x,y,t} pixel waypoints (t = ms from start).')\n .option('--hold-start <ms>', 'Leading press-hold before moving (best-effort: uses `uitest drag`).')\n .option('--hold-end <ms>', 'Trailing hold before lifting (no uitest equivalent; ignored).')\n .option('--device <serial>', 'Target device serial.')\n .action(async (opts: GestureOpts) => {\n const { config, logger } = getRuntime();\n const waypoints = JSON.parse(opts.waypoints) as Waypoint[];\n await sendGesture({\n config,\n waypoints,\n holdStartMs: num(opts.holdStart),\n holdEndMs: num(opts.holdEnd),\n deviceSerial: opts.device,\n logger,\n });\n logger.info('Gesture sent.');\n });\n}\n"],"mappings":"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","names":["Command","OniroError","path","path","createHarmonyOsSession","createHarmonyOsSession","path","path","ALL_SDKS","fs","path","ALL_SDKS","Option","Option","fs","path","path","Option","Option","Command","OniroError"]}
1
+ {"version":3,"sources":["../src/bin/oniro-app.ts","../src/commands/sdk.ts","../src/adapters/logger.ts","../src/adapters/progress.ts","../src/adapters/config.ts","../src/lib/runtime.ts","../src/commands/cmdtools.ts","../src/commands/emulator.ts","../src/commands/build.ts","../src/commands/sign.ts","../src/commands/auth.ts","../src/commands/app.ts","../src/commands/create.ts","../src/lib/templateRoot.ts","../src/commands/templates.ts","../src/commands/reboot.ts","../src/commands/wait.ts","../src/lib/target.ts","../src/commands/watch.ts","../src/commands/screenshot.ts","../src/lib/screenshotImage.ts","../src/commands/dump.ts","../src/lib/layoutText.ts","../src/commands/devices.ts","../src/commands/file.ts","../src/commands/lint.ts","../src/commands/input.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { OniroError } from '@oniroproject/core';\nimport { registerSdkCommand } from '../commands/sdk.js';\nimport { registerCmdToolsCommand } from '../commands/cmdtools.js';\nimport { registerEmulatorCommand } from '../commands/emulator.js';\nimport { registerBuildCommand } from '../commands/build.js';\nimport { registerSignCommand } from '../commands/sign.js';\nimport { registerAuthCommand } from '../commands/auth.js';\nimport { registerAppCommand } from '../commands/app.js';\nimport { registerCreateCommand } from '../commands/create.js';\nimport { registerTemplatesCommand } from '../commands/templates.js';\nimport { registerRebootCommand } from '../commands/reboot.js';\nimport { registerWaitCommand } from '../commands/wait.js';\nimport { registerWatchCommand } from '../commands/watch.js';\nimport { registerScreenshotCommand } from '../commands/screenshot.js';\nimport { registerDumpCommand } from '../commands/dump.js';\nimport { registerDevicesCommand } from '../commands/devices.js';\nimport { registerFileCommand } from '../commands/file.js';\nimport { registerLintCommand } from '../commands/lint.js';\nimport { registerInputCommand } from '../commands/input.js';\n\ndeclare const __CLI_VERSION__: string;\nconst CLI_VERSION = __CLI_VERSION__;\n\nfunction buildProgram(): Command {\n const program = new Command()\n .name('oniro-app')\n .description(\n 'Cross-platform CLI for Oniro/OpenHarmony app development.\\n\\n' +\n 'Designed for non-interactive use (CI, scripts, agents): every command\\n' +\n 'takes explicit flags, results go to stdout, progress/logs go to stderr,\\n' +\n 'and a non-zero exit code indicates failure.',\n )\n .version(CLI_VERSION)\n .showHelpAfterError();\n\n registerSdkCommand(program);\n registerCmdToolsCommand(program);\n registerEmulatorCommand(program);\n registerBuildCommand(program);\n registerSignCommand(program);\n registerAuthCommand(program);\n registerAppCommand(program);\n registerCreateCommand(program);\n registerTemplatesCommand(program);\n registerRebootCommand(program);\n registerWaitCommand(program);\n registerWatchCommand(program);\n registerScreenshotCommand(program);\n registerDumpCommand(program);\n registerDevicesCommand(program);\n registerFileCommand(program);\n registerLintCommand(program);\n registerInputCommand(program);\n\n return program;\n}\n\nasync function main(): Promise<void> {\n const program = buildProgram();\n try {\n await program.parseAsync(process.argv);\n } catch (err) {\n const message = err instanceof OniroError ? err.message : err instanceof Error ? err.message : String(err);\n process.stderr.write(`[error] ${message}\\n`);\n if (process.env.ONIRO_DEBUG === '1' && err instanceof Error && err.stack) {\n process.stderr.write(`${err.stack}\\n`);\n }\n process.exit(1);\n }\n}\n\nvoid main();\n","import { Command } from 'commander';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport {\n ALL_SDKS,\n downloadAndInstallSdk,\n getOsFolder,\n getSdkRootDir,\n getSupportedSdksForUi,\n removeSdk,\n} from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\n\nexport function registerSdkCommand(program: Command): void {\n const sdk = program.command('sdk').description('Manage OpenHarmony SDK installs.');\n\n sdk\n .command('install <version>')\n .description('Download and install an OpenHarmony SDK. Skips if already installed.')\n .option('--force', 'Reinstall even if the SDK is already present.')\n .option(\n '--tmp-dir <path>',\n 'Directory for download/extract temporaries (default: ONIRO_TMP_DIR, else .oniro-tmp next to ' +\n 'the install target). Use this when that filesystem is short on space.',\n )\n .action(async (version: string, opts: { force?: boolean; tmpDir?: string }) => {\n const { config, logger, progress } = getRuntime();\n const release = ALL_SDKS.find((s) => s.version === version);\n if (!release) {\n throw new Error(\n `Unknown SDK version \"${version}\". Known: ${ALL_SDKS.map((s) => s.version).join(', ')}`,\n );\n }\n const sdkInstallDir = path.join(getSdkRootDir(config), getOsFolder(), release.api);\n if (fs.existsSync(sdkInstallDir) && !opts.force) {\n logger.info(\n `SDK ${release.version} (api ${release.api}) already installed at ${sdkInstallDir}; pass --force to reinstall.`,\n );\n return;\n }\n logger.info(`Installing OpenHarmony SDK ${release.version} (api ${release.api})...`);\n await downloadAndInstallSdk({\n config,\n version: release.version,\n api: release.api,\n progress,\n logger,\n tmpDir: opts.tmpDir,\n });\n logger.info('SDK installed.');\n });\n\n sdk\n .command('list')\n .description('List known SDK versions and whether they are installed on this machine.')\n .option('--json', 'Emit machine-readable JSON instead of a table.')\n .action((opts: { json?: boolean }) => {\n const { config } = getRuntime();\n const sdks = getSupportedSdksForUi(config);\n if (opts.json) {\n process.stdout.write(`${JSON.stringify(sdks, null, 2)}\\n`);\n return;\n }\n const rows = sdks.map((s) => `${s.installed ? '*' : ' '} ${s.version.padEnd(8)} api ${s.api}`);\n process.stdout.write(`${rows.join('\\n')}\\n`);\n });\n\n sdk\n .command('remove <api>')\n .description('Remove an installed SDK by API level (e.g. 18, 20).')\n .action((api: string) => {\n const { config, logger } = getRuntime();\n const removed = removeSdk(config, api);\n if (!removed) {\n logger.warn(`No SDK with api ${api} found under the configured SDK root.`);\n process.exit(1);\n }\n logger.info(`Removed SDK api ${api}.`);\n });\n}\n","import type { Logger } from '@oniroproject/core';\n\n/**\n * Stderr-only logger. All diagnostic output goes to stderr so command stdout\n * stays clean for machine consumers (json results, paths, etc.).\n *\n * Debug lines are suppressed unless `ONIRO_DEBUG=1`.\n */\nexport function createCliLogger(): Logger {\n const debugEnabled = process.env.ONIRO_DEBUG === '1' || process.env.ONIRO_DEBUG === 'true';\n return {\n debug(m) {\n if (debugEnabled) process.stderr.write(`[debug] ${m}\\n`);\n },\n info(m) {\n process.stderr.write(`${m}\\n`);\n },\n warn(m) {\n process.stderr.write(`[warn] ${m}\\n`);\n },\n error(m) {\n process.stderr.write(`[error] ${m}\\n`);\n },\n };\n}\n","import type { ProgressReporter } from '@oniroproject/core';\n\n/**\n * Line-per-update progress reporter, designed for machine consumers and log scrapers.\n * Format: `[progress NN%] message` (or `[progress] message` if no percent is known).\n * Updates that don't change the percent and don't carry a message are suppressed\n * to keep output volume reasonable on chatty downloads.\n */\nexport function createCliProgress(): ProgressReporter {\n let total = 0;\n let lastEmitted = -1;\n let lastMessage = '';\n return {\n report({ message, increment }) {\n if (typeof increment === 'number') total = Math.min(100, total + increment);\n const pct = total > 0 ? Math.round(total) : null;\n const msg = message ?? lastMessage;\n // Drop redundant updates: same message, same percent.\n if (pct === lastEmitted && msg === lastMessage) return;\n const prefix = pct === null ? '[progress]' : `[progress ${pct}%]`;\n process.stderr.write(`${prefix} ${msg}\\n`);\n lastEmitted = pct ?? lastEmitted;\n if (message) lastMessage = message;\n },\n };\n}\n","import * as os from 'node:os';\nimport type { ConfigKey, ConfigProvider } from '@oniroproject/core';\n\n/**\n * Maps a core ConfigKey to its environment variable name.\n * Convention: ONIRO_<UPPER_SNAKE>.\n */\nconst ENV_VAR_BY_KEY: Record<ConfigKey, string> = {\n sdkRootDir: 'ONIRO_SDK_ROOT_DIR',\n cmdToolsPath: 'ONIRO_CMD_TOOLS_PATH',\n hdcPath: 'ONIRO_HDC',\n emulatorDir: 'ONIRO_EMULATOR_DIR',\n hapPath: 'ONIRO_HAP_PATH',\n cmdToolsUrlLinux: 'ONIRO_CMD_TOOLS_URL_LINUX',\n cmdToolsUrlWindows: 'ONIRO_CMD_TOOLS_URL_WINDOWS',\n cmdToolsUrlMac: 'ONIRO_CMD_TOOLS_URL_MAC',\n emulatorUrl: 'ONIRO_EMULATOR_URL',\n tmpDir: 'ONIRO_TMP_DIR',\n sdkUrlBase: 'ONIRO_SDK_URL_BASE',\n applicationCertPath: 'ONIRO_APPLICATION_CERT_PATH',\n harmonyosSdkPath: 'ONIRO_HARMONYOS_SDK_PATH',\n harmonyosAuthDir: 'ONIRO_HARMONYOS_AUTH_DIR',\n harmonyosSigningDir: 'ONIRO_HARMONYOS_SIGNING_DIR',\n};\n\n/**\n * Reads configuration from environment variables (ONIRO_*). Returns the fallback\n * when the variable is unset or empty. Expands `${userHome}` to the user's home\n * directory for parity with the VS Code extension's `${userHome}` expansion.\n */\nexport function createEnvConfig(env: NodeJS.ProcessEnv = process.env): ConfigProvider {\n return {\n get<T extends string | number | boolean>(key: ConfigKey, fallback: T): T {\n const envName = ENV_VAR_BY_KEY[key];\n const raw = env[envName];\n if (raw === undefined || raw === '') return fallback;\n const expanded = raw.includes('${userHome}')\n ? raw.replace(/\\$\\{userHome\\}/g, os.homedir())\n : raw;\n return expanded as unknown as T;\n },\n };\n}\n","import type { ConfigProvider, Logger, ProgressReporter } from '@oniroproject/core';\nimport { createCliLogger } from '../adapters/logger.js';\nimport { createCliProgress } from '../adapters/progress.js';\nimport { createEnvConfig } from '../adapters/config.js';\n\nexport interface CliRuntime {\n logger: Logger;\n config: ConfigProvider;\n progress: ProgressReporter;\n}\n\nlet cached: CliRuntime | null = null;\n\n/**\n * Build (and cache) the per-process runtime used by every command. Tests can\n * override the cached runtime via `setRuntime` to inject mocks.\n */\nexport function getRuntime(): CliRuntime {\n if (!cached) {\n cached = {\n logger: createCliLogger(),\n config: createEnvConfig(),\n progress: createCliProgress(),\n };\n }\n return cached;\n}\n\nexport function setRuntime(runtime: CliRuntime | null): void {\n cached = runtime;\n}\n","import { Command } from 'commander';\nimport { getCmdToolsStatus, installCmdTools, isCmdToolsInstalled, removeCmdTools } from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\n\nexport function registerCmdToolsCommand(program: Command): void {\n const cmdtools = program.command('cmdtools').description('Manage OpenHarmony command-line tools.');\n\n cmdtools\n .command('install')\n .description('Install the OpenHarmony command-line tools (hvigorw, ohpm, hdc). Skips if already installed.')\n .option('--from-zip <path>', 'Install from a local ZIP instead of downloading.')\n .option('--force', 'Reinstall even if the tools are already present.')\n .option(\n '--tmp-dir <path>',\n 'Directory for download/extract temporaries (default: ONIRO_TMP_DIR, else .oniro-tmp next to ' +\n 'the install target). Use this when that filesystem is short on space.',\n )\n .action(async (opts: { fromZip?: string; force?: boolean; tmpDir?: string }) => {\n const { config, logger, progress } = getRuntime();\n if (isCmdToolsInstalled(config) && !opts.force) {\n logger.info('Command-line tools already installed; pass --force to reinstall.');\n return;\n }\n logger.info('Installing OpenHarmony command-line tools...');\n await installCmdTools({ config, progress, logger, localZipPath: opts.fromZip, tmpDir: opts.tmpDir });\n logger.info('Command-line tools installed.');\n });\n\n cmdtools\n .command('status')\n .description('Report whether the command-line tools are installed and their version.')\n .option('--json', 'Emit machine-readable JSON.')\n .action((opts: { json?: boolean }) => {\n const { config } = getRuntime();\n const status = getCmdToolsStatus(config);\n if (opts.json) {\n process.stdout.write(`${JSON.stringify(status, null, 2)}\\n`);\n return;\n }\n process.stdout.write(`${status.status}\\n`);\n if (!status.installed) process.exit(1);\n });\n\n cmdtools\n .command('remove')\n .description('Delete the configured command-line tools directory.')\n .action(() => {\n const { config, logger } = getRuntime();\n removeCmdTools(config);\n logger.info('Command-line tools removed.');\n });\n}\n","import { Command } from 'commander';\nimport {\n attemptHdcConnection,\n installEmulator,\n isEmulatorInstalled,\n removeEmulator,\n startEmulator,\n stopEmulator,\n} from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\n\nexport function registerEmulatorCommand(program: Command): void {\n const emu = program.command('emulator').description('Manage the Oniro emulator.');\n\n emu\n .command('install')\n .description('Download and install the Oniro emulator (QEMU-based). Skips if already installed.')\n .option('--force', 'Reinstall even if the emulator is already present.')\n .option(\n '--tmp-dir <path>',\n 'Directory for the downloaded ZIP (default: ONIRO_TMP_DIR, else .oniro-tmp next to the ' +\n 'install target). Use this when that filesystem is short on space.',\n )\n .action(async (opts: { force?: boolean; tmpDir?: string }) => {\n const { config, logger, progress } = getRuntime();\n if (isEmulatorInstalled(config) && !opts.force) {\n logger.info('Emulator already installed; pass --force to reinstall.');\n return;\n }\n logger.info('Installing Oniro emulator...');\n await installEmulator({ config, progress, logger, tmpDir: opts.tmpDir });\n logger.info('Emulator installed.');\n });\n\n emu\n .command('start')\n .description('Start the Oniro emulator via the bundled launcher (run.sh / run.bat). Detaches so the CLI can exit while the emulator keeps running.')\n .option('--headless', 'Launch headless (VNC + telnet serial, no local window). Required in CI.')\n .option('--log <path>', 'Redirect launcher stdout/stderr to this file. Defaults to discarding output.')\n .option('--wait-for-hdc <seconds>', 'Wait up to N seconds for hdc to connect. 0 = do not wait.', (v) => parseInt(v, 10), 0)\n .option('--connect <host:port>', 'Override the launcher\\'s hdc port-forward bind address. Pass 0.0.0.0:55555 on hosts where QEMU refuses to bind 127.0.0.1 (some CI runners).')\n .action(async (opts: { headless?: boolean; log?: string; waitForHdc: number; connect?: string }) => {\n const { config, logger } = getRuntime();\n await startEmulator({\n config,\n logger,\n headless: opts.headless === true,\n logFile: opts.log,\n waitForHdcSeconds: opts.waitForHdc,\n connect: opts.connect,\n });\n logger.info('Emulator start command complete.');\n });\n\n emu\n .command('stop')\n .description('Kill running emulator processes.')\n .action(async () => {\n const { logger } = getRuntime();\n await stopEmulator(logger);\n logger.info('Emulator stopped.');\n });\n\n emu\n .command('connect')\n .description('Attempt to connect hdc to the emulator.')\n .option('--address <addr>', 'hdc address to connect to', '127.0.0.1:55555')\n .action(async (opts: { address: string }) => {\n const { config, logger } = getRuntime();\n const ok = await attemptHdcConnection(config, opts.address, logger);\n if (!ok) {\n logger.error(`Could not connect hdc to ${opts.address}.`);\n process.exit(1);\n }\n logger.info(`hdc connected to ${opts.address}.`);\n });\n\n emu\n .command('remove')\n .description('Delete the configured emulator directory.')\n .action(() => {\n const { config, logger } = getRuntime();\n removeEmulator(config);\n logger.info('Emulator removed.');\n });\n}\n","import { Command } from 'commander';\nimport * as path from 'node:path';\nimport { buildHap } from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\n\ninterface BuildOpts {\n product: string;\n module?: string;\n mode?: string;\n task: string;\n deps: boolean;\n parallel: boolean;\n json?: boolean;\n}\n\nexport function registerBuildCommand(program: Command): void {\n program\n .command('build [project-dir]')\n .description(\n 'Build an OpenHarmony or HarmonyOS app via hvigorw. Defaults to the current directory. ' +\n 'Projects declaring runtimeOS \"HarmonyOS\" build against the HarmonyOS SDK (ONIRO_HARMONYOS_SDK_PATH or an installed DevEco Studio).',\n )\n .option('--product <product>', 'hvigor product name', 'default')\n .option('--module <module>', 'restrict the build to a specific module')\n .option('--mode <mode>', 'hvigor build mode (e.g. release, debug)')\n .option('--task <task>', 'hvigor task to run', 'assembleHap')\n .option('--no-deps', 'skip the automatic `ohpm install --all` when oh_modules/ is missing')\n .option('--no-parallel', 'build modules serially (default: parallel)')\n .option('--json', 'emit the build result (discovered HAPs, warnings) as JSON')\n .action(async (projectDir: string | undefined, opts: BuildOpts) => {\n const { config, logger } = getRuntime();\n const dir = path.resolve(projectDir ?? process.cwd());\n logger.info(`Building project at ${dir}...`);\n const result = await buildHap({\n config,\n projectDir: dir,\n product: opts.product,\n module: opts.module,\n mode: opts.mode,\n task: opts.task,\n autoInstallDeps: opts.deps,\n parallel: opts.parallel,\n logger,\n // The logger already echoes spawn output; this hook is for streaming to other UIs.\n onOutput: () => {},\n });\n for (const w of result.warnings) logger.warn(w);\n if (opts.json) {\n process.stdout.write(`${JSON.stringify(result, null, 2)}\\n`);\n }\n logger.info('Build complete.');\n });\n}\n","import { Command, Option } from 'commander';\nimport * as path from 'node:path';\nimport {\n APL_VALUES,\n APP_FEATURE_VALUES,\n OniroError,\n createHarmonyOsSession,\n detectRuntimeOs,\n generateSigningConfigs,\n harmonyOsAutoSign,\n prepareSigning,\n getOhosBaseSdkHome,\n type Apl,\n type AppFeature,\n type SigningPasswords,\n} from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\n\nfunction parseAclsList(value: string): string[] {\n return value\n .split(',')\n .map((s) => s.trim())\n .filter((s) => s.length > 0);\n}\n\nexport function registerSignCommand(program: Command): void {\n program\n .command('sign [project-dir]')\n .description(\n [\n 'Generate signing keys, certificates, and signingConfigs for an OpenHarmony project.',\n 'Requires java on PATH. The generated profile uses the SDK\\'s built-in development',\n 'cert (issuer=pki_internal) and its bundled validity window — dev/local builds only.',\n 'Overwrites the `signingConfigs` block in build-profile.json5 (other keys preserved).',\n 'HarmonyOS projects need --harmonyos instead, which has AppGallery Connect issue the',\n 'certificate and profile for a signed-in Huawei account (`oniro-app auth login`).',\n ].join(' '),\n )\n .addOption(\n new Option(\n '--apl <level>',\n 'Ability Privilege Level written into the profile. Apps that request permissions above `normal` (e.g. ohos.permission.GET_WIFI_INFO_INTERNAL) need system_basic or system_core, which also switches the HAP-signing key to \"OpenHarmony Application Release\".',\n )\n .choices([...APL_VALUES])\n .default('normal'),\n )\n .addOption(\n new Option(\n '--app-feature <feature>',\n 'App feature written into the profile. Defaults: hos_normal_app for apl=normal; hos_system_app for apl=system_basic/system_core.',\n ).choices([...APP_FEATURE_VALUES]),\n )\n .addOption(\n new Option(\n '--acls <list>',\n 'Comma-separated permission names to write into the profile\\'s acls.allowed-acls. Required for apps that request permissions above their apl (e.g. a system_basic app requesting ohos.permission.CAPTURE_SCREEN). Example: --acls ohos.permission.REBOOT,ohos.permission.INJECT_INPUT_EVENT',\n ).argParser(parseAclsList),\n )\n .option(\n '--harmonyos',\n 'Sign a HarmonyOS project through AppGallery Connect. Needs `oniro-app auth login`, and a connected device unless the team already has devices registered.',\n )\n .option('--team-id <id>', 'With --harmonyos: the AGC team to sign under. Default: the account\\'s own (`oniro-app auth team list`).')\n .option('--product <name>', 'With --harmonyos: the product to sign. Default `default`.')\n .option('--force', 'With --harmonyos: regenerate the certificate and profile even when they are still valid.')\n .option('--bootstrap', 'No-op if signing material is already present; otherwise generate it.')\n .option('--store-password <pwd>', 'Keystore store password (default 123456 — the SDK keystore password).')\n .option('--key-password <pwd>', 'Keystore key password (default 123456 — the SDK keystore password).')\n .action(\n async (\n projectDir: string | undefined,\n opts: {\n apl: Apl;\n appFeature?: AppFeature;\n acls?: string[];\n bootstrap?: boolean;\n storePassword?: string;\n keyPassword?: string;\n harmonyos?: boolean;\n teamId?: string;\n product?: string;\n force?: boolean;\n },\n ) => {\n const { config, logger } = getRuntime();\n const dir = path.resolve(projectDir ?? process.cwd());\n\n if (opts.harmonyos) {\n const result = await harmonyOsAutoSign({\n config,\n session: createHarmonyOsSession({ config, logger }),\n projectDir: dir,\n productName: opts.product,\n teamId: opts.teamId,\n force: opts.force,\n logger,\n });\n logger.info(`Signing configs ready for ${result.bundleName} (profile names ${result.deviceIds.length} device(s)).`);\n return;\n }\n // The OpenHarmony development certificate cannot sign for a HarmonyOS device.\n if (detectRuntimeOs(dir, opts.product) === 'HarmonyOS') {\n throw new OniroError(\n `${dir} targets HarmonyOS, which needs a certificate from AppGallery Connect: run \\`oniro-app auth login\\` once, then \\`oniro-app sign --harmonyos\\`.`,\n );\n }\n const passwords: SigningPasswords | undefined =\n opts.storePassword || opts.keyPassword\n ? { store: opts.storePassword ?? '123456', key: opts.keyPassword ?? '123456' }\n : undefined;\n\n if (opts.bootstrap) {\n const result = prepareSigning({\n config,\n projectDir: dir,\n apl: opts.apl,\n appFeature: opts.appFeature,\n acls: opts.acls,\n passwords,\n logger,\n });\n logger.info(result.source === 'present' ? 'Signing material already present.' : 'Signing configs generated.');\n return;\n }\n\n const sdkHome = getOhosBaseSdkHome(config);\n logger.info(`Generating signing configs in ${dir} using SDK at ${sdkHome}...`);\n generateSigningConfigs({\n projectDir: dir,\n sdkHome,\n apl: opts.apl,\n appFeature: opts.appFeature,\n acls: opts.acls,\n passwords,\n logger,\n });\n logger.info('Signing configs generated.');\n },\n );\n}\n","import { Command } from 'commander';\nimport { HUAWEI_SITES, createHarmonyOsSession, type HarmonyOsSession } from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\n\n/** A session bound to the CLI runtime. The sign-in URL goes to stderr for headless hosts. */\nfunction session(): HarmonyOsSession {\n const { config, logger } = getRuntime();\n return createHarmonyOsSession({\n config,\n logger,\n onLoginUrl: (url) => process.stderr.write(`Opening the Huawei sign-in page. If no browser opens, visit:\\n ${url}\\n`),\n });\n}\n\nexport function registerAuthCommand(program: Command): void {\n const auth = program\n .command('auth')\n .description(\n 'Sign in to a Huawei developer account, which HarmonyOS signing (`oniro-app sign --harmonyos`) needs. ' +\n 'OpenHarmony signing needs no account. The token is stored encrypted under ONIRO_HARMONYOS_AUTH_DIR ' +\n '(default ~/.oniro/harmonyos).',\n );\n\n auth\n .command('login')\n .description('Sign in through the browser, which redirects back to a loopback port on this machine.')\n .option('--timeout <seconds>', 'How long to wait for the browser sign-in. Default 600.', (v) => Number(v))\n .action(async (opts: { timeout?: number }) => {\n const user = await session().login(opts.timeout ? { timeoutMs: Math.max(1, opts.timeout) * 1000 } : undefined);\n process.stdout.write(`${user.userName || user.userId}\\n`);\n });\n\n auth\n .command('logout')\n .description('Sign out and delete the stored token.')\n .action(async () => {\n const signedOut = await session().logout();\n getRuntime().logger.info(signedOut ? 'Signed out.' : 'Not signed in; nothing to do.');\n });\n\n auth\n .command('status')\n .description('Show the signed-in account. Exits non-zero when not signed in.')\n .option('--json', 'Emit the account details as JSON.')\n .action(async (opts: { json?: boolean }) => {\n const s = session();\n // Refreshed: a stale access token makes the agreement check fail.\n const user = await s.getUserInfo({ refresh: true });\n if (!user) {\n process.stderr.write('Not signed in. Run `oniro-app auth login`.\\n');\n process.exitCode = 1;\n return;\n }\n // Without real-name verification, the developer agreement is what allows signing.\n const agreement = user.isRealName ? null : await s.getDeveloperAgreement(user);\n if (opts.json) {\n const { userId, userName, countryCode, siteCode, isRealName } = user;\n const agcBaseUrl = HUAWEI_SITES[siteCode].agcBaseUrl;\n const status = { userId, userName, countryCode, site: siteCode, agcBaseUrl, isRealName, developerAgreement: agreement, tokenPath: s.tokenPath };\n process.stdout.write(`${JSON.stringify(status, null, 2)}\\n`);\n return;\n }\n process.stdout.write(`${user.userName || user.userId} (${user.userId}) [${user.siteCode}]\\n`);\n if (agreement && !(agreement.signed && agreement.latest)) {\n process.stderr.write(\n '[warn] This account has neither real-name verification nor the current HUAWEI Developer Basic Service Agreement accepted, so AppGallery Connect will not issue signing material. Accept the agreement in AppGallery Connect or DevEco Studio.\\n',\n );\n }\n });\n\n auth\n .command('team')\n .description('AGC teams this account belongs to.')\n .command('list')\n .description('List the AGC teams this account belongs to, for `oniro-app sign --harmonyos --team-id <id>`.')\n .option('--json', 'Emit the team list as JSON.')\n .action(async (opts: { json?: boolean }) => {\n const teams = await session().listTeams();\n if (opts.json) {\n process.stdout.write(`${JSON.stringify(teams, null, 2)}\\n`);\n return;\n }\n for (const t of teams) process.stdout.write(`${t.id}\\t${t.name}\\n`);\n });\n}\n","import { Command } from 'commander';\nimport * as path from 'node:path';\nimport { installApp, launchApp, uninstallApp, forceStop, applyChanges, getBundleName } from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\n\ninterface ApplyOpts {\n bundle?: string;\n module?: string;\n hap?: string;\n installedHap?: string;\n system?: boolean;\n allowUninstall?: boolean;\n device?: string;\n json?: boolean;\n}\n\nexport function registerAppCommand(program: Command): void {\n const app = program.command('app').description('Install, launch, and manage built apps on a connected device/emulator.');\n\n app\n .command('install [project-dir]')\n .description('Install the signed .hap on the connected device/emulator via hdc.')\n .option('--hap <path>', 'Override the .hap path (relative to project-dir or absolute).')\n .option('--device <serial>', 'Target device serial.')\n .action(async (projectDir: string | undefined, opts: { hap?: string; device?: string }) => {\n const { config, logger } = getRuntime();\n const dir = path.resolve(projectDir ?? process.cwd());\n logger.info(`Installing app from ${dir}...`);\n await installApp({ config, projectDir: dir, hapPath: opts.hap, deviceSerial: opts.device, logger });\n logger.info('App installed.');\n });\n\n app\n .command('launch [project-dir]')\n .description(\n 'Launch an app on the connected device/emulator. Project mode (default): resolves ' +\n 'bundle + main ability from the project. Bundle mode (--bundle): launch an ' +\n 'already-installed app by bundle name, no project needed.',\n )\n .option('--bundle <bundle>', 'Launch an already-installed app by bundle name (no project needed).')\n .option('--module <module>', 'Module folder name (project mode).', 'entry')\n .option('--ability <name>', 'Explicit ability to launch (defaults to the module mainElement in project mode, or the installed bundle main ability in --bundle mode).')\n .option('--device <serial>', 'Target device serial.')\n .action(async (projectDir: string | undefined, opts: { bundle?: string; module: string; ability?: string; device?: string }) => {\n const { config, logger } = getRuntime();\n if (opts.bundle) {\n logger.info(`Launching installed bundle ${opts.bundle}...`);\n await launchApp({ config, bundleName: opts.bundle, abilityName: opts.ability, deviceSerial: opts.device, logger });\n } else {\n const dir = path.resolve(projectDir ?? process.cwd());\n logger.info(`Launching app from ${dir}...`);\n await launchApp({ config, projectDir: dir, moduleName: opts.module, abilityName: opts.ability, deviceSerial: opts.device, logger });\n }\n logger.info('App launched.');\n });\n\n app\n .command('apply [project-dir]')\n .description(\n 'Install a HAP and verify the running process took the change. Handles sign-info mismatch, ' +\n 'asset-cache invalidation, and persistent-bundle restart.',\n )\n .option('--bundle <bundle>', 'Bundle name to apply changes to. Defaults to the bundleName in the project AppScope/app.json5.')\n .option('--module <module>', 'Module to resolve the HAP from (multi-module projects).')\n .option('--hap <path>', 'Explicit .hap path (relative to project-dir or absolute).')\n .option('--installed-hap <path>', 'Local path to the currently-installed HAP, to enable the asset-cache reboot.')\n .option('--system', 'Treat as a persistent/system bundle (refuses uninstall on sign-info mismatch).')\n .option('--allow-uninstall', 'Permit uninstalling a system bundle on sign-info mismatch (dangerous).')\n .option('--device <serial>', 'Target device serial.')\n .option('--json', 'Emit the result as JSON.')\n .action(async (projectDir: string | undefined, opts: ApplyOpts) => {\n const { config, logger } = getRuntime();\n const dir = path.resolve(projectDir ?? process.cwd());\n const bundle = opts.bundle ?? getBundleName(dir);\n const result = await applyChanges({\n config,\n bundle,\n hapPath: opts.hap,\n projectDir: dir,\n module: opts.module,\n installedHapPath: opts.installedHap,\n isSystemBundle: opts.system,\n allowUninstall: opts.allowUninstall,\n deviceSerial: opts.device,\n logger,\n });\n if (opts.json) {\n process.stdout.write(`${JSON.stringify(result, null, 2)}\\n`);\n } else {\n logger.info(\n `apply: method=${result.method} pid ${result.preInstallPid ?? '-'} -> ${result.postInstallPid ?? '-'}` +\n `${result.cacheCleared ? ' (cache cleared)' : ''}`,\n );\n }\n });\n\n app\n .command('uninstall <bundle>')\n .description('Uninstall an app by bundle name.')\n .option('--device <serial>', 'Target device serial.')\n .action(async (bundle: string, opts: { device?: string }) => {\n const { config, logger } = getRuntime();\n await uninstallApp({ config, bundle, deviceSerial: opts.device, logger });\n logger.info(`Uninstalled ${bundle}.`);\n });\n\n app\n .command('stop <bundle>')\n .description('Force-stop an app by bundle name.')\n .option('--device <serial>', 'Target device serial.')\n .action(async (bundle: string, opts: { device?: string }) => {\n const { config, logger } = getRuntime();\n await forceStop({ config, bundle, deviceSerial: opts.device, logger });\n logger.info(`Stopped ${bundle}.`);\n });\n}\n","import { Command } from 'commander';\nimport * as path from 'node:path';\nimport {\n ALL_SDKS,\n createScaffold,\n isValidBundleName,\n isValidProjectName,\n} from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\nimport { getBundledTemplateRoot } from '../lib/templateRoot.js';\n\ninterface CreateOpts {\n name: string;\n bundle: string;\n location: string;\n sdk: string;\n template: string;\n module?: string;\n overwrite?: boolean;\n}\n\nexport function registerCreateCommand(program: Command): void {\n program\n .command('create')\n .description('Scaffold a new Oniro/OpenHarmony or HarmonyOS app from a template. All flags are required (non-interactive).')\n .requiredOption('--name <name>', 'Project folder name (letters, digits, ._- only)')\n .requiredOption('--bundle <bundleName>', 'Bundle name in reverse-DNS form, e.g. com.example.myapp')\n .requiredOption('--location <dir>', 'Parent directory where the new project folder will be created')\n .requiredOption('--sdk <api>', 'Target SDK API level (e.g. 18, 20)')\n .option('--template <id>', 'Template id', 'EmptyAbility')\n .option('--module <name>', 'Module folder name (defaults to the template default, usually `entry`)')\n .option('--overwrite', 'Replace the destination if it already exists')\n .action(async (opts: CreateOpts) => {\n const { config, logger } = getRuntime();\n\n if (!isValidProjectName(opts.name)) {\n throw new Error(`Invalid --name '${opts.name}'. Use letters/numbers/._- and no slashes.`);\n }\n if (!isValidBundleName(opts.bundle)) {\n throw new Error(`Invalid --bundle '${opts.bundle}'. Example: com.example.myapp`);\n }\n const sdkApi = Number(opts.sdk);\n if (!Number.isFinite(sdkApi)) {\n throw new Error(`--sdk must be a numeric api level. Known: ${ALL_SDKS.map((s) => s.api).join(', ')}`);\n }\n\n const templateRoot = getBundledTemplateRoot();\n const result = await createScaffold({\n config,\n templateId: opts.template,\n projectName: opts.name,\n bundleName: opts.bundle,\n location: path.resolve(opts.location),\n sdkApi,\n moduleName: opts.module,\n templateRoot,\n overwrite: opts.overwrite,\n logger,\n });\n\n logger.info(`Project created at ${result.projectDir}`);\n process.stdout.write(`${result.projectDir}\\n`);\n });\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\n/**\n * Resolve the bundled `templates/` directory shipped inside this CLI package.\n *\n * The CLI's `dist/oniro-app.js` lives at `<pkg>/dist/oniro-app.js` after build\n * and the templates ship at `<pkg>/templates/`. During development the entrypoint\n * lives at `<pkg>/src/bin/oniro-app.ts` so we also try `../../templates` from there.\n */\nexport function getBundledTemplateRoot(): string {\n const here = path.dirname(fileURLToPath(import.meta.url));\n const candidates = [\n path.resolve(here, '../templates'), // dist/oniro-app.js → ../templates\n path.resolve(here, '../../templates'), // src/bin/oniro-app.ts → ../../templates\n ];\n for (const c of candidates) {\n if (fs.existsSync(c)) return c;\n }\n // Return the most likely path even if it doesn't exist yet; createScaffold will\n // surface a clear error from there.\n return candidates[0]!;\n}\n","import { Command } from 'commander';\nimport { listTemplates } from '@oniroproject/core';\nimport { getBundledTemplateRoot } from '../lib/templateRoot.js';\n\nexport function registerTemplatesCommand(program: Command): void {\n const templates = program.command('templates').description('Inspect the templates bundled with this CLI.');\n\n templates\n .command('list')\n .description('List available project templates.')\n .option('--json', 'Emit machine-readable JSON.')\n .action((opts: { json?: boolean }) => {\n const root = getBundledTemplateRoot();\n const list = listTemplates(root);\n if (opts.json) {\n process.stdout.write(`${JSON.stringify(list, null, 2)}\\n`);\n return;\n }\n if (list.length === 0) {\n process.stdout.write('No templates available.\\n');\n return;\n }\n const rows = list.map((t) => `${t.id.padEnd(20)} ${t.label.padEnd(24)} ${t.description}`);\n process.stdout.write(`${rows.join('\\n')}\\n`);\n });\n}\n","import { Command, Option } from 'commander';\nimport { reboot } from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\n\nexport function registerRebootCommand(program: Command): void {\n program\n .command('reboot')\n .description('Reboot the connected device/emulator.')\n .addOption(\n new Option('--mode <mode>', 'Reboot target.').choices(['system', 'bootloader', 'recovery']).default('system'),\n )\n .option('--wait-bundle <bundle>', 'After a system reboot, wait until this bundle is running again.')\n .option('--timeout <ms>', 'Max time to wait for the bundle, ms.', '180000')\n .option('--device <serial>', 'Target device serial.')\n .action(\n async (opts: {\n mode: 'system' | 'bootloader' | 'recovery';\n waitBundle?: string;\n timeout: string;\n device?: string;\n }) => {\n const { config, logger } = getRuntime();\n logger.info(`Rebooting device (${opts.mode})...`);\n await reboot({\n config,\n mode: opts.mode,\n waitForBundle: opts.waitBundle,\n timeoutMs: Number(opts.timeout),\n deviceSerial: opts.device,\n logger,\n });\n logger.info('Reboot complete.');\n },\n );\n}\n","import { Command } from 'commander';\nimport { waitForLog, waitForBoot, waitForBundle, waitForTarget, describeLayoutNode } from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\nimport { addTargetOptions, selectorFrom, type TargetOpts } from '../lib/target.js';\n\ninterface WaitOpts extends TargetOpts {\n log?: string;\n boot?: boolean;\n bundle?: string;\n pidOf?: string;\n domain?: string;\n gone?: boolean;\n interval: string;\n timeout: string;\n device?: string;\n json?: boolean;\n}\n\nexport function registerWaitCommand(program: Command): void {\n const wait = program\n .command('wait')\n .description(\n 'Wait for a device condition: a log line (--log), boot (--boot), a bundle to start (--bundle), ' +\n 'or an on-screen element (--target / --target-id / --target-type).',\n )\n .option('--log <pattern>', 'Resolve when a hilog line (tag: message) matches this regex.')\n .option('--boot', 'Resolve when the device is reachable (optionally also --pid-of).')\n .option('--bundle <bundle>', 'With --log: filter to this bundle. Alone: wait until this bundle is running.')\n .option('--pid-of <name>', 'With --boot: also require this process to have a pid.')\n .option('--domain <domain>', 'With --log: hilog domain filter (e.g. 0xD003900).');\n addTargetOptions(wait, 'Resolve when', { index: false });\n wait\n .option('--gone', 'With --target*: resolve when no uncovered element matches any more.')\n .option('--interval <ms>', 'With --target*: poll interval, ms (each poll is a layout dump).', '500')\n .option('--timeout <ms>', 'Max wait, ms.', '30000')\n .option('--device <serial>', 'Target device serial.')\n .option('--json', 'With --log or --target*: emit the matched entry/element as JSON.')\n .action(async (opts: WaitOpts) => {\n const { config, logger } = getRuntime();\n const timeoutMs = Number(opts.timeout);\n const selector = selectorFrom(opts);\n\n if (opts.log) {\n const entry = await waitForLog({\n config,\n pattern: new RegExp(opts.log),\n timeoutMs,\n bundle: opts.bundle,\n domain: opts.domain,\n deviceSerial: opts.device,\n logger,\n });\n if (opts.json) process.stdout.write(`${JSON.stringify(entry, null, 2)}\\n`);\n else logger.info(`matched: ${entry.tag}: ${entry.message}`);\n return;\n }\n if (opts.boot) {\n await waitForBoot({ config, untilPidOf: opts.pidOf, timeoutMs, deviceSerial: opts.device, logger });\n logger.info('Device booted.');\n return;\n }\n if (selector) {\n const node = await waitForTarget({\n config,\n selector,\n gone: opts.gone,\n timeoutMs,\n pollMs: Number(opts.interval) || 500,\n deviceSerial: opts.device,\n logger,\n });\n if (!node) {\n logger.info('Element is gone.');\n return;\n }\n if (opts.json) process.stdout.write(`${JSON.stringify(node, null, 2)}\\n`);\n else logger.info(`found: ${describeLayoutNode(node)}`);\n return;\n }\n if (opts.bundle) {\n await waitForBundle({ config, bundle: opts.bundle, timeoutMs, deviceSerial: opts.device, logger });\n logger.info(`Bundle ${opts.bundle} is running.`);\n return;\n }\n throw new Error('Specify one of --log <pattern>, --boot, --bundle <bundle>, or --target <text> (or --target-id / --target-type).');\n });\n}\n","import type { Command } from 'commander';\nimport type { LayoutSelector } from '@oniroproject/core';\n\n/** The shared element-selector flags, as commander parses them. */\nexport interface TargetOpts {\n target?: string;\n targetId?: string;\n targetType?: string;\n targetIndex?: string;\n}\n\n/**\n * Add the element-selector flags shared by `input`, `wait`, and `screenshot`.\n * `verb` completes the `--target` help text (e.g. \"Tap\" → \"Tap the element …\").\n */\nexport function addTargetOptions(cmd: Command, verb: string, opts: { index?: boolean } = {}): Command {\n cmd\n .option(\n '--target <text>',\n `${verb} the element whose text, description, or placeholder matches ` +\n '(case-insensitive; exact matches win, else substring). Covered elements are skipped.',\n )\n .option('--target-id <id>', 'Match the element by its id or key.')\n .option('--target-type <type>', 'Restrict the match to a component type (e.g. Button, TextInput).');\n if (opts.index !== false) {\n cmd.option('--target-index <n>', 'Pick the n-th (0-based) of several matching elements.');\n }\n return cmd;\n}\n\n/** The selector built from the flags, or undefined when none was given. */\nexport function selectorFrom(opts: TargetOpts): LayoutSelector | undefined {\n if (opts.target === undefined && opts.targetId === undefined && opts.targetType === undefined) return undefined;\n return { text: opts.target, id: opts.targetId, type: opts.targetType };\n}\n\nexport function targetIndexFrom(opts: TargetOpts): number | undefined {\n if (opts.targetIndex === undefined) return undefined;\n const n = Number(opts.targetIndex);\n if (!Number.isInteger(n) || n < 0) throw new Error(`--target-index must be a non-negative integer; got ${opts.targetIndex}.`);\n return n;\n}\n","import { Command } from 'commander';\nimport { watchLog } from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\n\ninterface WatchOpts {\n log?: string;\n for: string;\n bundle?: string;\n domain?: string;\n dedup: boolean;\n device?: string;\n json?: boolean;\n}\n\nexport function registerWatchCommand(program: Command): void {\n program\n .command('watch')\n .description('Collect hilog lines matching a pattern for a fixed duration.')\n .option('--log <pattern>', 'Regex tested against each line (tag: message).')\n .option('--for <ms>', 'Duration to watch, ms.', '10000')\n .option('--bundle <bundle>', 'Filter to this bundle.')\n .option('--domain <domain>', 'hilog domain filter (e.g. 0xD003900).')\n .option('--no-dedup', 'Do not collapse consecutive duplicate lines.')\n .option('--device <serial>', 'Target device serial.')\n .option('--json', 'Emit the entries as JSON.')\n .action(async (opts: WatchOpts) => {\n const { config, logger } = getRuntime();\n if (!opts.log) throw new Error('watch requires --log <pattern>.');\n const entries = await watchLog({\n config,\n pattern: new RegExp(opts.log),\n durationMs: Number(opts.for),\n bundle: opts.bundle,\n domain: opts.domain,\n dedup: opts.dedup,\n deviceSerial: opts.device,\n logger,\n });\n if (opts.json) {\n process.stdout.write(`${JSON.stringify(entries, null, 2)}\\n`);\n } else {\n for (const e of entries) process.stdout.write(`${e.time} ${e.level} ${e.tag}: ${e.message}\\n`);\n }\n });\n}\n","import { Command } from 'commander';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { takeScreenshot, captureBurst, locateTarget, describeLayoutNode } from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\nimport {\n renderWithGrid,\n buildContactSheet,\n frameDiffs,\n cropImage,\n parseCropRect,\n padCropRect,\n type CropRect,\n} from '../lib/screenshotImage.js';\nimport { addTargetOptions, selectorFrom, targetIndexFrom, type TargetOpts } from '../lib/target.js';\n\ninterface ScreenshotOpts extends TargetOpts {\n output: string;\n grid?: boolean;\n maxDim: string;\n crop?: string;\n contactSheet?: boolean;\n burst?: string;\n interval: string;\n json?: boolean;\n device?: string;\n}\n\nconst DEFAULT_CONTACT_SHEET_FRAMES = 8;\n// Margin kept around a --target element when cropping to it, as a fraction of the display.\nconst TARGET_CROP_PAD = 0.02;\n\nfunction clampMaxDim(raw: string): number {\n const n = Number(raw);\n if (!Number.isFinite(n)) return 1024;\n return Math.max(256, Math.min(4096, Math.round(n)));\n}\n\nexport function registerScreenshotCommand(program: Command): void {\n const screenshot = program\n .command('screenshot')\n .description(\n 'Capture the screen. Default: full-resolution raw JPEG. ' +\n '--grid: downscaled JPEG with a 10x10 grid (axes 0.0-1.0) for picking tap coordinates. ' +\n '--crop / --target: a full-resolution crop of one region or element, for checking detail cheaply. ' +\n '--contact-sheet: capture a burst and tile it into one image with per-frame change diffs.',\n )\n .option('-o, --output <file>', 'Output file path.', 'screenshot.jpeg')\n .option('--grid', 'Downscale (to --max-dim) and overlay a 10x10 coordinate grid.')\n .option('--max-dim <px>', 'Longest-side cap for --grid / --crop / --target / --contact-sheet (256-4096).', '1024')\n .option('--crop <x1,y1,x2,y2>', 'Crop to this region, given as 0-1 fractions of the screen.');\n addTargetOptions(screenshot, 'Crop to');\n screenshot\n .option('--contact-sheet', 'Capture a burst and composite it into one tiled contact sheet.')\n .option('--burst <count>', 'Capture N frames; writes <base>-<i><ext> (or feeds --contact-sheet).')\n .option('--interval <ms>', 'Delay between burst frames, ms.', '50')\n .option('--json', 'Emit the full result object as JSON on stdout (with --contact-sheet).')\n .option('--device <serial>', 'Target device serial.')\n .action(async (opts: ScreenshotOpts, command: Command) => {\n const { config, logger } = getRuntime();\n const maxDim = clampMaxDim(opts.maxDim);\n const intervalMs = Number(opts.interval) || 50;\n\n // --- Crop: one region (or element) at full resolution ---\n const selector = selectorFrom(opts);\n if (opts.crop !== undefined || selector) {\n if (opts.crop !== undefined && selector) throw new Error('Use either --crop or --target*, not both.');\n if (opts.grid || opts.contactSheet || opts.burst) {\n throw new Error('--crop / --target cannot be combined with --grid, --contact-sheet, or --burst.');\n }\n let rect: CropRect;\n let label: string;\n if (selector) {\n // Leave the keyboard alone: dismissing it would change what we are capturing.\n const located = await locateTarget({\n config,\n selector,\n index: targetIndexFrom(opts),\n hideKeyboard: false,\n deviceSerial: opts.device,\n logger,\n });\n if (!located.node.b) throw new Error(`${describeLayoutNode(located.node)} has no bounds to crop to.`);\n rect = padCropRect(located.node.b, TARGET_CROP_PAD);\n label = describeLayoutNode(located.node);\n } else {\n rect = parseCropRect(opts.crop!);\n label = rect.map((n) => n.toFixed(3)).join(',');\n }\n const shot = await takeScreenshot({ config, deviceSerial: opts.device, logger });\n const cropped = await cropImage(shot.pixels, rect, { maxDim });\n fs.writeFileSync(opts.output, cropped.buf);\n logger.info(\n `Wrote ${opts.output} (${cropped.width}x${cropped.height} from a ${cropped.cropWidth}x${cropped.cropHeight} ` +\n `crop at ${cropped.left},${cropped.top}: ${label}).`,\n );\n return;\n }\n\n // --- Contact sheet: burst -> one tiled image + per-frame diffs ---\n if (opts.contactSheet) {\n const count = opts.burst ? Math.max(1, Number(opts.burst)) : DEFAULT_CONTACT_SHEET_FRAMES;\n const frames = await captureBurst({ config, count, intervalMs, deviceSerial: opts.device, logger });\n const diffs = await frameDiffs(frames);\n const sheet = await buildContactSheet(frames, { maxDim, diffs });\n fs.writeFileSync(opts.output, sheet.buf);\n\n // Only fan out the individual raw frames when --burst was also requested.\n if (opts.burst) {\n const ext = path.extname(opts.output) || '.jpeg';\n const base = opts.output.slice(0, opts.output.length - ext.length);\n frames.forEach((frame, i) => fs.writeFileSync(`${base}-${i}${ext}`, frame));\n }\n\n const perFrame = frames.map((_, i) => ({ idx: i, t_ms: i * intervalMs, diffVsPrev: diffs[i] ?? 0 }));\n if (opts.json) {\n process.stdout.write(\n `${JSON.stringify(\n {\n sheet: opts.output,\n frameCount: frames.length,\n cols: sheet.cols,\n rows: sheet.rows,\n intervalMs,\n note: 't_ms is nominal (idx*interval); diffVsPrev is 0..1 mean greyscale diff vs the previous frame.',\n frames: perFrame,\n },\n null,\n 2,\n )}\\n`,\n );\n } else {\n process.stdout.write(`${JSON.stringify(perFrame)}\\n`);\n }\n\n let peak = 0;\n for (let i = 1; i < diffs.length; i++) if ((diffs[i] ?? 0) > (diffs[peak] ?? 0)) peak = i;\n logger.info(\n `Wrote contact sheet ${opts.output} (${sheet.cols}x${sheet.rows}, ${frames.length} frames). ` +\n `Biggest change at frame ${peak} (Δ${(diffs[peak] ?? 0).toFixed(2)}).`,\n );\n return;\n }\n\n // --- Burst (raw frames) — unchanged behaviour ---\n if (opts.burst) {\n const frames = await captureBurst({\n config,\n count: Number(opts.burst),\n intervalMs,\n deviceSerial: opts.device,\n logger,\n });\n const ext = path.extname(opts.output) || '.jpeg';\n const base = opts.output.slice(0, opts.output.length - ext.length);\n frames.forEach((frame, i) => fs.writeFileSync(`${base}-${i}${ext}`, frame));\n logger.info(`Wrote ${frames.length} frames to ${base}-<0..${frames.length - 1}>${ext}.`);\n return;\n }\n\n // --- Single shot ---\n const shot = await takeScreenshot({ config, deviceSerial: opts.device, logger });\n const maxDimProvided = command.getOptionValueSource('maxDim') === 'cli';\n if (opts.grid || maxDimProvided) {\n const rendered = await renderWithGrid(shot.pixels, { maxDim, grid: !!opts.grid });\n fs.writeFileSync(opts.output, rendered.buf);\n logger.info(\n `Wrote ${opts.output} (${rendered.width}x${rendered.height} from ` +\n `${rendered.originalWidth}x${rendered.originalHeight}${opts.grid ? ', 10x10 grid' : ''}).`,\n );\n return;\n }\n fs.writeFileSync(opts.output, shot.pixels);\n logger.info(`Wrote ${opts.output} (${shot.width}x${shot.height}).`);\n });\n}\n","import sharp from 'sharp';\n\n/**\n * Agent-facing screenshot image processing for the CLI.\n *\n * `@oniroproject/core` deliberately ships no image dependency — it returns raw\n * JPEG buffers. The grid overlay / downscale and the burst contact-sheet live\n * here (the CLI is the affordance layer), so `oniro-app screenshot` can produce\n * exactly what the ohos-hdc MCP used to. The grid drawing is ported verbatim\n * from that MCP so the output is equivalent.\n */\n\nexport interface RenderResult {\n /** Encoded JPEG. */\n buf: Buffer;\n /** Rendered (post-downscale) dimensions. */\n width: number;\n height: number;\n /** Source dimensions, before downscale. */\n originalWidth: number;\n originalHeight: number;\n}\n\nexport interface RenderWithGridOptions {\n /** Longest-side cap in pixels. The image is downscaled (never upscaled) to fit. */\n maxDim: number;\n /** Overlay the 10x10 grid with 0.0–1.0 axis labels after downscaling. */\n grid?: boolean;\n}\n\n/**\n * Build an SVG overlay: a 10x10 grid with X/Y axis labels (0.0–1.0) sized to the\n * given image dimensions. Ported verbatim from the ohos-hdc MCP so the gridded\n * output matches what agents are used to.\n */\nexport function buildGridSvg(width: number, height: number): string {\n const lineColor = 'rgba(255,80,80,0.55)';\n const labelBg = 'rgba(0,0,0,0.7)';\n const labelFg = '#fff';\n const fontSize = Math.max(10, Math.round(Math.min(width, height) / 60));\n const padding = Math.round(fontSize * 0.4);\n const labels: string[] = [];\n const lines: string[] = [];\n for (let i = 0; i <= 10; i++) {\n const f = i / 10;\n const x = Math.round(f * (width - 1));\n const y = Math.round(f * (height - 1));\n // grid lines (skip 0 and 10 — those are the image edges)\n if (i > 0 && i < 10) {\n lines.push(`<line x1=\"${x}\" y1=\"0\" x2=\"${x}\" y2=\"${height}\" stroke=\"${lineColor}\" stroke-width=\"1\"/>`);\n lines.push(`<line x1=\"0\" y1=\"${y}\" x2=\"${width}\" y2=\"${y}\" stroke=\"${lineColor}\" stroke-width=\"1\"/>`);\n }\n const tag = f.toFixed(1);\n // X-axis labels along the top\n const tx = i === 0 ? padding : i === 10 ? width - padding : x;\n const anchorX = i === 0 ? 'start' : i === 10 ? 'end' : 'middle';\n labels.push(\n `<text x=\"${tx}\" y=\"${fontSize + padding}\" font-family=\"monospace\" font-size=\"${fontSize}\" font-weight=\"bold\" fill=\"${labelFg}\" stroke=\"${labelBg}\" stroke-width=\"3\" paint-order=\"stroke\" text-anchor=\"${anchorX}\">${tag}</text>`,\n );\n // Y-axis labels along the left\n const ty = i === 0 ? fontSize + padding : i === 10 ? height - padding : y + fontSize / 3;\n labels.push(\n `<text x=\"${padding}\" y=\"${ty}\" font-family=\"monospace\" font-size=\"${fontSize}\" font-weight=\"bold\" fill=\"${labelFg}\" stroke=\"${labelBg}\" stroke-width=\"3\" paint-order=\"stroke\" text-anchor=\"start\">${tag}</text>`,\n );\n }\n // Axis title markers in the corners\n labels.push(\n `<text x=\"${width / 2}\" y=\"${fontSize * 2.4 + padding}\" font-family=\"monospace\" font-size=\"${fontSize}\" font-weight=\"bold\" fill=\"${labelFg}\" stroke=\"${labelBg}\" stroke-width=\"3\" paint-order=\"stroke\" text-anchor=\"middle\">X →</text>`,\n );\n labels.push(\n `<text x=\"${padding}\" y=\"${fontSize * 2.6 + padding}\" font-family=\"monospace\" font-size=\"${fontSize}\" font-weight=\"bold\" fill=\"${labelFg}\" stroke=\"${labelBg}\" stroke-width=\"3\" paint-order=\"stroke\" text-anchor=\"start\">Y ↓</text>`,\n );\n return `<svg width=\"${width}\" height=\"${height}\" xmlns=\"http://www.w3.org/2000/svg\">${lines.join('')}${labels.join('')}</svg>`;\n}\n\n/**\n * Downscale a JPEG so its longest side is <= `maxDim` (never upscaling) and,\n * when `grid` is set, overlay the coordinate grid. Returns the encoded JPEG plus\n * rendered and original dimensions.\n */\nexport async function renderWithGrid(jpeg: Buffer, opts: RenderWithGridOptions): Promise<RenderResult> {\n const meta = await sharp(jpeg).metadata();\n const originalWidth = meta.width ?? 0;\n const originalHeight = meta.height ?? 0;\n const longest = Math.max(originalWidth, originalHeight) || 1;\n const scale = Math.min(1, opts.maxDim / longest);\n const width = Math.max(1, Math.round(originalWidth * scale));\n const height = Math.max(1, Math.round(originalHeight * scale));\n const resized = await sharp(jpeg).resize(width, height).jpeg({ quality: 80 }).toBuffer();\n if (!opts.grid) {\n return { buf: resized, width, height, originalWidth, originalHeight };\n }\n const svg = buildGridSvg(width, height);\n const buf = await sharp(resized)\n .composite([{ input: Buffer.from(svg) }])\n .jpeg({ quality: 80 })\n .toBuffer();\n return { buf, width, height, originalWidth, originalHeight };\n}\n\n/** A region as [x1, y1, x2, y2] fractions (0–1) of the image. */\nexport type CropRect = [number, number, number, number];\n\n/** Parse `\"x1,y1,x2,y2\"` (0–1 fractions, x1<x2, y1<y2) into a {@link CropRect}. */\nexport function parseCropRect(spec: string): CropRect {\n const parts = spec.split(',').map((s) => Number(s.trim()));\n if (parts.length !== 4 || parts.some((n) => !Number.isFinite(n) || n < 0 || n > 1)) {\n throw new Error(`--crop expects four 0-1 fractions \"x1,y1,x2,y2\"; got \"${spec}\".`);\n }\n const [x1, y1, x2, y2] = parts as CropRect;\n if (!(x2 > x1 && y2 > y1)) throw new Error(`--crop needs x1 < x2 and y1 < y2; got \"${spec}\".`);\n return [x1, y1, x2, y2];\n}\n\n/** Grow a rect by `pad` (a fraction) on every side, clamped to 0–1. */\nexport function padCropRect(r: CropRect, pad: number): CropRect {\n return [Math.max(0, r[0] - pad), Math.max(0, r[1] - pad), Math.min(1, r[2] + pad), Math.min(1, r[3] + pad)];\n}\n\nexport interface CropResult {\n /** Encoded JPEG. */\n buf: Buffer;\n /** Rendered (post-downscale) dimensions. */\n width: number;\n height: number;\n /** The cropped region in source pixels. */\n left: number;\n top: number;\n cropWidth: number;\n cropHeight: number;\n}\n\n/**\n * Crop a JPEG to a 0–1 region at full resolution, then downscale so the longest\n * side is <= `maxDim` (never upscaling). Detail where it is needed, at a\n * fraction of a full-resolution screenshot's size.\n */\nexport async function cropImage(jpeg: Buffer, rect: CropRect, opts: { maxDim: number }): Promise<CropResult> {\n const meta = await sharp(jpeg).metadata();\n const w = meta.width ?? 1;\n const h = meta.height ?? 1;\n const left = Math.min(w - 1, Math.floor(rect[0] * w));\n const top = Math.min(h - 1, Math.floor(rect[1] * h));\n const cropWidth = Math.max(1, Math.min(w, Math.ceil(rect[2] * w)) - left);\n const cropHeight = Math.max(1, Math.min(h, Math.ceil(rect[3] * h)) - top);\n const scale = Math.min(1, opts.maxDim / Math.max(cropWidth, cropHeight));\n const width = Math.max(1, Math.round(cropWidth * scale));\n const height = Math.max(1, Math.round(cropHeight * scale));\n const buf = await sharp(jpeg)\n .extract({ left, top, width: cropWidth, height: cropHeight })\n .resize(width, height)\n .jpeg({ quality: 85 })\n .toBuffer();\n return { buf, width, height, left, top, cropWidth, cropHeight };\n}\n\nexport interface ContactSheetOptions {\n /** Longest-side cap for the whole sheet; per-tile size derives from this. */\n maxDim: number;\n /** Tiles per row. Defaults to ceil(sqrt(N)). */\n cols?: number;\n /** Per-frame diff (0..1), index-aligned with `frames`; printed on each tile. */\n diffs?: number[];\n /** Gap between tiles, px. */\n gap?: number;\n}\n\nexport interface ContactSheetResult {\n buf: Buffer;\n width: number;\n height: number;\n cols: number;\n rows: number;\n tileWidth: number;\n tileHeight: number;\n count: number;\n}\n\nfunction buildTileLabelSvg(width: number, height: number, idx: number, diff?: number): string {\n const fontSize = Math.max(12, Math.round(Math.min(width, height) / 16));\n const pad = Math.round(fontSize * 0.4);\n let label = `#${idx}`;\n if (typeof diff === 'number') label += ` Δ${diff.toFixed(2)}`;\n const boxW = Math.round(label.length * fontSize * 0.62) + pad * 2;\n const boxH = fontSize + pad * 2;\n return (\n `<svg width=\"${width}\" height=\"${height}\" xmlns=\"http://www.w3.org/2000/svg\">` +\n `<rect x=\"0\" y=\"0\" width=\"${boxW}\" height=\"${boxH}\" fill=\"rgba(0,0,0,0.6)\"/>` +\n `<text x=\"${pad}\" y=\"${fontSize + pad - 1}\" font-family=\"monospace\" font-size=\"${fontSize}\" font-weight=\"bold\" fill=\"#fff\" stroke=\"rgba(0,0,0,0.85)\" stroke-width=\"3\" paint-order=\"stroke\" text-anchor=\"start\">${label}</text>` +\n `</svg>`\n );\n}\n\n/**\n * Composite a burst of JPEG frames into a single tiled contact sheet, each tile\n * labelled with its frame index (and per-frame diff when provided). One image\n * replaces N — a large token saving when verifying transient UI.\n */\nexport async function buildContactSheet(frames: Buffer[], opts: ContactSheetOptions): Promise<ContactSheetResult> {\n if (frames.length === 0) throw new Error('buildContactSheet: no frames');\n const count = frames.length;\n const cols = Math.max(1, opts.cols ?? Math.ceil(Math.sqrt(count)));\n const rows = Math.ceil(count / cols);\n const gap = opts.gap ?? 8;\n\n const meta0 = await sharp(frames[0]).metadata();\n const fw = meta0.width ?? 1;\n const fh = meta0.height ?? 1;\n const longest = Math.max(fw, fh) || 1;\n const tileScale = Math.min(1, opts.maxDim / cols / longest);\n const tileWidth = Math.max(1, Math.round(fw * tileScale));\n const tileHeight = Math.max(1, Math.round(fh * tileScale));\n\n const tiles = await Promise.all(\n frames.map((frame, i) => {\n const label = Buffer.from(buildTileLabelSvg(tileWidth, tileHeight, i, opts.diffs?.[i]));\n return sharp(frame)\n .resize(tileWidth, tileHeight, { fit: 'fill' })\n .composite([{ input: label, top: 0, left: 0 }])\n .png()\n .toBuffer();\n }),\n );\n\n const width = cols * tileWidth + (cols + 1) * gap;\n const height = rows * tileHeight + (rows + 1) * gap;\n const placements = tiles.map((input, i) => {\n const r = Math.floor(i / cols);\n const c = i % cols;\n return { input, left: gap + c * (tileWidth + gap), top: gap + r * (tileHeight + gap) };\n });\n\n const buf = await sharp({\n create: { width, height, channels: 3, background: { r: 20, g: 20, b: 20 } },\n })\n .composite(placements)\n .jpeg({ quality: 80 })\n .toBuffer();\n\n return { buf, width, height, cols, rows, tileWidth, tileHeight, count };\n}\n\n/**\n * Per-frame change metric: mean absolute difference of a downscaled greyscale\n * thumbnail vs. the previous frame, normalised to 0..1. Frame 0 is 0 (no\n * predecessor). Cheap, deterministic, and device-free.\n */\nexport async function frameDiffs(frames: Buffer[], opts: { sample?: number } = {}): Promise<number[]> {\n if (frames.length === 0) return [];\n const sample = opts.sample ?? 32;\n const thumbs = await Promise.all(\n frames.map((f) => sharp(f).greyscale().resize(sample, sample, { fit: 'fill' }).raw().toBuffer()),\n );\n const out: number[] = [0];\n for (let i = 1; i < thumbs.length; i++) {\n const a = thumbs[i - 1];\n const b = thumbs[i];\n if (!a || !b) {\n out.push(0);\n continue;\n }\n const n = Math.min(a.length, b.length) || 1;\n let s = 0;\n for (let k = 0; k < n; k++) s += Math.abs((a[k] ?? 0) - (b[k] ?? 0));\n out.push(+(s / n / 255).toFixed(4));\n }\n return out;\n}\n","import { Command } from 'commander';\nimport { dumpLayout } from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\nimport { formatFlatLayout } from '../lib/layoutText.js';\n\ninterface DumpOpts {\n bundle?: string;\n raw?: boolean;\n flat?: boolean;\n device?: string;\n}\n\nexport function registerDumpCommand(program: Command): void {\n program\n .command('dump [target]')\n .description(\n 'Dump device state. Currently supports `dump layout` (the default target): JSON by default, ' +\n 'or one line per element with --flat.',\n )\n .option('--bundle <bundle>', 'Filter the layout to a single window/bundle.')\n .option('--raw', 'Return the unpruned layout tree.')\n .option('--flat', 'One line per element (type, label, center as 0-1 fractions, flags) instead of a JSON tree.')\n .option('--device <serial>', 'Target device serial.')\n .action(async (target: string | undefined, opts: DumpOpts) => {\n const { config, logger } = getRuntime();\n const what = target ?? 'layout';\n if (what !== 'layout') throw new Error(`Unknown dump target \"${what}\". Supported: layout.`);\n if (opts.raw && opts.flat) throw new Error('--raw and --flat cannot be combined.');\n const result = await dumpLayout({\n config,\n bundleName: opts.bundle,\n prune: !opts.raw,\n detectKeyboard: !opts.raw,\n deviceSerial: opts.device,\n logger,\n });\n process.stdout.write(opts.flat ? formatFlatLayout(result) : `${JSON.stringify(result, null, 2)}\\n`);\n });\n}\n","import { flattenLayout, type DumpLayoutResult, type FlatLayoutNode } from '@oniroproject/core';\n\nconst MAX_TEXT = 80;\n\nfunction quote(s: string): string {\n return JSON.stringify(s.length > MAX_TEXT ? `${s.slice(0, MAX_TEXT - 1)}…` : s);\n}\n\nfunction flags(n: FlatLayoutNode): string[] {\n const out: string[] = [];\n if (n.click) out.push('click');\n if (n.longClick) out.push('longClick');\n if (n.scroll) out.push('scroll');\n if (n.checked) out.push('checked');\n else if (n.check) out.push('checkable');\n if (n.sel) out.push('selected');\n if (n.focus) out.push('focus');\n if (n.disabled) out.push('disabled');\n if (n.covered) out.push('covered');\n return out;\n}\n\n/** One line per element: type, label, center (0–1 fractions), and state flags. */\nexport function formatLayoutLine(n: FlatLayoutNode): string {\n const parts: string[] = [n.type ?? 'node'];\n if (n.text !== undefined) parts.push(quote(n.text));\n if (n.desc !== undefined) parts.push(`desc=${quote(n.desc)}`);\n if (n.hint !== undefined) parts.push(`hint=${quote(n.hint)}`);\n if (n.id !== undefined) parts.push(`#${n.id}`);\n if (n.key !== undefined) parts.push(`key=${n.key}`);\n if (n.c) parts.push(`c=${n.c[0].toFixed(3)},${n.c[1].toFixed(3)}`);\n parts.push(...flags(n));\n return parts.join(' ');\n}\n\n/** Worth a line: it has a label to read or match, or it can be interacted with. */\nfunction isListed(n: FlatLayoutNode): boolean {\n const labelled = n.text !== undefined || n.desc !== undefined || n.hint !== undefined;\n return labelled || !!(n.click || n.longClick || n.scroll || n.check || n.focus);\n}\n\n/**\n * Render a pruned layout as compact text for agents: a `[window <bundle>]`\n * header per window, then one line per labelled or interactive element in\n * paint order (decorative images and id-only wrappers are left to the JSON\n * output). The soft keyboard collapses to a single `[keyboard <bundle>]` line\n * instead of listing every key.\n */\nexport function formatFlatLayout(result: DumpLayoutResult): string {\n const lines: string[] = [];\n const d = result.display;\n lines.push(\n `# display ${d ? `${d.width}x${d.height}` : 'unknown'}; c = element center as 0-1 fractions ` +\n '(input --fx/--fy), or act by label with input --target \"<text>\"',\n );\n const keyboardBundle = result.keyboard?.shown ? result.keyboard.bundle : undefined;\n let window: string | undefined;\n for (const n of flattenLayout(result.tree)) {\n if (n.window !== window) {\n window = n.window;\n if (window !== undefined && window === keyboardBundle) {\n lines.push(`[keyboard ${window}] up — dismiss with input --type hideKeyboard`);\n } else if (window !== undefined) {\n lines.push(`[window ${window}]`);\n }\n }\n if (window !== undefined && window === keyboardBundle) continue;\n if (n.bundle !== undefined && n.text === undefined && !n.click) continue; // the window root itself\n if (isListed(n)) lines.push(formatLayoutLine(n));\n }\n return `${lines.join('\\n')}\\n`;\n}\n","import { Command } from 'commander';\nimport { listDevices } from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\n\nexport function registerDevicesCommand(program: Command): void {\n program\n .command('devices')\n .description('List connected hdc devices.')\n .option('--json', 'Emit machine-readable JSON.')\n .action(async (opts: { json?: boolean }) => {\n const { config } = getRuntime();\n const devices = await listDevices(config);\n if (opts.json) {\n process.stdout.write(`${JSON.stringify(devices, null, 2)}\\n`);\n return;\n }\n if (devices.length === 0) {\n process.stdout.write('(no devices)\\n');\n return;\n }\n for (const d of devices) {\n process.stdout.write(`${d.serial}\\t${d.connection ?? ''}\\t${d.status}\\n`);\n }\n });\n}\n","import { Command } from 'commander';\nimport { sendFile, recvFile } from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\n\nexport function registerFileCommand(program: Command): void {\n const file = program.command('file').description('Transfer files to/from the device (hdc file send/recv).');\n\n file\n .command('send <local> <remote>')\n .description('Push a local file to the device.')\n .option('--device <serial>', 'Target device serial.')\n .action(async (local: string, remote: string, opts: { device?: string }) => {\n const { config, logger } = getRuntime();\n await sendFile({ config, local, remote, deviceSerial: opts.device, logger });\n logger.info(`Sent ${local} -> ${remote}.`);\n });\n\n file\n .command('recv <remote> <local>')\n .description('Pull a file from the device.')\n .option('--device <serial>', 'Target device serial.')\n .action(async (remote: string, local: string, opts: { device?: string }) => {\n const { config, logger } = getRuntime();\n await recvFile({ config, remote, local, deviceSerial: opts.device, logger });\n logger.info(`Received ${remote} -> ${local}.`);\n });\n}\n","import { Command } from 'commander';\nimport * as path from 'node:path';\nimport { runCodelinter } from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\n\ninterface LintOpts {\n files?: string[];\n json?: boolean;\n}\n\nexport function registerLintCommand(program: Command): void {\n program\n .command('lint [project-dir]')\n .description('Run the OpenHarmony codelinter on a project. Defaults to the current directory.')\n .option('--files <globs...>', 'Specific files/globs to lint (default: the whole project).')\n .option('--json', 'Emit findings as JSON.')\n .action(async (projectDir: string | undefined, opts: LintOpts) => {\n const { config, logger } = getRuntime();\n const dir = path.resolve(projectDir ?? process.cwd());\n const result = await runCodelinter({ config, projectDir: dir, files: opts.files, logger });\n if (opts.json) {\n process.stdout.write(`${JSON.stringify(result, null, 2)}\\n`);\n } else {\n for (const f of result.findings) {\n process.stdout.write(`${f.file}:${f.line} ${f.severity} ${f.message}${f.code ? ` [${f.code}]` : ''}\\n`);\n }\n if (result.findings.length === 0) process.stdout.write('No findings.\\n');\n }\n // Surface a non-zero codelinter exit to the caller (CI), but let output flush.\n if (result.code !== 0) process.exitCode = result.code;\n });\n}\n","import { Command, Option } from 'commander';\nimport {\n performInput,\n sendGesture,\n getDisplaySize,\n describeLayoutNode,\n type UiInputType,\n type Waypoint,\n} from '@oniroproject/core';\nimport { getRuntime } from '../lib/runtime.js';\nimport { addTargetOptions, selectorFrom, targetIndexFrom, type TargetOpts } from '../lib/target.js';\n\nconst INPUT_TYPES: UiInputType[] = [\n 'click',\n 'doubleClick',\n 'longClick',\n 'swipe',\n 'drag',\n 'fling',\n 'keyEvent',\n 'inputText',\n 'clearText',\n 'hideKeyboard',\n];\n\nconst num = (v: string | undefined): number | undefined => (v === undefined ? undefined : Number(v));\n\ninterface InputOpts extends TargetOpts {\n type: UiInputType;\n x?: string;\n y?: string;\n x2?: string;\n y2?: string;\n fx?: string;\n fy?: string;\n fx2?: string;\n fy2?: string;\n speed?: string;\n key?: string;\n text?: string;\n clear?: boolean;\n hideKeyboard?: boolean;\n device?: string;\n}\n\ninterface GestureOpts {\n waypoints: string;\n fractions?: boolean;\n holdStart?: string;\n holdEnd?: string;\n device?: string;\n}\n\nexport function registerInputCommand(program: Command): void {\n const input = program\n .command('input')\n .description(\n 'Inject a UI input event via uitest uiInput. Position it with --target (an on-screen element), ' +\n '--fx/--fy (0-1 fractions of the display, as in `dump layout` and the screenshot grid), or --x/--y (pixels).',\n )\n .addOption(new Option('--type <type>', 'Input type.').choices(INPUT_TYPES).makeOptionMandatory());\n addTargetOptions(input, 'Act on');\n input\n .option('--fx <fraction>', 'Start X as a 0-1 fraction of the display width.')\n .option('--fy <fraction>', 'Start Y as a 0-1 fraction of the display height.')\n .option('--fx2 <fraction>', 'End X fraction (swipe/drag/fling).')\n .option('--fy2 <fraction>', 'End Y fraction (swipe/drag/fling).')\n .option('--x <px>', 'X pixel (click/swipe start).')\n .option('--y <px>', 'Y pixel (click/swipe start).')\n .option('--x2 <px>', 'End X pixel (swipe/drag/fling).')\n .option('--y2 <px>', 'End Y pixel (swipe/drag/fling).')\n .option('--speed <px-per-s>', 'Velocity for swipe/drag/fling.')\n .option(\n '--key <key>',\n 'Key for keyEvent: Back/Home/Power, a name (Delete, Enter, Tab, Escape, MoveHome, MoveEnd, …), ' +\n 'a letter, a KeyCode id, or a combo like Ctrl+A.',\n )\n .option('--text <text>', 'Text for inputText.')\n .option('--clear', 'inputText: clear the field (Ctrl+A, Delete) before typing.')\n .option('--hide-keyboard', 'Dismiss the soft keyboard afterwards, if it is up.')\n .option('--device <serial>', 'Target device serial.')\n .action(async (opts: InputOpts) => {\n const { config, logger } = getRuntime();\n const result = await performInput({\n config,\n type: opts.type,\n target: selectorFrom(opts),\n targetIndex: targetIndexFrom(opts),\n fx: num(opts.fx),\n fy: num(opts.fy),\n fx2: num(opts.fx2),\n fy2: num(opts.fy2),\n pxX: num(opts.x),\n pxY: num(opts.y),\n pxX2: num(opts.x2),\n pxY2: num(opts.y2),\n speed: num(opts.speed),\n key: opts.key,\n text: opts.text,\n clear: opts.clear,\n hideKeyboard: opts.hideKeyboard,\n deviceSerial: opts.device,\n logger,\n });\n if (opts.type === 'hideKeyboard') {\n logger.info(result.keyboardHidden ? 'Dismissed the keyboard.' : 'The keyboard was not shown.');\n return;\n }\n const at = result.x !== undefined ? ` at ${result.x},${result.y}` : '';\n const on = result.target ? ` on ${describeLayoutNode(result.target)}` : '';\n const kb = result.keyboardHidden ? ' (dismissed the keyboard)' : '';\n logger.info(`Sent ${opts.type}${at}${on}${kb}.`);\n });\n\n program\n .command('gesture')\n .description('Inject a multi-waypoint gesture. Waypoints are JSON: [{\"x\":..,\"y\":..,\"t\":..}] in pixels (or fractions with --fractions).')\n .requiredOption('--waypoints <json>', 'JSON array of {x,y,t} waypoints (t = ms from start).')\n .option('--fractions', 'Waypoint x/y are 0-1 fractions of the display instead of pixels.')\n .option('--hold-start <ms>', 'Leading press-hold before moving (best-effort: uses `uitest drag`).')\n .option('--hold-end <ms>', 'Trailing hold before lifting (no uitest equivalent; ignored).')\n .option('--device <serial>', 'Target device serial.')\n .action(async (opts: GestureOpts) => {\n const { config, logger } = getRuntime();\n let waypoints = JSON.parse(opts.waypoints) as Waypoint[];\n if (opts.fractions) {\n const bad = waypoints.find((w) => !(w.x >= 0 && w.x <= 1 && w.y >= 0 && w.y <= 1));\n if (bad) throw new Error(`With --fractions, waypoint x and y must be 0-1; got ${bad.x},${bad.y}.`);\n const display = await getDisplaySize(config, { deviceSerial: opts.device, logger });\n if (!display) throw new Error('Could not read the display size to convert fractions to pixels.');\n // 1.0 maps to the last pixel, not one past the edge.\n const px = (f: number, size: number): number => Math.min(size - 1, Math.round(f * size));\n waypoints = waypoints.map((w) => ({ ...w, x: px(w.x, display.width), y: px(w.y, display.height) }));\n }\n await sendGesture({\n config,\n waypoints,\n holdStartMs: num(opts.holdStart),\n holdEndMs: num(opts.holdEnd),\n deviceSerial: opts.device,\n logger,\n });\n logger.info('Gesture sent.');\n });\n}\n"],"mappings":";;;AAAA,SAAS,WAAAA,gBAAe;AACxB,SAAS,cAAAC,mBAAkB;;;ACA3B,YAAY,QAAQ;AACpB,YAAY,UAAU;AACtB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;ACFA,SAAS,kBAA0B;AACxC,QAAM,eAAe,QAAQ,IAAI,gBAAgB,OAAO,QAAQ,IAAI,gBAAgB;AACpF,SAAO;AAAA,IACL,MAAM,GAAG;AACP,UAAI,aAAc,SAAQ,OAAO,MAAM,WAAW,CAAC;AAAA,CAAI;AAAA,IACzD;AAAA,IACA,KAAK,GAAG;AACN,cAAQ,OAAO,MAAM,GAAG,CAAC;AAAA,CAAI;AAAA,IAC/B;AAAA,IACA,KAAK,GAAG;AACN,cAAQ,OAAO,MAAM,UAAU,CAAC;AAAA,CAAI;AAAA,IACtC;AAAA,IACA,MAAM,GAAG;AACP,cAAQ,OAAO,MAAM,WAAW,CAAC;AAAA,CAAI;AAAA,IACvC;AAAA,EACF;AACF;;;AChBO,SAAS,oBAAsC;AACpD,MAAI,QAAQ;AACZ,MAAI,cAAc;AAClB,MAAI,cAAc;AAClB,SAAO;AAAA,IACL,OAAO,EAAE,SAAS,UAAU,GAAG;AAC7B,UAAI,OAAO,cAAc,SAAU,SAAQ,KAAK,IAAI,KAAK,QAAQ,SAAS;AAC1E,YAAM,MAAM,QAAQ,IAAI,KAAK,MAAM,KAAK,IAAI;AAC5C,YAAM,MAAM,WAAW;AAEvB,UAAI,QAAQ,eAAe,QAAQ,YAAa;AAChD,YAAM,SAAS,QAAQ,OAAO,eAAe,aAAa,GAAG;AAC7D,cAAQ,OAAO,MAAM,GAAG,MAAM,IAAI,GAAG;AAAA,CAAI;AACzC,oBAAc,OAAO;AACrB,UAAI,QAAS,eAAc;AAAA,IAC7B;AAAA,EACF;AACF;;;ACzBA,YAAY,QAAQ;AAOpB,IAAM,iBAA4C;AAAA,EAChD,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,SAAS;AAAA,EACT,aAAa;AAAA,EACb,SAAS;AAAA,EACT,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,qBAAqB;AAAA,EACrB,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB,qBAAqB;AACvB;AAOO,SAAS,gBAAgB,MAAyB,QAAQ,KAAqB;AACpF,SAAO;AAAA,IACL,IAAyC,KAAgB,UAAgB;AACvE,YAAM,UAAU,eAAe,GAAG;AAClC,YAAM,MAAM,IAAI,OAAO;AACvB,UAAI,QAAQ,UAAa,QAAQ,GAAI,QAAO;AAC5C,YAAM,WAAW,IAAI,SAAS,aAAa,IACvC,IAAI,QAAQ,mBAAsB,WAAQ,CAAC,IAC3C;AACJ,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;AC/BA,IAAI,SAA4B;AAMzB,SAAS,aAAyB;AACvC,MAAI,CAAC,QAAQ;AACX,aAAS;AAAA,MACP,QAAQ,gBAAgB;AAAA,MACxB,QAAQ,gBAAgB;AAAA,MACxB,UAAU,kBAAkB;AAAA,IAC9B;AAAA,EACF;AACA,SAAO;AACT;;;AJbO,SAAS,mBAAmB,SAAwB;AACzD,QAAM,MAAM,QAAQ,QAAQ,KAAK,EAAE,YAAY,kCAAkC;AAEjF,MACG,QAAQ,mBAAmB,EAC3B,YAAY,sEAAsE,EAClF,OAAO,WAAW,+CAA+C,EACjE;AAAA,IACC;AAAA,IACA;AAAA,EAEF,EACC,OAAO,OAAO,SAAiB,SAA+C;AAC7E,UAAM,EAAE,QAAQ,QAAQ,SAAS,IAAI,WAAW;AAChD,UAAM,UAAU,SAAS,KAAK,CAAC,MAAM,EAAE,YAAY,OAAO;AAC1D,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI;AAAA,QACR,wBAAwB,OAAO,aAAa,SAAS,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,MACvF;AAAA,IACF;AACA,UAAM,gBAAqB,UAAK,cAAc,MAAM,GAAG,YAAY,GAAG,QAAQ,GAAG;AACjF,QAAO,cAAW,aAAa,KAAK,CAAC,KAAK,OAAO;AAC/C,aAAO;AAAA,QACL,OAAO,QAAQ,OAAO,SAAS,QAAQ,GAAG,0BAA0B,aAAa;AAAA,MACnF;AACA;AAAA,IACF;AACA,WAAO,KAAK,8BAA8B,QAAQ,OAAO,SAAS,QAAQ,GAAG,MAAM;AACnF,UAAM,sBAAsB;AAAA,MAC1B;AAAA,MACA,SAAS,QAAQ;AAAA,MACjB,KAAK,QAAQ;AAAA,MACb;AAAA,MACA;AAAA,MACA,QAAQ,KAAK;AAAA,IACf,CAAC;AACD,WAAO,KAAK,gBAAgB;AAAA,EAC9B,CAAC;AAEH,MACG,QAAQ,MAAM,EACd,YAAY,yEAAyE,EACrF,OAAO,UAAU,gDAAgD,EACjE,OAAO,CAAC,SAA6B;AACpC,UAAM,EAAE,OAAO,IAAI,WAAW;AAC9B,UAAM,OAAO,sBAAsB,MAAM;AACzC,QAAI,KAAK,MAAM;AACb,cAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAAA,CAAI;AACzD;AAAA,IACF;AACA,UAAM,OAAO,KAAK,IAAI,CAAC,MAAM,GAAG,EAAE,YAAY,MAAM,GAAG,KAAK,EAAE,QAAQ,OAAO,CAAC,CAAC,QAAQ,EAAE,GAAG,EAAE;AAC9F,YAAQ,OAAO,MAAM,GAAG,KAAK,KAAK,IAAI,CAAC;AAAA,CAAI;AAAA,EAC7C,CAAC;AAEH,MACG,QAAQ,cAAc,EACtB,YAAY,qDAAqD,EACjE,OAAO,CAAC,QAAgB;AACvB,UAAM,EAAE,QAAQ,OAAO,IAAI,WAAW;AACtC,UAAM,UAAU,UAAU,QAAQ,GAAG;AACrC,QAAI,CAAC,SAAS;AACZ,aAAO,KAAK,mBAAmB,GAAG,uCAAuC;AACzE,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,WAAO,KAAK,mBAAmB,GAAG,GAAG;AAAA,EACvC,CAAC;AACL;;;AK9EA,SAAS,mBAAmB,iBAAiB,qBAAqB,sBAAsB;AAGjF,SAAS,wBAAwB,SAAwB;AAC9D,QAAM,WAAW,QAAQ,QAAQ,UAAU,EAAE,YAAY,wCAAwC;AAEjG,WACG,QAAQ,SAAS,EACjB,YAAY,8FAA8F,EAC1G,OAAO,qBAAqB,kDAAkD,EAC9E,OAAO,WAAW,kDAAkD,EACpE;AAAA,IACC;AAAA,IACA;AAAA,EAEF,EACC,OAAO,OAAO,SAAiE;AAC9E,UAAM,EAAE,QAAQ,QAAQ,SAAS,IAAI,WAAW;AAChD,QAAI,oBAAoB,MAAM,KAAK,CAAC,KAAK,OAAO;AAC9C,aAAO,KAAK,kEAAkE;AAC9E;AAAA,IACF;AACA,WAAO,KAAK,8CAA8C;AAC1D,UAAM,gBAAgB,EAAE,QAAQ,UAAU,QAAQ,cAAc,KAAK,SAAS,QAAQ,KAAK,OAAO,CAAC;AACnG,WAAO,KAAK,+BAA+B;AAAA,EAC7C,CAAC;AAEH,WACG,QAAQ,QAAQ,EAChB,YAAY,wEAAwE,EACpF,OAAO,UAAU,6BAA6B,EAC9C,OAAO,CAAC,SAA6B;AACpC,UAAM,EAAE,OAAO,IAAI,WAAW;AAC9B,UAAM,SAAS,kBAAkB,MAAM;AACvC,QAAI,KAAK,MAAM;AACb,cAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,CAAI;AAC3D;AAAA,IACF;AACA,YAAQ,OAAO,MAAM,GAAG,OAAO,MAAM;AAAA,CAAI;AACzC,QAAI,CAAC,OAAO,UAAW,SAAQ,KAAK,CAAC;AAAA,EACvC,CAAC;AAEH,WACG,QAAQ,QAAQ,EAChB,YAAY,qDAAqD,EACjE,OAAO,MAAM;AACZ,UAAM,EAAE,QAAQ,OAAO,IAAI,WAAW;AACtC,mBAAe,MAAM;AACrB,WAAO,KAAK,6BAA6B;AAAA,EAC3C,CAAC;AACL;;;AClDA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGA,SAAS,wBAAwB,SAAwB;AAC9D,QAAM,MAAM,QAAQ,QAAQ,UAAU,EAAE,YAAY,4BAA4B;AAEhF,MACG,QAAQ,SAAS,EACjB,YAAY,mFAAmF,EAC/F,OAAO,WAAW,oDAAoD,EACtE;AAAA,IACC;AAAA,IACA;AAAA,EAEF,EACC,OAAO,OAAO,SAA+C;AAC5D,UAAM,EAAE,QAAQ,QAAQ,SAAS,IAAI,WAAW;AAChD,QAAI,oBAAoB,MAAM,KAAK,CAAC,KAAK,OAAO;AAC9C,aAAO,KAAK,wDAAwD;AACpE;AAAA,IACF;AACA,WAAO,KAAK,8BAA8B;AAC1C,UAAM,gBAAgB,EAAE,QAAQ,UAAU,QAAQ,QAAQ,KAAK,OAAO,CAAC;AACvE,WAAO,KAAK,qBAAqB;AAAA,EACnC,CAAC;AAEH,MACG,QAAQ,OAAO,EACf,YAAY,sIAAsI,EAClJ,OAAO,cAAc,yEAAyE,EAC9F,OAAO,gBAAgB,8EAA8E,EACrG,OAAO,4BAA4B,6DAA6D,CAAC,MAAM,SAAS,GAAG,EAAE,GAAG,CAAC,EACzH,OAAO,yBAAyB,4IAA6I,EAC7K,OAAO,OAAO,SAAqF;AAClG,UAAM,EAAE,QAAQ,OAAO,IAAI,WAAW;AACtC,UAAM,cAAc;AAAA,MAClB;AAAA,MACA;AAAA,MACA,UAAU,KAAK,aAAa;AAAA,MAC5B,SAAS,KAAK;AAAA,MACd,mBAAmB,KAAK;AAAA,MACxB,SAAS,KAAK;AAAA,IAChB,CAAC;AACD,WAAO,KAAK,kCAAkC;AAAA,EAChD,CAAC;AAEH,MACG,QAAQ,MAAM,EACd,YAAY,kCAAkC,EAC9C,OAAO,YAAY;AAClB,UAAM,EAAE,OAAO,IAAI,WAAW;AAC9B,UAAM,aAAa,MAAM;AACzB,WAAO,KAAK,mBAAmB;AAAA,EACjC,CAAC;AAEH,MACG,QAAQ,SAAS,EACjB,YAAY,yCAAyC,EACrD,OAAO,oBAAoB,6BAA6B,iBAAiB,EACzE,OAAO,OAAO,SAA8B;AAC3C,UAAM,EAAE,QAAQ,OAAO,IAAI,WAAW;AACtC,UAAM,KAAK,MAAM,qBAAqB,QAAQ,KAAK,SAAS,MAAM;AAClE,QAAI,CAAC,IAAI;AACP,aAAO,MAAM,4BAA4B,KAAK,OAAO,GAAG;AACxD,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,WAAO,KAAK,oBAAoB,KAAK,OAAO,GAAG;AAAA,EACjD,CAAC;AAEH,MACG,QAAQ,QAAQ,EAChB,YAAY,2CAA2C,EACvD,OAAO,MAAM;AACZ,UAAM,EAAE,QAAQ,OAAO,IAAI,WAAW;AACtC,mBAAe,MAAM;AACrB,WAAO,KAAK,mBAAmB;AAAA,EACjC,CAAC;AACL;;;ACpFA,YAAYC,WAAU;AACtB,SAAS,gBAAgB;AAalB,SAAS,qBAAqB,SAAwB;AAC3D,UACG,QAAQ,qBAAqB,EAC7B;AAAA,IACC;AAAA,EAEF,EACC,OAAO,uBAAuB,uBAAuB,SAAS,EAC9D,OAAO,qBAAqB,yCAAyC,EACrE,OAAO,iBAAiB,yCAAyC,EACjE,OAAO,iBAAiB,sBAAsB,aAAa,EAC3D,OAAO,aAAa,qEAAqE,EACzF,OAAO,iBAAiB,4CAA4C,EACpE,OAAO,UAAU,2DAA2D,EAC5E,OAAO,OAAO,YAAgC,SAAoB;AACjE,UAAM,EAAE,QAAQ,OAAO,IAAI,WAAW;AACtC,UAAM,MAAW,cAAQ,cAAc,QAAQ,IAAI,CAAC;AACpD,WAAO,KAAK,uBAAuB,GAAG,KAAK;AAC3C,UAAM,SAAS,MAAM,SAAS;AAAA,MAC5B;AAAA,MACA,YAAY;AAAA,MACZ,SAAS,KAAK;AAAA,MACd,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,iBAAiB,KAAK;AAAA,MACtB,UAAU,KAAK;AAAA,MACf;AAAA;AAAA,MAEA,UAAU,MAAM;AAAA,MAAC;AAAA,IACnB,CAAC;AACD,eAAW,KAAK,OAAO,SAAU,QAAO,KAAK,CAAC;AAC9C,QAAI,KAAK,MAAM;AACb,cAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,CAAI;AAAA,IAC7D;AACA,WAAO,KAAK,iBAAiB;AAAA,EAC/B,CAAC;AACL;;;ACpDA,SAAkB,cAAc;AAChC,YAAYC,WAAU;AACtB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AAGP,SAAS,cAAc,OAAyB;AAC9C,SAAO,MACJ,MAAM,GAAG,EACT,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC;AAC/B;AAEO,SAAS,oBAAoB,SAAwB;AAC1D,UACG,QAAQ,oBAAoB,EAC5B;AAAA,IACC;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE,KAAK,GAAG;AAAA,EACZ,EACC;AAAA,IACC,IAAI;AAAA,MACF;AAAA,MACA;AAAA,IACF,EACG,QAAQ,CAAC,GAAG,UAAU,CAAC,EACvB,QAAQ,QAAQ;AAAA,EACrB,EACC;AAAA,IACC,IAAI;AAAA,MACF;AAAA,MACA;AAAA,IACF,EAAE,QAAQ,CAAC,GAAG,kBAAkB,CAAC;AAAA,EACnC,EACC;AAAA,IACC,IAAI;AAAA,MACF;AAAA,MACA;AAAA,IACF,EAAE,UAAU,aAAa;AAAA,EAC3B,EACC;AAAA,IACC;AAAA,IACA;AAAA,EACF,EACC,OAAO,kBAAkB,wGAAyG,EAClI,OAAO,oBAAoB,2DAA2D,EACtF,OAAO,WAAW,0FAA0F,EAC5G,OAAO,eAAe,sEAAsE,EAC5F,OAAO,0BAA0B,4EAAuE,EACxG,OAAO,wBAAwB,0EAAqE,EACpG;AAAA,IACC,OACE,YACA,SAYG;AACH,YAAM,EAAE,QAAQ,OAAO,IAAI,WAAW;AACtC,YAAM,MAAW,cAAQ,cAAc,QAAQ,IAAI,CAAC;AAEpD,UAAI,KAAK,WAAW;AAClB,cAAM,SAAS,MAAM,kBAAkB;AAAA,UACrC;AAAA,UACA,SAAS,uBAAuB,EAAE,QAAQ,OAAO,CAAC;AAAA,UAClD,YAAY;AAAA,UACZ,aAAa,KAAK;AAAA,UAClB,QAAQ,KAAK;AAAA,UACb,OAAO,KAAK;AAAA,UACZ;AAAA,QACF,CAAC;AACD,eAAO,KAAK,6BAA6B,OAAO,UAAU,mBAAmB,OAAO,UAAU,MAAM,cAAc;AAClH;AAAA,MACF;AAEA,UAAI,gBAAgB,KAAK,KAAK,OAAO,MAAM,aAAa;AACtD,cAAM,IAAI;AAAA,UACR,GAAG,GAAG;AAAA,QACR;AAAA,MACF;AACA,YAAM,YACJ,KAAK,iBAAiB,KAAK,cACvB,EAAE,OAAO,KAAK,iBAAiB,UAAU,KAAK,KAAK,eAAe,SAAS,IAC3E;AAEN,UAAI,KAAK,WAAW;AAClB,cAAM,SAAS,eAAe;AAAA,UAC5B;AAAA,UACA,YAAY;AAAA,UACZ,KAAK,KAAK;AAAA,UACV,YAAY,KAAK;AAAA,UACjB,MAAM,KAAK;AAAA,UACX;AAAA,UACA;AAAA,QACF,CAAC;AACD,eAAO,KAAK,OAAO,WAAW,YAAY,sCAAsC,4BAA4B;AAC5G;AAAA,MACF;AAEA,YAAM,UAAU,mBAAmB,MAAM;AACzC,aAAO,KAAK,iCAAiC,GAAG,iBAAiB,OAAO,KAAK;AAC7E,6BAAuB;AAAA,QACrB,YAAY;AAAA,QACZ;AAAA,QACA,KAAK,KAAK;AAAA,QACV,YAAY,KAAK;AAAA,QACjB,MAAM,KAAK;AAAA,QACX;AAAA,QACA;AAAA,MACF,CAAC;AACD,aAAO,KAAK,4BAA4B;AAAA,IAC1C;AAAA,EACF;AACJ;;;AC1IA,SAAS,cAAc,0BAAAC,+BAAqD;AAI5E,SAAS,UAA4B;AACnC,QAAM,EAAE,QAAQ,OAAO,IAAI,WAAW;AACtC,SAAOC,wBAAuB;AAAA,IAC5B;AAAA,IACA;AAAA,IACA,YAAY,CAAC,QAAQ,QAAQ,OAAO,MAAM;AAAA,IAAmE,GAAG;AAAA,CAAI;AAAA,EACtH,CAAC;AACH;AAEO,SAAS,oBAAoB,SAAwB;AAC1D,QAAM,OAAO,QACV,QAAQ,MAAM,EACd;AAAA,IACC;AAAA,EAGF;AAEF,OACG,QAAQ,OAAO,EACf,YAAY,uFAAuF,EACnG,OAAO,uBAAuB,0DAA0D,CAAC,MAAM,OAAO,CAAC,CAAC,EACxG,OAAO,OAAO,SAA+B;AAC5C,UAAM,OAAO,MAAM,QAAQ,EAAE,MAAM,KAAK,UAAU,EAAE,WAAW,KAAK,IAAI,GAAG,KAAK,OAAO,IAAI,IAAK,IAAI,MAAS;AAC7G,YAAQ,OAAO,MAAM,GAAG,KAAK,YAAY,KAAK,MAAM;AAAA,CAAI;AAAA,EAC1D,CAAC;AAEH,OACG,QAAQ,QAAQ,EAChB,YAAY,uCAAuC,EACnD,OAAO,YAAY;AAClB,UAAM,YAAY,MAAM,QAAQ,EAAE,OAAO;AACzC,eAAW,EAAE,OAAO,KAAK,YAAY,gBAAgB,+BAA+B;AAAA,EACtF,CAAC;AAEH,OACG,QAAQ,QAAQ,EAChB,YAAY,gEAAgE,EAC5E,OAAO,UAAU,mCAAmC,EACpD,OAAO,OAAO,SAA6B;AAC1C,UAAM,IAAI,QAAQ;AAElB,UAAM,OAAO,MAAM,EAAE,YAAY,EAAE,SAAS,KAAK,CAAC;AAClD,QAAI,CAAC,MAAM;AACT,cAAQ,OAAO,MAAM,8CAA8C;AACnE,cAAQ,WAAW;AACnB;AAAA,IACF;AAEA,UAAM,YAAY,KAAK,aAAa,OAAO,MAAM,EAAE,sBAAsB,IAAI;AAC7E,QAAI,KAAK,MAAM;AACb,YAAM,EAAE,QAAQ,UAAU,aAAa,UAAU,WAAW,IAAI;AAChE,YAAM,aAAa,aAAa,QAAQ,EAAE;AAC1C,YAAM,SAAS,EAAE,QAAQ,UAAU,aAAa,MAAM,UAAU,YAAY,YAAY,oBAAoB,WAAW,WAAW,EAAE,UAAU;AAC9I,cAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,CAAI;AAC3D;AAAA,IACF;AACA,YAAQ,OAAO,MAAM,GAAG,KAAK,YAAY,KAAK,MAAM,KAAK,KAAK,MAAM,MAAM,KAAK,QAAQ;AAAA,CAAK;AAC5F,QAAI,aAAa,EAAE,UAAU,UAAU,UAAU,SAAS;AACxD,cAAQ,OAAO;AAAA,QACb;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AAEH,OACG,QAAQ,MAAM,EACd,YAAY,oCAAoC,EAChD,QAAQ,MAAM,EACd,YAAY,8FAA8F,EAC1G,OAAO,UAAU,6BAA6B,EAC9C,OAAO,OAAO,SAA6B;AAC1C,UAAM,QAAQ,MAAM,QAAQ,EAAE,UAAU;AACxC,QAAI,KAAK,MAAM;AACb,cAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AAAA,CAAI;AAC1D;AAAA,IACF;AACA,eAAW,KAAK,MAAO,SAAQ,OAAO,MAAM,GAAG,EAAE,EAAE,IAAK,EAAE,IAAI;AAAA,CAAI;AAAA,EACpE,CAAC;AACL;;;ACnFA,YAAYC,WAAU;AACtB,SAAS,YAAY,WAAW,cAAc,WAAW,cAAc,qBAAqB;AAcrF,SAAS,mBAAmB,SAAwB;AACzD,QAAM,MAAM,QAAQ,QAAQ,KAAK,EAAE,YAAY,wEAAwE;AAEvH,MACG,QAAQ,uBAAuB,EAC/B,YAAY,mEAAmE,EAC/E,OAAO,gBAAgB,+DAA+D,EACtF,OAAO,qBAAqB,uBAAuB,EACnD,OAAO,OAAO,YAAgC,SAA4C;AACzF,UAAM,EAAE,QAAQ,OAAO,IAAI,WAAW;AACtC,UAAM,MAAW,cAAQ,cAAc,QAAQ,IAAI,CAAC;AACpD,WAAO,KAAK,uBAAuB,GAAG,KAAK;AAC3C,UAAM,WAAW,EAAE,QAAQ,YAAY,KAAK,SAAS,KAAK,KAAK,cAAc,KAAK,QAAQ,OAAO,CAAC;AAClG,WAAO,KAAK,gBAAgB;AAAA,EAC9B,CAAC;AAEH,MACG,QAAQ,sBAAsB,EAC9B;AAAA,IACC;AAAA,EAGF,EACC,OAAO,qBAAqB,qEAAqE,EACjG,OAAO,qBAAqB,sCAAsC,OAAO,EACzE,OAAO,oBAAoB,yIAAyI,EACpK,OAAO,qBAAqB,uBAAuB,EACnD,OAAO,OAAO,YAAgC,SAAiF;AAC9H,UAAM,EAAE,QAAQ,OAAO,IAAI,WAAW;AACtC,QAAI,KAAK,QAAQ;AACf,aAAO,KAAK,8BAA8B,KAAK,MAAM,KAAK;AAC1D,YAAM,UAAU,EAAE,QAAQ,YAAY,KAAK,QAAQ,aAAa,KAAK,SAAS,cAAc,KAAK,QAAQ,OAAO,CAAC;AAAA,IACnH,OAAO;AACL,YAAM,MAAW,cAAQ,cAAc,QAAQ,IAAI,CAAC;AACpD,aAAO,KAAK,sBAAsB,GAAG,KAAK;AAC1C,YAAM,UAAU,EAAE,QAAQ,YAAY,KAAK,YAAY,KAAK,QAAQ,aAAa,KAAK,SAAS,cAAc,KAAK,QAAQ,OAAO,CAAC;AAAA,IACpI;AACA,WAAO,KAAK,eAAe;AAAA,EAC7B,CAAC;AAEH,MACG,QAAQ,qBAAqB,EAC7B;AAAA,IACC;AAAA,EAEF,EACC,OAAO,qBAAqB,gGAAgG,EAC5H,OAAO,qBAAqB,yDAAyD,EACrF,OAAO,gBAAgB,2DAA2D,EAClF,OAAO,0BAA0B,8EAA8E,EAC/G,OAAO,YAAY,gFAAgF,EACnG,OAAO,qBAAqB,wEAAwE,EACpG,OAAO,qBAAqB,uBAAuB,EACnD,OAAO,UAAU,0BAA0B,EAC3C,OAAO,OAAO,YAAgC,SAAoB;AACjE,UAAM,EAAE,QAAQ,OAAO,IAAI,WAAW;AACtC,UAAM,MAAW,cAAQ,cAAc,QAAQ,IAAI,CAAC;AACpD,UAAM,SAAS,KAAK,UAAU,cAAc,GAAG;AAC/C,UAAM,SAAS,MAAM,aAAa;AAAA,MAChC;AAAA,MACA;AAAA,MACA,SAAS,KAAK;AAAA,MACd,YAAY;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb,kBAAkB,KAAK;AAAA,MACvB,gBAAgB,KAAK;AAAA,MACrB,gBAAgB,KAAK;AAAA,MACrB,cAAc,KAAK;AAAA,MACnB;AAAA,IACF,CAAC;AACD,QAAI,KAAK,MAAM;AACb,cAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,CAAI;AAAA,IAC7D,OAAO;AACL,aAAO;AAAA,QACL,iBAAiB,OAAO,MAAM,QAAQ,OAAO,iBAAiB,GAAG,OAAO,OAAO,kBAAkB,GAAG,GAC/F,OAAO,eAAe,qBAAqB,EAAE;AAAA,MACpD;AAAA,IACF;AAAA,EACF,CAAC;AAEH,MACG,QAAQ,oBAAoB,EAC5B,YAAY,kCAAkC,EAC9C,OAAO,qBAAqB,uBAAuB,EACnD,OAAO,OAAO,QAAgB,SAA8B;AAC3D,UAAM,EAAE,QAAQ,OAAO,IAAI,WAAW;AACtC,UAAM,aAAa,EAAE,QAAQ,QAAQ,cAAc,KAAK,QAAQ,OAAO,CAAC;AACxE,WAAO,KAAK,eAAe,MAAM,GAAG;AAAA,EACtC,CAAC;AAEH,MACG,QAAQ,eAAe,EACvB,YAAY,mCAAmC,EAC/C,OAAO,qBAAqB,uBAAuB,EACnD,OAAO,OAAO,QAAgB,SAA8B;AAC3D,UAAM,EAAE,QAAQ,OAAO,IAAI,WAAW;AACtC,UAAM,UAAU,EAAE,QAAQ,QAAQ,cAAc,KAAK,QAAQ,OAAO,CAAC;AACrE,WAAO,KAAK,WAAW,MAAM,GAAG;AAAA,EAClC,CAAC;AACL;;;AClHA,YAAYC,WAAU;AACtB;AAAA,EACE,YAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;ACPP,YAAYC,SAAQ;AACpB,YAAYC,WAAU;AACtB,SAAS,qBAAqB;AASvB,SAAS,yBAAiC;AAC/C,QAAM,OAAY,cAAQ,cAAc,YAAY,GAAG,CAAC;AACxD,QAAM,aAAa;AAAA,IACZ,cAAQ,MAAM,cAAc;AAAA;AAAA,IAC5B,cAAQ,MAAM,iBAAiB;AAAA;AAAA,EACtC;AACA,aAAW,KAAK,YAAY;AAC1B,QAAO,eAAW,CAAC,EAAG,QAAO;AAAA,EAC/B;AAGA,SAAO,WAAW,CAAC;AACrB;;;ADFO,SAAS,sBAAsB,SAAwB;AAC5D,UACG,QAAQ,QAAQ,EAChB,YAAY,8GAA8G,EAC1H,eAAe,iBAAiB,iDAAiD,EACjF,eAAe,yBAAyB,yDAAyD,EACjG,eAAe,oBAAoB,+DAA+D,EAClG,eAAe,eAAe,oCAAoC,EAClE,OAAO,mBAAmB,eAAe,cAAc,EACvD,OAAO,mBAAmB,wEAAwE,EAClG,OAAO,eAAe,8CAA8C,EACpE,OAAO,OAAO,SAAqB;AAClC,UAAM,EAAE,QAAQ,OAAO,IAAI,WAAW;AAEtC,QAAI,CAAC,mBAAmB,KAAK,IAAI,GAAG;AAClC,YAAM,IAAI,MAAM,mBAAmB,KAAK,IAAI,4CAA4C;AAAA,IAC1F;AACA,QAAI,CAAC,kBAAkB,KAAK,MAAM,GAAG;AACnC,YAAM,IAAI,MAAM,qBAAqB,KAAK,MAAM,+BAA+B;AAAA,IACjF;AACA,UAAM,SAAS,OAAO,KAAK,GAAG;AAC9B,QAAI,CAAC,OAAO,SAAS,MAAM,GAAG;AAC5B,YAAM,IAAI,MAAM,6CAA6CC,UAAS,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC,EAAE;AAAA,IACtG;AAEA,UAAM,eAAe,uBAAuB;AAC5C,UAAM,SAAS,MAAM,eAAe;AAAA,MAClC;AAAA,MACA,YAAY,KAAK;AAAA,MACjB,aAAa,KAAK;AAAA,MAClB,YAAY,KAAK;AAAA,MACjB,UAAe,cAAQ,KAAK,QAAQ;AAAA,MACpC;AAAA,MACA,YAAY,KAAK;AAAA,MACjB;AAAA,MACA,WAAW,KAAK;AAAA,MAChB;AAAA,IACF,CAAC;AAED,WAAO,KAAK,sBAAsB,OAAO,UAAU,EAAE;AACrD,YAAQ,OAAO,MAAM,GAAG,OAAO,UAAU;AAAA,CAAI;AAAA,EAC/C,CAAC;AACL;;;AE9DA,SAAS,qBAAqB;AAGvB,SAAS,yBAAyB,SAAwB;AAC/D,QAAM,YAAY,QAAQ,QAAQ,WAAW,EAAE,YAAY,8CAA8C;AAEzG,YACG,QAAQ,MAAM,EACd,YAAY,mCAAmC,EAC/C,OAAO,UAAU,6BAA6B,EAC9C,OAAO,CAAC,SAA6B;AACpC,UAAM,OAAO,uBAAuB;AACpC,UAAM,OAAO,cAAc,IAAI;AAC/B,QAAI,KAAK,MAAM;AACb,cAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAAA,CAAI;AACzD;AAAA,IACF;AACA,QAAI,KAAK,WAAW,GAAG;AACrB,cAAQ,OAAO,MAAM,2BAA2B;AAChD;AAAA,IACF;AACA,UAAM,OAAO,KAAK,IAAI,CAAC,MAAM,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,OAAO,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE;AACxF,YAAQ,OAAO,MAAM,GAAG,KAAK,KAAK,IAAI,CAAC;AAAA,CAAI;AAAA,EAC7C,CAAC;AACL;;;ACzBA,SAAkB,UAAAC,eAAc;AAChC,SAAS,cAAc;AAGhB,SAAS,sBAAsB,SAAwB;AAC5D,UACG,QAAQ,QAAQ,EAChB,YAAY,uCAAuC,EACnD;AAAA,IACC,IAAIC,QAAO,iBAAiB,gBAAgB,EAAE,QAAQ,CAAC,UAAU,cAAc,UAAU,CAAC,EAAE,QAAQ,QAAQ;AAAA,EAC9G,EACC,OAAO,0BAA0B,iEAAiE,EAClG,OAAO,kBAAkB,wCAAwC,QAAQ,EACzE,OAAO,qBAAqB,uBAAuB,EACnD;AAAA,IACC,OAAO,SAKD;AACJ,YAAM,EAAE,QAAQ,OAAO,IAAI,WAAW;AACtC,aAAO,KAAK,qBAAqB,KAAK,IAAI,MAAM;AAChD,YAAM,OAAO;AAAA,QACX;AAAA,QACA,MAAM,KAAK;AAAA,QACX,eAAe,KAAK;AAAA,QACpB,WAAW,OAAO,KAAK,OAAO;AAAA,QAC9B,cAAc,KAAK;AAAA,QACnB;AAAA,MACF,CAAC;AACD,aAAO,KAAK,kBAAkB;AAAA,IAChC;AAAA,EACF;AACJ;;;ACjCA,SAAS,YAAY,aAAa,eAAe,eAAe,0BAA0B;;;ACcnF,SAAS,iBAAiB,KAAc,MAAc,OAA4B,CAAC,GAAY;AACpG,MACG;AAAA,IACC;AAAA,IACA,GAAG,IAAI;AAAA,EAET,EACC,OAAO,oBAAoB,qCAAqC,EAChE,OAAO,wBAAwB,kEAAkE;AACpG,MAAI,KAAK,UAAU,OAAO;AACxB,QAAI,OAAO,sBAAsB,uDAAuD;AAAA,EAC1F;AACA,SAAO;AACT;AAGO,SAAS,aAAa,MAA8C;AACzE,MAAI,KAAK,WAAW,UAAa,KAAK,aAAa,UAAa,KAAK,eAAe,OAAW,QAAO;AACtG,SAAO,EAAE,MAAM,KAAK,QAAQ,IAAI,KAAK,UAAU,MAAM,KAAK,WAAW;AACvE;AAEO,SAAS,gBAAgB,MAAsC;AACpE,MAAI,KAAK,gBAAgB,OAAW,QAAO;AAC3C,QAAM,IAAI,OAAO,KAAK,WAAW;AACjC,MAAI,CAAC,OAAO,UAAU,CAAC,KAAK,IAAI,EAAG,OAAM,IAAI,MAAM,sDAAsD,KAAK,WAAW,GAAG;AAC5H,SAAO;AACT;;;ADvBO,SAAS,oBAAoB,SAAwB;AAC1D,QAAM,OAAO,QACV,QAAQ,MAAM,EACd;AAAA,IACC;AAAA,EAEF,EACC,OAAO,mBAAmB,8DAA8D,EACxF,OAAO,UAAU,kEAAkE,EACnF,OAAO,qBAAqB,8EAA8E,EAC1G,OAAO,mBAAmB,uDAAuD,EACjF,OAAO,qBAAqB,mDAAmD;AAClF,mBAAiB,MAAM,gBAAgB,EAAE,OAAO,MAAM,CAAC;AACvD,OACG,OAAO,UAAU,qEAAqE,EACtF,OAAO,mBAAmB,mEAAmE,KAAK,EAClG,OAAO,kBAAkB,iBAAiB,OAAO,EACjD,OAAO,qBAAqB,uBAAuB,EACnD,OAAO,UAAU,kEAAkE,EACnF,OAAO,OAAO,SAAmB;AAChC,UAAM,EAAE,QAAQ,OAAO,IAAI,WAAW;AACtC,UAAM,YAAY,OAAO,KAAK,OAAO;AACrC,UAAM,WAAW,aAAa,IAAI;AAElC,QAAI,KAAK,KAAK;AACZ,YAAM,QAAQ,MAAM,WAAW;AAAA,QAC7B;AAAA,QACA,SAAS,IAAI,OAAO,KAAK,GAAG;AAAA,QAC5B;AAAA,QACA,QAAQ,KAAK;AAAA,QACb,QAAQ,KAAK;AAAA,QACb,cAAc,KAAK;AAAA,QACnB;AAAA,MACF,CAAC;AACD,UAAI,KAAK,KAAM,SAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AAAA,CAAI;AAAA,UACpE,QAAO,KAAK,YAAY,MAAM,GAAG,KAAK,MAAM,OAAO,EAAE;AAC1D;AAAA,IACF;AACA,QAAI,KAAK,MAAM;AACb,YAAM,YAAY,EAAE,QAAQ,YAAY,KAAK,OAAO,WAAW,cAAc,KAAK,QAAQ,OAAO,CAAC;AAClG,aAAO,KAAK,gBAAgB;AAC5B;AAAA,IACF;AACA,QAAI,UAAU;AACZ,YAAM,OAAO,MAAM,cAAc;AAAA,QAC/B;AAAA,QACA;AAAA,QACA,MAAM,KAAK;AAAA,QACX;AAAA,QACA,QAAQ,OAAO,KAAK,QAAQ,KAAK;AAAA,QACjC,cAAc,KAAK;AAAA,QACnB;AAAA,MACF,CAAC;AACD,UAAI,CAAC,MAAM;AACT,eAAO,KAAK,kBAAkB;AAC9B;AAAA,MACF;AACA,UAAI,KAAK,KAAM,SAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAAA,CAAI;AAAA,UACnE,QAAO,KAAK,UAAU,mBAAmB,IAAI,CAAC,EAAE;AACrD;AAAA,IACF;AACA,QAAI,KAAK,QAAQ;AACf,YAAM,cAAc,EAAE,QAAQ,QAAQ,KAAK,QAAQ,WAAW,cAAc,KAAK,QAAQ,OAAO,CAAC;AACjG,aAAO,KAAK,UAAU,KAAK,MAAM,cAAc;AAC/C;AAAA,IACF;AACA,UAAM,IAAI,MAAM,iHAAiH;AAAA,EACnI,CAAC;AACL;;;AErFA,SAAS,gBAAgB;AAalB,SAAS,qBAAqB,SAAwB;AAC3D,UACG,QAAQ,OAAO,EACf,YAAY,8DAA8D,EAC1E,OAAO,mBAAmB,gDAAgD,EAC1E,OAAO,cAAc,0BAA0B,OAAO,EACtD,OAAO,qBAAqB,wBAAwB,EACpD,OAAO,qBAAqB,uCAAuC,EACnE,OAAO,cAAc,8CAA8C,EACnE,OAAO,qBAAqB,uBAAuB,EACnD,OAAO,UAAU,2BAA2B,EAC5C,OAAO,OAAO,SAAoB;AACjC,UAAM,EAAE,QAAQ,OAAO,IAAI,WAAW;AACtC,QAAI,CAAC,KAAK,IAAK,OAAM,IAAI,MAAM,iCAAiC;AAChE,UAAM,UAAU,MAAM,SAAS;AAAA,MAC7B;AAAA,MACA,SAAS,IAAI,OAAO,KAAK,GAAG;AAAA,MAC5B,YAAY,OAAO,KAAK,GAAG;AAAA,MAC3B,QAAQ,KAAK;AAAA,MACb,QAAQ,KAAK;AAAA,MACb,OAAO,KAAK;AAAA,MACZ,cAAc,KAAK;AAAA,MACnB;AAAA,IACF,CAAC;AACD,QAAI,KAAK,MAAM;AACb,cAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAAA,CAAI;AAAA,IAC9D,OAAO;AACL,iBAAW,KAAK,QAAS,SAAQ,OAAO,MAAM,GAAG,EAAE,IAAI,KAAK,EAAE,KAAK,KAAK,EAAE,GAAG,KAAK,EAAE,OAAO;AAAA,CAAI;AAAA,IACjG;AAAA,EACF,CAAC;AACL;;;AC3CA,YAAYC,SAAQ;AACpB,YAAYC,WAAU;AACtB,SAAS,gBAAgB,cAAc,cAAc,sBAAAC,2BAA0B;;;ACH/E,OAAO,WAAW;AAmCX,SAAS,aAAa,OAAe,QAAwB;AAClE,QAAM,YAAY;AAClB,QAAM,UAAU;AAChB,QAAM,UAAU;AAChB,QAAM,WAAW,KAAK,IAAI,IAAI,KAAK,MAAM,KAAK,IAAI,OAAO,MAAM,IAAI,EAAE,CAAC;AACtE,QAAM,UAAU,KAAK,MAAM,WAAW,GAAG;AACzC,QAAM,SAAmB,CAAC;AAC1B,QAAM,QAAkB,CAAC;AACzB,WAAS,IAAI,GAAG,KAAK,IAAI,KAAK;AAC5B,UAAM,IAAI,IAAI;AACd,UAAM,IAAI,KAAK,MAAM,KAAK,QAAQ,EAAE;AACpC,UAAM,IAAI,KAAK,MAAM,KAAK,SAAS,EAAE;AAErC,QAAI,IAAI,KAAK,IAAI,IAAI;AACnB,YAAM,KAAK,aAAa,CAAC,gBAAgB,CAAC,SAAS,MAAM,aAAa,SAAS,sBAAsB;AACrG,YAAM,KAAK,oBAAoB,CAAC,SAAS,KAAK,SAAS,CAAC,aAAa,SAAS,sBAAsB;AAAA,IACtG;AACA,UAAM,MAAM,EAAE,QAAQ,CAAC;AAEvB,UAAM,KAAK,MAAM,IAAI,UAAU,MAAM,KAAK,QAAQ,UAAU;AAC5D,UAAM,UAAU,MAAM,IAAI,UAAU,MAAM,KAAK,QAAQ;AACvD,WAAO;AAAA,MACL,YAAY,EAAE,QAAQ,WAAW,OAAO,wCAAwC,QAAQ,8BAA8B,OAAO,aAAa,OAAO,wDAAwD,OAAO,KAAK,GAAG;AAAA,IAC1N;AAEA,UAAM,KAAK,MAAM,IAAI,WAAW,UAAU,MAAM,KAAK,SAAS,UAAU,IAAI,WAAW;AACvF,WAAO;AAAA,MACL,YAAY,OAAO,QAAQ,EAAE,wCAAwC,QAAQ,8BAA8B,OAAO,aAAa,OAAO,+DAA+D,GAAG;AAAA,IAC1M;AAAA,EACF;AAEA,SAAO;AAAA,IACL,YAAY,QAAQ,CAAC,QAAQ,WAAW,MAAM,OAAO,wCAAwC,QAAQ,8BAA8B,OAAO,aAAa,OAAO;AAAA,EAChK;AACA,SAAO;AAAA,IACL,YAAY,OAAO,QAAQ,WAAW,MAAM,OAAO,wCAAwC,QAAQ,8BAA8B,OAAO,aAAa,OAAO;AAAA,EAC9J;AACA,SAAO,eAAe,KAAK,aAAa,MAAM,wCAAwC,MAAM,KAAK,EAAE,CAAC,GAAG,OAAO,KAAK,EAAE,CAAC;AACxH;AAOA,eAAsB,eAAe,MAAc,MAAoD;AACrG,QAAM,OAAO,MAAM,MAAM,IAAI,EAAE,SAAS;AACxC,QAAM,gBAAgB,KAAK,SAAS;AACpC,QAAM,iBAAiB,KAAK,UAAU;AACtC,QAAM,UAAU,KAAK,IAAI,eAAe,cAAc,KAAK;AAC3D,QAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,SAAS,OAAO;AAC/C,QAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,MAAM,gBAAgB,KAAK,CAAC;AAC3D,QAAM,SAAS,KAAK,IAAI,GAAG,KAAK,MAAM,iBAAiB,KAAK,CAAC;AAC7D,QAAM,UAAU,MAAM,MAAM,IAAI,EAAE,OAAO,OAAO,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,CAAC,EAAE,SAAS;AACvF,MAAI,CAAC,KAAK,MAAM;AACd,WAAO,EAAE,KAAK,SAAS,OAAO,QAAQ,eAAe,eAAe;AAAA,EACtE;AACA,QAAM,MAAM,aAAa,OAAO,MAAM;AACtC,QAAM,MAAM,MAAM,MAAM,OAAO,EAC5B,UAAU,CAAC,EAAE,OAAO,OAAO,KAAK,GAAG,EAAE,CAAC,CAAC,EACvC,KAAK,EAAE,SAAS,GAAG,CAAC,EACpB,SAAS;AACZ,SAAO,EAAE,KAAK,OAAO,QAAQ,eAAe,eAAe;AAC7D;AAMO,SAAS,cAAc,MAAwB;AACpD,QAAM,QAAQ,KAAK,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,OAAO,EAAE,KAAK,CAAC,CAAC;AACzD,MAAI,MAAM,WAAW,KAAK,MAAM,KAAK,CAAC,MAAM,CAAC,OAAO,SAAS,CAAC,KAAK,IAAI,KAAK,IAAI,CAAC,GAAG;AAClF,UAAM,IAAI,MAAM,yDAAyD,IAAI,IAAI;AAAA,EACnF;AACA,QAAM,CAAC,IAAI,IAAI,IAAI,EAAE,IAAI;AACzB,MAAI,EAAE,KAAK,MAAM,KAAK,IAAK,OAAM,IAAI,MAAM,0CAA0C,IAAI,IAAI;AAC7F,SAAO,CAAC,IAAI,IAAI,IAAI,EAAE;AACxB;AAGO,SAAS,YAAY,GAAa,KAAuB;AAC9D,SAAO,CAAC,KAAK,IAAI,GAAG,EAAE,CAAC,IAAI,GAAG,GAAG,KAAK,IAAI,GAAG,EAAE,CAAC,IAAI,GAAG,GAAG,KAAK,IAAI,GAAG,EAAE,CAAC,IAAI,GAAG,GAAG,KAAK,IAAI,GAAG,EAAE,CAAC,IAAI,GAAG,CAAC;AAC5G;AAoBA,eAAsB,UAAU,MAAc,MAAgB,MAA+C;AAC3G,QAAM,OAAO,MAAM,MAAM,IAAI,EAAE,SAAS;AACxC,QAAM,IAAI,KAAK,SAAS;AACxB,QAAM,IAAI,KAAK,UAAU;AACzB,QAAM,OAAO,KAAK,IAAI,IAAI,GAAG,KAAK,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;AACpD,QAAM,MAAM,KAAK,IAAI,IAAI,GAAG,KAAK,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;AACnD,QAAM,YAAY,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,KAAK,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI;AACxE,QAAM,aAAa,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,KAAK,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG;AACxE,QAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,SAAS,KAAK,IAAI,WAAW,UAAU,CAAC;AACvE,QAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,MAAM,YAAY,KAAK,CAAC;AACvD,QAAM,SAAS,KAAK,IAAI,GAAG,KAAK,MAAM,aAAa,KAAK,CAAC;AACzD,QAAM,MAAM,MAAM,MAAM,IAAI,EACzB,QAAQ,EAAE,MAAM,KAAK,OAAO,WAAW,QAAQ,WAAW,CAAC,EAC3D,OAAO,OAAO,MAAM,EACpB,KAAK,EAAE,SAAS,GAAG,CAAC,EACpB,SAAS;AACZ,SAAO,EAAE,KAAK,OAAO,QAAQ,MAAM,KAAK,WAAW,WAAW;AAChE;AAwBA,SAAS,kBAAkB,OAAe,QAAgB,KAAa,MAAuB;AAC5F,QAAM,WAAW,KAAK,IAAI,IAAI,KAAK,MAAM,KAAK,IAAI,OAAO,MAAM,IAAI,EAAE,CAAC;AACtE,QAAM,MAAM,KAAK,MAAM,WAAW,GAAG;AACrC,MAAI,QAAQ,IAAI,GAAG;AACnB,MAAI,OAAO,SAAS,SAAU,UAAS,WAAM,KAAK,QAAQ,CAAC,CAAC;AAC5D,QAAM,OAAO,KAAK,MAAM,MAAM,SAAS,WAAW,IAAI,IAAI,MAAM;AAChE,QAAM,OAAO,WAAW,MAAM;AAC9B,SACE,eAAe,KAAK,aAAa,MAAM,iEACX,IAAI,aAAa,IAAI,sCACrC,GAAG,QAAQ,WAAW,MAAM,CAAC,wCAAwC,QAAQ,wHAAwH,KAAK;AAG1N;AAOA,eAAsB,kBAAkB,QAAkB,MAAwD;AAChH,MAAI,OAAO,WAAW,EAAG,OAAM,IAAI,MAAM,8BAA8B;AACvE,QAAM,QAAQ,OAAO;AACrB,QAAM,OAAO,KAAK,IAAI,GAAG,KAAK,QAAQ,KAAK,KAAK,KAAK,KAAK,KAAK,CAAC,CAAC;AACjE,QAAM,OAAO,KAAK,KAAK,QAAQ,IAAI;AACnC,QAAM,MAAM,KAAK,OAAO;AAExB,QAAM,QAAQ,MAAM,MAAM,OAAO,CAAC,CAAC,EAAE,SAAS;AAC9C,QAAM,KAAK,MAAM,SAAS;AAC1B,QAAM,KAAK,MAAM,UAAU;AAC3B,QAAM,UAAU,KAAK,IAAI,IAAI,EAAE,KAAK;AACpC,QAAM,YAAY,KAAK,IAAI,GAAG,KAAK,SAAS,OAAO,OAAO;AAC1D,QAAM,YAAY,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,SAAS,CAAC;AACxD,QAAM,aAAa,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,SAAS,CAAC;AAEzD,QAAM,QAAQ,MAAM,QAAQ;AAAA,IAC1B,OAAO,IAAI,CAAC,OAAO,MAAM;AACvB,YAAM,QAAQ,OAAO,KAAK,kBAAkB,WAAW,YAAY,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC;AACtF,aAAO,MAAM,KAAK,EACf,OAAO,WAAW,YAAY,EAAE,KAAK,OAAO,CAAC,EAC7C,UAAU,CAAC,EAAE,OAAO,OAAO,KAAK,GAAG,MAAM,EAAE,CAAC,CAAC,EAC7C,IAAI,EACJ,SAAS;AAAA,IACd,CAAC;AAAA,EACH;AAEA,QAAM,QAAQ,OAAO,aAAa,OAAO,KAAK;AAC9C,QAAM,SAAS,OAAO,cAAc,OAAO,KAAK;AAChD,QAAM,aAAa,MAAM,IAAI,CAAC,OAAO,MAAM;AACzC,UAAM,IAAI,KAAK,MAAM,IAAI,IAAI;AAC7B,UAAM,IAAI,IAAI;AACd,WAAO,EAAE,OAAO,MAAM,MAAM,KAAK,YAAY,MAAM,KAAK,MAAM,KAAK,aAAa,KAAK;AAAA,EACvF,CAAC;AAED,QAAM,MAAM,MAAM,MAAM;AAAA,IACtB,QAAQ,EAAE,OAAO,QAAQ,UAAU,GAAG,YAAY,EAAE,GAAG,IAAI,GAAG,IAAI,GAAG,GAAG,EAAE;AAAA,EAC5E,CAAC,EACE,UAAU,UAAU,EACpB,KAAK,EAAE,SAAS,GAAG,CAAC,EACpB,SAAS;AAEZ,SAAO,EAAE,KAAK,OAAO,QAAQ,MAAM,MAAM,WAAW,YAAY,MAAM;AACxE;AAOA,eAAsB,WAAW,QAAkB,OAA4B,CAAC,GAAsB;AACpG,MAAI,OAAO,WAAW,EAAG,QAAO,CAAC;AACjC,QAAM,SAAS,KAAK,UAAU;AAC9B,QAAM,SAAS,MAAM,QAAQ;AAAA,IAC3B,OAAO,IAAI,CAAC,MAAM,MAAM,CAAC,EAAE,UAAU,EAAE,OAAO,QAAQ,QAAQ,EAAE,KAAK,OAAO,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC;AAAA,EACjG;AACA,QAAM,MAAgB,CAAC,CAAC;AACxB,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,UAAM,IAAI,OAAO,IAAI,CAAC;AACtB,UAAM,IAAI,OAAO,CAAC;AAClB,QAAI,CAAC,KAAK,CAAC,GAAG;AACZ,UAAI,KAAK,CAAC;AACV;AAAA,IACF;AACA,UAAM,IAAI,KAAK,IAAI,EAAE,QAAQ,EAAE,MAAM,KAAK;AAC1C,QAAI,IAAI;AACR,aAAS,IAAI,GAAG,IAAI,GAAG,IAAK,MAAK,KAAK,KAAK,EAAE,CAAC,KAAK,MAAM,EAAE,CAAC,KAAK,EAAE;AACnE,QAAI,KAAK,EAAE,IAAI,IAAI,KAAK,QAAQ,CAAC,CAAC;AAAA,EACpC;AACA,SAAO;AACT;;;AD/OA,IAAM,+BAA+B;AAErC,IAAM,kBAAkB;AAExB,SAAS,YAAY,KAAqB;AACxC,QAAM,IAAI,OAAO,GAAG;AACpB,MAAI,CAAC,OAAO,SAAS,CAAC,EAAG,QAAO;AAChC,SAAO,KAAK,IAAI,KAAK,KAAK,IAAI,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC;AACpD;AAEO,SAAS,0BAA0B,SAAwB;AAChE,QAAM,aAAa,QAChB,QAAQ,YAAY,EACpB;AAAA,IACC;AAAA,EAIF,EACC,OAAO,uBAAuB,qBAAqB,iBAAiB,EACpE,OAAO,UAAU,+DAA+D,EAChF,OAAO,kBAAkB,iFAAiF,MAAM,EAChH,OAAO,wBAAwB,4DAA4D;AAC9F,mBAAiB,YAAY,SAAS;AACtC,aACG,OAAO,mBAAmB,gEAAgE,EAC1F,OAAO,mBAAmB,sEAAsE,EAChG,OAAO,mBAAmB,mCAAmC,IAAI,EACjE,OAAO,UAAU,uEAAuE,EACxF,OAAO,qBAAqB,uBAAuB,EACnD,OAAO,OAAO,MAAsB,YAAqB;AACxD,UAAM,EAAE,QAAQ,OAAO,IAAI,WAAW;AACtC,UAAM,SAAS,YAAY,KAAK,MAAM;AACtC,UAAM,aAAa,OAAO,KAAK,QAAQ,KAAK;AAG5C,UAAM,WAAW,aAAa,IAAI;AAClC,QAAI,KAAK,SAAS,UAAa,UAAU;AACvC,UAAI,KAAK,SAAS,UAAa,SAAU,OAAM,IAAI,MAAM,2CAA2C;AACpG,UAAI,KAAK,QAAQ,KAAK,gBAAgB,KAAK,OAAO;AAChD,cAAM,IAAI,MAAM,gFAAgF;AAAA,MAClG;AACA,UAAI;AACJ,UAAI;AACJ,UAAI,UAAU;AAEZ,cAAM,UAAU,MAAM,aAAa;AAAA,UACjC;AAAA,UACA;AAAA,UACA,OAAO,gBAAgB,IAAI;AAAA,UAC3B,cAAc;AAAA,UACd,cAAc,KAAK;AAAA,UACnB;AAAA,QACF,CAAC;AACD,YAAI,CAAC,QAAQ,KAAK,EAAG,OAAM,IAAI,MAAM,GAAGC,oBAAmB,QAAQ,IAAI,CAAC,4BAA4B;AACpG,eAAO,YAAY,QAAQ,KAAK,GAAG,eAAe;AAClD,gBAAQA,oBAAmB,QAAQ,IAAI;AAAA,MACzC,OAAO;AACL,eAAO,cAAc,KAAK,IAAK;AAC/B,gBAAQ,KAAK,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,EAAE,KAAK,GAAG;AAAA,MAChD;AACA,YAAMC,QAAO,MAAM,eAAe,EAAE,QAAQ,cAAc,KAAK,QAAQ,OAAO,CAAC;AAC/E,YAAM,UAAU,MAAM,UAAUA,MAAK,QAAQ,MAAM,EAAE,OAAO,CAAC;AAC7D,MAAG,kBAAc,KAAK,QAAQ,QAAQ,GAAG;AACzC,aAAO;AAAA,QACL,SAAS,KAAK,MAAM,KAAK,QAAQ,KAAK,IAAI,QAAQ,MAAM,WAAW,QAAQ,SAAS,IAAI,QAAQ,UAAU,YAC7F,QAAQ,IAAI,IAAI,QAAQ,GAAG,KAAK,KAAK;AAAA,MACpD;AACA;AAAA,IACF;AAGA,QAAI,KAAK,cAAc;AACrB,YAAM,QAAQ,KAAK,QAAQ,KAAK,IAAI,GAAG,OAAO,KAAK,KAAK,CAAC,IAAI;AAC7D,YAAM,SAAS,MAAM,aAAa,EAAE,QAAQ,OAAO,YAAY,cAAc,KAAK,QAAQ,OAAO,CAAC;AAClG,YAAM,QAAQ,MAAM,WAAW,MAAM;AACrC,YAAM,QAAQ,MAAM,kBAAkB,QAAQ,EAAE,QAAQ,MAAM,CAAC;AAC/D,MAAG,kBAAc,KAAK,QAAQ,MAAM,GAAG;AAGvC,UAAI,KAAK,OAAO;AACd,cAAM,MAAW,cAAQ,KAAK,MAAM,KAAK;AACzC,cAAM,OAAO,KAAK,OAAO,MAAM,GAAG,KAAK,OAAO,SAAS,IAAI,MAAM;AACjE,eAAO,QAAQ,CAAC,OAAO,MAAS,kBAAc,GAAG,IAAI,IAAI,CAAC,GAAG,GAAG,IAAI,KAAK,CAAC;AAAA,MAC5E;AAEA,YAAM,WAAW,OAAO,IAAI,CAAC,GAAG,OAAO,EAAE,KAAK,GAAG,MAAM,IAAI,YAAY,YAAY,MAAM,CAAC,KAAK,EAAE,EAAE;AACnG,UAAI,KAAK,MAAM;AACb,gBAAQ,OAAO;AAAA,UACb,GAAG,KAAK;AAAA,YACN;AAAA,cACE,OAAO,KAAK;AAAA,cACZ,YAAY,OAAO;AAAA,cACnB,MAAM,MAAM;AAAA,cACZ,MAAM,MAAM;AAAA,cACZ;AAAA,cACA,MAAM;AAAA,cACN,QAAQ;AAAA,YACV;AAAA,YACA;AAAA,YACA;AAAA,UACF,CAAC;AAAA;AAAA,QACH;AAAA,MACF,OAAO;AACL,gBAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,QAAQ,CAAC;AAAA,CAAI;AAAA,MACtD;AAEA,UAAI,OAAO;AACX,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAK,MAAK,MAAM,CAAC,KAAK,MAAM,MAAM,IAAI,KAAK,GAAI,QAAO;AACxF,aAAO;AAAA,QACL,uBAAuB,KAAK,MAAM,KAAK,MAAM,IAAI,IAAI,MAAM,IAAI,KAAK,OAAO,MAAM,qCACpD,IAAI,YAAO,MAAM,IAAI,KAAK,GAAG,QAAQ,CAAC,CAAC;AAAA,MACtE;AACA;AAAA,IACF;AAGA,QAAI,KAAK,OAAO;AACd,YAAM,SAAS,MAAM,aAAa;AAAA,QAChC;AAAA,QACA,OAAO,OAAO,KAAK,KAAK;AAAA,QACxB;AAAA,QACA,cAAc,KAAK;AAAA,QACnB;AAAA,MACF,CAAC;AACD,YAAM,MAAW,cAAQ,KAAK,MAAM,KAAK;AACzC,YAAM,OAAO,KAAK,OAAO,MAAM,GAAG,KAAK,OAAO,SAAS,IAAI,MAAM;AACjE,aAAO,QAAQ,CAAC,OAAO,MAAS,kBAAc,GAAG,IAAI,IAAI,CAAC,GAAG,GAAG,IAAI,KAAK,CAAC;AAC1E,aAAO,KAAK,SAAS,OAAO,MAAM,cAAc,IAAI,QAAQ,OAAO,SAAS,CAAC,IAAI,GAAG,GAAG;AACvF;AAAA,IACF;AAGA,UAAM,OAAO,MAAM,eAAe,EAAE,QAAQ,cAAc,KAAK,QAAQ,OAAO,CAAC;AAC/E,UAAM,iBAAiB,QAAQ,qBAAqB,QAAQ,MAAM;AAClE,QAAI,KAAK,QAAQ,gBAAgB;AAC/B,YAAM,WAAW,MAAM,eAAe,KAAK,QAAQ,EAAE,QAAQ,MAAM,CAAC,CAAC,KAAK,KAAK,CAAC;AAChF,MAAG,kBAAc,KAAK,QAAQ,SAAS,GAAG;AAC1C,aAAO;AAAA,QACL,SAAS,KAAK,MAAM,KAAK,SAAS,KAAK,IAAI,SAAS,MAAM,SACrD,SAAS,aAAa,IAAI,SAAS,cAAc,GAAG,KAAK,OAAO,iBAAiB,EAAE;AAAA,MAC1F;AACA;AAAA,IACF;AACA,IAAG,kBAAc,KAAK,QAAQ,KAAK,MAAM;AACzC,WAAO,KAAK,SAAS,KAAK,MAAM,KAAK,KAAK,KAAK,IAAI,KAAK,MAAM,IAAI;AAAA,EACpE,CAAC;AACL;;;AE9KA,SAAS,kBAAkB;;;ACD3B,SAAS,qBAAiE;AAE1E,IAAM,WAAW;AAEjB,SAAS,MAAM,GAAmB;AAChC,SAAO,KAAK,UAAU,EAAE,SAAS,WAAW,GAAG,EAAE,MAAM,GAAG,WAAW,CAAC,CAAC,WAAM,CAAC;AAChF;AAEA,SAAS,MAAM,GAA6B;AAC1C,QAAM,MAAgB,CAAC;AACvB,MAAI,EAAE,MAAO,KAAI,KAAK,OAAO;AAC7B,MAAI,EAAE,UAAW,KAAI,KAAK,WAAW;AACrC,MAAI,EAAE,OAAQ,KAAI,KAAK,QAAQ;AAC/B,MAAI,EAAE,QAAS,KAAI,KAAK,SAAS;AAAA,WACxB,EAAE,MAAO,KAAI,KAAK,WAAW;AACtC,MAAI,EAAE,IAAK,KAAI,KAAK,UAAU;AAC9B,MAAI,EAAE,MAAO,KAAI,KAAK,OAAO;AAC7B,MAAI,EAAE,SAAU,KAAI,KAAK,UAAU;AACnC,MAAI,EAAE,QAAS,KAAI,KAAK,SAAS;AACjC,SAAO;AACT;AAGO,SAAS,iBAAiB,GAA2B;AAC1D,QAAM,QAAkB,CAAC,EAAE,QAAQ,MAAM;AACzC,MAAI,EAAE,SAAS,OAAW,OAAM,KAAK,MAAM,EAAE,IAAI,CAAC;AAClD,MAAI,EAAE,SAAS,OAAW,OAAM,KAAK,QAAQ,MAAM,EAAE,IAAI,CAAC,EAAE;AAC5D,MAAI,EAAE,SAAS,OAAW,OAAM,KAAK,QAAQ,MAAM,EAAE,IAAI,CAAC,EAAE;AAC5D,MAAI,EAAE,OAAO,OAAW,OAAM,KAAK,IAAI,EAAE,EAAE,EAAE;AAC7C,MAAI,EAAE,QAAQ,OAAW,OAAM,KAAK,OAAO,EAAE,GAAG,EAAE;AAClD,MAAI,EAAE,EAAG,OAAM,KAAK,KAAK,EAAE,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,EAAE;AACjE,QAAM,KAAK,GAAG,MAAM,CAAC,CAAC;AACtB,SAAO,MAAM,KAAK,GAAG;AACvB;AAGA,SAAS,SAAS,GAA4B;AAC5C,QAAM,WAAW,EAAE,SAAS,UAAa,EAAE,SAAS,UAAa,EAAE,SAAS;AAC5E,SAAO,YAAY,CAAC,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE;AAC3E;AASO,SAAS,iBAAiB,QAAkC;AACjE,QAAM,QAAkB,CAAC;AACzB,QAAM,IAAI,OAAO;AACjB,QAAM;AAAA,IACJ,aAAa,IAAI,GAAG,EAAE,KAAK,IAAI,EAAE,MAAM,KAAK,SAAS;AAAA,EAEvD;AACA,QAAM,iBAAiB,OAAO,UAAU,QAAQ,OAAO,SAAS,SAAS;AACzE,MAAI;AACJ,aAAW,KAAK,cAAc,OAAO,IAAI,GAAG;AAC1C,QAAI,EAAE,WAAW,QAAQ;AACvB,eAAS,EAAE;AACX,UAAI,WAAW,UAAa,WAAW,gBAAgB;AACrD,cAAM,KAAK,aAAa,MAAM,oDAA+C;AAAA,MAC/E,WAAW,WAAW,QAAW;AAC/B,cAAM,KAAK,WAAW,MAAM,GAAG;AAAA,MACjC;AAAA,IACF;AACA,QAAI,WAAW,UAAa,WAAW,eAAgB;AACvD,QAAI,EAAE,WAAW,UAAa,EAAE,SAAS,UAAa,CAAC,EAAE,MAAO;AAChE,QAAI,SAAS,CAAC,EAAG,OAAM,KAAK,iBAAiB,CAAC,CAAC;AAAA,EACjD;AACA,SAAO,GAAG,MAAM,KAAK,IAAI,CAAC;AAAA;AAC5B;;;AD3DO,SAAS,oBAAoB,SAAwB;AAC1D,UACG,QAAQ,eAAe,EACvB;AAAA,IACC;AAAA,EAEF,EACC,OAAO,qBAAqB,8CAA8C,EAC1E,OAAO,SAAS,kCAAkC,EAClD,OAAO,UAAU,4FAA4F,EAC7G,OAAO,qBAAqB,uBAAuB,EACnD,OAAO,OAAO,QAA4B,SAAmB;AAC5D,UAAM,EAAE,QAAQ,OAAO,IAAI,WAAW;AACtC,UAAM,OAAO,UAAU;AACvB,QAAI,SAAS,SAAU,OAAM,IAAI,MAAM,wBAAwB,IAAI,uBAAuB;AAC1F,QAAI,KAAK,OAAO,KAAK,KAAM,OAAM,IAAI,MAAM,sCAAsC;AACjF,UAAM,SAAS,MAAM,WAAW;AAAA,MAC9B;AAAA,MACA,YAAY,KAAK;AAAA,MACjB,OAAO,CAAC,KAAK;AAAA,MACb,gBAAgB,CAAC,KAAK;AAAA,MACtB,cAAc,KAAK;AAAA,MACnB;AAAA,IACF,CAAC;AACD,YAAQ,OAAO,MAAM,KAAK,OAAO,iBAAiB,MAAM,IAAI,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,CAAI;AAAA,EACpG,CAAC;AACL;;;AErCA,SAAS,mBAAmB;AAGrB,SAAS,uBAAuB,SAAwB;AAC7D,UACG,QAAQ,SAAS,EACjB,YAAY,6BAA6B,EACzC,OAAO,UAAU,6BAA6B,EAC9C,OAAO,OAAO,SAA6B;AAC1C,UAAM,EAAE,OAAO,IAAI,WAAW;AAC9B,UAAM,UAAU,MAAM,YAAY,MAAM;AACxC,QAAI,KAAK,MAAM;AACb,cAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAAA,CAAI;AAC5D;AAAA,IACF;AACA,QAAI,QAAQ,WAAW,GAAG;AACxB,cAAQ,OAAO,MAAM,gBAAgB;AACrC;AAAA,IACF;AACA,eAAW,KAAK,SAAS;AACvB,cAAQ,OAAO,MAAM,GAAG,EAAE,MAAM,IAAK,EAAE,cAAc,EAAE,IAAK,EAAE,MAAM;AAAA,CAAI;AAAA,IAC1E;AAAA,EACF,CAAC;AACL;;;ACvBA,SAAS,UAAU,gBAAgB;AAG5B,SAAS,oBAAoB,SAAwB;AAC1D,QAAM,OAAO,QAAQ,QAAQ,MAAM,EAAE,YAAY,yDAAyD;AAE1G,OACG,QAAQ,uBAAuB,EAC/B,YAAY,kCAAkC,EAC9C,OAAO,qBAAqB,uBAAuB,EACnD,OAAO,OAAO,OAAe,QAAgB,SAA8B;AAC1E,UAAM,EAAE,QAAQ,OAAO,IAAI,WAAW;AACtC,UAAM,SAAS,EAAE,QAAQ,OAAO,QAAQ,cAAc,KAAK,QAAQ,OAAO,CAAC;AAC3E,WAAO,KAAK,QAAQ,KAAK,OAAO,MAAM,GAAG;AAAA,EAC3C,CAAC;AAEH,OACG,QAAQ,uBAAuB,EAC/B,YAAY,8BAA8B,EAC1C,OAAO,qBAAqB,uBAAuB,EACnD,OAAO,OAAO,QAAgB,OAAe,SAA8B;AAC1E,UAAM,EAAE,QAAQ,OAAO,IAAI,WAAW;AACtC,UAAM,SAAS,EAAE,QAAQ,QAAQ,OAAO,cAAc,KAAK,QAAQ,OAAO,CAAC;AAC3E,WAAO,KAAK,YAAY,MAAM,OAAO,KAAK,GAAG;AAAA,EAC/C,CAAC;AACL;;;ACzBA,YAAYC,WAAU;AACtB,SAAS,qBAAqB;AAQvB,SAAS,oBAAoB,SAAwB;AAC1D,UACG,QAAQ,oBAAoB,EAC5B,YAAY,iFAAiF,EAC7F,OAAO,sBAAsB,4DAA4D,EACzF,OAAO,UAAU,wBAAwB,EACzC,OAAO,OAAO,YAAgC,SAAmB;AAChE,UAAM,EAAE,QAAQ,OAAO,IAAI,WAAW;AACtC,UAAM,MAAW,cAAQ,cAAc,QAAQ,IAAI,CAAC;AACpD,UAAM,SAAS,MAAM,cAAc,EAAE,QAAQ,YAAY,KAAK,OAAO,KAAK,OAAO,OAAO,CAAC;AACzF,QAAI,KAAK,MAAM;AACb,cAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,CAAI;AAAA,IAC7D,OAAO;AACL,iBAAW,KAAK,OAAO,UAAU;AAC/B,gBAAQ,OAAO,MAAM,GAAG,EAAE,IAAI,IAAI,EAAE,IAAI,IAAI,EAAE,QAAQ,IAAI,EAAE,OAAO,GAAG,EAAE,OAAO,KAAK,EAAE,IAAI,MAAM,EAAE;AAAA,CAAI;AAAA,MACxG;AACA,UAAI,OAAO,SAAS,WAAW,EAAG,SAAQ,OAAO,MAAM,gBAAgB;AAAA,IACzE;AAEA,QAAI,OAAO,SAAS,EAAG,SAAQ,WAAW,OAAO;AAAA,EACnD,CAAC;AACL;;;AC/BA,SAAkB,UAAAC,eAAc;AAChC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA,sBAAAC;AAAA,OAGK;AAIP,IAAM,cAA6B;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,MAAM,CAAC,MAA+C,MAAM,SAAY,SAAY,OAAO,CAAC;AA4B3F,SAAS,qBAAqB,SAAwB;AAC3D,QAAM,QAAQ,QACX,QAAQ,OAAO,EACf;AAAA,IACC;AAAA,EAEF,EACC,UAAU,IAAIC,QAAO,iBAAiB,aAAa,EAAE,QAAQ,WAAW,EAAE,oBAAoB,CAAC;AAClG,mBAAiB,OAAO,QAAQ;AAChC,QACG,OAAO,mBAAmB,iDAAiD,EAC3E,OAAO,mBAAmB,kDAAkD,EAC5E,OAAO,oBAAoB,oCAAoC,EAC/D,OAAO,oBAAoB,oCAAoC,EAC/D,OAAO,YAAY,8BAA8B,EACjD,OAAO,YAAY,8BAA8B,EACjD,OAAO,aAAa,iCAAiC,EACrD,OAAO,aAAa,iCAAiC,EACrD,OAAO,sBAAsB,gCAAgC,EAC7D;AAAA,IACC;AAAA,IACA;AAAA,EAEF,EACC,OAAO,iBAAiB,qBAAqB,EAC7C,OAAO,WAAW,4DAA4D,EAC9E,OAAO,mBAAmB,oDAAoD,EAC9E,OAAO,qBAAqB,uBAAuB,EACnD,OAAO,OAAO,SAAoB;AACjC,UAAM,EAAE,QAAQ,OAAO,IAAI,WAAW;AACtC,UAAM,SAAS,MAAM,aAAa;AAAA,MAChC;AAAA,MACA,MAAM,KAAK;AAAA,MACX,QAAQ,aAAa,IAAI;AAAA,MACzB,aAAa,gBAAgB,IAAI;AAAA,MACjC,IAAI,IAAI,KAAK,EAAE;AAAA,MACf,IAAI,IAAI,KAAK,EAAE;AAAA,MACf,KAAK,IAAI,KAAK,GAAG;AAAA,MACjB,KAAK,IAAI,KAAK,GAAG;AAAA,MACjB,KAAK,IAAI,KAAK,CAAC;AAAA,MACf,KAAK,IAAI,KAAK,CAAC;AAAA,MACf,MAAM,IAAI,KAAK,EAAE;AAAA,MACjB,MAAM,IAAI,KAAK,EAAE;AAAA,MACjB,OAAO,IAAI,KAAK,KAAK;AAAA,MACrB,KAAK,KAAK;AAAA,MACV,MAAM,KAAK;AAAA,MACX,OAAO,KAAK;AAAA,MACZ,cAAc,KAAK;AAAA,MACnB,cAAc,KAAK;AAAA,MACnB;AAAA,IACF,CAAC;AACD,QAAI,KAAK,SAAS,gBAAgB;AAChC,aAAO,KAAK,OAAO,iBAAiB,4BAA4B,6BAA6B;AAC7F;AAAA,IACF;AACA,UAAM,KAAK,OAAO,MAAM,SAAY,OAAO,OAAO,CAAC,IAAI,OAAO,CAAC,KAAK;AACpE,UAAM,KAAK,OAAO,SAAS,OAAOC,oBAAmB,OAAO,MAAM,CAAC,KAAK;AACxE,UAAM,KAAK,OAAO,iBAAiB,8BAA8B;AACjE,WAAO,KAAK,QAAQ,KAAK,IAAI,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG;AAAA,EACjD,CAAC;AAEH,UACG,QAAQ,SAAS,EACjB,YAAY,0HAA0H,EACtI,eAAe,sBAAsB,sDAAsD,EAC3F,OAAO,eAAe,kEAAkE,EACxF,OAAO,qBAAqB,qEAAqE,EACjG,OAAO,mBAAmB,+DAA+D,EACzF,OAAO,qBAAqB,uBAAuB,EACnD,OAAO,OAAO,SAAsB;AACnC,UAAM,EAAE,QAAQ,OAAO,IAAI,WAAW;AACtC,QAAI,YAAY,KAAK,MAAM,KAAK,SAAS;AACzC,QAAI,KAAK,WAAW;AAClB,YAAM,MAAM,UAAU,KAAK,CAAC,MAAM,EAAE,EAAE,KAAK,KAAK,EAAE,KAAK,KAAK,EAAE,KAAK,KAAK,EAAE,KAAK,EAAE;AACjF,UAAI,IAAK,OAAM,IAAI,MAAM,uDAAuD,IAAI,CAAC,IAAI,IAAI,CAAC,GAAG;AACjG,YAAM,UAAU,MAAM,eAAe,QAAQ,EAAE,cAAc,KAAK,QAAQ,OAAO,CAAC;AAClF,UAAI,CAAC,QAAS,OAAM,IAAI,MAAM,iEAAiE;AAE/F,YAAM,KAAK,CAAC,GAAW,SAAyB,KAAK,IAAI,OAAO,GAAG,KAAK,MAAM,IAAI,IAAI,CAAC;AACvF,kBAAY,UAAU,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,GAAG,GAAG,EAAE,GAAG,QAAQ,KAAK,GAAG,GAAG,GAAG,EAAE,GAAG,QAAQ,MAAM,EAAE,EAAE;AAAA,IACpG;AACA,UAAM,YAAY;AAAA,MAChB;AAAA,MACA;AAAA,MACA,aAAa,IAAI,KAAK,SAAS;AAAA,MAC/B,WAAW,IAAI,KAAK,OAAO;AAAA,MAC3B,cAAc,KAAK;AAAA,MACnB;AAAA,IACF,CAAC;AACD,WAAO,KAAK,eAAe;AAAA,EAC7B,CAAC;AACL;;;A1B1HA,IAAM,cAAc;AAEpB,SAAS,eAAwB;AAC/B,QAAM,UAAU,IAAIC,SAAQ,EACzB,KAAK,WAAW,EAChB;AAAA,IACC;AAAA,EAIF,EACC,QAAQ,WAAW,EACnB,mBAAmB;AAEtB,qBAAmB,OAAO;AAC1B,0BAAwB,OAAO;AAC/B,0BAAwB,OAAO;AAC/B,uBAAqB,OAAO;AAC5B,sBAAoB,OAAO;AAC3B,sBAAoB,OAAO;AAC3B,qBAAmB,OAAO;AAC1B,wBAAsB,OAAO;AAC7B,2BAAyB,OAAO;AAChC,wBAAsB,OAAO;AAC7B,sBAAoB,OAAO;AAC3B,uBAAqB,OAAO;AAC5B,4BAA0B,OAAO;AACjC,sBAAoB,OAAO;AAC3B,yBAAuB,OAAO;AAC9B,sBAAoB,OAAO;AAC3B,sBAAoB,OAAO;AAC3B,uBAAqB,OAAO;AAE5B,SAAO;AACT;AAEA,eAAe,OAAsB;AACnC,QAAM,UAAU,aAAa;AAC7B,MAAI;AACF,UAAM,QAAQ,WAAW,QAAQ,IAAI;AAAA,EACvC,SAAS,KAAK;AACZ,UAAM,UAAU,eAAeC,cAAa,IAAI,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AACzG,YAAQ,OAAO,MAAM,WAAW,OAAO;AAAA,CAAI;AAC3C,QAAI,QAAQ,IAAI,gBAAgB,OAAO,eAAe,SAAS,IAAI,OAAO;AACxE,cAAQ,OAAO,MAAM,GAAG,IAAI,KAAK;AAAA,CAAI;AAAA,IACvC;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAEA,KAAK,KAAK;","names":["Command","OniroError","path","path","createHarmonyOsSession","createHarmonyOsSession","path","path","ALL_SDKS","fs","path","ALL_SDKS","Option","Option","fs","path","describeLayoutNode","describeLayoutNode","shot","path","Option","describeLayoutNode","Option","describeLayoutNode","Command","OniroError"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oniroproject/oniro-app",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "description": "Cross-platform CLI for Oniro/OpenHarmony application development.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -24,7 +24,7 @@
24
24
  "clean": "rm -rf dist"
25
25
  },
26
26
  "dependencies": {
27
- "@oniroproject/core": "0.12.0",
27
+ "@oniroproject/core": "0.13.0",
28
28
  "commander": "^12.1.0",
29
29
  "sharp": "^0.34.5"
30
30
  },