@xaidenlabs/uso 1.1.81 → 1.1.83

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/README.md CHANGED
@@ -10,6 +10,7 @@ USO is a zero-friction CLI toolchain that installs, manages, and runs your entir
10
10
 
11
11
  - [Installation](#installation)
12
12
  - [Quick Start](#quick-start)
13
+ - [AI Agent (New)](#ai-agent-new)
13
14
  - [Stealth WSL Mode (Windows)](#stealth-wsl-mode-windows)
14
15
  - [Full Environment Setup](#full-environment-setup)
15
16
  - [Granular Installation](#granular-installation)
@@ -66,6 +67,48 @@ uso dev
66
67
 
67
68
  ---
68
69
 
70
+ ## AI Agent (New)
71
+
72
+ USO isn't just a command runner — it's an **Autonomous AI Agent** that can write code, build programs, debug errors, and deploy. Powered by ReAct (Reason + Act) architecture, the agent thinks step-by-step and uses tools to accomplish your goals.
73
+
74
+ ### 1. Configure an LLM Provider
75
+
76
+ The agent needs an LLM to think. It supports four providers out of the box:
77
+
78
+ ```bash
79
+ # Option A: Local & Free (Ollama)
80
+ # Install from ollama.com, then run:
81
+ ollama pull llama3.1:8b
82
+
83
+ # Option B: GitHub Models (Free with GitHub Account)
84
+ uso agent-config --github-token <your-github-pat>
85
+
86
+ # Option C: Gemini
87
+ uso agent-config --gemini-key <your-api-key>
88
+
89
+ # Option D: OpenAI
90
+ uso agent-config --openai-key <your-api-key>
91
+ ```
92
+
93
+ ### 2. Give it a Goal
94
+
95
+ Just tell the agent what you want to do. It will check your environment, plan a strategy, execute the commands, and automatically self-heal if any step fails.
96
+
97
+ ```bash
98
+ # General environment fixing
99
+ uso agent "Check my Solana development environment and fix any missing tools"
100
+
101
+ # Build and test cycle
102
+ uso agent "Build my program and run the tests. If tests fail, fix the errors."
103
+
104
+ # Deployment
105
+ uso agent "Deploy my staking program to devnet and airdrop SOL if I don't have enough."
106
+ ```
107
+
108
+ The agent runs a continuous FSM loop (`plan` → `execute` → `validate` → `heal`), streaming its thoughts and actions directly to your terminal.
109
+
110
+ ---
111
+
69
112
  ## Stealth WSL Mode (Windows Only)
70
113
 
71
114
  **The recommended mode for Windows developers.** Stealth Mode deploys a hidden WSL2 Linux environment (the "Uso Engine") that runs all your tooling inside Linux while you stay in PowerShell.
@@ -397,6 +440,8 @@ npm uninstall -g @xaidenlabs/uso
397
440
  | `uso init rust` | `uso install rust` | Install Rust only |
398
441
  | `uso init solana` | `uso install solana` | Install Solana CLI only |
399
442
  | `uso init anchor` | `uso install anchor` | Install Anchor Framework only |
443
+ | `uso agent <goal>` | — | Run the Autonomous AI Agent |
444
+ | `uso agent-config` | — | Configure Agent LLM providers |
400
445
  | `uso doctor` | — | Diagnose environment |
401
446
  | `uso verify` | — | End-to-end verification build |
402
447
  | `uso create <name>` | — | Scaffold a new Anchor project |
package/bin/index.js CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
  const { program } = require('commander');
3
3
  const { init } = require('../src/commands/init');
4
4
  const { doctor } = require('../src/commands/doctor');
@@ -6,6 +6,7 @@ const { verify } = require('../src/commands/verify');
6
6
  const { create } = require('../src/commands/create');
7
7
  const { build, test, deploy, clean, unblock, airdrop, address, balance, validator, dev } = require('../src/commands/workflow');
8
8
  const { uninstall } = require('../src/commands/uninstall');
9
+ const { agent, agentConfig } = require('../src/commands/agent');
9
10
 
10
11
  program
11
12
  .name('uso')
@@ -101,4 +102,21 @@ program
101
102
  .description('Uninstall uso components (rust, solana, anchor) or all')
102
103
  .action(uninstall);
103
104
 
105
+ program
106
+ .command('agent [goal...]')
107
+ .description('Start the AI Agent to accomplish a goal autonomously')
108
+ .option('--model <model>', 'LLM model to use (e.g., llama3.1:8b, gemini-2.0-flash, openai/gpt-4o)')
109
+ .option('--provider <provider>', 'Force a specific LLM provider (ollama, gemini, openai, github)')
110
+ .option('--max-loops <n>', 'Maximum reasoning iterations', '3')
111
+ .option('--verbose', 'Show full reasoning traces')
112
+ .action(agent);
113
+
114
+ program
115
+ .command('agent-config')
116
+ .description('Configure API keys and preferences for the AI Agent')
117
+ .option('--gemini-key <key>', 'Set Gemini API key')
118
+ .option('--openai-key <key>', 'Set OpenAI API key')
119
+ .option('--github-token <token>', 'Set GitHub Models PAT token')
120
+ .action(agentConfig);
121
+
104
122
  program.parse(process.argv);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xaidenlabs/uso",
3
- "version": "1.1.81",
3
+ "version": "1.1.83",
4
4
  "description": "Universal Solana Development Toolchain. Native or Stealth WSL Mode. Build, test, and deploy without the friction.",
5
5
  "bin": {
6
6
  "uso": "bin/index.js"
@@ -0,0 +1,295 @@
1
+ const os = require("os");
2
+ const path = require("path");
3
+ const chalk = require("chalk");
4
+ const { log, spinner } = require("../utils/logger");
5
+
6
+ /**
7
+ * `uso agent "<goal>"` — Run the AI Agent to accomplish a goal.
8
+ *
9
+ * This command handler:
10
+ * 1. Loads agent config from ~/.uso-agent.json
11
+ * 2. Resolves an LLM provider (Ollama → GitHub → Gemini → OpenAI)
12
+ * 3. Runs the ReAct FSM loop
13
+ * 4. Streams reasoning + actions to the terminal with styled output
14
+ */
15
+ const agent = async (goalParts, options) => {
16
+ // Commander passes args differently depending on definition
17
+ const goalArray = Array.isArray(goalParts) ? goalParts : [goalParts];
18
+ const goal = goalArray.filter(Boolean).join(" ").trim();
19
+
20
+ if (!goal) {
21
+ log.error("❌ No goal provided.");
22
+ log.info('Usage: uso agent "Deploy my staking program to devnet"');
23
+ log.info(' uso agent "Check my environment and fix any issues"');
24
+ log.info(' uso agent "Build and test my program"');
25
+ return;
26
+ }
27
+
28
+ // Dynamic import of uso-core (ESM from CJS)
29
+ let UsoAgent, loadAgentConfig;
30
+ try {
31
+ const core = require("../../packages/uso-core/dist/cjs/index.js");
32
+ UsoAgent = core.UsoAgent;
33
+ loadAgentConfig = core.loadAgentConfig;
34
+ } catch (err) {
35
+ log.error("❌ uso-core agent module not found.");
36
+ log.warn(
37
+ "Run 'cd packages/uso-core && npm run build' to compile the agent.",
38
+ );
39
+ log.warn(`Detail: ${err.message}`);
40
+ return;
41
+ }
42
+
43
+ const config = loadAgentConfig();
44
+
45
+ // Override config from CLI flags
46
+ if (options.model) {
47
+ // Try to infer provider from model name
48
+ if (options.model.includes("/")) {
49
+ // GitHub Models format: "openai/gpt-4o-mini"
50
+ config.github = { ...config.github, model: options.model };
51
+ } else if (options.model.startsWith("gemini")) {
52
+ config.gemini = { ...config.gemini, model: options.model };
53
+ } else if (
54
+ options.model.startsWith("gpt") ||
55
+ options.model.startsWith("o1") ||
56
+ options.model.startsWith("o3")
57
+ ) {
58
+ config.openai = { ...config.openai, model: options.model };
59
+ } else {
60
+ config.ollama = { ...config.ollama, model: options.model };
61
+ }
62
+ }
63
+
64
+ const maxLoops = parseInt(options.maxLoops || "3", 10);
65
+
66
+ // ─── Banner ────────────────────────────────────────────────
67
+ console.log();
68
+ console.log(
69
+ chalk.bold.cyan(" ┌─────────────────────────────────────────┐"),
70
+ );
71
+ console.log(
72
+ chalk.bold.cyan(" │") +
73
+ chalk.bold.white(" USO Agent v1.0 ") +
74
+ chalk.bold.cyan("│"),
75
+ );
76
+ console.log(
77
+ chalk.bold.cyan(" │") +
78
+ chalk.dim(" Autonomous Solana DevOps Engine ") +
79
+ chalk.bold.cyan("│"),
80
+ );
81
+ console.log(
82
+ chalk.bold.cyan(" └─────────────────────────────────────────┘"),
83
+ );
84
+ console.log();
85
+ console.log(chalk.dim(" Goal: ") + chalk.white.bold(goal));
86
+ console.log(chalk.dim(" Max iterations: ") + chalk.yellow(maxLoops));
87
+ console.log();
88
+
89
+ // ─── FSM Callbacks (render to terminal) ────────────────────
90
+ const callbacks = {
91
+ onPhaseChange: (phase, state) => {
92
+ const phases = {
93
+ planning: "🧠 Planning",
94
+ executing: "⚡ Executing",
95
+ validating: "✅ Validating",
96
+ healing: "🔧 Self-Healing",
97
+ };
98
+ if (phases[phase]) {
99
+ console.log(chalk.dim(` ── ${phases[phase]} ──`));
100
+ }
101
+ },
102
+
103
+ onThought: (thought, state) => {
104
+ console.log(chalk.blue(" 💭 ") + chalk.italic(thought));
105
+ },
106
+
107
+ onToolCall: (toolName, params, state) => {
108
+ const paramStr = Object.keys(params).length > 0
109
+ ? chalk.dim(` ${JSON.stringify(params).slice(0, 80)}`)
110
+ : "";
111
+ console.log(chalk.yellow(" 🔧 ") + chalk.bold(toolName) + paramStr);
112
+ },
113
+
114
+ onObservation: (observation, success, state) => {
115
+ const lines = observation.split("\n").slice(0, 10);
116
+ const color = success ? chalk.green : chalk.red;
117
+ const icon = success ? " ✅ " : " ❌ ";
118
+
119
+ for (const line of lines) {
120
+ if (line.trim()) {
121
+ console.log(color(icon + line.trim().slice(0, 120)));
122
+ }
123
+ }
124
+ if (observation.split("\n").length > 10) {
125
+ console.log(chalk.dim(" ... (output truncated)"));
126
+ }
127
+ },
128
+
129
+ onIteration: (iteration, maxIterations, state) => {
130
+ console.log(
131
+ chalk.dim(`\n ─── Iteration ${iteration}/${maxIterations} ───`),
132
+ );
133
+ },
134
+
135
+ onComplete: (summary, state) => {
136
+ console.log();
137
+ console.log(chalk.green.bold(" ✅ GOAL ACCOMPLISHED"));
138
+ console.log(chalk.green(" " + summary));
139
+ console.log();
140
+ },
141
+
142
+ onFailed: (reason, state) => {
143
+ console.log();
144
+ console.log(chalk.red.bold(" ❌ GOAL FAILED"));
145
+ console.log(chalk.red(" " + reason));
146
+ console.log();
147
+ },
148
+ };
149
+
150
+ // ─── Run Agent ─────────────────────────────────────────────
151
+ const spin = spinner("Resolving LLM provider...").start();
152
+
153
+ try {
154
+ const usoAgent = new UsoAgent(config);
155
+
156
+ // Resolve LLM first to show which provider is being used
157
+ const llmDiag = await usoAgent.diagnoseLlm();
158
+ const available = llmDiag.filter((d) => d.available);
159
+
160
+ if (available.length === 0) {
161
+ spin.fail("No LLM provider available.");
162
+ console.log();
163
+ log.error("The USO Agent needs at least one LLM to reason.");
164
+ console.log();
165
+ log.info("Options (pick any):");
166
+ log.info(" 1. Install Ollama (free, local): https://ollama.com");
167
+ log.info(" Then run: ollama pull llama3.1:8b");
168
+ log.info(
169
+ " 2. uso agent-config --github-token <your-github-pat>",
170
+ );
171
+ log.info(
172
+ " 3. uso agent-config --gemini-key <your-api-key>",
173
+ );
174
+ log.info(
175
+ " 4. uso agent-config --openai-key <your-api-key>",
176
+ );
177
+ return;
178
+ }
179
+
180
+ spin.succeed(
181
+ `LLM: ${chalk.bold(available[0].name)} ${chalk.dim(`(${available.length} provider${available.length > 1 ? "s" : ""} available)`)}`,
182
+ );
183
+
184
+ // Run the agent
185
+ const result = await usoAgent.run({
186
+ goal,
187
+ provider: options.provider,
188
+ maxIterations: maxLoops,
189
+ verbose: !!options.verbose,
190
+ callbacks,
191
+ });
192
+
193
+ // ─── Summary ───────────────────────────────────────────
194
+ console.log(chalk.dim(" ─────────────────────────────────────────"));
195
+ console.log(
196
+ chalk.dim(" Provider: ") + chalk.white(result.llmProvider),
197
+ );
198
+ console.log(
199
+ chalk.dim(" Iterations: ") +
200
+ chalk.white(`${result.totalIterations}/${maxLoops}`),
201
+ );
202
+ console.log(
203
+ chalk.dim(" Duration: ") +
204
+ chalk.white(`${(result.durationMs / 1000).toFixed(1)}s`),
205
+ );
206
+ console.log(
207
+ chalk.dim(" Status: ") +
208
+ (result.success
209
+ ? chalk.green.bold("SUCCESS")
210
+ : chalk.red.bold("FAILED")),
211
+ );
212
+ console.log();
213
+
214
+ process.exitCode = result.success ? 0 : 1;
215
+ } catch (err) {
216
+ spin.fail("Agent failed to start.");
217
+ log.error(`Error: ${err.message}`);
218
+ process.exitCode = 1;
219
+ }
220
+ };
221
+
222
+ /**
223
+ * `uso agent-config` — Configure API keys and preferences.
224
+ */
225
+ const agentConfig = async (options) => {
226
+ let setApiKey, loadAgentConfig, saveAgentConfig;
227
+ try {
228
+ const core = require("../../packages/uso-core/dist/cjs/index.js");
229
+ setApiKey = core.setApiKey;
230
+ loadAgentConfig = core.loadAgentConfig;
231
+ saveAgentConfig = core.saveAgentConfig;
232
+ } catch (err) {
233
+ log.error("❌ uso-core agent module not found.");
234
+ log.warn("Run 'cd packages/uso-core && npm run build' to compile.");
235
+ return;
236
+ }
237
+
238
+ // Set API keys from flags
239
+ if (options.geminiKey) {
240
+ setApiKey("gemini", options.geminiKey);
241
+ log.success("✅ Gemini API key saved.");
242
+ }
243
+ if (options.openaiKey) {
244
+ setApiKey("openai", options.openaiKey);
245
+ log.success("✅ OpenAI API key saved.");
246
+ }
247
+ if (options.githubToken) {
248
+ setApiKey("github", options.githubToken);
249
+ log.success("✅ GitHub Models token saved.");
250
+ }
251
+
252
+ // Show current config
253
+ if (!options.geminiKey && !options.openaiKey && !options.githubToken) {
254
+ const config = loadAgentConfig();
255
+ console.log();
256
+ console.log(chalk.bold("USO Agent Configuration"));
257
+ console.log(chalk.dim("Config file: ~/.uso-agent.json"));
258
+ console.log();
259
+ console.log(chalk.bold("LLM Providers:"));
260
+ console.log(
261
+ ` Ollama: model=${chalk.cyan(config.ollama?.model || "llama3.1:8b")} url=${chalk.dim(config.ollama?.baseUrl || "http://localhost:11434")}`,
262
+ );
263
+ console.log(
264
+ ` GitHub: model=${chalk.cyan(config.github?.model || "openai/gpt-4o-mini")} token=${config.github?.token ? chalk.green("SET") : chalk.red("NOT SET")}`,
265
+ );
266
+ console.log(
267
+ ` Gemini: model=${chalk.cyan(config.gemini?.model || "gemini-2.0-flash")} key=${config.gemini?.apiKey ? chalk.green("SET") : chalk.red("NOT SET")}`,
268
+ );
269
+ console.log(
270
+ ` OpenAI: model=${chalk.cyan(config.openai?.model || "gpt-4o-mini")} key=${config.openai?.apiKey ? chalk.green("SET") : chalk.red("NOT SET")}`,
271
+ );
272
+ console.log();
273
+ console.log(chalk.bold("Agent Settings:"));
274
+ console.log(
275
+ ` Max iterations: ${chalk.cyan(config.agent?.maxIterations || 3)}`,
276
+ );
277
+ console.log(
278
+ ` Confirm destructive: ${chalk.cyan(config.agent?.confirmDestructive ?? true)}`,
279
+ );
280
+ console.log();
281
+ console.log(chalk.dim("Set API keys:"));
282
+ console.log(
283
+ chalk.dim(" uso agent-config --gemini-key <key>"),
284
+ );
285
+ console.log(
286
+ chalk.dim(" uso agent-config --openai-key <key>"),
287
+ );
288
+ console.log(
289
+ chalk.dim(" uso agent-config --github-token <token>"),
290
+ );
291
+ console.log();
292
+ }
293
+ };
294
+
295
+ module.exports = { agent, agentConfig };
@@ -100,98 +100,6 @@ const uninstallAnchorComponents = (stealth) => {
100
100
  }
101
101
 
102
102
  log.success("Anchor removal steps completed.");
103
- };
104
-
105
- /**
106
- * Runs a command and attempts to elevate privileges if it fails with a permission error.
107
- */
108
- const runOrElevate = (
109
- command,
110
- description,
111
- stealth = { enabled: false, distro: "Ubuntu" },
112
- ) => {
113
- if (stealth.enabled) {
114
- const result = runInStealth(command, stealth, true);
115
-
116
- if (result.code === 0) {
117
- if (result.stdout) console.log(result.stdout);
118
- return true;
119
- }
120
-
121
- if (result.stdout) console.log(result.stdout);
122
- if (result.stderr) console.error(result.stderr);
123
- log.error(`❌ Command failed in WSL: ${description}`);
124
- return false;
125
- }
126
-
127
- // We run without silent:true initially to let the user see output,
128
- // but detecting the error code is what matters.
129
- // actually, to detect the specific string "os error 1314", we need to capture output.
130
- // So we run silently first? Or we just run and if it fails, we assume it *might* be elevation if on Windows?
131
- // Let's run synchronously and capture output.
132
-
133
- const result = shell.exec(command, { silent: true });
134
-
135
- if (result.code === 0) {
136
- console.log(result.stdout);
137
- return true;
138
- }
139
-
140
- // Print the error output to the user
141
- console.log(result.stdout);
142
- console.error(result.stderr);
143
-
144
- const output = result.stderr + result.stdout;
145
-
146
- // Check for common permission errors
147
- // "os error 1314" is specific to Windows symlink privilege
148
- if (
149
- (output.includes("os error 1314") ||
150
- output.includes("EPERM") ||
151
- output.includes("permission denied")) &&
152
- os.platform() === "win32"
153
- ) {
154
- log.warn(`⚠️ Permission denied during: ${description}`);
155
- log.info("🛡️ Triggering Run as Administrator (UAC) to retry...");
156
-
157
- // Construct PowerShell command to run cmd /c <command> as admin
158
- // We need to be careful with quoting.
159
- const escapedCommand = command.replace(/'/g, "''"); // Basic PowerShell escaping for single quotes
160
- const elevateCmd = `powershell -Command "Start-Process -FilePath 'cmd.exe' -ArgumentList '/c ${escapedCommand}' -Verb RunAs -Wait"`;
161
-
162
- const elevatedRun = shell.exec(elevateCmd);
163
-
164
- if (elevatedRun.code === 0) {
165
- log.success(`✅ ${description} completed (Elevated).`);
166
- return true;
167
- } else {
168
- log.error(`❌ Elevated execution failed for: ${description}`);
169
- return false;
170
- }
171
- }
172
-
173
- log.error(`❌ Command failed: ${description}`);
174
- return false;
175
- };
176
-
177
- const uninstall = async (component) => {
178
- const stealth = getStealthContext();
179
- log.header("🗑️ USO Uninstallation & Cleanup");
180
- if (stealth.enabled) {
181
- log.info(
182
- `🐧 Stealth Mode detected. Uninstall targets WSL distro: ${stealth.distro}`,
183
- );
184
- }
185
-
186
- if (component) {
187
- component = component.toLowerCase();
188
- log.info(`🎯 Targeted uninstallation: ${component}`);
189
-
190
- if (component === "anchor") {
191
- const anchorInstalled = commandExists("anchor", stealth);
192
- if (anchorInstalled) {
193
- log.info("Removing Anchor...");
194
- uninstallAnchorComponents(stealth);
195
103
  } else {
196
104
  log.success("✅ Anchor is not installed.");
197
105
  }
@@ -362,6 +270,7 @@ const uninstall = async (component) => {
362
270
  }
363
271
  }
364
272
 
273
+ <<<<<<< HEAD
365
274
  // 3.5 Remove WSL Distro (if stealth mode is active)
366
275
  if (stealth.enabled && os.platform() === "win32") {
367
276
  const removeWslDistro = await askQuestion(
@@ -391,6 +300,8 @@ const uninstall = async (component) => {
391
300
  }
392
301
  }
393
302
 
303
+ =======
304
+ >>>>>>> d47ca156cb2a252419c54c520c7fcd0f0c18c525
394
305
  // 4. WALLET REMOVAL (DANGER)
395
306
  const walletPath = path.join(os.homedir(), ".config", "solana", "id.json");
396
307
  const wslWalletPath = "$HOME/.config/solana/id.json";
@@ -41,74 +41,6 @@ run_with_progress() {
41
41
  }
42
42
  `.replace(/\r\n/g, "\n");
43
43
 
44
- /**
45
- * Installs the WSL Windows Feature via an elevated PowerShell UAC prompt.
46
- * This is needed when `wsl.exe` is not present on the system at all.
47
- * Returns true if WSL is now available after the attempt, false otherwise.
48
- */
49
- const installWslFeature = async () => {
50
- log.warn(
51
- "⚠️ WSL (Windows Subsystem for Linux) is not installed on this machine.",
52
- );
53
- log.info("🛡️ Administrator permission is required to install WSL.");
54
- log.info(
55
- "👉 A UAC (User Account Control) popup will appear — please click 'Yes' to allow the installation.",
56
- );
57
- console.log("");
58
-
59
- // Run `wsl --install --no-distribution` elevated.
60
- // --no-distribution: only enables the WSL feature, does not pull a distro yet.
61
- // We wait for it to finish (-Wait) so we can check the result.
62
- const elevateCmd = `powershell -Command "Start-Process -FilePath 'wsl.exe' -ArgumentList '--install', '--no-distribution' -Verb RunAs -Wait"`;
63
- const result = shell.exec(elevateCmd, { silent: false });
64
-
65
- if (result.code !== 0) {
66
- // User likely denied UAC or the command failed
67
- log.error("❌ WSL installation was cancelled or failed.");
68
- log.warn(
69
- "👉 To install manually, open PowerShell as Administrator and run:",
70
- );
71
- console.log(chalk.bold.yellow(" wsl --install"));
72
- return false;
73
- }
74
-
75
- // Verify wsl is now available
76
- const check = shell.exec("wsl --status", { silent: true });
77
- if (check.code !== 0) {
78
- // WSL was just installed — a reboot is almost certainly required
79
- log.warn(
80
- "⚠️ WSL feature has been installed, but a system restart is required to complete setup.",
81
- );
82
- log.warn(
83
- "👉 Please RESTART your computer, then run `uso install` again to set up the toolchain.",
84
- );
85
- return false; // Signal caller that we need a restart before proceeding
86
- }
87
-
88
- log.success("✅ WSL feature installed successfully.");
89
- return true;
90
- };
91
-
92
- const installWsl = async () => {
93
- log.header("🐧 Configuring Stealth WSL Environment...");
94
-
95
- // 1. Check if WSL is enabled
96
- if (!shell.which("wsl")) {
97
- log.error("❌ WSL is not enabled on this Windows machine.");
98
- log.warn(
99
- "👉 Please enable 'Windows Subsystem for Linux' in 'Turn Windows features on or off'.",
100
- );
101
- log.warn("👉 Or run this in PowerShell as Admin: wsl --install");
102
- return false;
103
- }
104
-
105
- // 2. Install Ubuntu silently (Branded as Uso Engine)
106
- // We use 'wsl -d Ubuntu -e true' to check if it's installed and runnable.
107
- // 'wsl -l -v' output is notoriously unreliable due to charset encoding (UTF-16) on Windows.
108
- const checkDistro = shell.exec(`wsl -d ${WSL_DISTRO} -e true`, {
109
- silent: true,
110
- });
111
-
112
44
  // If exit code is 0, it's installed and working.
113
45
  if (checkDistro.code !== 0) {
114
46
  log.info(