@buaa_smat/hometrans 0.1.15 → 0.1.17
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 +108 -99
- package/agents/build-fixer.md +15 -14
- package/agents/code-reviewer.md +3 -3
- package/agents/logic-coder.md +1 -1
- package/agents/logic-context-builder.md +1 -1
- package/agents/self-tester.md +16 -13
- package/dist/cli/config-store.js +127 -29
- package/dist/cli/config.js +9 -2
- package/dist/cli/init.js +431 -248
- package/dist/cli/uninstall.js +103 -8
- package/dist/context/index.js +19 -2
- package/env-requirements.json +19 -23
- package/package.json +1 -1
- package/resource/choose_editor.png +0 -0
- package/resource/set_environment.png +0 -0
- package/resource/set_multimodel.png +0 -0
- package/resource/set_sdk.png +0 -0
- package/skills/hmos-batch-ui-align/SKILL.md +8 -6
- package/skills/hmos-convert-pipeline/SKILL.md +7 -7
- package/skills/hmos-fix-build-errors/SKILL.md +4 -3
- package/skills/hmos-incremental-ui-align/README.md +9 -12
- package/skills/hmos-incremental-ui-align/SKILL.md +9 -9
- package/skills/hmos-incremental-ui-align/scripts/__pycache__/app_feature_verify.cpython-314.pyc +0 -0
- package/skills/hmos-incremental-ui-align/scripts/app_feature_verify.py +128 -29
- package/skills/hmos-incremental-ui-align/scripts/navigation-capure.md +37 -37
- package/skills/hmos-incremental-ui-align/scripts/page_capture.py +7 -2
- package/skills/hmos-integration-test/README.md +3 -3
- package/skills/hmos-integration-test/SKILL.md +7 -7
- package/skills/hmos-spec-generate/SKILL.md +45 -52
- package/tools/test-tools/autotest/README.md +10 -11
- package/tools/test-tools/autotest/self_test_runner.py +40 -12
- package/resource/common_config.png +0 -0
- package/resource/integration_test_config.png +0 -0
- package/resource/set_env.png +0 -0
- package/resource/ui_align_config.png +0 -0
- package/skills/hmos-resources-convert/tools/apktool.bat +0 -85
package/dist/cli/uninstall.js
CHANGED
|
@@ -22,9 +22,19 @@ import { removeEnvVars } from './env-vars.js';
|
|
|
22
22
|
const execFileAsync = promisify(execFile);
|
|
23
23
|
const __filename = fileURLToPath(import.meta.url);
|
|
24
24
|
const __dirname = path.dirname(__filename);
|
|
25
|
-
/**
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Global Node CLIs that `ht init` installs as a pair (`npm install -g homegraph
|
|
27
|
+
* arkanalyzer`). `ht uninstall` removes the same pair so the two commands stay
|
|
28
|
+
* symmetric.
|
|
29
|
+
*/
|
|
30
|
+
const NODE_DEPS = ['homegraph', 'arkanalyzer'];
|
|
31
|
+
/**
|
|
32
|
+
* Machine env var names that `ht init` may have set and that have a non-empty
|
|
33
|
+
* value in config.env: the SDK paths / tool dir plus the mirrored unified model
|
|
34
|
+
* fields (HOMETRANS_MODEL_*, kept in sync with autotest.unified_model on load).
|
|
35
|
+
*/
|
|
36
|
+
function plannedEnvVarNames(config) {
|
|
37
|
+
return MACHINE_ENV_KEYS.filter((k) => (config.env[k] ?? '').trim().length > 0);
|
|
28
38
|
}
|
|
29
39
|
/* ------------------------------------------------------------------ */
|
|
30
40
|
/* Bundled content discovery */
|
|
@@ -68,6 +78,57 @@ async function listBundledAgentEntries(agentsRoot) {
|
|
|
68
78
|
}
|
|
69
79
|
}
|
|
70
80
|
/* ------------------------------------------------------------------ */
|
|
81
|
+
/* Global npm dependency removal */
|
|
82
|
+
/* ------------------------------------------------------------------ */
|
|
83
|
+
/**
|
|
84
|
+
* Is `npm` runnable? On Windows the global npm bin is a `.cmd` shim, so the
|
|
85
|
+
* command must run through the shell there (same as init's homegraphVersion()).
|
|
86
|
+
*/
|
|
87
|
+
async function npmAvailable() {
|
|
88
|
+
try {
|
|
89
|
+
await execFileAsync('npm', ['--version'], {
|
|
90
|
+
timeout: 15000,
|
|
91
|
+
shell: process.platform === 'win32',
|
|
92
|
+
});
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Does `homegraph --version` return normally (exit 0)? Used as the presence
|
|
101
|
+
* probe for the homegraph/arkanalyzer pair — the symmetric counterpart to
|
|
102
|
+
* init's idempotency check, which skips the install when homegraph is already
|
|
103
|
+
* present.
|
|
104
|
+
*/
|
|
105
|
+
async function homegraphInstalled() {
|
|
106
|
+
try {
|
|
107
|
+
await execFileAsync('homegraph', ['--version'], {
|
|
108
|
+
timeout: 15000,
|
|
109
|
+
shell: process.platform === 'win32',
|
|
110
|
+
});
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Decide which global npm packages to remove. Returns the homegraph/arkanalyzer
|
|
119
|
+
* pair when homegraph is detected on the machine (mirroring init, which installs
|
|
120
|
+
* them together), or an empty list when npm is unavailable or homegraph is not
|
|
121
|
+
* present — so a machine that never ran `ht init`'s dependency install shows
|
|
122
|
+
* nothing to remove here.
|
|
123
|
+
*/
|
|
124
|
+
async function detectNodeDepsToRemove() {
|
|
125
|
+
if (!(await npmAvailable()))
|
|
126
|
+
return [];
|
|
127
|
+
if (!(await homegraphInstalled()))
|
|
128
|
+
return [];
|
|
129
|
+
return [...NODE_DEPS];
|
|
130
|
+
}
|
|
131
|
+
/* ------------------------------------------------------------------ */
|
|
71
132
|
/* MCP config removal helpers */
|
|
72
133
|
/* ------------------------------------------------------------------ */
|
|
73
134
|
function detectIndentation(raw) {
|
|
@@ -299,6 +360,7 @@ function renderDiff(oldContent, newContent, context = 3) {
|
|
|
299
360
|
function isPlanEmpty(plan) {
|
|
300
361
|
return (plan.deletions.length === 0 &&
|
|
301
362
|
plan.modifications.length === 0 &&
|
|
363
|
+
plan.npmDeps.length === 0 &&
|
|
302
364
|
plan.envVars.length === 0 &&
|
|
303
365
|
plan.configDir === null);
|
|
304
366
|
}
|
|
@@ -325,6 +387,14 @@ function renderPlan(plan) {
|
|
|
325
387
|
console.log('');
|
|
326
388
|
}
|
|
327
389
|
}
|
|
390
|
+
if (plan.npmDeps.length > 0) {
|
|
391
|
+
console.log(chalk.red.bold(` Global npm packages to remove (${plan.npmDeps.length}):`));
|
|
392
|
+
console.log(chalk.gray(` (will run: npm uninstall -g ${plan.npmDeps.join(' ')})`));
|
|
393
|
+
for (const dep of plan.npmDeps) {
|
|
394
|
+
console.log(` ${chalk.red('-')} ${dep}`);
|
|
395
|
+
}
|
|
396
|
+
console.log('');
|
|
397
|
+
}
|
|
328
398
|
if (plan.envVars.length > 0) {
|
|
329
399
|
console.log(chalk.red.bold(` Environment variables to remove (${plan.envVars.length}):`));
|
|
330
400
|
console.log(chalk.gray(process.platform === 'win32'
|
|
@@ -347,6 +417,7 @@ function renderPlan(plan) {
|
|
|
347
417
|
async function executePlan(plan) {
|
|
348
418
|
let deleted = 0;
|
|
349
419
|
let modified = 0;
|
|
420
|
+
let npmNote = null;
|
|
350
421
|
let envNote = null;
|
|
351
422
|
for (const mod of plan.modifications) {
|
|
352
423
|
await fs.writeFile(mod.absPath, mod.newContent, 'utf-8');
|
|
@@ -362,6 +433,22 @@ async function executePlan(plan) {
|
|
|
362
433
|
// codex CLI unavailable or failed — TOML path already handled above
|
|
363
434
|
}
|
|
364
435
|
}
|
|
436
|
+
// Remove the global npm CLIs installed by `ht init` (homegraph + arkanalyzer).
|
|
437
|
+
// Best-effort: a failure is reported in the note but never aborts the rest of
|
|
438
|
+
// the uninstall.
|
|
439
|
+
if (plan.npmDeps.length > 0) {
|
|
440
|
+
console.log(chalk.gray(` Running: npm uninstall -g ${plan.npmDeps.join(' ')} ...`));
|
|
441
|
+
try {
|
|
442
|
+
await execFileAsync('npm', ['uninstall', '-g', ...plan.npmDeps], {
|
|
443
|
+
timeout: 5 * 60 * 1000,
|
|
444
|
+
shell: process.platform === 'win32',
|
|
445
|
+
});
|
|
446
|
+
npmNote = `removed ${plan.npmDeps.join(', ')}`;
|
|
447
|
+
}
|
|
448
|
+
catch (err) {
|
|
449
|
+
npmNote = `failed (${err.message}) — remove manually: npm uninstall -g ${plan.npmDeps.join(' ')}`;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
365
452
|
for (const del of plan.deletions) {
|
|
366
453
|
try {
|
|
367
454
|
await fs.rm(del.absPath, { recursive: true, force: true });
|
|
@@ -384,7 +471,7 @@ async function executePlan(plan) {
|
|
|
384
471
|
// best-effort
|
|
385
472
|
}
|
|
386
473
|
}
|
|
387
|
-
return { deleted, modified, envNote };
|
|
474
|
+
return { deleted, modified, npmNote, envNote };
|
|
388
475
|
}
|
|
389
476
|
/* ------------------------------------------------------------------ */
|
|
390
477
|
/* Entry point */
|
|
@@ -398,20 +485,25 @@ export async function uninstallCommand() {
|
|
|
398
485
|
console.log(chalk.gray(' Reinstall hometrans or manually remove skill/agent directories from your editors.\n'));
|
|
399
486
|
return;
|
|
400
487
|
}
|
|
401
|
-
const
|
|
488
|
+
const config = await loadHomeTransConfig();
|
|
489
|
+
const { editors } = config;
|
|
402
490
|
const plan = {
|
|
403
491
|
deletions: [],
|
|
404
492
|
modifications: [],
|
|
405
493
|
codexRemove: false,
|
|
494
|
+
npmDeps: [],
|
|
406
495
|
envVars: [],
|
|
407
496
|
configDir: null,
|
|
408
497
|
};
|
|
409
498
|
for (const editor of editors) {
|
|
410
499
|
await buildPlanForEditor(editor, skillNames, agentEntries, plan);
|
|
411
500
|
}
|
|
412
|
-
//
|
|
413
|
-
//
|
|
414
|
-
plan.
|
|
501
|
+
// Global npm CLIs installed by `ht init` (homegraph + arkanalyzer) — detected
|
|
502
|
+
// the same way init decides whether to (re)install them.
|
|
503
|
+
plan.npmDeps = await detectNodeDepsToRemove();
|
|
504
|
+
// Env vars to remove come from config.json (`env` + the unified model
|
|
505
|
+
// fields); the ~/.hometrans dir (which holds config.json) is deleted last.
|
|
506
|
+
plan.envVars = plannedEnvVarNames(config);
|
|
415
507
|
const configDir = getConfigDir();
|
|
416
508
|
if (await dirExists(configDir)) {
|
|
417
509
|
plan.configDir = configDir;
|
|
@@ -446,6 +538,9 @@ export async function uninstallCommand() {
|
|
|
446
538
|
const summary = await executePlan(plan);
|
|
447
539
|
console.log('');
|
|
448
540
|
console.log(chalk.green(` Uninstalled: ${summary.deleted} entries deleted, ${summary.modified} files modified.`));
|
|
541
|
+
if (summary.npmNote) {
|
|
542
|
+
console.log(chalk.green(` Global npm packages: ${summary.npmNote}`));
|
|
543
|
+
}
|
|
449
544
|
if (summary.envNote) {
|
|
450
545
|
console.log(chalk.green(` Environment variables: ${summary.envNote}`));
|
|
451
546
|
}
|
package/dist/context/index.js
CHANGED
|
@@ -10,8 +10,25 @@ import {
|
|
|
10
10
|
} from "arkanalyzer";
|
|
11
11
|
|
|
12
12
|
// src/cli/config-store.ts
|
|
13
|
+
import { readFileSync } from "node:fs";
|
|
13
14
|
import path from "node:path";
|
|
14
15
|
import os from "node:os";
|
|
16
|
+
function getConfigDir() {
|
|
17
|
+
return path.join(os.homedir(), ".hometrans");
|
|
18
|
+
}
|
|
19
|
+
function getConfigPath() {
|
|
20
|
+
return path.join(getConfigDir(), "config.json");
|
|
21
|
+
}
|
|
22
|
+
function readConfigEnvFieldSync(key) {
|
|
23
|
+
try {
|
|
24
|
+
const raw = readFileSync(getConfigPath(), "utf-8");
|
|
25
|
+
const parsed = JSON.parse(raw);
|
|
26
|
+
const v = parsed?.env?.[key];
|
|
27
|
+
return typeof v === "string" ? v : "";
|
|
28
|
+
} catch {
|
|
29
|
+
return "";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
15
32
|
function expandHome(p) {
|
|
16
33
|
if (!p) return p;
|
|
17
34
|
if (p === "~") return os.homedir();
|
|
@@ -594,10 +611,10 @@ async function extractCommitContext(input) {
|
|
|
594
611
|
const { projectPath, commitId } = input;
|
|
595
612
|
const mode = input.mode ?? "default";
|
|
596
613
|
const ohosSdkPath = expandHome(
|
|
597
|
-
input.ohosSdkPath
|
|
614
|
+
input.ohosSdkPath || process.env.OHOS_SDK_PATH || readConfigEnvFieldSync("OHOS_SDK_PATH")
|
|
598
615
|
);
|
|
599
616
|
const hmsSdkPath = expandHome(
|
|
600
|
-
input.hmsSdkPath
|
|
617
|
+
input.hmsSdkPath || process.env.HMS_SDK_PATH || readConfigEnvFieldSync("HMS_SDK_PATH")
|
|
601
618
|
);
|
|
602
619
|
if (!projectPath) {
|
|
603
620
|
throw new Error("extractCommitContext: projectPath is required");
|
package/env-requirements.json
CHANGED
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
|
|
28
28
|
"tools": {
|
|
29
29
|
"deveco": {
|
|
30
|
+
"label": "harmony sdk",
|
|
30
31
|
"source": "env-dir",
|
|
31
32
|
"envVar": "DEVECO_SDK_HOME",
|
|
32
33
|
"hint": "set DEVECO_SDK_HOME via `ht init` (DevEco Studio install)"
|
|
@@ -46,20 +47,12 @@
|
|
|
46
47
|
"fallback": { "base": "DEVECO_SDK_HOME", "segments": ["default", "openharmony", "toolchains"], "exe": "hdc" },
|
|
47
48
|
"hint": "ships with DevEco: <sdk>/default/openharmony/toolchains"
|
|
48
49
|
},
|
|
49
|
-
"python": {
|
|
50
|
-
"source": "path",
|
|
51
|
-
"aliases": ["python", "python3", "py"],
|
|
52
|
-
"verify": ["--version"],
|
|
53
|
-
"versionRegex": "(\\d+\\.\\d+(?:\\.\\d+)?)",
|
|
54
|
-
"version": { "min": "3.10.0", "max": null },
|
|
55
|
-
"hint": "install Python >= 3.10 and add to PATH (UI-align capture/parse scripts)"
|
|
56
|
-
},
|
|
57
50
|
"uv": {
|
|
58
51
|
"source": "path",
|
|
59
52
|
"aliases": ["uv"],
|
|
60
53
|
"verify": ["--version"],
|
|
61
54
|
"versionRegex": "(\\d+\\.\\d+(?:\\.\\d+)?)",
|
|
62
|
-
"hint": "https://docs.astral.sh/uv (AutoTest
|
|
55
|
+
"hint": "https://docs.astral.sh/uv — runs every Python script (AutoTest, UI-align, logic) via `uv run` and provides Python ≥ 3.10 on demand (no standalone Python needed)"
|
|
63
56
|
},
|
|
64
57
|
"java": {
|
|
65
58
|
"source": "path",
|
|
@@ -70,12 +63,12 @@
|
|
|
70
63
|
"fallback": { "base": "DEVECO_HOME", "segments": ["jbr", "bin"], "exe": "java" },
|
|
71
64
|
"hint": "any JDK 17+, or reuse DevEco jbr: <deveco>/jbr/bin"
|
|
72
65
|
},
|
|
73
|
-
"
|
|
66
|
+
"homegraph": {
|
|
74
67
|
"source": "path",
|
|
75
|
-
"aliases": ["
|
|
68
|
+
"aliases": ["homegraph"],
|
|
76
69
|
"verify": ["--version"],
|
|
77
70
|
"versionRegex": "(\\d+\\.\\d+(?:\\.\\d+)?)",
|
|
78
|
-
"hint": "npm
|
|
71
|
+
"hint": "npm install -g homegraph arkanalyzer (code-graph backend for spec generation)"
|
|
79
72
|
}
|
|
80
73
|
},
|
|
81
74
|
|
|
@@ -83,7 +76,7 @@
|
|
|
83
76
|
{
|
|
84
77
|
"name": "hmos-spec-generate",
|
|
85
78
|
"kind": "skill",
|
|
86
|
-
"dependencies": [{ "tool": "
|
|
79
|
+
"dependencies": [{ "tool": "homegraph", "level": "required" }]
|
|
87
80
|
},
|
|
88
81
|
{
|
|
89
82
|
"name": "hmos-resources-convert",
|
|
@@ -95,20 +88,21 @@
|
|
|
95
88
|
"name": "hmos-batch-ui-align",
|
|
96
89
|
"kind": "skill",
|
|
97
90
|
"dependencies": [
|
|
98
|
-
{ "tool": "
|
|
91
|
+
{ "tool": "uv", "level": "required" },
|
|
99
92
|
{ "tool": "adb", "level": "optional" }
|
|
100
93
|
],
|
|
101
|
-
"note": "adb only for page exploration"
|
|
94
|
+
"note": "android_parse_fast.py runs via `uv run` (uv provides Python); adb only for page exploration"
|
|
102
95
|
},
|
|
103
96
|
{
|
|
104
97
|
"name": "hmos-incremental-ui-align",
|
|
105
98
|
"kind": "skill",
|
|
106
99
|
"dependencies": [
|
|
107
100
|
{ "tool": "deveco", "level": "required" },
|
|
108
|
-
{ "tool": "
|
|
101
|
+
{ "tool": "uv", "level": "required" },
|
|
109
102
|
{ "tool": "hdc", "level": "required" },
|
|
110
103
|
{ "tool": "adb", "level": "required" }
|
|
111
|
-
]
|
|
104
|
+
],
|
|
105
|
+
"note": "app_feature_verify.py / page_capture.py run via `uv run` (PEP 723 inline deps; uv provides Python)"
|
|
112
106
|
},
|
|
113
107
|
{
|
|
114
108
|
"name": "hmos-integration-test",
|
|
@@ -117,7 +111,8 @@
|
|
|
117
111
|
{ "tool": "deveco", "level": "required" },
|
|
118
112
|
{ "tool": "uv", "level": "required" },
|
|
119
113
|
{ "tool": "hdc", "level": "required" }
|
|
120
|
-
]
|
|
114
|
+
],
|
|
115
|
+
"note": "self_test_runner.py runs via `uv run --no-project python` (uv provides Python) and then `uv sync`s the AutoTest venv"
|
|
121
116
|
},
|
|
122
117
|
{
|
|
123
118
|
"name": "hmos-fix-build-errors",
|
|
@@ -132,22 +127,22 @@
|
|
|
132
127
|
{ "tool": "uv", "level": "optional" },
|
|
133
128
|
{ "tool": "hdc", "level": "optional" }
|
|
134
129
|
],
|
|
135
|
-
"note": "test stage skippable via skip_test"
|
|
130
|
+
"note": "test stage skippable via skip_test; when run it needs uv + hdc"
|
|
136
131
|
},
|
|
137
132
|
{
|
|
138
133
|
"name": "logic-context-builder",
|
|
139
134
|
"kind": "agent",
|
|
140
|
-
"dependencies": [{ "tool": "
|
|
135
|
+
"dependencies": [{ "tool": "uv", "level": "optional" }]
|
|
141
136
|
},
|
|
142
137
|
{
|
|
143
138
|
"name": "logic-coder",
|
|
144
139
|
"kind": "agent",
|
|
145
|
-
"dependencies": [{ "tool": "
|
|
140
|
+
"dependencies": [{ "tool": "uv", "level": "optional" }]
|
|
146
141
|
},
|
|
147
142
|
{
|
|
148
143
|
"name": "spec-generator",
|
|
149
144
|
"kind": "agent",
|
|
150
|
-
"dependencies": [{ "tool": "
|
|
145
|
+
"dependencies": [{ "tool": "homegraph", "level": "required" }]
|
|
151
146
|
},
|
|
152
147
|
{
|
|
153
148
|
"name": "build-fixer",
|
|
@@ -170,7 +165,8 @@
|
|
|
170
165
|
"dependencies": [
|
|
171
166
|
{ "tool": "uv", "level": "required" },
|
|
172
167
|
{ "tool": "hdc", "level": "required" }
|
|
173
|
-
]
|
|
168
|
+
],
|
|
169
|
+
"note": "invokes `uv run --no-project python self_test_runner.py run/status/kill` (uv provides Python; --no-project keeps the interpreter out of the .venv it rebuilds)"
|
|
174
170
|
},
|
|
175
171
|
{
|
|
176
172
|
"name": "self-test-fixer",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@buaa_smat/hometrans",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.17",
|
|
4
4
|
"description": "HomeTrans (Android-to-HarmonyOS) skill + agent installer. Run `ht init` to distribute conversion skills and subagents into AI editors.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -9,13 +9,13 @@ Batch-convert a set of Android page snapshots (each snapshot is a `page_NNNN_Act
|
|
|
9
9
|
|
|
10
10
|
## Step 0 — Environment Variables Check (run first)
|
|
11
11
|
|
|
12
|
-
The final build (Step 6, via `hmos_fix_build_errors`)
|
|
12
|
+
The final build (Step 6, via `hmos_fix_build_errors`) resolves the DevEco location along the standard chain — **OS environment variable first, then `~/.hometrans/config.json`, then ask the user** (read env vars with `echo "$VAR"` on macOS/Linux; `$env:VAR` in PowerShell on Windows):
|
|
13
13
|
|
|
14
|
-
| Variable | Needed for | Valid when |
|
|
15
|
-
|
|
16
|
-
| `DEVECO_HOME` *(or `DEVECO_SDK_HOME`)* | Step 6 unified build | resolves to a valid DevEco install |
|
|
14
|
+
| Variable | config.json fallback | Needed for | Valid when |
|
|
15
|
+
|---|---|---|---|
|
|
16
|
+
| `DEVECO_HOME` *(or `DEVECO_SDK_HOME`)* | `env.DEVECO_HOME` / `env.DEVECO_SDK_HOME` | Step 6 unified build | resolves to a valid DevEco install |
|
|
17
17
|
|
|
18
|
-
If neither
|
|
18
|
+
If neither the env var nor `~/.hometrans/config.json` yields a valid DevEco install, **ask the user** for the DevEco Studio install path before proceeding (suggest running `ht init` to persist it as a machine environment variable).
|
|
19
19
|
|
|
20
20
|
## Step 1 — Parse User Request
|
|
21
21
|
|
|
@@ -27,6 +27,7 @@ Extract 4 paths from the user's message (natural language, no fixed format):
|
|
|
27
27
|
| `harmony_project_dir` | HarmonyOS target project root | "target Harmony project", "鸿蒙项目", "output project" |
|
|
28
28
|
| `ui_info_root` | **Parent directory containing all `page_NNNN_*` subdirectories** | "page screenshots and view tree", "page snapshots", "page folder" |
|
|
29
29
|
| `pages` (optional) | User-explicitly listed page subset | When user lists `1. .../page_0001_X` ... take these |
|
|
30
|
+
| `apk_path` (optional) | Full path of the Android APK corresponding to `android_project_dir`. Passed through to `hmos-resources-convert` in Step 2 to skip the Gradle build and decompile this APK directly with apktool to extract resources | "APK path", "apk文件", "安卓apk" |
|
|
30
31
|
|
|
31
32
|
**`references_dir` and MVVM document directories always use skill-bundled relative paths** — **do not** accept user-provided overrides:
|
|
32
33
|
|
|
@@ -41,6 +42,7 @@ Invoke the `hmos-resources-convert` skill with the following parameters:
|
|
|
41
42
|
1. **Android project path** = `android_project_dir`
|
|
42
43
|
2. **HarmonyOS project output path** = `harmony_project_dir`
|
|
43
44
|
3. **resource_mapping_path** = generate the resource mapping document under `harmony_project_dir` at `${harmony_project_dir}/resource_mapping.md`
|
|
45
|
+
4. **Android apk path** = `apk_path` — **only if the user provided it**. When passed through, `hmos-resources-convert` skips the Gradle build and decompiles this APK directly with apktool to extract resources. Omit this parameter entirely when `apk_path` was not provided.
|
|
44
46
|
|
|
45
47
|
This skill batch-converts Android resources (strings, colors, drawables, images, etc.) to HarmonyOS resource format and generates the mapping document.
|
|
46
48
|
|
|
@@ -50,7 +52,7 @@ This skill batch-converts Android resources (strings, colors, drawables, images,
|
|
|
50
52
|
2. Otherwise, determine the target App package name (`package`). If the user didn't provide it, extract the `package` attribute from `AndroidManifest.xml` in `android_project_dir`; if still unavailable, ask the user.
|
|
51
53
|
3. Execute with Bash:
|
|
52
54
|
```
|
|
53
|
-
python ./scripts/android_parse_fast.py --package <package_name> --output <ui_info_root_absolute_path>
|
|
55
|
+
uv run --no-project python ./scripts/android_parse_fast.py --package <package_name> --output <ui_info_root_absolute_path>
|
|
54
56
|
```
|
|
55
57
|
This script connects to the Android emulator via ADB, BFS-traverses all reachable pages in the App, and for each page saves `screenshot.png`, `view.xml`, `meta.json` into `page_NNNN_ActivityName/` subdirectories. It also generates `index.json` and `report.html` under `ui_info_root`.
|
|
56
58
|
4. After execution, confirm that `index.json` has been generated under `ui_info_root`. If not, report an error and abort.
|
|
@@ -47,15 +47,15 @@ Define shorthand variables for the instructions below:
|
|
|
47
47
|
|
|
48
48
|
## Environment Variables Check (run before Stage 1)
|
|
49
49
|
|
|
50
|
-
The pipeline's sub-agents
|
|
50
|
+
The pipeline's sub-agents resolve each setting along the standard chain — **OS environment variable first, then `~/.hometrans/config.json`, then ask the user**. Verify upfront so the long pipeline fails fast (read env vars with `echo "$VAR"` on macOS/Linux; `$env:VAR` in PowerShell on Windows):
|
|
51
51
|
|
|
52
|
-
| Variable | Needed for | Valid when |
|
|
53
|
-
|
|
54
|
-
| `DEVECO_HOME` *(or `DEVECO_SDK_HOME`)* | Stage 2 build + Stage 3a/4b rebuilds | resolves to a valid DevEco install |
|
|
55
|
-
| `TEST_API_KEY` | Stage 4 self-test (only when `SKIP_TEST=false`) | non-empty |
|
|
56
|
-
| `HOMETRANS_TOOL_PATH` | Stage 4 self-test AutoTest dir
|
|
52
|
+
| Variable | config.json fallback | Needed for | Valid when |
|
|
53
|
+
|---|---|---|---|
|
|
54
|
+
| `DEVECO_HOME` *(or `DEVECO_SDK_HOME`)* | `env.DEVECO_HOME` / `env.DEVECO_SDK_HOME` | Stage 2 build + Stage 3a/4b rebuilds | resolves to a valid DevEco install |
|
|
55
|
+
| `HOMETRANS_MODEL_API_KEY` *(legacy `TEST_API_KEY` still honored as a fallback)* | `autotest.unified_model.api_key` | Stage 4 self-test (only when `SKIP_TEST=false`) | non-empty / not the placeholder |
|
|
56
|
+
| `HOMETRANS_TOOL_PATH` | `env.HOMETRANS_TOOL_PATH` (defaults to `~/.hometrans/tools`) | Stage 4 self-test AutoTest dir | path exists on disk |
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
For each value, if the env var is unset, fall back to the listed `~/.hometrans/config.json` field. If neither yields a value: for the DevEco path / model api_key, **ask the user** (for the api_key they may instead pass `skip_test=true`). Suggest running `ht init` to persist these as machine environment variables.
|
|
59
59
|
|
|
60
60
|
---
|
|
61
61
|
|
|
@@ -21,10 +21,11 @@ Automatically build a HarmonyOS NEXT project from the command line, parse compil
|
|
|
21
21
|
|
|
22
22
|
1. **Verify project exists** — Check that `$ARGUMENTS[0]` contains a valid HarmonyOS project (look for `build-profile.json5`, `entry/src` directory, `oh-package.json5`).
|
|
23
23
|
|
|
24
|
-
2. **Resolve `<deveco-path>`** —
|
|
24
|
+
2. **Resolve `<deveco-path>`** — follow the standard config chain, stopping at the first source that yields a valid path:
|
|
25
25
|
1. `$ARGUMENTS[1]` if provided (and not `--signed`).
|
|
26
|
-
2.
|
|
27
|
-
3.
|
|
26
|
+
2. **OS environment variables** (`echo "$VAR"` on macOS/Linux; `$env:VAR` in PowerShell on Windows): `DEVECO_HOME` → parent of `DEVECO_SDK_HOME` → strip the trailing `/sdk/default/openharmony/ets` from `OHOS_SDK_PATH` (legacy).
|
|
27
|
+
3. **`~/.hometrans/config.json`** — read `env.DEVECO_HOME`, else parent of `env.DEVECO_SDK_HOME` (written by `ht init`).
|
|
28
|
+
4. **Ask the user** for the DevEco Studio install path (suggest running `ht init` to persist it as an environment variable).
|
|
28
29
|
|
|
29
30
|
**Verify the resolved `<deveco-path>`** contains:
|
|
30
31
|
- `tools/node/node.exe`
|
|
@@ -13,7 +13,7 @@ HarmonyOS-Android UI 自动对齐流水线。
|
|
|
13
13
|
每多一个页面/弹窗/tab,上述步骤都要重复一遍,非常费时。
|
|
14
14
|
|
|
15
15
|
本 skill 做了三件事:
|
|
16
|
-
-
|
|
16
|
+
- 用 phone-agent 自动**寻路**(根据自然语言点到指定页面,模型复用 `~/.hometrans/config.json` 统一配置)
|
|
17
17
|
- 自动**采集** view tree + 截图(安卓走 adb、鸿蒙走 hdc)
|
|
18
18
|
- 自动**对比 + 改码**,并按 MVVM 模式把 mock 数据放到 Model 层
|
|
19
19
|
|
|
@@ -31,12 +31,10 @@ HarmonyOS-Android UI 自动对齐流水线。
|
|
|
31
31
|
- 两台设备建议都保持亮屏解锁
|
|
32
32
|
|
|
33
33
|
2. **Python 依赖**
|
|
34
|
-
|
|
35
|
-
pip install openpyxl phone-agent
|
|
36
|
-
```
|
|
34
|
+
无需手动安装。脚本通过 `uv run` 调用,`openpyxl` / `phone-agent` 已在 `app_feature_verify.py` 顶部的 PEP 723 内联元数据里声明,uv 首次运行时自动解析安装(走清华镜像)。只需确保已安装 `uv`(`uv --version`)。
|
|
37
35
|
|
|
38
|
-
3.
|
|
39
|
-
|
|
36
|
+
3. **模型配置**(phone-agent 导航用)
|
|
37
|
+
与自测共用同一个多模态模型:`ht init` 把模型四要素(api_key / name / base_url / provider)写入 `~/.hometrans/config.json` 的 `autotest.unified_model`,并导出为 `HOMETRANS_MODEL_*` 环境变量。脚本优先读环境变量,缺失时回落 config.json;都没有时兼容老版本的 `GLM_API_KEY`(走智谱 GLM 端点)。无需单独设置 API Key。
|
|
40
38
|
|
|
41
39
|
4. **鸿蒙 SDK 路径**(给改码阶段查 API 用)
|
|
42
40
|
取自 OS 环境变量 `OHOS_SDK_PATH` / `HMS_SDK_PATH`(为空时由 `DEVECO_SDK_HOME` 派生),由 `ht init` 写入机器环境变量;例如 DevEco Studio 自带的 `E:\DevEco Studio\sdk\default\openharmony\ets`。
|
|
@@ -55,9 +53,9 @@ HarmonyOS-Android UI 自动对齐流水线。
|
|
|
55
53
|
| `harmony_project_dir` | 是 | 鸿蒙工程根目录(会被直接修改) |
|
|
56
54
|
| `capture_output_dir` | 否 | 采集产物输出目录(截图/view tree/分析报告)。默认 `<harmony_project_dir>/.hometrans/capture_output` |
|
|
57
55
|
|
|
58
|
-
**②
|
|
56
|
+
**② 全局配置**(统一链路「环境变量 → `~/.hometrans/config.json` → 询问用户」,由 `ht init` 同时写入机器环境变量与 config.json,无需每次传):
|
|
59
57
|
|
|
60
|
-
-
|
|
58
|
+
- 模型配置 ← `HOMETRANS_MODEL_*` 环境变量(缺失时回落 `~/.hometrans/config.json` 的 `autotest.unified_model`;与自测共用同一个模型)
|
|
61
59
|
- 鸿蒙 SDK ETS API 目录 ← 环境变量 `OHOS_SDK_PATH` / `HMS_SDK_PATH`(为空时由 `DEVECO_SDK_HOME` 派生为 `<DEVECO_SDK_HOME>/default/openharmony/ets`、`.../hms/ets`)
|
|
62
60
|
|
|
63
61
|
> **Step 0.0** 会在执行前检查这些环境变量是否存在;缺失时会要求用户输入。
|
|
@@ -120,7 +118,7 @@ HarmonyOS-Android UI 自动对齐流水线。
|
|
|
120
118
|
skill 会严格按 `SKILL.md` 里的 5 步流水线跑:
|
|
121
119
|
|
|
122
120
|
### Step 0 · 解析入参
|
|
123
|
-
读取调用入参 `android_project_dir` / `harmony_project_dir` / `capture_output_dir
|
|
121
|
+
读取调用入参 `android_project_dir` / `harmony_project_dir` / `capture_output_dir`,并按统一链路「环境变量 → config.json → 询问」解析 `HOMETRANS_MODEL_*`(统一模型,回落 `~/.hometrans/config.json` 的 `autotest.unified_model`)与 `OHOS_SDK_PATH` / `HMS_SDK_PATH`(回落 config.json 的 `env.*`;**Step 0.0** 会先做存在性检查,两层都缺失才要求用户输入)。随后 **Step 0.1** 按两个工程目录自动解析两端的 App 显示名与包名(无需手动配置)。
|
|
124
122
|
|
|
125
123
|
### Step 1 · 双端页面采集
|
|
126
124
|
1.1 解析你的需求,拆成一组「基础页」,每个基础页有 `android_nav_path` 和 `hmos_nav_path`
|
|
@@ -193,16 +191,15 @@ Agents/hmos-ui-align/
|
|
|
193
191
|
```powershell
|
|
194
192
|
# 安卓寻路
|
|
195
193
|
$env:PYTHONIOENCODING="utf-8"
|
|
196
|
-
|
|
194
|
+
uv run Agents/hmos-ui-align/scripts/app_feature_verify.py `
|
|
197
195
|
--device adb `
|
|
198
196
|
--app "Salt Player" `
|
|
199
197
|
--package "com.salt.music" `
|
|
200
198
|
--prompt "进入首页-点击AI智能填报-点击专业筛选按钮" `
|
|
201
|
-
--api-key "$env:GLM_API_KEY" `
|
|
202
199
|
--max-steps 15
|
|
203
200
|
|
|
204
201
|
# 安卓采集
|
|
205
|
-
|
|
202
|
+
uv run Agents/hmos-ui-align/scripts/page_capture.py --device adb -o ./tmp/android_page_1_xxx
|
|
206
203
|
|
|
207
204
|
# 鸿蒙同理,把 --device adb 换成 --device hdc
|
|
208
205
|
```
|
|
@@ -18,7 +18,7 @@ You are writing ArkTS codes.
|
|
|
18
18
|
|
|
19
19
|
## Step 0: Resolve Inputs
|
|
20
20
|
|
|
21
|
-
This skill takes three path inputs from the invocation and
|
|
21
|
+
This skill takes three path inputs from the invocation and resolves its other settings along the standard chain — **OS environment variable → `~/.hometrans/config.json` → ask the user** (see Step 0.0).
|
|
22
22
|
|
|
23
23
|
### Skill input arguments (provided by the user when invoking the skill)
|
|
24
24
|
|
|
@@ -32,17 +32,17 @@ The user may pass them as named args (e.g. `android_project_dir: D:\path\to\andr
|
|
|
32
32
|
|
|
33
33
|
### Step 0.0: Environment Variables Check (run first)
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
Resolve each value along the standard chain — **OS environment variable first, then `~/.hometrans/config.json`, then ask the user** (read env vars with `echo "$VAR"` on macOS/Linux; `$env:VAR` in PowerShell / `echo %VAR%` in cmd on Windows).
|
|
36
36
|
|
|
37
|
-
| Variable | Purpose | Valid when |
|
|
38
|
-
|
|
39
|
-
| `
|
|
40
|
-
| `OHOS_SDK_PATH` | HarmonyOS SDK ETS API reference (Step 3) | path exists on disk |
|
|
41
|
-
| `HMS_SDK_PATH` | HMS SDK ETS API reference (Step 3) | path exists on disk |
|
|
37
|
+
| Variable | config.json fallback | Purpose | Valid when |
|
|
38
|
+
|---|---|---|---|
|
|
39
|
+
| `HOMETRANS_MODEL_*` (`HOMETRANS_MODEL_API_KEY` / `HOMETRANS_MODEL_NAME` / `HOMETRANS_MODEL_BASE_URL`) | `autotest.unified_model.{api_key,name,base_url}`(provider 默认 openai,不导出环境变量;再兜底老版本 `GLM_API_KEY` → 智谱 GLM 端点) | 统一多模态模型(UI 对齐 + 自测共用),由 `ht init` 导出 | `HOMETRANS_MODEL_API_KEY` 非空(或 config.json 已配置,或老版本 `GLM_API_KEY` 已设置) |
|
|
40
|
+
| `OHOS_SDK_PATH` | `env.OHOS_SDK_PATH` | HarmonyOS SDK ETS API reference (Step 3) | path exists on disk |
|
|
41
|
+
| `HMS_SDK_PATH` | `env.HMS_SDK_PATH` | HMS SDK ETS API reference (Step 3) | path exists on disk |
|
|
42
42
|
|
|
43
|
-
For `OHOS_SDK_PATH` / `HMS_SDK_PATH`, if
|
|
43
|
+
The model config is resolved automatically by `scripts/app_feature_verify.py` (env → config.json), so you don't read it by hand — just confirm `HOMETRANS_MODEL_API_KEY` or `autotest.unified_model.api_key` is set. For `OHOS_SDK_PATH` / `HMS_SDK_PATH`, if both the env var and `~/.hometrans/config.json` are empty but `DEVECO_SDK_HOME` is set (env or `env.DEVECO_SDK_HOME` in config.json), derive them as `<DEVECO_SDK_HOME>/default/openharmony/ets` and `<DEVECO_SDK_HOME>/default/hms/ets`.
|
|
44
44
|
|
|
45
|
-
For each
|
|
45
|
+
For each value that is still missing/empty (or a path that does not exist) after both the env var and `~/.hometrans/config.json`, **stop and ask the user to provide a value**, then use what they give for this run. Suggest running `ht init` to persist them as machine environment variables for next time.
|
|
46
46
|
|
|
47
47
|
### Step 0.1: Auto-derive App Names & Package Names
|
|
48
48
|
|