@learnrudi/cli 1.8.6 → 1.8.8

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.
Files changed (2) hide show
  1. package/dist/index.cjs +69 -5
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -203,10 +203,18 @@ async function installDependencies(stackPath, manifest) {
203
203
  }
204
204
  const pipCmd = getBundledBinary("python", "pip");
205
205
  console.log(` Installing pip dependencies...`);
206
- (0, import_child_process.execSync)(`"${pipCmd}" install -r requirements.txt`, {
207
- cwd: reqCwd,
208
- stdio: "pipe"
209
- });
206
+ try {
207
+ (0, import_child_process.execSync)(`"${pipCmd}" install -r requirements.txt`, {
208
+ cwd: reqCwd,
209
+ stdio: "pipe"
210
+ });
211
+ } catch (pipError) {
212
+ const stderr = pipError.stderr?.toString() || "";
213
+ const stdout = pipError.stdout?.toString() || "";
214
+ const output = stderr || stdout || pipError.message;
215
+ return { installed: false, error: `pip install failed:
216
+ ${output}` };
217
+ }
210
218
  return { installed: true };
211
219
  }
212
220
  return { installed: false, reason: `Unknown runtime: ${runtime}` };
@@ -225,6 +233,49 @@ function getSecretLink(secret) {
225
233
  if (typeof secret !== "object" || !secret) return null;
226
234
  return secret.link || secret.helpUrl || null;
227
235
  }
236
+ function validateStackEntryPoint(stackPath, manifest) {
237
+ let command = manifest.command;
238
+ if (!command || command.length === 0) {
239
+ if (manifest.mcp?.command) {
240
+ const mcpCmd = manifest.mcp.command;
241
+ const mcpArgs = manifest.mcp.args || [];
242
+ command = [mcpCmd, ...mcpArgs];
243
+ }
244
+ }
245
+ if (!command || command.length === 0) {
246
+ return { valid: false, error: "No command defined in manifest" };
247
+ }
248
+ const skipCommands = [
249
+ "node",
250
+ "python",
251
+ "python3",
252
+ "npx",
253
+ "deno",
254
+ "bun",
255
+ "tsx",
256
+ "ts-node",
257
+ "tsm",
258
+ "esno",
259
+ "esbuild-register",
260
+ // TypeScript runners
261
+ "-y",
262
+ "--yes"
263
+ // npx flags
264
+ ];
265
+ const fileExtensions = [".js", ".ts", ".mjs", ".cjs", ".py", ".mts", ".cts"];
266
+ for (const arg of command) {
267
+ if (skipCommands.includes(arg)) continue;
268
+ if (arg.startsWith("-")) continue;
269
+ const looksLikeFile = fileExtensions.some((ext) => arg.endsWith(ext)) || arg.includes("/");
270
+ if (!looksLikeFile) continue;
271
+ const entryPath = require("path").join(stackPath, arg);
272
+ if (!require("fs").existsSync(entryPath)) {
273
+ return { valid: false, error: `Entry point not found: ${arg}` };
274
+ }
275
+ return { valid: true };
276
+ }
277
+ return { valid: true };
278
+ }
228
279
  async function checkSecrets(manifest) {
229
280
  const secrets = getManifestSecrets(manifest);
230
281
  const found = [];
@@ -352,11 +403,24 @@ Installing...`);
352
403
  if (resolved.kind === "stack") {
353
404
  const manifest = await loadManifest(result.path);
354
405
  if (manifest) {
406
+ const validation = validateStackEntryPoint(result.path, manifest);
407
+ if (!validation.valid) {
408
+ console.error(`
409
+ \u2717 Stack validation failed: ${validation.error}`);
410
+ console.error(` The stack may be incomplete or misconfigured.`);
411
+ process.exit(1);
412
+ }
355
413
  const depResult = await installDependencies(result.path, manifest);
356
414
  if (depResult.installed) {
357
415
  console.log(` \u2713 Dependencies installed`);
358
416
  } else if (depResult.error) {
359
- console.log(` \u26A0 Failed to install dependencies: ${depResult.error}`);
417
+ console.error(`
418
+ \u2717 Failed to install dependencies:`);
419
+ console.error(` ${depResult.error}`);
420
+ console.error(`
421
+ Stack installed but may not work. Fix dependencies and run:`);
422
+ console.error(` rudi install ${result.id}`);
423
+ process.exit(1);
360
424
  }
361
425
  const { found, missing } = await checkSecrets(manifest);
362
426
  const envExampleKeys = await parseEnvExample(result.path);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@learnrudi/cli",
3
- "version": "1.8.6",
3
+ "version": "1.8.8",
4
4
  "description": "RUDI CLI - Install and manage MCP stacks, runtimes, and AI agents",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",