@oniroproject/core 0.6.1 → 0.7.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/dist/index.d.ts CHANGED
@@ -8,6 +8,12 @@ interface Logger {
8
8
  }
9
9
  declare const noopLogger: Logger;
10
10
  declare const consoleLogger: Logger;
11
+ /**
12
+ * Wrap a Logger so every message is prefixed with `[<scope>] `. Standardizes the
13
+ * ad-hoc `[hdc]` / `[build]` / `[sign]` / `[hilog]` / `[emulator]` prefixes that
14
+ * were previously hand-written at each call site.
15
+ */
16
+ declare function scopedLogger(logger: Logger, scope: string): Logger;
11
17
 
12
18
  interface ProgressUpdate {
13
19
  message?: string;
@@ -22,7 +28,7 @@ declare const noopProgress: ProgressReporter;
22
28
  * Keys read from the ConfigProvider by core. Frontends (CLI, VS Code extension)
23
29
  * implement the provider however they like (env vars, settings.json, etc.).
24
30
  */
25
- type ConfigKey = 'sdkRootDir' | 'cmdToolsPath' | 'emulatorDir' | 'hapPath' | 'cmdToolsUrlLinux' | 'cmdToolsUrlWindows' | 'cmdToolsUrlMac' | 'emulatorUrl';
31
+ type ConfigKey = 'sdkRootDir' | 'cmdToolsPath' | 'emulatorDir' | 'hapPath' | 'cmdToolsUrlLinux' | 'cmdToolsUrlWindows' | 'cmdToolsUrlMac' | 'emulatorUrl' | 'sdkUrlBase' | 'applicationCertPath';
26
32
  interface ConfigProvider {
27
33
  /**
28
34
  * Get the configured value for `key`, or `fallback` if unset/empty.
@@ -93,6 +99,17 @@ declare class ChecksumMismatchError extends OniroError {
93
99
  declare class CancelledError extends OniroError {
94
100
  constructor(message?: string);
95
101
  }
102
+ /**
103
+ * A spawned command ran to completion but exited non-zero. Lets callers
104
+ * distinguish "the tool ran and failed" from "the tool could not be spawned"
105
+ * (a missing binary surfaces as an OniroError / CmdToolsNotInstalledError).
106
+ */
107
+ declare class CommandFailedError extends OniroError {
108
+ readonly command: string;
109
+ readonly exitCode: number;
110
+ readonly stderr: string;
111
+ constructor(command: string, exitCode: number, stderr: string);
112
+ }
96
113
 
97
114
  /**
98
115
  * Carries the cross-cutting dependencies most core functions need: a Logger and a ConfigProvider.
@@ -107,6 +124,17 @@ declare function defaultContext(overrides?: Partial<OniroContext>): OniroContext
107
124
  interface SdkRelease {
108
125
  version: string;
109
126
  api: string;
127
+ /**
128
+ * Number of leading path components to strip when extracting the release
129
+ * tarball, per OS family. The Huawei mirror packs linux+windows in one
130
+ * tarball (no top-level wrapper for some releases → 0, else 1); macOS
131
+ * tarballs have a deeper layout (3). This table is the single source of
132
+ * truth read by `getSdkFilename()`.
133
+ */
134
+ tarballStrip: {
135
+ linuxWindows: number;
136
+ darwin: number;
137
+ };
110
138
  }
111
139
  /**
112
140
  * Known OpenHarmony SDK releases. Kept in sync with the bash CLI / extension.
@@ -131,9 +159,9 @@ interface SdkArchiveInfo {
131
159
  * Resolve the SDK archive filename, OS folder, and tar strip count for the current platform.
132
160
  *
133
161
  * The Huawei mirror packages Linux and Windows together in one tarball with `linux/` and
134
- * `windows/` subfolders. For 5.0.0/5.0.1/6.0 the tarball has no extra top-level wrapper
135
- * (strip=0); newer/older releases wrap the OS folders in a single top-level directory (strip=1).
136
- * macOS tarballs have a deeper layout (strip=3).
162
+ * `windows/` subfolders; macOS tarballs have a deeper layout. The per-release strip counts
163
+ * live in {@link ALL_SDKS} (`tarballStrip`). An unrecognized version falls back to the
164
+ * historical default (linux/windows=1, darwin=3).
137
165
  */
138
166
  declare function getSdkFilename(version?: string): SdkArchiveInfo;
139
167
 
@@ -146,18 +174,24 @@ declare function getOhosBaseSdkHome(config: ConfigProvider): string;
146
174
  declare function getCmdToolsPath(config: ConfigProvider): string;
147
175
  declare function getEmulatorDir(config: ConfigProvider): string;
148
176
  /**
149
- * Resolve the OHPM binary path inside the command-line tools install.
150
- * On Windows tries common executable suffixes (.exe, .cmd, .bat) before the POSIX name.
177
+ * Resolve a binary inside the command-line tools `bin/` directory by name
178
+ * (e.g. `'ohpm'`, `'hvigorw'`, `'codelinter'`). On Windows tries common
179
+ * executable suffixes (.exe, .cmd, .bat) before the POSIX name.
151
180
  */
152
- declare function getCmdToolsBin(config: ConfigProvider): string;
181
+ declare function getCmdToolsBin(config: ConfigProvider, name?: string): string;
182
+ /** Resolve the OHPM binary path inside the command-line tools install. */
183
+ declare function getOhpmPath(config: ConfigProvider): string;
153
184
  /**
154
185
  * Resolve the hdc binary path inside the SDK toolchains tree.
155
186
  */
156
187
  declare function getHdcPath(config: ConfigProvider): string;
157
188
  /**
158
- * Resolve the hvigorw wrapper for a project, preferring the project-local copy
159
- * (which carries the project's pinned hvigor version) and falling back to the
160
- * one shipped with the command-line tools.
189
+ * Resolve the hvigorw wrapper for a project. Prefers the project-local copy
190
+ * (which carries the project's pinned hvigor version) — but ONLY when that
191
+ * wrapper is structurally complete. HMOS-vendored projects (systemui, launcher)
192
+ * ship a project-local `hvigorw` whose `hvigor/` install is absent, so the
193
+ * wrapper crashes on startup; in that case we fall back to the hvigorw bundled
194
+ * with the command-line tools, which is always installed.
161
195
  */
162
196
  declare function getHvigorwPath(config: ConfigProvider, projectDir: string): string;
163
197
 
@@ -321,6 +355,28 @@ type Apl = 'normal' | 'system_basic' | 'system_core';
321
355
  type AppFeature = 'hos_normal_app' | 'hos_system_app';
322
356
  declare const APL_VALUES: readonly Apl[];
323
357
  declare const APP_FEATURE_VALUES: readonly AppFeature[];
358
+ /** Keystore passwords. These must match the keystore in use. */
359
+ interface SigningPasswords {
360
+ store: string;
361
+ key: string;
362
+ }
363
+ /**
364
+ * Which signing key pairs with the chosen `apl`.
365
+ *
366
+ * - `'profile-release'` — the **OpenHarmony Application Profile Release** key.
367
+ * Default for apl=normal. Matches the cert chain that ships with the SDK
368
+ * (`OpenHarmonyProfileRelease.pem`). What `hvigor` uses for ordinary apps.
369
+ *
370
+ * - `'application-release'` — the **OpenHarmony Application Release** key.
371
+ * Required for apl=system_basic|system_core. BMS's parse-profile-prop check
372
+ * rejects HAPs whose `distribution-certificate` subject is "Application
373
+ * Profile Release" when the HAP requests permissions above its apl. The
374
+ * matching cert chain (`OpenHarmonyApplication.cer`) is not shipped in the
375
+ * SDK, so we ship it ourselves under `applicationCert.ts`.
376
+ */
377
+ type SigningKind = 'profile-release' | 'application-release';
378
+ /** @internal exposed for tests. */
379
+ declare function pickSigningKind(apl: Apl): SigningKind;
324
380
  interface GenerateSigningConfigsOptions {
325
381
  /** Absolute path to the OpenHarmony project (the folder containing build-profile.json5). */
326
382
  projectDir: string;
@@ -338,9 +394,35 @@ interface GenerateSigningConfigsOptions {
338
394
  * when `apl='normal'`, otherwise `'hos_system_app'`.
339
395
  */
340
396
  appFeature?: AppFeature;
397
+ /**
398
+ * Permission names to write into the profile's `acls.allowed-acls`. Required for
399
+ * apps that request permissions above their `apl` (e.g. a system_basic app
400
+ * requesting `ohos.permission.CAPTURE_SCREEN`). When omitted, the template's
401
+ * existing `allowed-acls` is left alone.
402
+ */
403
+ acls?: string[];
404
+ /**
405
+ * Keystore passwords written into the profile sign step and the build-profile
406
+ * signingConfigs. Defaults to `'123456'` (the SDK's bundled OpenHarmony.p12
407
+ * password). Only override when supplying a matching custom keystore.
408
+ */
409
+ passwords?: SigningPasswords;
410
+ /**
411
+ * Override the bundled application cert chain (application-release kind only).
412
+ * When set, this file is copied to `signatures/OpenHarmonyApplication.cer`
413
+ * instead of the inlined cert. May also be sourced from `config.applicationCertPath`.
414
+ */
415
+ applicationCertPath?: string;
341
416
  /** Optional logger; defaults to no-op. */
342
417
  logger?: Logger;
343
418
  }
419
+ /**
420
+ * Read all `products[*].signingConfig` names from the project's build-profile.json5.
421
+ * Returns the unique names in declaration order. Falls back to `['default']` when
422
+ * the file is missing or has no products.
423
+ * @internal exposed for tests.
424
+ */
425
+ declare function detectSigningConfigNames(projectDir: string): string[];
344
426
  /**
345
427
  * Generate signing configs for an OpenHarmony project: copies certs, signs the profile,
346
428
  * generates the signing material, and writes the resulting `signingConfigs` entry into
@@ -361,8 +443,9 @@ interface InstallEmulatorOptions {
361
443
  */
362
444
  declare function installEmulator(opts: InstallEmulatorOptions): Promise<void>;
363
445
  /**
364
- * Heuristic: emulator is considered installed if `images/run.sh` is present.
365
- * On Windows-only emulator builds (when they exist) this may not apply.
446
+ * Heuristic: the emulator is considered installed if either bundled launcher
447
+ * (`images/run.sh` or `images/run.bat`) is present, so a Windows-only build is
448
+ * detected too.
366
449
  */
367
450
  declare function isEmulatorInstalled(config: ConfigProvider): boolean;
368
451
  declare function removeEmulator(config: ConfigProvider): void;
@@ -408,16 +491,427 @@ interface StartEmulatorOptions {
408
491
  declare function startEmulator(opts: StartEmulatorOptions): Promise<void>;
409
492
  declare function stopEmulator(logger?: Logger): Promise<void>;
410
493
 
494
+ /** Result of a spawned command. `code` is the process exit code (-1 if it was killed). */
495
+ interface HdcExecResult {
496
+ code: number;
497
+ stdout: string;
498
+ stderr: string;
499
+ }
500
+ /** Streamed output callback, invoked per stdout/stderr chunk as it arrives. */
501
+ type OutputSink = (chunk: string, stream: 'stdout' | 'stderr') => void;
502
+ interface RunProcessOptions {
503
+ /** Executable to spawn. */
504
+ command: string;
505
+ /** Args passed verbatim (spawn runs with `shell: false`, so no shell parsing). */
506
+ args: readonly string[];
507
+ cwd?: string;
508
+ env?: NodeJS.ProcessEnv;
509
+ /** Kill the process after this many ms and reject. Default 60_000. */
510
+ timeoutMs?: number;
511
+ /** Abort the process; rejects with CancelledError. */
512
+ abortSignal?: AbortSignal;
513
+ /** Receive stdout/stderr chunks as they arrive (in addition to the buffered result). */
514
+ onOutput?: OutputSink;
515
+ /** Reserved for future scoped diagnostics; the buffered result is returned regardless. */
516
+ logger?: Logger;
517
+ }
518
+ /**
519
+ * Spawn an arbitrary process with `shell: false` and collect its output. The
520
+ * single low-level primitive every other command in the package builds on —
521
+ * because args are passed as an array and never interpolated into a shell
522
+ * string, command construction is injection-safe by construction.
523
+ *
524
+ * Resolves with `{ code, stdout, stderr }` for ANY exit code (callers opt into
525
+ * throw-on-non-zero via {@link ensureOk}). Rejects only on spawn failure
526
+ * (e.g. missing binary), timeout, or abort.
527
+ */
528
+ declare function runProcess(opts: RunProcessOptions): Promise<HdcExecResult>;
529
+ interface HdcExecOptions {
530
+ config: ConfigProvider;
531
+ /** Args passed to hdc verbatim, e.g. `['shell','aa','start','-a',ability,'-b',bundle]`. */
532
+ args: readonly string[];
533
+ /** Device serial; when set, prepends `['-t', serial]`. */
534
+ deviceSerial?: string;
535
+ /** Default 60_000. */
536
+ timeoutMs?: number;
537
+ abortSignal?: AbortSignal;
538
+ onOutput?: OutputSink;
539
+ logger?: Logger;
540
+ }
541
+ /**
542
+ * Run `hdc [-t <serial>] <args...>`. Resolves with `{ code, stdout, stderr }`
543
+ * for any exit code; use {@link ensureOk} to throw on non-zero.
544
+ */
545
+ declare function hdcExec(opts: HdcExecOptions): Promise<HdcExecResult>;
546
+ interface HdcShellOptions extends Omit<HdcExecOptions, 'args'> {
547
+ /** A single shell command, run as `hdc shell <command>` (one argv element — not host word-split). */
548
+ command: string;
549
+ }
550
+ /** Convenience wrapper for `hdc shell <command>`. */
551
+ declare function shell(opts: HdcShellOptions): Promise<HdcExecResult>;
552
+ /**
553
+ * Throw a typed {@link CommandFailedError} when `result.code !== 0`, otherwise
554
+ * return the result unchanged. Lets callers opt into throw-semantics.
555
+ */
556
+ declare function ensureOk(result: HdcExecResult, command: string): HdcExecResult;
557
+
558
+ interface DeviceInfo {
559
+ /** Connect key — a USB serial or a `host:port` for a TCP target. */
560
+ serial: string;
561
+ /** 'Connected' | 'Offline' | 'Unauthorized' | … | 'Unknown' when not reported. */
562
+ status: string;
563
+ /** 'USB' | 'TCP' | … when reported by `-v`. */
564
+ connection?: string;
565
+ /** Device model, populated by getDeviceInfo (not by the bare target list). */
566
+ model?: string;
567
+ }
568
+ /**
569
+ * Parse the output of `hdc list targets -v` into structured rows. The first token
570
+ * of each non-empty row is the connect key (serial); connection/status are matched
571
+ * by keyword among the remaining tokens. `[Empty]` (no devices) yields `[]`.
572
+ */
573
+ declare function parseDeviceList(stdout: string): DeviceInfo[];
574
+ /** List connected hdc targets via `hdc list targets -v`. Empty list when none. */
575
+ declare function listDevices(config: ConfigProvider, opts?: {
576
+ timeoutMs?: number;
577
+ logger?: Logger;
578
+ }): Promise<DeviceInfo[]>;
579
+ /**
580
+ * Resolve which device serial to address: an explicit `serial` wins, then the
581
+ * `ONIRO_DEVICE_SERIAL` / `DEVICE_SERIAL` env vars, then the single connected
582
+ * device. Throws when none or more than one is connected and nothing was specified.
583
+ */
584
+ declare function selectDevice(config: ConfigProvider, serial?: string, opts?: {
585
+ timeoutMs?: number;
586
+ logger?: Logger;
587
+ }): Promise<string>;
588
+
589
+ interface ParamOptions {
590
+ deviceSerial?: string;
591
+ timeoutMs?: number;
592
+ logger?: Logger;
593
+ }
594
+ /** Read a system property via `hdc shell param get <key>`. Returns the trimmed value. */
595
+ declare function paramGet(config: ConfigProvider, key: string, opts?: ParamOptions): Promise<string>;
596
+ /**
597
+ * Set a system property via `hdc shell param set <key> <value>`. The canonical
598
+ * reboot path is `paramSet(config, 'ohos.startup.powerctrl', 'reboot')`.
599
+ */
600
+ declare function paramSet(config: ConfigProvider, key: string, value: string, opts?: ParamOptions): Promise<void>;
601
+
602
+ interface SendFileOptions {
603
+ config: ConfigProvider;
604
+ /** Local source path. */
605
+ local: string;
606
+ /** Remote destination path on the device. */
607
+ remote: string;
608
+ deviceSerial?: string;
609
+ timeoutMs?: number;
610
+ abortSignal?: AbortSignal;
611
+ onOutput?: OutputSink;
612
+ logger?: Logger;
613
+ }
614
+ /** Push a local file to the device via `hdc file send <local> <remote>`. */
615
+ declare function sendFile(opts: SendFileOptions): Promise<void>;
616
+ interface RecvFileOptions {
617
+ config: ConfigProvider;
618
+ /** Remote source path on the device. */
619
+ remote: string;
620
+ /** Local destination path. */
621
+ local: string;
622
+ deviceSerial?: string;
623
+ timeoutMs?: number;
624
+ abortSignal?: AbortSignal;
625
+ onOutput?: OutputSink;
626
+ logger?: Logger;
627
+ }
628
+ /** Pull a file from the device via `hdc file recv <remote> <local>`. */
629
+ declare function recvFile(opts: RecvFileOptions): Promise<void>;
630
+
631
+ interface DisplaySize {
632
+ width: number;
633
+ height: number;
634
+ }
635
+ interface DisplaySizeOptions {
636
+ deviceSerial?: string;
637
+ timeoutMs?: number;
638
+ logger?: Logger;
639
+ }
640
+ /**
641
+ * Resolve the device's render resolution from `hidumper -s 10 -a screen`
642
+ * (`render resolution=WxH`). Returns null when unavailable. This is the W/H
643
+ * source for screenshots and the 0–1 normalization of layout bounds — no image
644
+ * decoding is involved.
645
+ */
646
+ declare function getDisplaySize(config: ConfigProvider, opts?: DisplaySizeOptions): Promise<DisplaySize | null>;
647
+
648
+ interface WaitForConditionOptions {
649
+ /** Resolves true when the condition is satisfied. Called once per poll. */
650
+ probe: () => Promise<boolean>;
651
+ /** Overall deadline. */
652
+ timeoutMs: number;
653
+ /** Poll interval. Default 2000. */
654
+ pollMs?: number;
655
+ /** Abort the wait; rejects with CancelledError. */
656
+ abortSignal?: AbortSignal;
657
+ /** Called every `heartbeatEvery` attempts (default 6) with progress info. */
658
+ onHeartbeat?: (attempt: number, remainingMs: number) => void;
659
+ heartbeatEvery?: number;
660
+ logger?: Logger;
661
+ /** Message for the timeout error. */
662
+ timeoutMessage?: string;
663
+ }
664
+ /**
665
+ * Generic deadline + poll + heartbeat loop. Calls `probe()` every `pollMs` until
666
+ * it resolves true (→ resolve) or the deadline passes (→ throw OniroError).
667
+ * A probe that throws is treated as "not yet" (the loop keeps polling) — this is
668
+ * what lets device waits tolerate transient hdc disconnects mid-reboot. Aborting
669
+ * the signal rejects with CancelledError.
670
+ *
671
+ * Extracted from the emulator hdc-wait loop so device lifecycle helpers share it.
672
+ */
673
+ declare function waitForCondition(opts: WaitForConditionOptions): Promise<void>;
674
+
675
+ interface WaitForBundleOptions {
676
+ config: ConfigProvider;
677
+ bundle: string;
678
+ deviceSerial?: string;
679
+ timeoutMs?: number;
680
+ abortSignal?: AbortSignal;
681
+ logger?: Logger;
682
+ }
683
+ /**
684
+ * Poll `pidof <bundle>` until the bundle has a clean numeric pid. Empty/failed
685
+ * pidof responses (including while the device is unreachable) do NOT count.
686
+ */
687
+ declare function waitForBundle(opts: WaitForBundleOptions): Promise<void>;
688
+ interface WaitForBootOptions {
689
+ config: ConfigProvider;
690
+ /** Require a clean numeric pid for this process/bundle name before returning. */
691
+ untilPidOf?: string;
692
+ deviceSerial?: string;
693
+ timeoutMs?: number;
694
+ abortSignal?: AbortSignal;
695
+ logger?: Logger;
696
+ }
697
+ /**
698
+ * Poll until the device responds AND (when `untilPidOf` is set) that process has
699
+ * a clean numeric pid. Tolerates the transient hdc disconnect during a reboot.
700
+ */
701
+ declare function waitForBoot(opts: WaitForBootOptions): Promise<void>;
702
+ interface RebootOptions {
703
+ config: ConfigProvider;
704
+ /** 'system' (default) reboots via param set; bootloader/recovery via `reboot <mode>`. */
705
+ mode?: 'system' | 'bootloader' | 'recovery';
706
+ /** When set (system mode), block until this bundle has a clean numeric pid after the reboot. */
707
+ waitForBundle?: string;
708
+ deviceSerial?: string;
709
+ timeoutMs?: number;
710
+ abortSignal?: AbortSignal;
711
+ logger?: Logger;
712
+ }
713
+ /**
714
+ * Reboot the device. System reboots use `param set ohos.startup.powerctrl reboot`
715
+ * (the path that works when force-stopping systemui is blocked); bootloader/
716
+ * recovery use `hdc shell reboot <mode>`. A reboot frequently tears down the hdc
717
+ * connection before the command returns, so command failure here is tolerated.
718
+ *
719
+ * When `waitForBundle` is set (system mode), waits for the device to drop and
720
+ * come back with the bundle running — so it doesn't return on the pre-reboot pid.
721
+ * A TCP target (e.g. an emulator at `127.0.0.1:55555`) is reconnected via
722
+ * `hdc tconn` during that wait, since hdc does not auto-reconnect TCP sessions
723
+ * across a reboot the way it does USB devices — pass the address as `deviceSerial`.
724
+ */
725
+ declare function reboot(opts: RebootOptions): Promise<void>;
726
+
727
+ interface Screenshot {
728
+ /** Raw JPEG bytes, exactly as `snapshot_display` wrote them (no decode/resize). */
729
+ pixels: Buffer;
730
+ /** Device render width/height from hidumper; 0 when it couldn't be resolved. */
731
+ width: number;
732
+ height: number;
733
+ }
734
+ interface ScreenshotOptions {
735
+ config: ConfigProvider;
736
+ deviceSerial?: string;
737
+ timeoutMs?: number;
738
+ logger?: Logger;
739
+ }
740
+ /**
741
+ * Capture the screen via on-device `snapshot_display`, pull the JPEG bytes back,
742
+ * and return them raw alongside the device resolution. The agent-facing grid
743
+ * overlay / downscale / base64 encoding stays in the MCP — core does no image
744
+ * decoding and adds no image dependency.
745
+ */
746
+ declare function takeScreenshot(opts: ScreenshotOptions): Promise<Screenshot>;
747
+ interface CaptureBurstOptions {
748
+ config: ConfigProvider;
749
+ count: number;
750
+ /** Delay between device-side captures, ms. */
751
+ intervalMs: number;
752
+ deviceSerial?: string;
753
+ timeoutMs?: number;
754
+ logger?: Logger;
755
+ }
756
+ /**
757
+ * Capture `count` frames `intervalMs` apart in a single device-side loop, then
758
+ * pull each frame back. Returns the raw JPEG buffers in order. The MCP composites
759
+ * these into a contact sheet + per-frame diff; core just returns the frames.
760
+ */
761
+ declare function captureBurst(opts: CaptureBurstOptions): Promise<Buffer[]>;
762
+
763
+ type InputType = 'click' | 'doubleClick' | 'longClick' | 'swipe' | 'drag' | 'fling' | 'keyEvent' | 'inputText';
764
+ interface SendInputOptions {
765
+ config: ConfigProvider;
766
+ type: InputType;
767
+ /** Pixel coordinates. The %→px conversion lives in the MCP, not core. */
768
+ pxX?: number;
769
+ pxY?: number;
770
+ pxX2?: number;
771
+ pxY2?: number;
772
+ /** Velocity for swipe/drag/fling. */
773
+ speed?: number;
774
+ /** Key id or symbolic name (Back/Home/Power) for keyEvent. */
775
+ key?: string | number;
776
+ /** Text for inputText. */
777
+ text?: string;
778
+ deviceSerial?: string;
779
+ logger?: Logger;
780
+ }
781
+ /**
782
+ * Build the `uitest uiInput …` command for an input action, in pixel space.
783
+ * Pure (no I/O) so it is unit-testable. Mirrors the proven MCP construction
784
+ * minus the percentage→pixel step.
785
+ */
786
+ declare function buildInputCommand(opts: SendInputOptions): string;
787
+ /** Inject a UI input action via `uitest uiInput` (pixel coordinates). */
788
+ declare function sendInput(opts: SendInputOptions): Promise<void>;
789
+ interface Waypoint {
790
+ /** Pixel x. */
791
+ x: number;
792
+ /** Pixel y. */
793
+ y: number;
794
+ /** Time in ms relative to the gesture start. */
795
+ t: number;
796
+ }
797
+ interface SendGestureOptions {
798
+ config: ConfigProvider;
799
+ waypoints: Waypoint[];
800
+ /** Hold at the first point before moving (ms). Honored via the raw-touch path. */
801
+ holdStartMs?: number;
802
+ /** Hold at the last point before lifting (ms). Honored via the raw-touch path. */
803
+ holdEndMs?: number;
804
+ deviceSerial?: string;
805
+ logger?: Logger;
806
+ }
807
+ /**
808
+ * Build the chained `uitest uiInput drag` commands for a multi-segment path.
809
+ * Per segment, speed is derived from the waypoint time deltas (px/s). Pure.
810
+ */
811
+ declare function buildGestureCommands(waypoints: Waypoint[]): string[];
812
+ interface RawTouchEvent {
813
+ type: 'down' | 'move' | 'up';
814
+ x: number;
815
+ y: number;
816
+ /** Time in ms relative to the gesture start. */
817
+ t: number;
818
+ }
819
+ interface SendRawTouchOptions {
820
+ config: ConfigProvider;
821
+ events: RawTouchEvent[];
822
+ deviceSerial?: string;
823
+ logger?: Logger;
824
+ }
825
+ /**
826
+ * Build a single `uinput -T` touch operation sequence from down/move/up events,
827
+ * interleaving `-i <ms>` intervals from the event time deltas. Pure.
828
+ */
829
+ declare function buildRawTouchCommand(events: RawTouchEvent[]): string;
830
+ /**
831
+ * Drive a smooth multi-waypoint path. With no holds, issues chained
832
+ * `uitest uiInput drag` segments. When `holdStartMs`/`holdEndMs` are set, routes
833
+ * through {@link sendRawTouch} (uinput), the only path with real press-time control.
834
+ */
835
+ declare function sendGesture(opts: SendGestureOptions): Promise<void>;
836
+ /**
837
+ * Low-level touch injection via `uinput -T`. The escape hatch when press timing
838
+ * matters (e.g. Quickstep motion-pause), which `uitest uiInput` can't express.
839
+ *
840
+ * WARNING: uinput's gesture form `uinput -T -g x1 y1 x2 y2 [press] [total]`
841
+ * silently no-ops if `press < 500ms` or `total - press < 500ms` ("press time is
842
+ * out of range" — it runs nothing). Keep press and post-press windows ≥ 500ms.
843
+ */
844
+ declare function sendRawTouch(opts: SendRawTouchOptions): Promise<void>;
845
+
846
+ /** A raw `uitest dumpLayout` node (attributes are strings). */
847
+ interface RawLayoutNode {
848
+ attributes?: Record<string, string>;
849
+ children?: RawLayoutNode[];
850
+ }
851
+ /** A pruned, 0–1-normalized layout node. */
852
+ interface LayoutNode {
853
+ /** bounds [x1,y1,x2,y2] normalized to 0–1 of the display. */
854
+ b?: [number, number, number, number];
855
+ /** center [x,y] normalized to 0–1. */
856
+ c?: [number, number];
857
+ type?: string;
858
+ text?: string;
859
+ desc?: string;
860
+ id?: string;
861
+ key?: string;
862
+ bundle?: string;
863
+ click?: boolean;
864
+ check?: boolean;
865
+ checked?: boolean;
866
+ sel?: boolean;
867
+ focus?: boolean;
868
+ scroll?: boolean;
869
+ longClick?: boolean;
870
+ children?: LayoutNode[];
871
+ }
872
+ interface DumpLayoutResult {
873
+ display: DisplaySize | null;
874
+ tree: LayoutNode;
875
+ }
876
+ /** Parse a uitest bounds string `"[x1,y1][x2,y2]"` into a tuple, or null. */
877
+ declare function parseBounds(s: string | undefined): [number, number, number, number] | null;
878
+ /**
879
+ * Prune a raw `uitest dumpLayout` tree into a compact, signal-bearing tree with
880
+ * bounds/center normalized to 0–1 of the display. Structural wrapper nodes with
881
+ * no signal collapse into their children. Returns a node, a flat list of nodes
882
+ * (collapsed wrapper with multiple children), or null (nothing useful). Ported
883
+ * verbatim from the proven MCP `pruneNode`.
884
+ */
885
+ declare function pruneLayout(node: RawLayoutNode, display: DisplaySize | null): LayoutNode | LayoutNode[] | null;
886
+ interface DumpLayoutOptions {
887
+ config: ConfigProvider;
888
+ /** Filter to a single window/bundle (`uitest dumpLayout -b '<bundle>'`). */
889
+ bundleName?: string;
890
+ /** When false, return the parsed-but-unpruned tree. Default true. */
891
+ prune?: boolean;
892
+ deviceSerial?: string;
893
+ timeoutMs?: number;
894
+ logger?: Logger;
895
+ }
896
+ /**
897
+ * Dump the current on-screen layout via `uitest dumpLayout`, pull the JSON, and
898
+ * return a pruned, 0–1-normalized tree (or the raw parsed tree when `prune:false`).
899
+ */
900
+ declare function dumpLayout(opts: DumpLayoutOptions): Promise<DumpLayoutResult>;
901
+
411
902
  /**
412
903
  * Read the project's bundle name from `AppScope/app.json5`.
413
904
  */
414
905
  declare function getBundleName(projectDir: string): string;
415
906
  /**
416
- * Read the main ability from `<module>/src/main/module.json5`. Defaults to `entry`
417
- * for the module folder name if not provided — projects with custom module names
418
- * should pass it explicitly.
907
+ * Read the ability to launch from `<module>/src/main/module.json5`. Defaults to
908
+ * `entry` for the module folder name. Resolution order:
909
+ * 1. `abilityName`, if given and present in `module.abilities[]`.
910
+ * 2. `module.mainElement`.
911
+ * 3. The first `visible` ability, then the first ability, from `module.abilities[]`.
912
+ * Modules with multiple abilities can be targeted explicitly via `abilityName`.
419
913
  */
420
- declare function getMainAbility(projectDir: string, moduleName?: string): string;
914
+ declare function getMainAbility(projectDir: string, moduleName?: string, abilityName?: string): string;
421
915
 
422
916
  interface InstallAppOptions {
423
917
  config: ConfigProvider;
@@ -429,14 +923,32 @@ interface InstallAppOptions {
429
923
  hapPath?: string;
430
924
  logger?: Logger;
431
925
  }
432
- declare function installApp(opts: InstallAppOptions): Promise<void>;
926
+ interface InstallAppResult {
927
+ installed: boolean;
928
+ /** Bundle name read from the project's AppScope/app.json5, or '' if unavailable. */
929
+ bundleName: string;
930
+ /** The resolved absolute HAP path that was installed. */
931
+ hapPath: string;
932
+ /** Combined stdout+stderr from the install, trimmed. */
933
+ output: string;
934
+ }
935
+ declare function installApp(opts: InstallAppOptions): Promise<InstallAppResult>;
433
936
  interface LaunchAppOptions {
434
937
  config: ConfigProvider;
435
938
  projectDir: string;
436
939
  /** Override the module name if it isn't the default `entry`. */
437
940
  moduleName?: string;
941
+ /** Explicit ability to launch; defaults to the module's mainElement / first visible ability. */
942
+ abilityName?: string;
438
943
  logger?: Logger;
439
944
  }
945
+ /**
946
+ * `aa start` exits 0 even when the launch is refused — a locked screen
947
+ * (`Error Code:10106102`), a missing ability, a permission denial, etc. The failure
948
+ * only shows up in its output. Returns the offending text when the output indicates a
949
+ * failed launch, or null when it looks like a success.
950
+ */
951
+ declare function detectAaStartFailure(output: string): string | null;
440
952
  declare function launchApp(opts: LaunchAppOptions): Promise<void>;
441
953
  interface RunningProcess {
442
954
  pid: string;
@@ -453,6 +965,24 @@ declare function listRunningProcesses(config: ConfigProvider, options?: {
453
965
  logger?: Logger;
454
966
  }): Promise<RunningProcess[] | string>;
455
967
  declare function findAppProcessId(config: ConfigProvider, projectDir: string, logger?: Logger): Promise<string>;
968
+ interface BundleOptions {
969
+ config: ConfigProvider;
970
+ bundle: string;
971
+ deviceSerial?: string;
972
+ timeoutMs?: number;
973
+ logger?: Logger;
974
+ }
975
+ /**
976
+ * Non-throwing companion to {@link listRunningProcesses}: resolve the running
977
+ * process for a bundle via `pidof`, or `null` when it isn't running. Suitable
978
+ * for "is X running?" checks (e.g. the pre/post-install pid comparison in
979
+ * applyChanges).
980
+ */
981
+ declare function findRunningProcess(opts: BundleOptions): Promise<RunningProcess | null>;
982
+ /** Uninstall an app by bundle name (`hdc uninstall <bundle>`). */
983
+ declare function uninstallApp(opts: BundleOptions): Promise<void>;
984
+ /** Force-stop an app (`hdc shell aa force-stop <bundle>`). */
985
+ declare function forceStop(opts: BundleOptions): Promise<void>;
456
986
 
457
987
  type HilogLevel = 'DEBUG' | 'INFO' | 'WARN' | 'ERROR' | 'FATAL';
458
988
  /** A parsed line of `hdc shell hilog` output. */
@@ -481,11 +1011,16 @@ interface StreamHilogOptions {
481
1011
  config: ConfigProvider;
482
1012
  /** Restrict the stream to a single process id (passed as `-P <pid>`). */
483
1013
  processId?: string;
1014
+ /** Filter by hilog domain, e.g. '0xD003900' (passed as `-D <domain>`). */
1015
+ domain?: string | number;
1016
+ /** Address a specific device (`-t <serial>`). */
1017
+ deviceSerial?: string;
484
1018
  }
485
1019
  /**
486
- * Spawn `hdc shell hilog [-P <pid>]` and return the child process. The caller
487
- * owns the stdout/stderr streams (typically wired through `parseHilogLine`) and
488
- * is responsible for killing the process when streaming should stop.
1020
+ * Spawn `hdc [-t serial] shell hilog [-P <pid>] [-D <domain>]` and return the
1021
+ * child process. The caller owns the stdout/stderr streams (typically wired
1022
+ * through `parseHilogLine`) and is responsible for killing the process when
1023
+ * streaming should stop.
489
1024
  */
490
1025
  declare function streamHilog(opts: StreamHilogOptions): ChildProcessWithoutNullStreams;
491
1026
  /**
@@ -494,6 +1029,61 @@ declare function streamHilog(opts: StreamHilogOptions): ChildProcessWithoutNullS
494
1029
  * banners, blank lines, or partial chunks).
495
1030
  */
496
1031
  declare function parseHilogLine(line: string): HilogEntry | null;
1032
+ /** Collapse consecutive duplicate entries (same level/tag/message), ignoring time/pid. */
1033
+ declare function dedupEntries(entries: HilogEntry[]): HilogEntry[];
1034
+ interface WaitForLogOptions {
1035
+ config: ConfigProvider;
1036
+ /** Tested against `"<tag>: <message>"` of each parsed line. */
1037
+ pattern: RegExp;
1038
+ timeoutMs: number;
1039
+ /** Restrict to a bundle's pid (resolved via pidof; re-resolved on each reconnect). */
1040
+ bundle?: string;
1041
+ domain?: string | number;
1042
+ deviceSerial?: string;
1043
+ abortSignal?: AbortSignal;
1044
+ logger?: Logger;
1045
+ }
1046
+ /**
1047
+ * Resolve with the first hilog entry whose `"<tag>: <message>"` matches `pattern`.
1048
+ * The underlying stream is auto-respawned if it dies before the deadline, so the
1049
+ * wait survives a reboot mid-observation. Rejects on timeout (OniroError) or
1050
+ * abort (CancelledError).
1051
+ */
1052
+ declare function waitForLog(opts: WaitForLogOptions): Promise<HilogEntry>;
1053
+ interface WatchLogOptions {
1054
+ config: ConfigProvider;
1055
+ pattern: RegExp;
1056
+ /** How long to collect matching entries. */
1057
+ durationMs: number;
1058
+ bundle?: string;
1059
+ domain?: string | number;
1060
+ deviceSerial?: string;
1061
+ /** Collapse consecutive duplicate lines. Default true. */
1062
+ dedup?: boolean;
1063
+ abortSignal?: AbortSignal;
1064
+ logger?: Logger;
1065
+ }
1066
+ /** Collect all hilog entries matching `pattern` for `durationMs`. Deduped by default. */
1067
+ declare function watchLog(opts: WatchLogOptions): Promise<HilogEntry[]>;
1068
+ interface DumpLogOptions {
1069
+ config: ConfigProvider;
1070
+ /** Cap the result to the last N lines (device-side `tail -n`). */
1071
+ lines?: number;
1072
+ /** Restrict to a bundle's running pid (no output if it isn't running). */
1073
+ bundle?: string;
1074
+ /** Extended-regex string applied device-side via `grep -E`. */
1075
+ grep?: string;
1076
+ domain?: string | number;
1077
+ deviceSerial?: string;
1078
+ timeoutMs?: number;
1079
+ logger?: Logger;
1080
+ }
1081
+ /**
1082
+ * One-shot `hilog -x` dump, optionally filtered by domain, bundle pid, and a
1083
+ * grep regex, capped to the last `lines`. Mirrors the proven MCP get_logs
1084
+ * pipeline. Returns parsed entries.
1085
+ */
1086
+ declare function dumpLog(opts: DumpLogOptions): Promise<HilogEntry[]>;
497
1087
 
498
1088
  interface RunHvigorwOptions {
499
1089
  config: ConfigProvider;
@@ -508,6 +1098,13 @@ interface RunHvigorwOptions {
508
1098
  task?: string;
509
1099
  /** Extra raw args appended after the standard ones. */
510
1100
  extraArgs?: readonly string[];
1101
+ /**
1102
+ * Build modules in parallel. Default `true`. Pass `false` to add `--no-parallel`
1103
+ * for projects that require serial builds.
1104
+ */
1105
+ parallel?: boolean;
1106
+ /** Abort the build; rejects with CancelledError and kills the hvigorw process. */
1107
+ abortSignal?: AbortSignal;
511
1108
  logger?: Logger;
512
1109
  /**
513
1110
  * Optional callback for each stdout/stderr chunk, lets callers stream output
@@ -518,12 +1115,131 @@ interface RunHvigorwOptions {
518
1115
  interface RunHvigorwResult {
519
1116
  exitCode: number;
520
1117
  }
1118
+ /**
1119
+ * Build the hvigorw argv. Pure (no I/O) so it is unit-testable. `--no-parallel`
1120
+ * is added ONLY when `parallel === false` — builds are parallel by default.
1121
+ */
1122
+ declare function buildHvigorwArgs(opts: {
1123
+ task?: string;
1124
+ product?: string;
1125
+ module?: string;
1126
+ buildMode?: string;
1127
+ parallel?: boolean;
1128
+ extraArgs?: readonly string[];
1129
+ }): string[];
521
1130
  /**
522
1131
  * Run the project's `hvigorw` wrapper. Replaces the extension's vscode-tasks indirection
523
1132
  * and the bash CLI's chained `clean` + `assembleHap` calls with a single direct spawn.
524
1133
  */
525
1134
  declare function runHvigorw(opts: RunHvigorwOptions): Promise<RunHvigorwResult>;
526
1135
 
1136
+ interface ModuleHaps {
1137
+ signed: string[];
1138
+ unsigned: string[];
1139
+ }
1140
+ interface DiscoverHapsOptions {
1141
+ projectDir: string;
1142
+ /** Max directory recursion depth. Default 8. */
1143
+ maxDepth?: number;
1144
+ }
1145
+ /**
1146
+ * Walk a project's build outputs and group `*-signed.hap` / `*-unsigned.hap`
1147
+ * by module folder. Skips `node_modules` / `oh_modules` / `.git`. Ported from
1148
+ * the proven MCP `findHaps`, extended with per-module grouping so multi-module
1149
+ * projects can install the right HAP. Empty object when nothing is built.
1150
+ */
1151
+ declare function discoverHaps(opts: DiscoverHapsOptions): Promise<Record<string, ModuleHaps>>;
1152
+
1153
+ interface RunOhpmOptions {
1154
+ config: ConfigProvider;
1155
+ projectDir: string;
1156
+ args: readonly string[];
1157
+ timeoutMs?: number;
1158
+ abortSignal?: AbortSignal;
1159
+ onOutput?: OutputSink;
1160
+ logger?: Logger;
1161
+ }
1162
+ /** Run `ohpm <args>` in the project directory. Resolves with the raw result (any exit code). */
1163
+ declare function runOhpm(opts: RunOhpmOptions): Promise<HdcExecResult>;
1164
+ /**
1165
+ * Install dependencies (`ohpm install --all`) only when `oh_modules/` is missing.
1166
+ * Returns `{ installed: true }` when it ran. Throws CommandFailedError if the
1167
+ * install ran and failed.
1168
+ */
1169
+ declare function ensureOhModules(opts: {
1170
+ config: ConfigProvider;
1171
+ projectDir: string;
1172
+ abortSignal?: AbortSignal;
1173
+ onOutput?: OutputSink;
1174
+ logger?: Logger;
1175
+ }): Promise<{
1176
+ installed: boolean;
1177
+ }>;
1178
+
1179
+ interface CodelinterFinding {
1180
+ file: string;
1181
+ line: number;
1182
+ severity: string;
1183
+ /** Rule code/id when present in the output, else ''. */
1184
+ code: string;
1185
+ message: string;
1186
+ }
1187
+ interface CodelinterResult {
1188
+ /** codelinter process exit code. */
1189
+ code: number;
1190
+ findings: CodelinterFinding[];
1191
+ /** Combined stdout+stderr, for callers that want the raw report. */
1192
+ raw: string;
1193
+ }
1194
+ /**
1195
+ * Best-effort parser for codelinter output lines of the shape
1196
+ * `<file>:<line>[:<col>]: <severity>: <message> [<rule-code>]`. Lines that don't
1197
+ * match are ignored. Exported as a pure function so it is unit-testable.
1198
+ */
1199
+ declare function parseCodelinterFindings(output: string): CodelinterFinding[];
1200
+ interface RunCodelinterOptions {
1201
+ config: ConfigProvider;
1202
+ projectDir: string;
1203
+ /** Files/globs to lint; when omitted, codelinter is run with no file args. */
1204
+ files?: readonly string[];
1205
+ timeoutMs?: number;
1206
+ abortSignal?: AbortSignal;
1207
+ logger?: Logger;
1208
+ }
1209
+ /** Run the OpenHarmony codelinter and return parsed findings + the raw report. */
1210
+ declare function runCodelinter(opts: RunCodelinterOptions): Promise<CodelinterResult>;
1211
+
1212
+ interface BuildHapOptions {
1213
+ config: ConfigProvider;
1214
+ projectDir: string;
1215
+ product?: string;
1216
+ module?: string;
1217
+ /** Forwarded as hvigor `buildMode` (e.g. release, debug). */
1218
+ mode?: string;
1219
+ /** hvigor task. Default `assembleHap`. */
1220
+ task?: string;
1221
+ /** Run `ohpm install --all` first when `oh_modules/` is missing. Default true. */
1222
+ autoInstallDeps?: boolean;
1223
+ /** Build modules in parallel. Default true (see runHvigorw). */
1224
+ parallel?: boolean;
1225
+ abortSignal?: AbortSignal;
1226
+ onOutput?: (chunk: string, stream: 'stdout' | 'stderr') => void;
1227
+ logger?: Logger;
1228
+ }
1229
+ interface BuildHapResult {
1230
+ exitCode: number;
1231
+ durationMs: number;
1232
+ /** Built HAPs grouped by module folder. */
1233
+ discoveredHaps: Record<string, ModuleHaps>;
1234
+ warnings: string[];
1235
+ }
1236
+ /**
1237
+ * High-level build orchestration: ensure deps → run hvigorw → discover the
1238
+ * produced HAPs. The single call the CLI and MCP want; `runHvigorw` stays a raw
1239
+ * single-spawn primitive.
1240
+ */
1241
+ declare function buildHap(opts: BuildHapOptions): Promise<BuildHapResult>;
1242
+
527
1243
  /**
528
1244
  * Conservative project-folder-name validator (no path separators, conservative charset).
529
1245
  */
@@ -579,6 +1295,55 @@ interface CreateScaffoldResult {
579
1295
  */
580
1296
  declare function createScaffold(opts: CreateScaffoldOptions): Promise<CreateScaffoldResult>;
581
1297
 
1298
+ interface ProjectModule {
1299
+ name: string;
1300
+ /** Source path relative to the project root (e.g. `./entry`). */
1301
+ srcPath: string;
1302
+ /** Target names declared under the module (often empty). */
1303
+ targets: string[];
1304
+ }
1305
+ /**
1306
+ * Read the `modules[]` declared in `build-profile.json5` so callers can target a
1307
+ * specific module in a multi-module project.
1308
+ */
1309
+ declare function listModules(opts: {
1310
+ projectDir: string;
1311
+ }): ProjectModule[];
1312
+
1313
+ interface AbilityInfo {
1314
+ name: string;
1315
+ type?: string;
1316
+ visible?: boolean;
1317
+ srcEntry?: string;
1318
+ }
1319
+ /**
1320
+ * Read all abilities declared in a module's `module.json5` `abilities[]`.
1321
+ * Defaults to the `entry` module folder.
1322
+ */
1323
+ declare function listAbilities(opts: {
1324
+ projectDir: string;
1325
+ moduleName?: string;
1326
+ }): AbilityInfo[];
1327
+
1328
+ interface PrepareSigningOptions {
1329
+ config: ConfigProvider;
1330
+ projectDir: string;
1331
+ apl?: Apl;
1332
+ appFeature?: AppFeature;
1333
+ acls?: string[];
1334
+ passwords?: SigningPasswords;
1335
+ logger?: Logger;
1336
+ }
1337
+ interface PrepareSigningResult {
1338
+ source: 'present' | 'fresh';
1339
+ }
1340
+ /**
1341
+ * Ensure a project has signing material: a no-op when `signatures/` +
1342
+ * signingConfigs already exist ('present'), otherwise generate them via
1343
+ * {@link generateSigningConfigs} ('fresh', which needs java + the SDK).
1344
+ */
1345
+ declare function prepareSigning(opts: PrepareSigningOptions): PrepareSigningResult;
1346
+
582
1347
  declare function readJson5File<T>(filePath: string): T;
583
1348
  /**
584
1349
  * Write strict JSON content (quoted keys) to a `.json5` file. Keeps the file
@@ -588,6 +1353,127 @@ declare function writeJson5File(filePath: string, value: unknown): void;
588
1353
  declare function readJsonFile<T>(filePath: string): T;
589
1354
  declare function writeJsonFile(filePath: string, value: unknown): void;
590
1355
 
1356
+ interface HidumperOptions {
1357
+ config: ConfigProvider;
1358
+ deviceSerial?: string;
1359
+ timeoutMs?: number;
1360
+ logger?: Logger;
1361
+ }
1362
+ interface ScreenDump {
1363
+ width: number;
1364
+ height: number;
1365
+ /** Raw hidumper screen output. */
1366
+ raw: string;
1367
+ }
1368
+ /** `hidumper -s 10 -a screen` → parsed render resolution + raw text, or null. */
1369
+ declare function dumpScreen(opts: HidumperOptions): Promise<ScreenDump | null>;
1370
+ /** `hidumper -s WindowManagerService -a -a` — windows in z-order with surface presence. */
1371
+ declare function dumpWindow(opts: HidumperOptions): Promise<string>;
1372
+ /** `hidumper -s RenderService -a allInfo` — composition state / refresh rate. */
1373
+ declare function dumpRenderService(opts: HidumperOptions): Promise<string>;
1374
+
1375
+ interface DeviceFullInfo {
1376
+ serial: string;
1377
+ model?: string;
1378
+ manufacturer?: string;
1379
+ brand?: string;
1380
+ osFullName?: string;
1381
+ osReleaseType?: string;
1382
+ sdkApiVersion?: string;
1383
+ buildVersion?: string;
1384
+ display: {
1385
+ width: number;
1386
+ height: number;
1387
+ } | null;
1388
+ }
1389
+ interface GetDeviceInfoOptions {
1390
+ config: ConfigProvider;
1391
+ deviceSerial?: string;
1392
+ timeoutMs?: number;
1393
+ logger?: Logger;
1394
+ }
1395
+ /** Collate device properties (`param get` × N) and the display resolution. */
1396
+ declare function getDeviceInfo(opts: GetDeviceInfoOptions): Promise<DeviceFullInfo>;
1397
+
1398
+ interface HapAssetDiff {
1399
+ /** File paths present in the new HAP but not the installed one. */
1400
+ addedAssetPaths: string[];
1401
+ /** File paths present in the installed HAP but not the new one. */
1402
+ removedAssetPaths: string[];
1403
+ }
1404
+ /** Pure set-diff of two file-name listings, sorted. */
1405
+ declare function diffEntryNames(installed: Iterable<string>, next: Iterable<string>): HapAssetDiff;
1406
+ /**
1407
+ * Diff the file manifests of two HAP (zip) archives. Drives the ACE-extractor
1408
+ * cache-invalidation reboot decision in `applyChanges`: when the new HAP adds or
1409
+ * renames file paths vs the installed one, the path-keyed asset cache can serve
1410
+ * stale "GetAsset failed" errors until a reboot.
1411
+ */
1412
+ declare function diffHapAssets(opts: {
1413
+ installedHap: string;
1414
+ newHap: string;
1415
+ }): Promise<HapAssetDiff>;
1416
+
1417
+ type InstallMethod = 'replace' | 'uninstall-install' | 'refuse';
1418
+ /**
1419
+ * P0-5a decision: how to install given whether `hdc install -r` reported a
1420
+ * sign-info-inconsistent error (9568332). System bundles are NOT silently
1421
+ * uninstalled (that can brick the device) unless explicitly allowed.
1422
+ */
1423
+ declare function decideInstallMethod(s: {
1424
+ signInfoInconsistent: boolean;
1425
+ isSystemBundle: boolean;
1426
+ allowUninstall: boolean;
1427
+ }): InstallMethod;
1428
+ interface RebootDecision {
1429
+ reboot: boolean;
1430
+ reason: 'asset-cache' | 'pid-unchanged' | 'none';
1431
+ }
1432
+ /**
1433
+ * P0-5b/c decision: whether to reboot after installing. Reboot when the HAP's
1434
+ * asset paths changed (ACE extractor cache is path-keyed and survives a process
1435
+ * kill), or when a persistent/system bundle's process didn't restart.
1436
+ */
1437
+ declare function decideReboot(s: {
1438
+ assetsChanged: boolean;
1439
+ isSystemBundle: boolean;
1440
+ preInstallPid: number | null;
1441
+ postInstallPid: number | null;
1442
+ }): RebootDecision;
1443
+ interface ApplyChangesOptions {
1444
+ config: ConfigProvider;
1445
+ bundle: string;
1446
+ /** Explicit HAP path. If omitted, resolved from projectDir (+ module) via discoverHaps. */
1447
+ hapPath?: string;
1448
+ projectDir?: string;
1449
+ module?: string;
1450
+ /** Local path to the currently-installed HAP; enables the asset-cache diff/reboot. */
1451
+ installedHapPath?: string;
1452
+ /** Persistent/system bundle (e.g. systemui). Default false. */
1453
+ isSystemBundle?: boolean;
1454
+ /** Permit uninstalling a system bundle on sign-info mismatch (dangerous). Default false. */
1455
+ allowUninstall?: boolean;
1456
+ deviceSerial?: string;
1457
+ abortSignal?: AbortSignal;
1458
+ logger?: Logger;
1459
+ }
1460
+ interface ApplyChangesResult {
1461
+ method: 'replace' | 'uninstall-install' | 'reboot';
1462
+ preInstallPid: number | null;
1463
+ postInstallPid: number | null;
1464
+ replaced: boolean;
1465
+ /** True when an asset-path change forced the reboot. */
1466
+ cacheCleared: boolean;
1467
+ }
1468
+ /**
1469
+ * Install a HAP and verify the running process took the change. Handles the
1470
+ * three failure modes the naive "install the most recent signed HAP" deploy
1471
+ * ignores: sign-info-inconsistent on `-r`, asset-cache invalidation, and a
1472
+ * persistent bundle that didn't restart. See {@link decideInstallMethod} /
1473
+ * {@link decideReboot} for the (pure, tested) branch logic.
1474
+ */
1475
+ declare function applyChanges(opts: ApplyChangesOptions): Promise<ApplyChangesResult>;
1476
+
591
1477
  declare const VERSION: string;
592
1478
 
593
- export { ALL_SDKS, APL_VALUES, APP_FEATURE_VALUES, type Apl, type AppFeature, CancelledError, ChecksumMismatchError, CmdToolsNotInstalledError, type CmdToolsStatus, type ConfigKey, type ConfigProvider, type CreateScaffoldOptions, type CreateScaffoldResult, type DownloadOptions, type ExtractZipOptions, type GenerateSigningConfigsOptions, type HilogEntry, type HilogLevel, type InstallAppOptions, type InstallCmdToolsOptions, type InstallEmulatorOptions, type InstallSdkOptions, type LaunchAppOptions, type Logger, OHOS_URL_BASE, type OniroContext, OniroError, type OsFolder, type ProgressReporter, type ProgressUpdate, type Prompter, type RunHvigorwOptions, type RunHvigorwResult, type RunningProcess, type SdkArchiveInfo, type SdkInfo, SdkNotInstalledError, type SdkRelease, type SetHilogLevelOptions, type StartEmulatorOptions, type StreamHilogOptions, type TemplateOption, UnsupportedPlatformError, VERSION, attemptHdcConnection, consoleLogger, createMaterial, createScaffold, decryptPwd, defaultContext, defaultPaths, detectProjectSdkVersion, downloadAndInstallSdk, downloadFile, encryptPwd, extractTarball, extractZipWithProgress, findAppProcessId, findCmdToolsSourceDir, generateSigningConfigs, getBundleName, getCmdToolsBin, getCmdToolsDownloadUrl, getCmdToolsPath, getCmdToolsStatus, getEmulatorDir, getHdcPath, getHvigorwPath, getInstalledSdks, getKey, getMainAbility, getOhosBaseSdkHome, getOsFolder, getSdkFilename, getSdkRootDir, getSupportedSdksForUi, installApp, installCmdTools, installEmulator, isCmdToolsInstalled, isEmulatorInstalled, isValidBundleName, isValidProjectName, launchApp, listRunningProcesses, listTemplates, nonInteractivePrompter, noopLogger, noopProgress, parseHilogLine, readJson5File, readJsonFile, removeCmdTools, removeEmulator, removeSdk, runHvigorw, setHilogLevel, startEmulator, staticConfig, stopEmulator, streamHilog, validateTemplateLayout, verifySha256, writeJson5File, writeJsonFile };
1479
+ export { ALL_SDKS, APL_VALUES, APP_FEATURE_VALUES, type AbilityInfo, type Apl, type AppFeature, type ApplyChangesOptions, type ApplyChangesResult, type BuildHapOptions, type BuildHapResult, type BundleOptions, CancelledError, type CaptureBurstOptions, ChecksumMismatchError, CmdToolsNotInstalledError, type CmdToolsStatus, type CodelinterFinding, type CodelinterResult, CommandFailedError, type ConfigKey, type ConfigProvider, type CreateScaffoldOptions, type CreateScaffoldResult, type DeviceFullInfo, type DeviceInfo, type DiscoverHapsOptions, type DisplaySize, type DisplaySizeOptions, type DownloadOptions, type DumpLayoutOptions, type DumpLayoutResult, type DumpLogOptions, type ExtractZipOptions, type GenerateSigningConfigsOptions, type GetDeviceInfoOptions, type HapAssetDiff, type HdcExecOptions, type HdcExecResult, type HdcShellOptions, type HidumperOptions, type HilogEntry, type HilogLevel, type InputType, type InstallAppOptions, type InstallAppResult, type InstallCmdToolsOptions, type InstallEmulatorOptions, type InstallMethod, type InstallSdkOptions, type LaunchAppOptions, type LayoutNode, type Logger, type ModuleHaps, OHOS_URL_BASE, type OniroContext, OniroError, type OsFolder, type OutputSink, type ParamOptions, type PrepareSigningOptions, type PrepareSigningResult, type ProgressReporter, type ProgressUpdate, type ProjectModule, type Prompter, type RawLayoutNode, type RawTouchEvent, type RebootDecision, type RebootOptions, type RecvFileOptions, type RunCodelinterOptions, type RunHvigorwOptions, type RunHvigorwResult, type RunOhpmOptions, type RunProcessOptions, type RunningProcess, type ScreenDump, type Screenshot, type ScreenshotOptions, type SdkArchiveInfo, type SdkInfo, SdkNotInstalledError, type SdkRelease, type SendFileOptions, type SendGestureOptions, type SendInputOptions, type SendRawTouchOptions, type SetHilogLevelOptions, type SigningKind, type SigningPasswords, type StartEmulatorOptions, type StreamHilogOptions, type TemplateOption, UnsupportedPlatformError, VERSION, type WaitForBootOptions, type WaitForBundleOptions, type WaitForConditionOptions, type WaitForLogOptions, type WatchLogOptions, type Waypoint, applyChanges, attemptHdcConnection, buildGestureCommands, buildHap, buildHvigorwArgs, buildInputCommand, buildRawTouchCommand, captureBurst, consoleLogger, createMaterial, createScaffold, decideInstallMethod, decideReboot, decryptPwd, dedupEntries, defaultContext, defaultPaths, detectAaStartFailure, detectProjectSdkVersion, detectSigningConfigNames, diffEntryNames, diffHapAssets, discoverHaps, downloadAndInstallSdk, downloadFile, dumpLayout, dumpLog, dumpRenderService, dumpScreen, dumpWindow, encryptPwd, ensureOhModules, ensureOk, extractTarball, extractZipWithProgress, findAppProcessId, findCmdToolsSourceDir, findRunningProcess, forceStop, generateSigningConfigs, getBundleName, getCmdToolsBin, getCmdToolsDownloadUrl, getCmdToolsPath, getCmdToolsStatus, getDeviceInfo, getDisplaySize, getEmulatorDir, getHdcPath, getHvigorwPath, getInstalledSdks, getKey, getMainAbility, getOhosBaseSdkHome, getOhpmPath, getOsFolder, getSdkFilename, getSdkRootDir, getSupportedSdksForUi, hdcExec, installApp, installCmdTools, installEmulator, isCmdToolsInstalled, isEmulatorInstalled, isValidBundleName, isValidProjectName, launchApp, listAbilities, listDevices, listModules, listRunningProcesses, listTemplates, nonInteractivePrompter, noopLogger, noopProgress, paramGet, paramSet, parseBounds, parseCodelinterFindings, parseDeviceList, parseHilogLine, pickSigningKind, prepareSigning, pruneLayout, readJson5File, readJsonFile, reboot, recvFile, removeCmdTools, removeEmulator, removeSdk, runCodelinter, runHvigorw, runOhpm, runProcess, scopedLogger, selectDevice, sendFile, sendGesture, sendInput, sendRawTouch, setHilogLevel, shell, startEmulator, staticConfig, stopEmulator, streamHilog, takeScreenshot, uninstallApp, validateTemplateLayout, verifySha256, waitForBoot, waitForBundle, waitForCondition, waitForLog, watchLog, writeJson5File, writeJsonFile };