android2harmony 0.1.3 → 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.
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/index.ts
2
- import path10 from "node:path";
2
+ import path5 from "node:path";
3
3
 
4
4
  // src/paths.ts
5
5
  import path from "node:path";
@@ -203,476 +203,11 @@ function makeA2hAppFeatureVerifyTool(deps) {
203
203
  };
204
204
  }
205
205
 
206
- // src/tools/a2h-autotest-resolve-metadata.ts
207
- import path6 from "node:path";
208
-
209
- // src/tools/autotest-shared.ts
210
- import { spawn as spawn2 } from "node:child_process";
211
- import path5 from "node:path";
212
- var AUTOTEST_ROOT = path5.join(PKG_ROOT, "tools", "autotest");
213
- var SECRET_ENV2 = [
214
- "HOMETRANS_MODEL_API_KEY",
215
- "HOMETRANS_MODEL_NAME",
216
- "HOMETRANS_MODEL_BASE_URL",
217
- "GLM_API_KEY",
218
- "TEST_API_KEY"
219
- ];
220
- function cap2(s, max = 5e4) {
221
- if (s.length <= max) return s;
222
- const half = Math.floor(max / 2);
223
- return s.slice(0, half) + `
224
- \u2026[truncated ${s.length - max} chars]\u2026
225
- ` + s.slice(-half);
226
- }
227
- function runAutotestScript(opts) {
228
- return new Promise((resolve) => {
229
- const scriptPath = path5.join(AUTOTEST_ROOT, opts.scriptRel);
230
- const env = { ...process.env };
231
- for (const k of SECRET_ENV2) delete env[k];
232
- const child = spawn2("node", [scriptPath, ...opts.argv], {
233
- cwd: opts.cwd,
234
- env,
235
- stdio: ["pipe", "pipe", "pipe"]
236
- });
237
- let stdout = "";
238
- let stderr = "";
239
- let spawnError = "";
240
- child.stdout.on("data", (chunk) => {
241
- const text = chunk.toString("utf8");
242
- stdout += text;
243
- opts.onStdoutChunk?.(text);
244
- });
245
- child.stderr.on("data", (chunk) => {
246
- stderr += chunk.toString("utf8");
247
- });
248
- child.stdin.end(opts.stdin ?? "");
249
- const onAbort = () => {
250
- if (!child.killed) child.kill("SIGTERM");
251
- };
252
- opts.abort.addEventListener("abort", onAbort);
253
- child.on("close", (code) => {
254
- opts.abort.removeEventListener("abort", onAbort);
255
- resolve({ ok: code === 0, exitCode: code ?? -1, stdout: cap2(stdout), stderr, spawnError });
256
- });
257
- child.on("error", (err) => {
258
- opts.abort.removeEventListener("abort", onAbort);
259
- spawnError = err.message;
260
- resolve({ ok: false, exitCode: -1, stdout: cap2(stdout), stderr, spawnError });
261
- });
262
- });
263
- }
264
- function autotestToolError(toolId, r) {
265
- if (r.spawnError) return new Error(`${toolId}: failed to spawn node \u2014 ${r.spawnError}`);
266
- const tail = r.stderr.slice(-2e3);
267
- return new Error(`${toolId} failed (exit ${r.exitCode}): ${tail || "(no stderr)"}`);
268
- }
269
-
270
- // src/tools/a2h-autotest-resolve-metadata.ts
271
- var SCRIPT_REL = path6.join("resolve-metadata-tool.ts");
272
- var TOOL_ID = "a2h_autotest_resolve_metadata";
273
- function makeA2hAutotestResolveMetadataTool(_deps) {
274
- return {
275
- description: "Resolve bundle_name / app_name from a HarmonyOS project (reads AppScope/app.json5 and resolves $string refs) and writes app-metadata.json. Pure metadata extraction \u2014 no model, no device. Use this instead of running `node resolve-metadata-tool.ts` directly. Returns the written metadata JSON path + stdout on success.",
276
- args: {
277
- type: "object",
278
- properties: {
279
- projectDir: {
280
- type: "string",
281
- description: "HarmonyOS \u5DE5\u7A0B\u6839\u76EE\u5F55\uFF08\u542B AppScope/app.json5\uFF09"
282
- },
283
- output: {
284
- type: "string",
285
- description: "app-metadata.json \u8F93\u51FA\u8DEF\u5F84"
286
- }
287
- },
288
- required: ["projectDir", "output"]
289
- },
290
- execute: async (args, context) => {
291
- const projectDir = String(args.projectDir ?? "");
292
- const output = String(args.output ?? "");
293
- if (!projectDir || !output) {
294
- throw new Error(`${TOOL_ID}: \`projectDir\` and \`output\` are required`);
295
- }
296
- const argv = ["--project-dir", projectDir, "--output", output];
297
- const r = await runAutotestScript({
298
- scriptRel: SCRIPT_REL,
299
- argv,
300
- cwd: context.directory,
301
- abort: context.abort
302
- });
303
- if (!r.ok) throw autotestToolError(TOOL_ID, r);
304
- return { ok: true, exitCode: r.exitCode, output: r.stdout };
305
- }
306
- };
307
- }
308
-
309
- // src/tools/a2h-autotest-testcases.ts
310
- import path7 from "node:path";
311
- var SCRIPT_REL2 = path7.join("engine", "testcases-tool.ts");
312
- var TOOL_ID2 = "a2h_autotest_testcases";
313
- function makeA2hAutotestTestcasesTool(_deps) {
314
- return {
315
- description: "HarmonyOS self-test testcases.json engine \u2014 grouped by noun, dispatched on `action`. `generate`: build a schema-compliant testcases.json from extractor output ({ bundle_name, app_name, cases:[{case_name,actions,expected_results}] }); pass `validate` to validate in place. `validate`: check an existing testcases.json against the schema. No model, no device. Non-zero exit is a failure (thrown). Use this instead of running `node testcases-tool.ts` directly.",
316
- args: {
317
- type: "object",
318
- properties: {
319
- action: {
320
- type: "string",
321
- enum: ["generate", "validate"],
322
- description: "generate=\u4ECE\u62BD\u53D6\u8F93\u51FA\u5EFA testcases.json\uFF1Bvalidate=\u6821\u9A8C\u5DF2\u6709 testcases.json"
323
- },
324
- input: { type: "string", description: "[generate] \u62BD\u53D6\u8F93\u51FA JSON \u8DEF\u5F84" },
325
- output: { type: "string", description: "[generate] testcases.json \u8F93\u51FA\u8DEF\u5F84" },
326
- validate: { type: "boolean", default: false, description: "[generate] \u5199\u5B8C\u540E\u5C31\u5730\u6821\u9A8C" },
327
- path: { type: "string", description: "[validate] \u8981\u6821\u9A8C\u7684 testcases.json \u8DEF\u5F84" }
328
- },
329
- required: ["action"]
330
- },
331
- execute: async (args, context) => {
332
- const action = String(args.action ?? "");
333
- if (action === "generate") {
334
- const input = String(args.input ?? "");
335
- const output = String(args.output ?? "");
336
- if (!input || !output) {
337
- throw new Error(`${TOOL_ID2}: \`action:"generate"\` requires \`input\` and \`output\``);
338
- }
339
- const argv = ["generate", input, output];
340
- if (args.validate === true) argv.push("--validate");
341
- const r = await runAutotestScript({
342
- scriptRel: SCRIPT_REL2,
343
- argv,
344
- cwd: context.directory,
345
- abort: context.abort
346
- });
347
- if (!r.ok) throw autotestToolError(TOOL_ID2, r);
348
- return { ok: true, exitCode: r.exitCode, output: r.stdout };
349
- }
350
- if (action === "validate") {
351
- const p = String(args.path ?? "");
352
- if (!p) {
353
- throw new Error(`${TOOL_ID2}: \`action:"validate"\` requires \`path\``);
354
- }
355
- const argv = ["validate", p];
356
- const r = await runAutotestScript({
357
- scriptRel: SCRIPT_REL2,
358
- argv,
359
- cwd: context.directory,
360
- abort: context.abort
361
- });
362
- if (!r.ok) throw autotestToolError(TOOL_ID2, r);
363
- return { ok: true, exitCode: r.exitCode, output: r.stdout };
364
- }
365
- throw new Error(`${TOOL_ID2}: unknown \`action\` "${action}" (expected generate|validate)`);
366
- }
367
- };
368
- }
369
-
370
- // src/tools/a2h-autotest-report.ts
371
- import path8 from "node:path";
372
- var SCRIPT_REL3 = path8.join("engine", "report-tool.ts");
373
- var TOOL_ID3 = "a2h_autotest_report";
374
- function makeA2hAutotestReportTool(_deps) {
375
- return {
376
- description: "HarmonyOS self-test report engine \u2014 grouped by noun, dispatched on `action`. `generate`: render self-test-report.md from a task_<ts>/ directory (summary.json + task_results.jsonl + per-case judgment logs): overview, pre-cases, regular-cases, summary table, suggestions; pass `validate` to validate in place. `validate`: check an existing report.md's layout. No model, no device. Non-zero exit is a failure (thrown). Use this instead of running `node report-tool.ts` directly.",
377
- args: {
378
- type: "object",
379
- properties: {
380
- action: {
381
- type: "string",
382
- enum: ["generate", "validate"],
383
- description: "generate=\u4ECE task \u76EE\u5F55\u6E32\u67D3 self-test-report.md\uFF1Bvalidate=\u6821\u9A8C\u5DF2\u6709 report.md \u5E03\u5C40"
384
- },
385
- taskSubdir: { type: "string", description: "[generate] task_<ts>/ \u76EE\u5F55\u8DEF\u5F84" },
386
- appMetadata: { type: "string", description: "[generate] app-metadata.json \u8DEF\u5F84" },
387
- hap: { type: "string", description: "[generate] HAP \u6587\u4EF6\u8DEF\u5F84" },
388
- device: { type: "string", description: "[generate] \u8BBE\u5907\u6807\u8BC6\uFF08\u5982 127.0.0.1:5555\uFF09" },
389
- suite: { type: "string", description: "[generate] \u6D4B\u8BD5\u5957\u4EF6\u6807\u9898" },
390
- out: { type: "string", description: "[generate] self-test-report.md \u8F93\u51FA\u8DEF\u5F84" },
391
- validate: { type: "boolean", default: false, description: "[generate] \u5199\u5B8C\u540E\u5C31\u5730\u6821\u9A8C" },
392
- path: { type: "string", description: "[validate] \u8981\u6821\u9A8C\u7684 report.md \u8DEF\u5F84" }
393
- },
394
- required: ["action"]
395
- },
396
- execute: async (args, context) => {
397
- const action = String(args.action ?? "");
398
- if (action === "generate") {
399
- const taskSubdir = String(args.taskSubdir ?? "");
400
- const appMetadata = String(args.appMetadata ?? "");
401
- const hap = String(args.hap ?? "");
402
- const device = String(args.device ?? "");
403
- const suite = String(args.suite ?? "");
404
- const out = String(args.out ?? "");
405
- if (!taskSubdir || !appMetadata || !hap || !device || !suite || !out) {
406
- throw new Error(
407
- `${TOOL_ID3}: \`action:"generate"\` requires \`taskSubdir\`, \`appMetadata\`, \`hap\`, \`device\`, \`suite\`, \`out\``
408
- );
409
- }
410
- const argv = [
411
- "generate",
412
- "--task-subdir",
413
- taskSubdir,
414
- "--app-metadata",
415
- appMetadata,
416
- "--hap",
417
- hap,
418
- "--device",
419
- device,
420
- "--suite",
421
- suite,
422
- "--out",
423
- out
424
- ];
425
- if (args.validate === true) argv.push("--validate");
426
- const r = await runAutotestScript({
427
- scriptRel: SCRIPT_REL3,
428
- argv,
429
- cwd: context.directory,
430
- abort: context.abort
431
- });
432
- if (!r.ok) throw autotestToolError(TOOL_ID3, r);
433
- return { ok: true, exitCode: r.exitCode, output: r.stdout };
434
- }
435
- if (action === "validate") {
436
- const p = String(args.path ?? "");
437
- if (!p) {
438
- throw new Error(`${TOOL_ID3}: \`action:"validate"\` requires \`path\``);
439
- }
440
- const argv = ["validate", p];
441
- const r = await runAutotestScript({
442
- scriptRel: SCRIPT_REL3,
443
- argv,
444
- cwd: context.directory,
445
- abort: context.abort
446
- });
447
- if (!r.ok) throw autotestToolError(TOOL_ID3, r);
448
- return { ok: true, exitCode: r.exitCode, output: r.stdout };
449
- }
450
- throw new Error(`${TOOL_ID3}: unknown \`action\` "${action}" (expected generate|validate)`);
451
- }
452
- };
453
- }
454
-
455
- // src/tools/a2h-autotest-selftest.ts
456
- import { spawn as spawn3 } from "node:child_process";
457
- import path9 from "node:path";
458
- var SCRIPT_REL4 = path9.join("engine", "self-test-runner.ts");
459
- var TOOL_ID4 = "a2h_autotest_selftest";
460
- function makeA2hAutotestSelftestTool(deps) {
461
- return {
462
- description: "HarmonyOS on-device self-test engine \u2014 grouped by noun, dispatched on `action`. `run`: hdc uninstall+install of HAP, then a detached @autotest/agent batch (multimodal model resolved by the host, piped via stdin; never env/argv/disk). Without `timeout` returns RUNNING immediately (exit 2); with `timeout` blocks until terminal (0 COMPLETED / 1 FAILED / 3 CRASHED / 4 NOT_STARTED / 5 TIMEOUT). `status`: probe on-disk state (0/2/3/4). `kill`: tear down the batch tree. `check_hap`/`check_inputs`/`check_pre`: pre-flight validators (0 = passed). Exit codes are states, not errors \u2014 branch on `status` in the returned JSON. Only `run` needs a model. Use this instead of running `node self-test-runner.ts` directly.",
463
- args: {
464
- type: "object",
465
- properties: {
466
- action: {
467
- type: "string",
468
- enum: ["run", "status", "kill", "check_hap", "check_inputs", "check_pre"],
469
- description: "run=\u88C5 HAP + \u8DD1 batch\uFF08\u9700\u6A21\u578B\uFF09\uFF1Bstatus=\u63A2\u72B6\u6001\uFF1Bkill=\u7EC8\u6B62 batch\uFF1Bcheck_hap=\u6821\u9A8C hap_path\uFF1Bcheck_inputs=\u6821\u9A8C testcases+metadata\uFF1Bcheck_pre=\u6821\u9A8C [PRE] \u8FDE\u7EED"
470
- },
471
- // ── run ──
472
- testcases: { type: "string", description: "[run/check_inputs/check_pre] \u6D4B\u8BD5\u7528\u4F8B\u6587\u4EF6\uFF08JSON \u6570\u7EC4\u6216 JSONL\uFF09" },
473
- hap: { type: "string", description: "[run/check_hap] \u7B7E\u540D\u5305\uFF08.hap/.hsp \u6587\u4EF6\u3001\u76EE\u5F55\uFF0C\u6216\u9017\u53F7\u5206\u9694\u591A\u9879\uFF09" },
474
- bundleName: { type: "string", description: "[run] \u5305\u540D\uFF08bundle_name\uFF09" },
475
- taskDir: {
476
- type: "string",
477
- description: "[run/status/kill] \u4EFB\u52A1\u76EE\u5F55\uFF08run \u5185\u90E8\u5EFA task_<ts> \u5B50\u76EE\u5F55\uFF1B\u4E0D\u4F20\u5219\u9ED8\u8BA4 'task'\uFF09\u3002status/kill \u636E\u6B64\u627E batch.pid"
478
- },
479
- outputDir: { type: "string", description: "[run/status] \u65E5\u5FD7\u76EE\u5F55\uFF08\u4E0D\u4F20\u5219\u540C taskDir\uFF09" },
480
- category: { type: "string", description: "[run] \u6D4B\u8BD5\u5206\u7C7B\u540D\uFF0C\u4F20\u7ED9 batch-launcher" },
481
- timeout: {
482
- type: ["number", "string"],
483
- description: '[run] \u963B\u585E\u81F3\u7EC8\u6001\u6216\u8D85\u65F6\u3002\u6570\u503C=\u79D2\u6570\uFF1B"auto"=\u5F15\u64CE\u89E3\u6790 testcases \u540E\u6309\u7528\u4F8B\u6570\xD7720s \u81EA\u52A8\u63A8\u5BFC\uFF08\u6BCF\u4F8B 10min + 20% \u4F59\u91CF\uFF09\u3002\u4E0D\u4F20\u5219\u7ACB\u5373\u8FD4\u56DE RUNNING\uFF1B\u8D85\u65F6\u540E\u81EA\u52A8 kill batch \u5E76\u8FD4\u56DE TIMEOUT\uFF08exit 5\uFF09'
484
- },
485
- deviceSn: { type: "string", description: "[run] \u8BBE\u5907\u5E8F\u5217\u53F7\uFF08\u2192 AutoTestAgent.deviceSn\uFF09" },
486
- ip: { type: "string", description: "[run] \u8BBE\u5907 IP\uFF08\u2192 AutoTestAgent.ip\uFF09" },
487
- port: { type: "string", description: "[run] \u8BBE\u5907\u7AEF\u53E3\uFF08\u2192 AutoTestAgent.port\uFF09" },
488
- agentMode: { type: "string", description: "[run] agent \u6A21\u5F0F\uFF08\u9ED8\u8BA4 single\uFF09" },
489
- maxSteps: { type: "number", description: "[run] \u5355\u7528\u4F8B\u6700\u5927\u6B65\u6570" },
490
- promptVersion: { type: "string", description: "[run] prompt \u7248\u672C\uFF08\u9ED8\u8BA4 v2.0\uFF09" },
491
- // ── check_inputs ──
492
- metadata: { type: "string", description: "[check_inputs] app-metadata.json \u8DEF\u5F84" }
493
- },
494
- required: ["action"]
495
- },
496
- execute: async (args, context) => {
497
- const action = String(args.action ?? "");
498
- if (action === "run") {
499
- const testcases = String(args.testcases ?? "");
500
- const hap = String(args.hap ?? "");
501
- const bundleName = String(args.bundleName ?? "");
502
- if (!testcases || !hap || !bundleName) {
503
- throw new Error(`${TOOL_ID4}: \`action:"run"\` requires \`testcases\`, \`hap\`, \`bundleName\``);
504
- }
505
- const taskDir = String(args.taskDir ?? "task");
506
- const argv = [
507
- "run",
508
- "--testcases",
509
- testcases,
510
- "--hap",
511
- hap,
512
- "--bundle-name",
513
- bundleName,
514
- "--task-dir",
515
- taskDir,
516
- "--model-stdin"
517
- ];
518
- if (args.outputDir) argv.push("--output-dir", String(args.outputDir));
519
- if (args.category) argv.push("--category", String(args.category));
520
- if (args.deviceSn) argv.push("--device-sn", String(args.deviceSn));
521
- if (args.ip) argv.push("--ip", String(args.ip));
522
- if (args.port) argv.push("--port", String(args.port));
523
- if (args.agentMode) argv.push("--agent-mode", String(args.agentMode));
524
- if (args.maxSteps !== void 0 && args.maxSteps !== null) {
525
- argv.push("--max-steps", String(args.maxSteps));
526
- }
527
- if (args.promptVersion) argv.push("--prompt-version", String(args.promptVersion));
528
- if (args.timeout !== void 0 && args.timeout !== null) {
529
- argv.push("--timeout", String(args.timeout));
530
- }
531
- const model = await deps.resolveModelParams(context.worktree);
532
- if (!model) {
533
- throw new Error(
534
- `${TOOL_ID4}: \`action:"run"\` needs a model but deps.resolveModelParams returned null for worktree ${context.worktree ?? "(none)"} \u2014 configure the host's model provider`
535
- );
536
- }
537
- const stdin = JSON.stringify({
538
- apiKey: model.apiKey,
539
- modelName: model.modelName,
540
- baseURL: model.baseURL
541
- });
542
- const onAbortKill = () => {
543
- try {
544
- const env = { ...process.env };
545
- delete env.HOMETRANS_MODEL_API_KEY;
546
- delete env.HOMETRANS_MODEL_NAME;
547
- delete env.HOMETRANS_MODEL_BASE_URL;
548
- delete env.GLM_API_KEY;
549
- delete env.TEST_API_KEY;
550
- const k = spawn3(
551
- "node",
552
- [path9.join(AUTOTEST_ROOT, SCRIPT_REL4), "kill", "--task-dir", taskDir],
553
- { cwd: context.directory, env, stdio: "ignore", detached: true, windowsHide: true }
554
- );
555
- k.on("error", () => {
556
- });
557
- k.unref();
558
- } catch {
559
- }
560
- };
561
- if (!context.abort.aborted) {
562
- context.abort.addEventListener("abort", onAbortKill);
563
- }
564
- const r = await runAutotestScript({
565
- scriptRel: SCRIPT_REL4,
566
- argv,
567
- cwd: context.directory,
568
- abort: context.abort,
569
- stdin
570
- });
571
- context.abort.removeEventListener("abort", onAbortKill);
572
- if (r.spawnError) {
573
- throw new Error(`${TOOL_ID4}: failed to spawn node \u2014 ${r.spawnError}`);
574
- }
575
- return { ok: r.exitCode === 0, exitCode: r.exitCode, output: r.stdout };
576
- }
577
- if (action === "status") {
578
- const taskDir = String(args.taskDir ?? "");
579
- if (!taskDir) {
580
- throw new Error(`${TOOL_ID4}: \`action:"status"\` requires \`taskDir\``);
581
- }
582
- const argv = ["status", "--task-dir", taskDir];
583
- if (args.outputDir) argv.push("--output-dir", String(args.outputDir));
584
- const r = await runAutotestScript({
585
- scriptRel: SCRIPT_REL4,
586
- argv,
587
- cwd: context.directory,
588
- abort: context.abort
589
- });
590
- if (r.spawnError) {
591
- throw new Error(`${TOOL_ID4}: failed to spawn node \u2014 ${r.spawnError}`);
592
- }
593
- return { ok: r.exitCode === 0, exitCode: r.exitCode, output: r.stdout };
594
- }
595
- if (action === "kill") {
596
- const taskDir = String(args.taskDir ?? "");
597
- if (!taskDir) {
598
- throw new Error(`${TOOL_ID4}: \`action:"kill"\` requires \`taskDir\``);
599
- }
600
- const argv = ["kill", "--task-dir", taskDir];
601
- const r = await runAutotestScript({
602
- scriptRel: SCRIPT_REL4,
603
- argv,
604
- cwd: context.directory,
605
- abort: context.abort
606
- });
607
- if (r.spawnError) {
608
- throw new Error(`${TOOL_ID4}: failed to spawn node \u2014 ${r.spawnError}`);
609
- }
610
- return { ok: r.exitCode === 0, exitCode: r.exitCode, output: r.stdout };
611
- }
612
- if (action === "check_hap") {
613
- const hap = String(args.hap ?? "");
614
- if (!hap) {
615
- throw new Error(`${TOOL_ID4}: \`action:"check_hap"\` requires \`hap\``);
616
- }
617
- const argv = ["check-hap", "--hap", hap];
618
- const r = await runAutotestScript({
619
- scriptRel: SCRIPT_REL4,
620
- argv,
621
- cwd: context.directory,
622
- abort: context.abort
623
- });
624
- if (r.spawnError) {
625
- throw new Error(`${TOOL_ID4}: failed to spawn node \u2014 ${r.spawnError}`);
626
- }
627
- return { ok: r.exitCode === 0, exitCode: r.exitCode, output: r.stdout };
628
- }
629
- if (action === "check_inputs") {
630
- const testcases = String(args.testcases ?? "");
631
- const metadata = String(args.metadata ?? "");
632
- if (!testcases || !metadata) {
633
- throw new Error(`${TOOL_ID4}: \`action:"check_inputs"\` requires \`testcases\` and \`metadata\``);
634
- }
635
- const argv = ["check-inputs", "--testcases", testcases, "--metadata", metadata];
636
- const r = await runAutotestScript({
637
- scriptRel: SCRIPT_REL4,
638
- argv,
639
- cwd: context.directory,
640
- abort: context.abort
641
- });
642
- if (r.spawnError) {
643
- throw new Error(`${TOOL_ID4}: failed to spawn node \u2014 ${r.spawnError}`);
644
- }
645
- return { ok: r.exitCode === 0, exitCode: r.exitCode, output: r.stdout };
646
- }
647
- if (action === "check_pre") {
648
- const testcases = String(args.testcases ?? "");
649
- if (!testcases) {
650
- throw new Error(`${TOOL_ID4}: \`action:"check_pre"\` requires \`testcases\``);
651
- }
652
- const argv = ["check-pre", "--testcases", testcases];
653
- const r = await runAutotestScript({
654
- scriptRel: SCRIPT_REL4,
655
- argv,
656
- cwd: context.directory,
657
- abort: context.abort
658
- });
659
- if (r.spawnError) {
660
- throw new Error(`${TOOL_ID4}: failed to spawn node \u2014 ${r.spawnError}`);
661
- }
662
- return { ok: r.exitCode === 0, exitCode: r.exitCode, output: r.stdout };
663
- }
664
- throw new Error(
665
- `${TOOL_ID4}: unknown \`action\` "${action}" (expected run|status|kill|check_hap|check_inputs|check_pre)`
666
- );
667
- }
668
- };
669
- }
670
-
671
206
  // src/index.ts
672
207
  function createServer(deps) {
673
208
  return async (input) => {
674
- const skillsRoot = path10.join(PKG_ROOT, "skills");
675
- const agentsRoot = path10.join(PKG_ROOT, "agents");
209
+ const skillsRoot = path5.join(PKG_ROOT, "skills");
210
+ const agentsRoot = path5.join(PKG_ROOT, "agents");
676
211
  const agentPrompts = discoverA2HAgents(agentsRoot);
677
212
  return {
678
213
  dispose: async () => {
@@ -699,10 +234,10 @@ function createServer(deps) {
699
234
  }
700
235
  }
701
236
  },
702
- // ── shell.env hook: inject DevEco Studio paths + multimodal model ──
703
- // params (from A2HHostDeps.resolveModelParams) as env vars, so the
704
- // UI-alignment scripts (app_feature_verify.ts) can call the model
705
- // without falling back to ~/.hometrans/config.json.
237
+ // ── shell.env hook: inject DevEco Studio / SDK path vars only. The ──
238
+ // multimodal model apiKey is deliberately NOT put in env (it would leak
239
+ // to every adb/hdc descendant); the a2h_app_feature_verify tool pipes it
240
+ // to the script over stdin instead. See src/env.ts.
706
241
  "shell.env": async (shellInput, output) => {
707
242
  const a2hEnv = await buildA2HEnvBase(deps);
708
243
  Object.assign(output.env, a2hEnv);
@@ -711,21 +246,13 @@ function createServer(deps) {
711
246
  // model apiKey into env/argv — it is resolved from the host and piped to
712
247
  // the script over stdin. See src/tools/a2h-app-feature-verify.ts.
713
248
  //
714
- // The autotest_* tools wrap the engine scripts under tools/autotest/
715
- // (vendored from HomeTrans). They are grouped by noun each tool
716
- // dispatches on an `action` enum (e.g. `a2h_autotest_selftest` covers
717
- // run|status|kill|check_hap|check_inputs|check_pre), so 11 engine
718
- // subcommands surface as 4 plugin tools. Only `a2h_autotest_selftest`
719
- // with `action:"run"` needs a model, resolved via deps.resolveModelParams
720
- // and piped over stdin with the same secret-handling discipline; the
721
- // rest are pure JSON/Markdown transforms or state probes with no model
722
- // and no device.
249
+ // The AutoTest engine (selftest / testcases / report / resolve-metadata)
250
+ // is no longer vendored here it lives in the HomeTrans package and is
251
+ // invoked directly via `node` by agents/self-tester.md (see that file's
252
+ // "Resolving the AutoTest Tools Directory" section). a2h therefore ships
253
+ // only this one plugin tool and carries no autotest runtime dependency.
723
254
  tool: {
724
- a2h_app_feature_verify: makeA2hAppFeatureVerifyTool(deps),
725
- a2h_autotest_resolve_metadata: makeA2hAutotestResolveMetadataTool(deps),
726
- a2h_autotest_testcases: makeA2hAutotestTestcasesTool(deps),
727
- a2h_autotest_report: makeA2hAutotestReportTool(deps),
728
- a2h_autotest_selftest: makeA2hAutotestSelftestTool(deps)
255
+ a2h_app_feature_verify: makeA2hAppFeatureVerifyTool(deps)
729
256
  }
730
257
  };
731
258
  };