android2harmony 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/agents/self-tester.md +376 -0
  2. package/dist/index.js +152 -7
  3. package/dist/index.js.map +4 -4
  4. package/package.json +32 -29
  5. package/skills/hmos-incremental-ui-align/README.md +251 -0
  6. package/skills/hmos-incremental-ui-align/SKILL.md +365 -0
  7. package/skills/hmos-incremental-ui-align/diff_analysis.md +53 -0
  8. package/skills/hmos-incremental-ui-align/page_align.md +62 -0
  9. package/skills/hmos-incremental-ui-align/references/Comparison_Template.md +38 -0
  10. package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Link/350/243/205/351/245/260/345/231/250/357/274/232/347/210/266/345/255/220/345/217/214/345/220/221/345/220/214/346/255/245.md +648 -0
  11. package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Observed/350/243/205/351/245/260/345/231/250/345/222/214@ObjectLink/350/243/205/351/245/260/345/231/250/357/274/232/345/265/214/345/245/227/347/261/273/345/257/271/350/261/241/345/261/236/346/200/247/345/217/230/345/214/226.md +2089 -0
  12. package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Prop/350/243/205/351/245/260/345/231/250/357/274/232/347/210/266/345/255/220/345/215/225/345/220/221/345/220/214/346/255/245.md +1033 -0
  13. package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Provide/350/243/205/351/245/260/345/231/250/345/222/214@Consume/350/243/205/351/245/260/345/231/250/357/274/232/344/270/216/345/220/216/344/273/243/347/273/204/344/273/266/345/217/214/345/220/221/345/220/214/346/255/245.md +1183 -0
  14. package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@State/350/243/205/351/245/260/345/231/250/357/274/232/347/273/204/344/273/266/345/206/205/347/212/266/346/200/201.md +576 -0
  15. package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Track/350/243/205/351/245/260/345/231/250/357/274/232class/345/257/271/350/261/241/345/261/236/346/200/247/347/272/247/346/233/264/346/226/260.md +297 -0
  16. package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Watch/350/243/205/351/245/260/345/231/250/357/274/232/347/212/266/346/200/201/345/217/230/351/207/217/346/233/264/346/224/271/351/200/232/347/237/245.md +395 -0
  17. package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/AppStorage/357/274/232/345/272/224/347/224/250/345/205/250/345/261/200/347/232/204UI/347/212/266/346/200/201/345/255/230/345/202/250.md +903 -0
  18. package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/Environment/357/274/232/350/256/276/345/244/207/347/216/257/345/242/203/346/237/245/350/257/242.md +106 -0
  19. package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/LocalStorage/357/274/232/351/241/265/351/235/242/347/272/247UI/347/212/266/346/200/201/345/255/230/345/202/250.md +1178 -0
  20. package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/MVVM/346/250/241/345/274/217V1.md +911 -0
  21. package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/PersistentStorage/357/274/232/346/214/201/344/271/205/345/214/226/345/255/230/345/202/250UI/347/212/266/346/200/201.md +355 -0
  22. package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243//347/256/241/347/220/206/345/272/224/347/224/250/346/213/245/346/234/211/347/232/204/347/212/266/346/200/201/346/246/202/350/277/260.md +11 -0
  23. package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243V2/!!/350/257/255/346/263/225/357/274/232/345/217/214/345/220/221/347/273/221/345/256/232.md +206 -0
  24. package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243V2/@Computed/350/243/205/351/245/260/345/231/250/357/274/232/350/256/241/347/256/227/345/261/236/346/200/247.md +373 -0
  25. package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243V2/@Event/350/243/205/351/245/260/345/231/250/357/274/232/350/247/204/350/214/203/347/273/204/344/273/266/350/276/223/345/207/272.md +158 -0
  26. package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243V2/@Local/350/243/205/351/245/260/345/231/250/357/274/232/347/273/204/344/273/266/345/206/205/351/203/250/347/212/266/346/200/201.md +750 -0
  27. package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243V2/@Monitor/350/243/205/351/245/260/345/231/250/357/274/232/347/212/266/346/200/201/345/217/230/351/207/217/344/277/256/346/224/271/345/274/202/346/255/245/347/233/221/345/220/254.md +1704 -0
  28. package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243V2/@ObservedV2/350/243/205/351/245/260/345/231/250/345/222/214@Trace/350/243/205/351/245/260/345/231/250/357/274/232/347/261/273/345/261/236/346/200/247/345/217/230/345/214/226/350/247/202/346/265/213.md +1012 -0
  29. package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243V2/@Once/350/243/205/351/245/260/345/231/250/357/274/232/345/210/235/345/247/213/345/214/226/345/220/214/346/255/245/344/270/200/346/254/241.md +164 -0
  30. package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243V2/@Param/350/243/205/351/245/260/345/231/250/357/274/232/347/273/204/344/273/266/345/244/226/351/203/250/350/276/223/345/205/245.md +840 -0
  31. package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243V2/@Provider/350/243/205/351/245/260/345/231/250/345/222/214@Consumer/350/243/205/351/245/260/345/231/250/357/274/232/350/267/250/347/273/204/344/273/266/345/261/202/347/272/247/345/217/214/345/220/221/345/220/214/346/255/245.md +856 -0
  32. package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243V2/@Type/350/243/205/351/245/260/345/231/250/357/274/232/346/240/207/350/256/260/347/261/273/345/261/236/346/200/247/347/232/204/347/261/273/345/236/213.md +83 -0
  33. package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243V2/AppStorageV2/357/274/232/345/272/224/347/224/250/345/205/250/345/261/200UI/347/212/266/346/200/201/345/255/230/345/202/250.md +294 -0
  34. package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243V2/MVVM/346/250/241/345/274/217/357/274/210V2/357/274/211.md +1407 -0
  35. package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243V2/PersistenceV2/357/274/232/346/214/201/344/271/205/345/214/226/345/255/230/345/202/250UI/347/212/266/346/200/201.md +1220 -0
  36. package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243V2/_/350/214/203/345/274/217/351/200/211/346/213/251/350/257/264/346/230/216.md +47 -0
  37. package/skills/hmos-incremental-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243V2//347/212/266/346/200/201/347/256/241/347/220/206V1/345/220/221V2/350/277/201/347/247/273/344/270/216/346/267/267/347/224/250/346/214/207/345/257/274.md +840 -0
  38. package/skills/hmos-incremental-ui-align/references/State_Model_Template.md +74 -0
  39. package/skills/hmos-incremental-ui-align/references/UI_Analysis_Template.md +34 -0
  40. package/skills/hmos-incremental-ui-align/references/android-to-harmonyOS-ui-atomic-component-mapping-reference.md +2533 -0
  41. package/skills/hmos-incremental-ui-align/references/android-to-harmonyOS-ui-interaction-mapping-reference.md +555 -0
  42. package/skills/hmos-incremental-ui-align/references/android-to-harmonyOS-ui-layout-mapping-reference.md +117 -0
  43. package/skills/hmos-incremental-ui-align/scripts/app_feature_verify.ts +999 -0
  44. package/skills/hmos-incremental-ui-align/scripts/extract_checklist.ts +343 -0
  45. package/skills/hmos-incremental-ui-align/scripts/navigation-capure.md +76 -0
  46. package/skills/hmos-incremental-ui-align/scripts/page_capture.ts +977 -0
  47. package/skills/hmos-incremental-ui-align/scripts/page_capture_burst.ts +188 -0
@@ -0,0 +1,188 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Android 定时连续采集工具 (TypeScript 版) —— 每隔1秒自动采集一次 view tree + 截图,持续 x 秒。
4
+ *
5
+ * 用于捕获动态UI效果(动画中间态、Toast、瞬态弹窗等)。
6
+ * 零第三方依赖,仅使用 Node 内置模块。
7
+ *
8
+ * 用法:
9
+ * node page_capture_burst.ts --device adb -o ./output --duration 10
10
+ * node page_capture_burst.ts --device adb -o ./output --duration 5 --serial emulator-5554
11
+ *
12
+ * 等价于原 page_capture_burst.py(functional equivalence,非逐字节一致)。
13
+ */
14
+
15
+ import { spawnSync } from 'node:child_process';
16
+ import * as fs from 'node:fs';
17
+ import * as path from 'node:path';
18
+ import { pathToFileURL } from 'node:url';
19
+
20
+ function sleep(seconds: number): void {
21
+ const end = Date.now() + seconds * 1000;
22
+ const sab = new SharedArrayBuffer(4);
23
+ const ia = new Int32Array(sab);
24
+ while (Date.now() < end) {
25
+ Atomics.wait(ia, 0, 0, Math.min(50, end - Date.now()));
26
+ }
27
+ }
28
+
29
+ function adb(args: string[], serial: string | null = null, timeout = 15): string {
30
+ const full: string[] = [];
31
+ if (serial) full.push('-s', serial);
32
+ full.push(...args);
33
+ const res = spawnSync('adb', full, {
34
+ timeout: timeout * 1000,
35
+ maxBuffer: 128 * 1024 * 1024,
36
+ windowsHide: true,
37
+ });
38
+ if (res.error && (res.error as NodeJS.ErrnoException).code === 'ETIMEDOUT') {
39
+ console.log(` [WARN] adb timeout: ${args.join(' ')}`);
40
+ return '';
41
+ }
42
+ const out = (res.stdout as Buffer) ?? Buffer.alloc(0);
43
+ return out.toString('utf-8').trim();
44
+ }
45
+
46
+ function adbShell(args: string[], serial: string | null = null, timeout = 15): string {
47
+ return adb(['shell', ...args], serial, timeout);
48
+ }
49
+
50
+ function adbScreenshot(outputDir: string, filename: string, serial: string | null = null): boolean {
51
+ const localPath = path.join(outputDir, filename);
52
+ const args: string[] = [];
53
+ if (serial) args.push('-s', serial);
54
+ args.push('exec-out', 'screencap', '-p');
55
+ const res = spawnSync('adb', args, {
56
+ timeout: 15 * 1000,
57
+ maxBuffer: 128 * 1024 * 1024,
58
+ windowsHide: true,
59
+ });
60
+ if (res.error && (res.error as NodeJS.ErrnoException).code === 'ETIMEDOUT') {
61
+ console.log(' [WARN] screenshot timeout');
62
+ return false;
63
+ }
64
+ const stdoutBuf = (res.stdout as Buffer) ?? Buffer.alloc(0);
65
+ if (stdoutBuf.length > 0) {
66
+ fs.writeFileSync(localPath, stdoutBuf);
67
+ return true;
68
+ }
69
+ return false;
70
+ }
71
+
72
+ function adbDumpXml(outputDir: string, filename: string, serial: string | null = null): string {
73
+ const remotePath = '/sdcard/ui_dump.xml';
74
+ adbShell(['rm', '-f', '/sdcard/ui_dump.xml', '&&', 'uiautomator', 'dump', '/sdcard/ui_dump.xml'], serial, 20);
75
+ for (let i = 0; i < 6; i++) {
76
+ const check = adbShell(['ls', remotePath], serial);
77
+ if (check.includes(remotePath)) break;
78
+ sleep(0.2);
79
+ }
80
+ const xmlContent = adbShell(['cat', remotePath], serial, 15);
81
+ if (xmlContent) {
82
+ fs.writeFileSync(path.join(outputDir, filename), xmlContent, 'utf-8');
83
+ }
84
+ return xmlContent;
85
+ }
86
+
87
+ interface CliArgs {
88
+ device: 'adb';
89
+ outputDir: string;
90
+ duration: number;
91
+ serial: string | null;
92
+ }
93
+
94
+ function parseArgs(argv: string[]): CliArgs {
95
+ const args: CliArgs = { device: 'adb', outputDir: '', duration: 10, serial: null };
96
+ for (let i = 0; i < argv.length; i++) {
97
+ const a = argv[i];
98
+ const next = (): string => {
99
+ if (i + 1 >= argv.length) {
100
+ console.error(`Missing value for ${a}`);
101
+ process.exit(2);
102
+ }
103
+ return argv[++i];
104
+ };
105
+ if (a === '--device') {
106
+ const v = next();
107
+ if (v !== 'adb') {
108
+ console.error('--device must be adb (currently adb only)');
109
+ process.exit(2);
110
+ }
111
+ args.device = v;
112
+ } else if (a === '--output-dir' || a === '-o') {
113
+ args.outputDir = next();
114
+ } else if (a === '--duration' || a === '-d') {
115
+ args.duration = parseInt(next(), 10);
116
+ } else if (a === '--serial') {
117
+ args.serial = next();
118
+ } else if (a === '-h' || a === '--help') {
119
+ printHelp();
120
+ process.exit(0);
121
+ } else {
122
+ console.error(`Unknown argument: ${a}`);
123
+ process.exit(2);
124
+ }
125
+ }
126
+ if (!args.outputDir) {
127
+ console.error('error: --output-dir/-o is required');
128
+ process.exit(2);
129
+ }
130
+ return args;
131
+ }
132
+
133
+ function printHelp(): void {
134
+ console.log(
135
+ [
136
+ 'Burst capture: take view tree + screenshot every 1s for N seconds',
137
+ '',
138
+ 'Usage: node page_capture_burst.ts --device adb -o <dir> [--duration N] [--serial S]',
139
+ '',
140
+ ' --device Device type (currently adb only)',
141
+ ' --output-dir,-o Output directory for captured files (required)',
142
+ ' --duration,-d Total capture duration in seconds (default: 10)',
143
+ ' --serial ADB device serial (optional)',
144
+ ].join('\n'),
145
+ );
146
+ }
147
+
148
+ function main(): number {
149
+ const args = parseArgs(process.argv.slice(2));
150
+ fs.mkdirSync(args.outputDir, { recursive: true });
151
+
152
+ console.log(`[Burst Capture] duration=${args.duration}s, output=${args.outputDir}`);
153
+ console.log('[Burst Capture] Starting continuous capture...');
154
+
155
+ const startTime = Date.now();
156
+ let frame = 0;
157
+
158
+ while (true) {
159
+ const elapsed = (Date.now() - startTime) / 1000;
160
+ if (elapsed >= args.duration) break;
161
+
162
+ frame += 1;
163
+ const frameStart = Date.now();
164
+ const frameStr = String(frame).padStart(3, '0');
165
+ process.stdout.write(` Frame ${frame} (t=${elapsed.toFixed(1)}s)... `);
166
+
167
+ const xmlOk = !!adbDumpXml(args.outputDir, `view_${frameStr}.xml`, args.serial);
168
+ const shotOk = adbScreenshot(args.outputDir, `screenshot_${frameStr}.png`, args.serial);
169
+
170
+ console.log(xmlOk && shotOk ? 'OK' : 'partial');
171
+
172
+ const frameElapsed = (Date.now() - frameStart) / 1000;
173
+ const sleepTime = Math.max(0, 1.0 - frameElapsed);
174
+ if (sleepTime > 0 && (Date.now() - startTime) / 1000 + sleepTime < args.duration) {
175
+ sleep(sleepTime);
176
+ }
177
+ }
178
+
179
+ console.log(`\n[Burst Capture] Done. ${frame} frames captured to ${args.outputDir}`);
180
+ return 0;
181
+ }
182
+
183
+ const isEntry = process.argv[1] !== undefined && import.meta.url === pathToFileURL(process.argv[1]).href;
184
+ if (isEntry) {
185
+ process.exit(main());
186
+ }
187
+
188
+ export { adbDumpXml, adbScreenshot, parseArgs };