yaver-cli 1.99.167 → 1.99.171
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 +1 -1
- package/src/agent-runtime.js +62 -3
package/package.json
CHANGED
package/src/agent-runtime.js
CHANGED
|
@@ -36,6 +36,25 @@ async function ensureAgentBinary({ quiet = false } = {}) {
|
|
|
36
36
|
const asset = await resolveAsset();
|
|
37
37
|
const localAgentPath = resolveLocalAgentBinary(asset);
|
|
38
38
|
if (localAgentPath) return localAgentPath;
|
|
39
|
+
// Defense in depth: if the cache holds a HIGHER version than
|
|
40
|
+
// what GH resolved, prefer it. Two failure modes this catches:
|
|
41
|
+
// 1. Older wrappers with the namespaced-tag-strip bug resolve
|
|
42
|
+
// to a stale legacy `v*` release even when newer `cli/v*`
|
|
43
|
+
// tags exist. Cache snapshot wins until npm catches up.
|
|
44
|
+
// 2. A new release publishes its tag but skips the platform
|
|
45
|
+
// asset (e.g. macOS notarize fails); falling back to a
|
|
46
|
+
// previously-cached newer build is better than running
|
|
47
|
+
// the older one.
|
|
48
|
+
const higherCached = findHigherCachedThan(asset.version);
|
|
49
|
+
if (higherCached) {
|
|
50
|
+
if (!quiet) {
|
|
51
|
+
console.error(
|
|
52
|
+
`[yaver] cache holds a newer agent (${higherCached.version}) than the resolved release ` +
|
|
53
|
+
`(${asset.version}); preferring cached binary.`,
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
return higherCached.path;
|
|
57
|
+
}
|
|
39
58
|
const installDir = path.join(CACHE_ROOT, asset.version, asset.cacheKey);
|
|
40
59
|
const binaryPath = path.join(installDir, asset.binaryName);
|
|
41
60
|
if (fs.existsSync(binaryPath)) {
|
|
@@ -62,6 +81,33 @@ async function ensureAgentBinary({ quiet = false } = {}) {
|
|
|
62
81
|
}
|
|
63
82
|
}
|
|
64
83
|
|
|
84
|
+
/** Walk CACHE_ROOT and return the path + version of any cached
|
|
85
|
+
* binary newer than `version` that matches this platform. Returns
|
|
86
|
+
* null when nothing higher is cached. Used as a "prefer-newer"
|
|
87
|
+
* override on top of the GH-resolved version. */
|
|
88
|
+
function findHigherCachedThan(version) {
|
|
89
|
+
if (!fs.existsSync(CACHE_ROOT)) return null;
|
|
90
|
+
if (!semver.valid(version)) return null;
|
|
91
|
+
const platform = process.platform;
|
|
92
|
+
const arch = process.arch;
|
|
93
|
+
const goArch = arch === 'x64' ? 'amd64' : arch === 'arm64' ? 'arm64' : arch;
|
|
94
|
+
const cacheKey = `${platform}-${goArch}`;
|
|
95
|
+
const binaryName = platform === 'win32' ? 'yaver.exe' : 'yaver';
|
|
96
|
+
const versions = fs.readdirSync(CACHE_ROOT).filter((v) => semver.valid(v));
|
|
97
|
+
versions.sort(semver.rcompare);
|
|
98
|
+
for (const v of versions) {
|
|
99
|
+
if (semver.lte(v, version)) break; // sorted desc; nothing higher remains
|
|
100
|
+
const p = path.join(CACHE_ROOT, v, cacheKey, binaryName);
|
|
101
|
+
if (fs.existsSync(p)) {
|
|
102
|
+
if (process.platform !== 'win32') {
|
|
103
|
+
try { fs.chmodSync(p, 0o755); } catch (_) {}
|
|
104
|
+
}
|
|
105
|
+
return { path: p, version: v };
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
|
|
65
111
|
/** Walk CACHE_ROOT and return the path to the newest yaver binary
|
|
66
112
|
* matching this platform — used as fallback when GH /releases is
|
|
67
113
|
* rate-limited and no specific version was resolvable. */
|
|
@@ -497,13 +543,13 @@ async function fetchRemoteAsset(platform, goArch) {
|
|
|
497
543
|
downloadName: asset.name,
|
|
498
544
|
archiveType: 'exe',
|
|
499
545
|
url: asset.browser_download_url,
|
|
500
|
-
version: release.tag_name
|
|
546
|
+
version: stripCliTagPrefix(release.tag_name),
|
|
501
547
|
};
|
|
502
548
|
}
|
|
503
549
|
|
|
504
550
|
if (platform === 'darwin' || platform === 'linux') {
|
|
505
551
|
const release = await fetchLatestRelease(DEFAULT_REPO);
|
|
506
|
-
const version = release.tag_name
|
|
552
|
+
const version = stripCliTagPrefix(release.tag_name);
|
|
507
553
|
const asset = findReleaseAsset(release, [
|
|
508
554
|
`yaver-v${version}-${platform}-${goArch}.tar.gz`,
|
|
509
555
|
`yaver-${platform}-${goArch}.tar.gz`,
|
|
@@ -525,6 +571,19 @@ async function fetchRemoteAsset(platform, goArch) {
|
|
|
525
571
|
throw new Error(`unsupported platform for npm bootstrap: ${platform}`);
|
|
526
572
|
}
|
|
527
573
|
|
|
574
|
+
// Strip the CLI release tag prefix and return the bare semver — or
|
|
575
|
+
// null if this isn't a CLI release at all. Tags now live in per-surface
|
|
576
|
+
// namespaces: `cli/v1.99.167`, `mobile/v1.18.91`, `web/v1.1.131`, etc.
|
|
577
|
+
// Pre-1.99.124 releases were just `v1.99.149`. Only those two shapes
|
|
578
|
+
// belong to the CLI; mobile/web/relay tags must NOT pass through, or
|
|
579
|
+
// `findReleaseAsset` will look for a yaver-linux-arm64 tarball on a
|
|
580
|
+
// mobile release and silently fail. Returning null here lets
|
|
581
|
+
// `semver.valid(stripCliTagPrefix(...))` filter non-CLI tags out.
|
|
582
|
+
function stripCliTagPrefix(tag) {
|
|
583
|
+
const match = String(tag || '').match(/^(?:cli\/)?v(.+)$/);
|
|
584
|
+
return match ? match[1] : null;
|
|
585
|
+
}
|
|
586
|
+
|
|
528
587
|
async function fetchLatestRelease(repo) {
|
|
529
588
|
const response = await request(`https://api.github.com/repos/${repo}/releases?per_page=20`, {
|
|
530
589
|
headers: {
|
|
@@ -545,7 +604,7 @@ async function fetchLatestRelease(repo) {
|
|
|
545
604
|
}
|
|
546
605
|
|
|
547
606
|
const latest = Array.isArray(releases)
|
|
548
|
-
? releases.find((release) => !release.draft && !release.prerelease && semver.valid(String(release.tag_name || '')
|
|
607
|
+
? releases.find((release) => !release.draft && !release.prerelease && semver.valid(stripCliTagPrefix(String(release.tag_name || ''))))
|
|
549
608
|
: null;
|
|
550
609
|
|
|
551
610
|
if (!latest || !latest.tag_name) {
|