yaver-cli 1.99.360 → 1.99.368
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 +61 -1
package/package.json
CHANGED
package/src/agent-runtime.js
CHANGED
|
@@ -59,7 +59,15 @@ async function ensureAgentBinary({ quiet = false } = {}) {
|
|
|
59
59
|
const binaryPath = path.join(installDir, asset.binaryName);
|
|
60
60
|
if (fs.existsSync(binaryPath)) {
|
|
61
61
|
if (process.platform !== 'win32') fs.chmodSync(binaryPath, 0o755);
|
|
62
|
-
return binaryPath;
|
|
62
|
+
if (cachedBinaryRuns(binaryPath)) return binaryPath;
|
|
63
|
+
// Present but unusable: re-download rather than hand back a brick. The
|
|
64
|
+
// old code returned it on existence alone, so one interrupted download
|
|
65
|
+
// wedged that version forever — every later run found the file, returned
|
|
66
|
+
// it, and failed identically with nothing to point at.
|
|
67
|
+
if (!quiet) {
|
|
68
|
+
console.error(`[yaver] cached agent ${asset.version} is present but will not run — re-downloading`);
|
|
69
|
+
}
|
|
70
|
+
try { fs.rmSync(installDir, { recursive: true, force: true }); } catch (_) {}
|
|
63
71
|
}
|
|
64
72
|
return await downloadAndCacheAgent(asset, { quiet });
|
|
65
73
|
} catch (err) {
|
|
@@ -81,6 +89,44 @@ async function ensureAgentBinary({ quiet = false } = {}) {
|
|
|
81
89
|
}
|
|
82
90
|
}
|
|
83
91
|
|
|
92
|
+
/** A cached agent binary is only usable if it actually RUNS.
|
|
93
|
+
*
|
|
94
|
+
* `fs.existsSync` answers "is there a file here", which is a proxy for the
|
|
95
|
+
* thing we need: "can this machine exec it and get a version back". The two
|
|
96
|
+
* disagree in exactly the cases that matter — an interrupted download leaves a
|
|
97
|
+
* truncated file, a killed extract leaves a 0-byte one, an unsigned or
|
|
98
|
+
* quarantined binary on macOS exists and refuses to launch. Every one of those
|
|
99
|
+
* passes existsSync and then dies at spawn with a bare exit code and nothing
|
|
100
|
+
* said (observed 2026-07-25: a launchd agent flapping on status 78 because its
|
|
101
|
+
* version dir held no binary — the operator sees "the daemon won't start" and
|
|
102
|
+
* no reason anywhere).
|
|
103
|
+
*
|
|
104
|
+
* So probe the operation: run `--version` with a short timeout. Cheap (single
|
|
105
|
+
* exec, no network) and it turns a silent brick into a fall back onto the last
|
|
106
|
+
* binary that demonstrably works. */
|
|
107
|
+
function cachedBinaryRuns(binaryPath) {
|
|
108
|
+
try {
|
|
109
|
+
const st = fs.statSync(binaryPath);
|
|
110
|
+
// A real agent is tens of MB; anything tiny is a truncated download, and
|
|
111
|
+
// exec'ing it would just be a slower way to learn that.
|
|
112
|
+
if (!st.isFile() || st.size < 1024 * 1024) return false;
|
|
113
|
+
} catch (_) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
try {
|
|
117
|
+
const res = spawnSync(binaryPath, ['--version'], {
|
|
118
|
+
timeout: 10_000,
|
|
119
|
+
encoding: 'utf8',
|
|
120
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
121
|
+
});
|
|
122
|
+
if (res.error) return false;
|
|
123
|
+
if (res.status !== 0) return false;
|
|
124
|
+
return /\byaver\b/i.test(String(res.stdout || '') + String(res.stderr || ''));
|
|
125
|
+
} catch (_) {
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
84
130
|
/** Walk CACHE_ROOT and return the path + version of any cached
|
|
85
131
|
* binary newer than `version` that matches this platform. Returns
|
|
86
132
|
* null when nothing higher is cached. Used as a "prefer-newer"
|
|
@@ -102,6 +148,13 @@ function findHigherCachedThan(version) {
|
|
|
102
148
|
if (process.platform !== 'win32') {
|
|
103
149
|
try { fs.chmodSync(p, 0o755); } catch (_) {}
|
|
104
150
|
}
|
|
151
|
+
// Verify before preferring it: a broken NEWER cache entry must not
|
|
152
|
+
// shadow a working older one. Skipping this is how "prefer newest"
|
|
153
|
+
// becomes "prefer whatever downloaded halfway".
|
|
154
|
+
if (!cachedBinaryRuns(p)) {
|
|
155
|
+
console.error(`[yaver] cached agent ${v} will not run (incomplete download?) — skipping it`);
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
105
158
|
return { path: p, version: v };
|
|
106
159
|
}
|
|
107
160
|
}
|
|
@@ -126,6 +179,13 @@ function findMostRecentCachedAgent() {
|
|
|
126
179
|
if (process.platform !== 'win32') {
|
|
127
180
|
try { fs.chmodSync(p, 0o755); } catch (_) {}
|
|
128
181
|
}
|
|
182
|
+
// This is the offline/rate-limited fallback — the LAST thing standing
|
|
183
|
+
// between the user and "yaver does nothing". Returning a file that
|
|
184
|
+
// cannot exec here produces a bare failure with no network to blame.
|
|
185
|
+
if (!cachedBinaryRuns(p)) {
|
|
186
|
+
console.error(`[yaver] cached agent ${v} will not run (incomplete download?) — trying an older one`);
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
129
189
|
return p;
|
|
130
190
|
}
|
|
131
191
|
}
|