@caliber-ai/cli 0.16.1 → 0.16.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.
package/dist/bin.js CHANGED
@@ -2392,11 +2392,15 @@ No ${options.status} recommendations.
2392
2392
  async function generateRecommendations(projectId) {
2393
2393
  const spinner = ora5("Detecting technologies and searching for skills...").start();
2394
2394
  try {
2395
- const recs = await apiRequest(
2395
+ const generated = await apiRequest(
2396
2396
  `/api/recommendations/project/${projectId}/generate`,
2397
2397
  { method: "POST" }
2398
2398
  );
2399
- spinner.succeed(`Found ${recs?.length || 0} recommendations`);
2399
+ spinner.succeed(`Found ${generated?.length || 0} recommendations`);
2400
+ if (!generated?.length) return generated;
2401
+ const recs = await apiRequest(
2402
+ `/api/recommendations/project/${projectId}?status=pending`
2403
+ );
2400
2404
  return recs;
2401
2405
  } catch (err) {
2402
2406
  spinner.fail("Failed to generate recommendations");
@@ -2493,32 +2497,44 @@ async function interactiveSelect(recs) {
2493
2497
  stdin.on("data", onData);
2494
2498
  });
2495
2499
  }
2500
+ async function fetchSkillContent(rec) {
2501
+ if (rec.id) {
2502
+ try {
2503
+ const result = await apiRequest(
2504
+ `/api/recommendations/${rec.id}/content`
2505
+ );
2506
+ if (result?.content) return result.content;
2507
+ } catch {
2508
+ }
2509
+ }
2510
+ if (rec.source_url && rec.skill_slug) {
2511
+ try {
2512
+ const url = `https://raw.githubusercontent.com/${rec.source_url}/HEAD/skills/${rec.skill_slug}/SKILL.md`;
2513
+ const resp = await fetch(url);
2514
+ if (resp.ok) return await resp.text();
2515
+ } catch {
2516
+ }
2517
+ }
2518
+ return null;
2519
+ }
2496
2520
  async function installSkills(recs, platforms) {
2497
2521
  const spinner = ora5(`Installing ${recs.length} skill${recs.length > 1 ? "s" : ""}...`).start();
2498
2522
  const installed = [];
2499
2523
  const warnings = [];
2500
2524
  for (const rec of recs) {
2501
- let accepted = false;
2525
+ const content = await fetchSkillContent(rec);
2526
+ if (!content) {
2527
+ warnings.push(`No content available for ${rec.skill_name}`);
2528
+ continue;
2529
+ }
2502
2530
  for (const platform of platforms) {
2503
- try {
2504
- const result = await apiRequest(
2505
- `/api/recommendations/${rec.id}/content?platform=${platform}`
2506
- );
2507
- if (!result?.content) {
2508
- warnings.push(`[${platform}] No content available for ${rec.skill_name}`);
2509
- continue;
2510
- }
2511
- const skillPath = getSkillPath(platform, rec.skill_slug);
2512
- const fullPath = join(process.cwd(), skillPath);
2513
- mkdirSync(dirname2(fullPath), { recursive: true });
2514
- writeFileSync(fullPath, result.content, "utf-8");
2515
- installed.push(`[${platform}] ${skillPath}`);
2516
- accepted = true;
2517
- } catch {
2518
- warnings.push(`[${platform}] Failed to fetch ${rec.skill_name}`);
2519
- }
2531
+ const skillPath = getSkillPath(platform, rec.skill_slug);
2532
+ const fullPath = join(process.cwd(), skillPath);
2533
+ mkdirSync(dirname2(fullPath), { recursive: true });
2534
+ writeFileSync(fullPath, content, "utf-8");
2535
+ installed.push(`[${platform}] ${skillPath}`);
2520
2536
  }
2521
- if (accepted) {
2537
+ if (rec.id) {
2522
2538
  try {
2523
2539
  await apiRequest(`/api/recommendations/${rec.id}/status`, {
2524
2540
  method: "PUT",