robot-resources 1.9.2 → 1.9.3

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.
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  findPython,
3
+ findOrInstallPython,
3
4
  ensureVenv,
4
5
  installRouter,
5
6
  isRouterInstalled,
@@ -7,22 +8,31 @@ import {
7
8
  } from '@robot-resources/cli-core/python-bridge.mjs';
8
9
 
9
10
  // Re-export shared primitives used by wizard.js and other CLI code.
10
- export { ensureVenv, isRouterInstalled, getVenvPythonPath };
11
+ export { findPython, ensureVenv, isRouterInstalled, getVenvPythonPath };
11
12
 
12
13
  /**
13
- * Full setup: find Python, create venv, install router.
14
- * Returns { venvPython, pythonVersion } or throws.
14
+ * Full setup: find Python (or bootstrap one via uv), create venv, install router.
15
+ *
16
+ * The uv-fallback path is what unblocks users without system Python. It
17
+ * downloads the uv binary to ~/.robot-resources/bin/ and uses it to
18
+ * install a standalone Python — nothing touches the user's system.
19
+ *
20
+ * Returns { venvPython, pythonVersion, pythonSource } or throws.
15
21
  */
16
22
  export async function setupRouter() {
17
- const python = findPython();
23
+ const python = await findOrInstallPython();
18
24
  if (!python) {
19
25
  throw new Error(
20
- 'Python 3.10+ not found. Install Python from https://python.org and try again.\n' +
21
- ' The Router requires Python. Scraper and MCP tools work without it.'
26
+ 'Python 3.10+ not found and uv bootstrap failed. ' +
27
+ 'Install Python from https://python.org and try again.'
22
28
  );
23
29
  }
24
30
 
25
31
  const venvPython = ensureVenv(python.bin);
26
32
  await installRouter();
27
- return { venvPython, pythonVersion: python.version };
33
+ return {
34
+ venvPython,
35
+ pythonVersion: python.version,
36
+ pythonSource: python.source, // 'system' | 'uv'
37
+ };
28
38
  }
package/lib/wizard.js CHANGED
@@ -158,24 +158,26 @@ export async function runWizard({ nonInteractive = false } = {}) {
158
158
  results.router = true;
159
159
  } else {
160
160
  const python = findPython();
161
- if (!python) {
162
- warn('Python 3.10+ not found — skipping Router installation');
163
- info('Install Python from https://python.org and re-run this wizard');
164
- info('Scraper works without Python');
165
- // Record the reason so install_complete tells us why router=false.
166
- results.routerError = { reason: 'python_not_found', detail: 'Python 3.10+ not detected on PATH' };
167
- } else {
161
+ if (python) {
168
162
  info(`Found Python ${python.version} (${python.bin})`);
169
- step('Installing Router (this may take a moment)...');
163
+ } else {
164
+ // No system Python — setupRouter() will bootstrap uv + install a
165
+ // standalone Python into ~/.robot-resources/. This used to be a hard
166
+ // fail; now it's the dominant auto-heal for the python_not_found
167
+ // cohort (2/3 of failures in recent telemetry).
168
+ warn('No system Python detected — bootstrapping one via uv.');
169
+ info('This downloads the uv binary (~15MB) and a managed Python to ~/.robot-resources/');
170
+ }
171
+ step('Installing Router (this may take a moment)...');
170
172
 
171
- try {
172
- await setupRouter();
173
- success('Router installed');
174
- results.router = true;
175
- } catch (err) {
176
- error(`Router installation failed: ${err.message}`);
177
- results.routerError = classifyRouterError(err);
178
- }
173
+ try {
174
+ const { pythonSource } = await setupRouter();
175
+ success(`Router installed${pythonSource === 'uv' ? ' (uv-managed Python)' : ''}`);
176
+ results.router = true;
177
+ results.pythonSource = pythonSource;
178
+ } catch (err) {
179
+ error(`Router installation failed: ${err.message}`);
180
+ results.routerError = classifyRouterError(err);
179
181
  }
180
182
  }
181
183
 
@@ -340,6 +342,12 @@ export async function runWizard({ nonInteractive = false } = {}) {
340
342
  scraper: results.scraper || false,
341
343
  source: 'wizard',
342
344
  };
345
+ if (results.pythonSource) {
346
+ // 'system' when the user had Python installed, 'uv' when we
347
+ // auto-bootstrapped one. Lets us measure how many installs were
348
+ // rescued by the uv fallback.
349
+ installPayload.pythonSource = results.pythonSource;
350
+ }
343
351
  if (results.routerError && typeof results.routerError === 'object') {
344
352
  installPayload.routerError = results.routerError.reason;
345
353
  installPayload.routerErrorDetail = results.routerError.detail;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "robot-resources",
3
- "version": "1.9.2",
3
+ "version": "1.9.3",
4
4
  "description": "Robot Resources — AI agent tools. One command to install everything.",
5
5
  "type": "module",
6
6
  "bin": {