@openagents-org/agent-launcher 0.2.184 → 0.2.185

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/src/wsl.js CHANGED
@@ -27,9 +27,10 @@
27
27
  * The mirror direction needs no marker: a path ending in .exe/.cmd/.bat while
28
28
  * we are running inside a distro is unambiguously a Windows binary.
29
29
  *
30
- * Cost: resolution never spawns wsl.exe per binary. One probe (5 min TTL) reads
31
- * the distro's login PATH, and every later lookup is a filesystem check through
32
- * the \\wsl.localhost UNC mount.
30
+ * Background resolution checks whether the default distro is already running
31
+ * before probing its login PATH or UNC mount. A stopped distro is left stopped;
32
+ * after the user starts it, the next scan can detect its CLIs. One PATH probe
33
+ * (5 min TTL) then serves later lookups through the \\wsl.localhost UNC mount.
33
34
  *
34
35
  * Inside the desktop app's main process none of that may block: starting
35
36
  * wsl.exe can mean booting the WSL VM, and the first touch of the UNC mount
@@ -53,6 +54,9 @@ const CACHE_TTL_MS = 30 * 1000;
53
54
  * the VM (and, in the desktop app, the window) busy for nothing.
54
55
  */
55
56
  const MACHINE_TTL_MS = 5 * 60 * 1000;
57
+ // A stopped distro must never be woken by background detection. Keep this
58
+ // short so a distro the user starts becomes visible on the next scan.
59
+ const RUNNING_TTL_MS = 2000;
56
60
 
57
61
  function _fresh(cache, ttl) {
58
62
  return !!cache.at && Date.now() - cache.at < ttl;
@@ -126,6 +130,8 @@ function isRunningInWsl() {
126
130
 
127
131
  let distrosCache = { value: null, at: 0 };
128
132
  let distrosRefresh = null;
133
+ let runningDistrosCache = { value: null, at: 0 };
134
+ let runningDistrosRefresh = null;
129
135
 
130
136
  function _parseDistros(buf) {
131
137
  return Buffer.from(buf)
@@ -203,6 +209,49 @@ function defaultDistro() {
203
209
  return wslDistros()[0] || null;
204
210
  }
205
211
 
212
+ function _refreshRunningDistros() {
213
+ if (_fresh(runningDistrosCache, RUNNING_TTL_MS)) return Promise.resolve();
214
+ if (!runningDistrosRefresh) {
215
+ runningDistrosRefresh = _execFileOut('wsl.exe', ['-l', '--running', '-q'], {
216
+ encoding: 'buffer', maxBuffer: 1024 * 1024,
217
+ })
218
+ .then((out) => { runningDistrosCache = { value: out ? _parseDistros(out) : [], at: Date.now() }; })
219
+ .finally(() => { runningDistrosRefresh = null; });
220
+ }
221
+ return runningDistrosRefresh;
222
+ }
223
+
224
+ /** Query WSL's management state without executing a command inside a distro. */
225
+ function _defaultDistroRunning() {
226
+ const distro = defaultDistro();
227
+ if (!distro) return false;
228
+ if (!_fresh(runningDistrosCache, RUNNING_TTL_MS)) {
229
+ if (!canBlock()) {
230
+ void _refreshRunningDistros();
231
+ } else {
232
+ let names = [];
233
+ try {
234
+ names = _parseDistros(execFileSync('wsl.exe', ['-l', '--running', '-q'], {
235
+ timeout: PROBE_TIMEOUT_MS,
236
+ windowsHide: true,
237
+ stdio: ['ignore', 'pipe', 'ignore'],
238
+ maxBuffer: 1024 * 1024,
239
+ }));
240
+ } catch { /* WSL unavailable: do not wake it */ }
241
+ runningDistrosCache = { value: names, at: Date.now() };
242
+ }
243
+ }
244
+ return (runningDistrosCache.value || []).includes(distro);
245
+ }
246
+
247
+ async function _defaultDistroRunningAsync() {
248
+ await _refreshDistros();
249
+ const distro = (distrosCache.value || [])[0];
250
+ if (!distro) return false;
251
+ await _refreshRunningDistros();
252
+ return (runningDistrosCache.value || []).includes(distro);
253
+ }
254
+
206
255
  // ---------------------------------------------------------------------------
207
256
  // Windows side: reaching into the distro's filesystem without starting one
208
257
  // ---------------------------------------------------------------------------
@@ -216,7 +265,7 @@ function _refreshUncRoot() {
216
265
  if (_fresh(uncRootCache, MACHINE_TTL_MS)) return Promise.resolve();
217
266
  if (!uncRootRefresh) {
218
267
  uncRootRefresh = (async () => {
219
- await _refreshDistros();
268
+ if (!(await _defaultDistroRunningAsync())) return;
220
269
  const distro = (distrosCache.value || [])[0];
221
270
  if (!distro) return;
222
271
  let root = null;
@@ -242,6 +291,7 @@ function _refreshUncRoot() {
242
291
  * WSL2 serves \\wsl.localhost\<distro>; WSL1 and older builds only \\wsl$\.
243
292
  */
244
293
  function _uncRoot() {
294
+ if (!_defaultDistroRunning()) return null;
245
295
  if (_fresh(uncRootCache, MACHINE_TTL_MS)) {
246
296
  return uncRootCache.value;
247
297
  }
@@ -334,8 +384,7 @@ function _refreshShellProbe() {
334
384
  if (_fresh(shellProbeCache, MACHINE_TTL_MS)) return Promise.resolve();
335
385
  if (!shellProbeRefresh) {
336
386
  shellProbeRefresh = (async () => {
337
- await _refreshDistros();
338
- if (!(distrosCache.value || []).length) return;
387
+ if (!(await _defaultDistroRunningAsync())) return;
339
388
  let out = null;
340
389
  for (const argv of SHELL_PROBE_ARGVS) {
341
390
  const raw = await _execFileOut('wsl.exe', argv, { encoding: 'utf-8', maxBuffer: 4 * 1024 * 1024 });
@@ -365,6 +414,7 @@ function _refreshShellProbe() {
365
414
  */
366
415
  function _shellProbe() {
367
416
  const empty = _emptyShellProbe();
417
+ if (!_defaultDistroRunning()) return empty;
368
418
  if (_fresh(shellProbeCache, MACHINE_TTL_MS)) {
369
419
  return shellProbeCache.value || empty;
370
420
  }
@@ -428,7 +478,7 @@ const wslBinaryRefresh = new Map();
428
478
  function _refreshWslBinary(key, list) {
429
479
  if (wslBinaryRefresh.has(key)) return wslBinaryRefresh.get(key);
430
480
  const job = (async () => {
431
- await _refreshDistros();
481
+ if (!(await _defaultDistroRunningAsync())) return;
432
482
  let value = null;
433
483
  if ((distrosCache.value || []).length) {
434
484
  await Promise.all([_refreshUncRoot(), _refreshShellProbe()]);
@@ -465,13 +515,14 @@ function _refreshWslBinary(key, list) {
465
515
  * Returns the path as the DISTRO sees it, behind the `wsl:` marker
466
516
  * (`wsl:/home/u/.local/bin/claude`) — the inner path is what `wsl.exe -e` must
467
517
  * be handed. Existence is proved through the UNC mount, so a machine with WSL
468
- * installed but no distro pays nothing beyond the single cached distro listing.
518
+ * installed but no running default distro pays only for WSL management queries.
469
519
  *
470
520
  * @param {string|string[]} names binary name(s), e.g. 'claude' or ['cursor-agent','agent']
471
521
  * @returns {string|null} marked in-distro path
472
522
  */
473
523
  function resolveWslBinary(names) {
474
524
  if (!IS_WINDOWS) return null;
525
+ if (!_defaultDistroRunning()) return null;
475
526
  const list = (Array.isArray(names) ? names : [names]).filter(Boolean);
476
527
  if (!list.length) return null;
477
528
  const key = list.join('\0');
@@ -520,6 +571,7 @@ function clearWslBinaryCache() {
520
571
  /** Full reset, including the per-process probes. For tests and rare rescans. */
521
572
  function clearWslCache() {
522
573
  distrosCache = { value: null, at: 0 };
574
+ runningDistrosCache = { value: null, at: 0 };
523
575
  uncRootCache = { value: null, at: 0 };
524
576
  shellProbeCache = { value: null, at: 0 };
525
577
  wslBinaryCache.clear();