neoagent 2.1.5 → 2.1.7
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/package.json
CHANGED
|
@@ -37,6 +37,6 @@ _flutter.buildConfig = {"engineRevision":"052f31d115eceda8cbff1b3481fcde4330c4ae
|
|
|
37
37
|
|
|
38
38
|
_flutter.loader.load({
|
|
39
39
|
serviceWorkerSettings: {
|
|
40
|
-
serviceWorkerVersion: "
|
|
40
|
+
serviceWorkerVersion: "204310170" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
|
|
41
41
|
}
|
|
42
42
|
});
|
|
@@ -47,6 +47,18 @@ function sleep(ms) {
|
|
|
47
47
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
function tailFile(filePath, maxLines = 40) {
|
|
51
|
+
try {
|
|
52
|
+
const lines = fs.readFileSync(filePath, 'utf8')
|
|
53
|
+
.split('\n')
|
|
54
|
+
.map((line) => line.trim())
|
|
55
|
+
.filter(Boolean);
|
|
56
|
+
return lines.slice(-maxLines);
|
|
57
|
+
} catch {
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
50
62
|
function commandExists(command) {
|
|
51
63
|
const probe = spawnSync('bash', ['-lc', `command -v "${command}"`], { encoding: 'utf8' });
|
|
52
64
|
return probe.status === 0;
|
|
@@ -270,25 +282,75 @@ function systemImageTagScore(tag) {
|
|
|
270
282
|
return 0;
|
|
271
283
|
}
|
|
272
284
|
|
|
285
|
+
function parseSystemImageCandidates(entries = []) {
|
|
286
|
+
return entries.map((entry) => {
|
|
287
|
+
const platform = parseSystemImagePlatform(entry.platformId);
|
|
288
|
+
return {
|
|
289
|
+
packageName: entry.packageName,
|
|
290
|
+
platformId: entry.platformId,
|
|
291
|
+
tag: entry.tag,
|
|
292
|
+
arch: entry.arch,
|
|
293
|
+
apiLevel: platform.apiLevel,
|
|
294
|
+
stable: platform.stable,
|
|
295
|
+
tagScore: systemImageTagScore(entry.tag),
|
|
296
|
+
};
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
|
|
273
300
|
function parseSystemImages(listOutput) {
|
|
274
301
|
const matches = [];
|
|
275
302
|
const regex = /system-images;(android-[^;\s]+);([^;\s]+);([^;\s]+)/g;
|
|
276
303
|
let match = regex.exec(listOutput);
|
|
277
304
|
while (match) {
|
|
278
|
-
const platform = parseSystemImagePlatform(match[1]);
|
|
279
305
|
matches.push({
|
|
280
306
|
packageName: match[0],
|
|
281
307
|
platformId: match[1],
|
|
282
308
|
tag: match[2],
|
|
283
309
|
arch: match[3],
|
|
284
|
-
apiLevel: platform.apiLevel,
|
|
285
|
-
stable: platform.stable,
|
|
286
|
-
tagScore: systemImageTagScore(match[2]),
|
|
287
310
|
});
|
|
288
311
|
match = regex.exec(listOutput);
|
|
289
312
|
}
|
|
290
313
|
|
|
291
|
-
return matches;
|
|
314
|
+
return parseSystemImageCandidates(matches);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function parseInstalledSystemImages() {
|
|
318
|
+
const root = path.join(SDK_ROOT, 'system-images');
|
|
319
|
+
if (!fs.existsSync(root)) {
|
|
320
|
+
return [];
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
const matches = [];
|
|
324
|
+
const platforms = fs.readdirSync(root, { withFileTypes: true })
|
|
325
|
+
.filter((entry) => entry.isDirectory())
|
|
326
|
+
.map((entry) => entry.name);
|
|
327
|
+
|
|
328
|
+
for (const platformId of platforms) {
|
|
329
|
+
const platformDir = path.join(root, platformId);
|
|
330
|
+
const tags = fs.readdirSync(platformDir, { withFileTypes: true })
|
|
331
|
+
.filter((entry) => entry.isDirectory())
|
|
332
|
+
.map((entry) => entry.name);
|
|
333
|
+
for (const tag of tags) {
|
|
334
|
+
const tagDir = path.join(platformDir, tag);
|
|
335
|
+
const archs = fs.readdirSync(tagDir, { withFileTypes: true })
|
|
336
|
+
.filter((entry) => entry.isDirectory())
|
|
337
|
+
.map((entry) => entry.name);
|
|
338
|
+
for (const arch of archs) {
|
|
339
|
+
const packageXml = path.join(tagDir, arch, 'package.xml');
|
|
340
|
+
if (!fs.existsSync(packageXml)) {
|
|
341
|
+
continue;
|
|
342
|
+
}
|
|
343
|
+
matches.push({
|
|
344
|
+
packageName: `system-images;${platformId};${tag};${arch}`,
|
|
345
|
+
platformId,
|
|
346
|
+
tag,
|
|
347
|
+
arch,
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
return parseSystemImageCandidates(matches);
|
|
292
354
|
}
|
|
293
355
|
|
|
294
356
|
function rankSystemImagePool(pool) {
|
|
@@ -297,8 +359,8 @@ function rankSystemImagePool(pool) {
|
|
|
297
359
|
|
|
298
360
|
rankedPool.sort((a, b) =>
|
|
299
361
|
Number(b.stable) - Number(a.stable) ||
|
|
300
|
-
b.apiLevel - a.apiLevel ||
|
|
301
362
|
b.tagScore - a.tagScore ||
|
|
363
|
+
b.apiLevel - a.apiLevel ||
|
|
302
364
|
a.packageName.localeCompare(b.packageName)
|
|
303
365
|
);
|
|
304
366
|
|
|
@@ -306,7 +368,9 @@ function rankSystemImagePool(pool) {
|
|
|
306
368
|
}
|
|
307
369
|
|
|
308
370
|
function chooseConfiguredSystemImage(listOutput) {
|
|
309
|
-
const matches =
|
|
371
|
+
const matches = Array.isArray(listOutput)
|
|
372
|
+
? parseSystemImageCandidates(listOutput)
|
|
373
|
+
: parseSystemImages(listOutput);
|
|
310
374
|
const packageName = configuredSystemImagePackage();
|
|
311
375
|
if (packageName) {
|
|
312
376
|
return matches.find((candidate) => candidate.packageName === packageName) || null;
|
|
@@ -328,7 +392,9 @@ function chooseConfiguredSystemImage(listOutput) {
|
|
|
328
392
|
}
|
|
329
393
|
|
|
330
394
|
function chooseLatestSystemImage(listOutput, preferredArchs = systemImageArchCandidates()) {
|
|
331
|
-
const matches =
|
|
395
|
+
const matches = Array.isArray(listOutput)
|
|
396
|
+
? parseSystemImageCandidates(listOutput)
|
|
397
|
+
: parseSystemImages(listOutput);
|
|
332
398
|
const archPool = Array.isArray(preferredArchs) && preferredArchs.length > 0
|
|
333
399
|
? preferredArchs
|
|
334
400
|
: systemImageArchCandidates();
|
|
@@ -347,7 +413,10 @@ function chooseLatestSystemImage(listOutput, preferredArchs = systemImageArchCan
|
|
|
347
413
|
}
|
|
348
414
|
|
|
349
415
|
function formatSystemImageError(listOutput) {
|
|
350
|
-
const
|
|
416
|
+
const candidates = Array.isArray(listOutput)
|
|
417
|
+
? parseSystemImageCandidates(listOutput)
|
|
418
|
+
: parseSystemImages(listOutput);
|
|
419
|
+
const availableArchs = [...new Set(candidates.map((candidate) => candidate.arch))].sort();
|
|
351
420
|
const wantedArchs = systemImageArchCandidates().join(', ');
|
|
352
421
|
const packageName = configuredSystemImagePackage();
|
|
353
422
|
const platformId = configuredSystemImagePlatform();
|
|
@@ -489,12 +558,27 @@ class AndroidController {
|
|
|
489
558
|
}
|
|
490
559
|
|
|
491
560
|
const state = readState();
|
|
492
|
-
if (
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
561
|
+
if (!shouldForceSdkRefresh()) {
|
|
562
|
+
const installedImages = parseInstalledSystemImages();
|
|
563
|
+
if (installedImages.length > 0) {
|
|
564
|
+
const preferredInstalled =
|
|
565
|
+
chooseConfiguredSystemImage(installedImages) ||
|
|
566
|
+
chooseLatestSystemImage(installedImages);
|
|
567
|
+
if (
|
|
568
|
+
preferredInstalled &&
|
|
569
|
+
preferredInstalled.packageName !== state.systemImage
|
|
570
|
+
) {
|
|
571
|
+
appendState({
|
|
572
|
+
bootstrapped: true,
|
|
573
|
+
systemImage: preferredInstalled.packageName,
|
|
574
|
+
apiLevel: preferredInstalled.apiLevel,
|
|
575
|
+
systemImageArch: preferredInstalled.arch,
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
return;
|
|
579
|
+
} else if (state.bootstrapped === true && state.systemImage) {
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
498
582
|
}
|
|
499
583
|
|
|
500
584
|
appendState({ bootstrapped: true });
|
|
@@ -693,7 +777,6 @@ class AndroidController {
|
|
|
693
777
|
stdio: ['ignore', out, out],
|
|
694
778
|
env: sdkEnv(),
|
|
695
779
|
});
|
|
696
|
-
child.unref();
|
|
697
780
|
|
|
698
781
|
console.log(`[Android] Emulator process started (pid ${child.pid})`);
|
|
699
782
|
appendState({
|
|
@@ -706,7 +789,38 @@ class AndroidController {
|
|
|
706
789
|
lastLogLine: 'Android emulator process started. Waiting for boot completion...',
|
|
707
790
|
});
|
|
708
791
|
|
|
709
|
-
const
|
|
792
|
+
const processExit = new Promise((resolve) => {
|
|
793
|
+
child.once('exit', (code, signal) => {
|
|
794
|
+
resolve({ code, signal });
|
|
795
|
+
});
|
|
796
|
+
child.once('error', (error) => {
|
|
797
|
+
resolve({ code: null, signal: null, error });
|
|
798
|
+
});
|
|
799
|
+
});
|
|
800
|
+
|
|
801
|
+
child.unref();
|
|
802
|
+
|
|
803
|
+
const bootResult = await Promise.race([
|
|
804
|
+
this.waitForDevice({ timeoutMs: options.timeoutMs || 240000 }).then((serial) => ({
|
|
805
|
+
serial,
|
|
806
|
+
exited: false,
|
|
807
|
+
})),
|
|
808
|
+
processExit.then((result) => ({
|
|
809
|
+
exited: true,
|
|
810
|
+
...result,
|
|
811
|
+
})),
|
|
812
|
+
]);
|
|
813
|
+
|
|
814
|
+
if (bootResult.exited) {
|
|
815
|
+
const recentLogLines = tailFile(logPath, 12);
|
|
816
|
+
const lastLine =
|
|
817
|
+
bootResult.error?.message ||
|
|
818
|
+
recentLogLines[recentLogLines.length - 1] ||
|
|
819
|
+
`Emulator process exited before boot completed (code ${bootResult.code ?? 'unknown'}, signal ${bootResult.signal ?? 'none'}).`;
|
|
820
|
+
throw new Error(lastLine);
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
const onlineSerial = bootResult.serial;
|
|
710
824
|
appendState({
|
|
711
825
|
serial: onlineSerial,
|
|
712
826
|
emulatorPid: child.pid,
|
|
@@ -772,14 +886,17 @@ class AndroidController {
|
|
|
772
886
|
lastLogLine: 'Android start requested.',
|
|
773
887
|
});
|
|
774
888
|
const startPromise = this.#startEmulatorBlocking(options).catch((err) => {
|
|
889
|
+
const state = readState();
|
|
890
|
+
const recentLogLines = state.logPath ? tailFile(state.logPath, 12) : [];
|
|
891
|
+
const detailedMessage = recentLogLines[recentLogLines.length - 1] || err.message;
|
|
775
892
|
appendState({
|
|
776
893
|
starting: false,
|
|
777
894
|
startupPhase: 'Start failed',
|
|
778
|
-
lastStartError:
|
|
779
|
-
lastLogLine:
|
|
895
|
+
lastStartError: detailedMessage,
|
|
896
|
+
lastLogLine: detailedMessage,
|
|
780
897
|
});
|
|
781
|
-
console.error('[Android] Emulator start failed:',
|
|
782
|
-
throw
|
|
898
|
+
console.error('[Android] Emulator start failed:', detailedMessage);
|
|
899
|
+
throw new Error(detailedMessage);
|
|
783
900
|
}).finally(() => {
|
|
784
901
|
if (this.startPromise === startPromise) {
|
|
785
902
|
this.startPromise = null;
|