skillstogether 0.1.11 → 0.1.12

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.js +108 -19
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2712,7 +2712,8 @@ async function uninstallSkill(organizationSlug, skillSlug, scope, skipConfirm) {
2712
2712
  // src/commands/update.ts
2713
2713
  import * as p9 from "@clack/prompts";
2714
2714
  import { Command as Command8 } from "commander";
2715
- import { writeFileSync as writeFileSync3 } from "fs";
2715
+ import { rmSync as rmSync2, writeFileSync as writeFileSync3 } from "fs";
2716
+ import { basename as basename2, dirname as dirname3 } from "path";
2716
2717
  import pc10 from "picocolors";
2717
2718
  function generateUpdatedContent(skill, organizationSlug) {
2718
2719
  const frontmatter = generateFrontmatter({
@@ -2730,6 +2731,25 @@ function generateUpdatedContent(skill, organizationSlug) {
2730
2731
  );
2731
2732
  return frontmatter + "\n" + normalizedContent;
2732
2733
  }
2734
+ function removeInstalledSkillPath(skillPath) {
2735
+ try {
2736
+ if (basename2(skillPath) === "SKILL.md") {
2737
+ rmSync2(dirname3(skillPath), { recursive: true, force: true });
2738
+ } else {
2739
+ rmSync2(skillPath, { force: true });
2740
+ try {
2741
+ rmSync2(dirname3(skillPath), { recursive: false });
2742
+ } catch {
2743
+ }
2744
+ }
2745
+ return { success: true };
2746
+ } catch (error) {
2747
+ return {
2748
+ success: false,
2749
+ error: formatErrorMessage(error)
2750
+ };
2751
+ }
2752
+ }
2733
2753
  var updateCommand = new Command8("update").description("Update installed skills to latest version").argument("[target]", "Organization slug").option("--global", "Update only globally installed skills").option("--project", "Update only project-installed skills").option(
2734
2754
  "--skill <slug>",
2735
2755
  "Update a specific skill by slug (already org-prefixed, e.g. acme-onboarding)"
@@ -2818,6 +2838,7 @@ var updateCommand = new Command8("update").description("Update installed skills
2818
2838
  const checkSpinner = p9.spinner();
2819
2839
  checkSpinner.start("Checking for updates...");
2820
2840
  const skillsToUpdate = [];
2841
+ const skillsToRemove = [];
2821
2842
  const errors = [];
2822
2843
  for (const [org, skills] of byOrg) {
2823
2844
  try {
@@ -2826,6 +2847,7 @@ var updateCommand = new Command8("update").description("Update installed skills
2826
2847
  installedAt: s2.installedAt
2827
2848
  }));
2828
2849
  const result = await checkForUpdates(org, skillsInfo);
2850
+ const remoteSlugs = new Set(result.updates.map((update) => update.slug));
2829
2851
  for (const update of result.updates) {
2830
2852
  if (update.hasUpdate) {
2831
2853
  const unique = skills.find((s2) => s2.slug === update.slug);
@@ -2838,12 +2860,17 @@ var updateCommand = new Command8("update").description("Update installed skills
2838
2860
  }
2839
2861
  }
2840
2862
  }
2863
+ for (const unique of skills) {
2864
+ if (!remoteSlugs.has(unique.slug)) {
2865
+ skillsToRemove.push({ unique });
2866
+ }
2867
+ }
2841
2868
  } catch (error) {
2842
2869
  errors.push(`${org}: ${formatErrorMessage(error)}`);
2843
2870
  }
2844
2871
  }
2845
2872
  checkSpinner.stop("Update check complete");
2846
- if (skillsToUpdate.length === 0) {
2873
+ if (skillsToUpdate.length === 0 && skillsToRemove.length === 0) {
2847
2874
  p9.log.success("All skills are up to date!");
2848
2875
  if (errors.length > 0) {
2849
2876
  console.log();
@@ -2857,19 +2884,38 @@ var updateCommand = new Command8("update").description("Update installed skills
2857
2884
  p9.outro(pc10.dim("Done"));
2858
2885
  return;
2859
2886
  }
2860
- const totalInstances = skillsToUpdate.reduce(
2887
+ const totalUpdatedInstances = skillsToUpdate.reduce(
2861
2888
  (sum, s2) => sum + s2.unique.paths.length,
2862
2889
  0
2863
2890
  );
2864
- console.log();
2865
- const updateMsg = skillsToUpdate.length === totalInstances ? `${pc10.yellow(skillsToUpdate.length.toString())} skill${skillsToUpdate.length !== 1 ? "s" : ""} will be updated:` : `${pc10.yellow(skillsToUpdate.length.toString())} skill${skillsToUpdate.length !== 1 ? "s" : ""} (${totalInstances} installations) will be updated:`;
2866
- p9.log.info(updateMsg);
2867
- for (const { unique, remoteVersion } of skillsToUpdate) {
2868
- const agentNames = unique.agents.map((a) => a.name).join(", ");
2869
- const scopeBadge = unique.scope === "global" ? pc10.yellow("(global)") : pc10.dim("(project)");
2870
- console.log(
2871
- ` ${pc10.yellow("\u2191")} ${pc10.white(`${unique.organization}/${unique.slug}`)} ${pc10.dim(`v${unique.version || "?"}`)} \u2192 ${pc10.green(`v${remoteVersion}`)} ${pc10.dim(`[${agentNames}]`)} ${scopeBadge}`
2872
- );
2891
+ const totalRemovedInstances = skillsToRemove.reduce(
2892
+ (sum, s2) => sum + s2.unique.paths.length,
2893
+ 0
2894
+ );
2895
+ const totalAffectedInstances = totalUpdatedInstances + totalRemovedInstances;
2896
+ if (skillsToUpdate.length > 0) {
2897
+ console.log();
2898
+ const updateMsg = skillsToUpdate.length === totalUpdatedInstances ? `${pc10.yellow(skillsToUpdate.length.toString())} skill${skillsToUpdate.length !== 1 ? "s" : ""} will be updated:` : `${pc10.yellow(skillsToUpdate.length.toString())} skill${skillsToUpdate.length !== 1 ? "s" : ""} (${totalUpdatedInstances} installations) will be updated:`;
2899
+ p9.log.info(updateMsg);
2900
+ for (const { unique, remoteVersion } of skillsToUpdate) {
2901
+ const agentNames = unique.agents.map((a) => a.name).join(", ");
2902
+ const scopeBadge = unique.scope === "global" ? pc10.yellow("(global)") : pc10.dim("(project)");
2903
+ console.log(
2904
+ ` ${pc10.yellow("\u2191")} ${pc10.white(`${unique.organization}/${unique.slug}`)} ${pc10.dim(`v${unique.version || "?"}`)} \u2192 ${pc10.green(`v${remoteVersion}`)} ${pc10.dim(`[${agentNames}]`)} ${scopeBadge}`
2905
+ );
2906
+ }
2907
+ }
2908
+ if (skillsToRemove.length > 0) {
2909
+ console.log();
2910
+ const removeMsg = skillsToRemove.length === totalRemovedInstances ? `${pc10.red(skillsToRemove.length.toString())} skill${skillsToRemove.length !== 1 ? "s" : ""} deleted from remote will be removed locally:` : `${pc10.red(skillsToRemove.length.toString())} skill${skillsToRemove.length !== 1 ? "s" : ""} deleted from remote will be removed locally (${totalRemovedInstances} installations):`;
2911
+ p9.log.warn(removeMsg);
2912
+ for (const { unique } of skillsToRemove) {
2913
+ const agentNames = unique.agents.map((a) => a.name).join(", ");
2914
+ const scopeBadge = unique.scope === "global" ? pc10.yellow("(global)") : pc10.dim("(project)");
2915
+ console.log(
2916
+ ` ${pc10.red("\u2193")} ${pc10.white(`${unique.organization}/${unique.slug}`)} ${pc10.dim(`[${agentNames}]`)} ${scopeBadge}`
2917
+ );
2918
+ }
2873
2919
  }
2874
2920
  console.log();
2875
2921
  if (options.dryRun) {
@@ -2878,7 +2924,15 @@ var updateCommand = new Command8("update").description("Update installed skills
2878
2924
  return;
2879
2925
  }
2880
2926
  if (!options.yes) {
2881
- const confirmMsg = skillsToUpdate.length === totalInstances ? `Update ${skillsToUpdate.length} skill${skillsToUpdate.length !== 1 ? "s" : ""}?` : `Update ${skillsToUpdate.length} skill${skillsToUpdate.length !== 1 ? "s" : ""} (${totalInstances} installations)?`;
2927
+ let confirmMsg;
2928
+ if (skillsToUpdate.length > 0 && skillsToRemove.length > 0) {
2929
+ const noun = totalAffectedInstances === 1 ? "installation" : "installations";
2930
+ confirmMsg = `Apply ${skillsToUpdate.length} update${skillsToUpdate.length !== 1 ? "s" : ""} and remove ${skillsToRemove.length} deleted skill${skillsToRemove.length !== 1 ? "s" : ""} (${totalAffectedInstances} ${noun})?`;
2931
+ } else if (skillsToUpdate.length > 0) {
2932
+ confirmMsg = skillsToUpdate.length === totalUpdatedInstances ? `Update ${skillsToUpdate.length} skill${skillsToUpdate.length !== 1 ? "s" : ""}?` : `Update ${skillsToUpdate.length} skill${skillsToUpdate.length !== 1 ? "s" : ""} (${totalUpdatedInstances} installations)?`;
2933
+ } else {
2934
+ confirmMsg = skillsToRemove.length === totalRemovedInstances ? `Remove ${skillsToRemove.length} deleted skill${skillsToRemove.length !== 1 ? "s" : ""} locally?` : `Remove ${skillsToRemove.length} deleted skill${skillsToRemove.length !== 1 ? "s" : ""} locally (${totalRemovedInstances} installations)?`;
2935
+ }
2882
2936
  const confirmed = await p9.confirm({
2883
2937
  message: confirmMsg,
2884
2938
  initialValue: true
@@ -2889,11 +2943,15 @@ var updateCommand = new Command8("update").description("Update installed skills
2889
2943
  }
2890
2944
  }
2891
2945
  const updateSpinner = p9.spinner();
2892
- updateSpinner.start("Updating skills...");
2946
+ updateSpinner.start("Applying changes...");
2893
2947
  let updatedSkills = 0;
2894
2948
  let updatedInstances = 0;
2895
- let failed = 0;
2949
+ let updateFailed = 0;
2896
2950
  const updateErrors = [];
2951
+ let removedSkills = 0;
2952
+ let removedInstances = 0;
2953
+ let removalFailed = 0;
2954
+ const removalErrors = [];
2897
2955
  for (const { unique } of skillsToUpdate) {
2898
2956
  try {
2899
2957
  const skill = await fetchSkill(unique.organization, unique.slug);
@@ -2904,25 +2962,56 @@ var updateCommand = new Command8("update").description("Update installed skills
2904
2962
  }
2905
2963
  updatedSkills++;
2906
2964
  } catch (error) {
2907
- failed++;
2965
+ updateFailed++;
2908
2966
  updateErrors.push(
2909
2967
  `${unique.organization}/${unique.slug}: ${formatErrorMessage(error)}`
2910
2968
  );
2911
2969
  }
2912
2970
  }
2913
- updateSpinner.stop("Update complete");
2971
+ for (const { unique } of skillsToRemove) {
2972
+ let allInstancesRemoved = true;
2973
+ for (const path of unique.paths) {
2974
+ const result = removeInstalledSkillPath(path);
2975
+ if (result.success) {
2976
+ removedInstances++;
2977
+ } else {
2978
+ allInstancesRemoved = false;
2979
+ removalErrors.push(
2980
+ `${unique.organization}/${unique.slug} (${path}): ${result.error}`
2981
+ );
2982
+ }
2983
+ }
2984
+ if (allInstancesRemoved) {
2985
+ removedSkills++;
2986
+ } else {
2987
+ removalFailed++;
2988
+ }
2989
+ }
2990
+ updateSpinner.stop("Changes applied");
2914
2991
  if (updatedSkills > 0) {
2915
2992
  const summaryMsg = updatedSkills === updatedInstances ? `Updated ${pc10.green(updatedSkills.toString())} skill${updatedSkills !== 1 ? "s" : ""}` : `Updated ${pc10.green(updatedSkills.toString())} skill${updatedSkills !== 1 ? "s" : ""} (${updatedInstances} installations)`;
2916
2993
  p9.log.success(summaryMsg);
2917
2994
  }
2918
- if (failed > 0) {
2995
+ if (updateFailed > 0) {
2919
2996
  p9.log.error(
2920
- `Failed to update ${pc10.red(failed.toString())} skill${failed !== 1 ? "s" : ""}`
2997
+ `Failed to update ${pc10.red(updateFailed.toString())} skill${updateFailed !== 1 ? "s" : ""}`
2921
2998
  );
2922
2999
  for (const error of updateErrors) {
2923
3000
  console.log(` ${pc10.red("\u2022")} ${error}`);
2924
3001
  }
2925
3002
  }
3003
+ if (removedSkills > 0) {
3004
+ const summaryMsg = removedSkills === removedInstances ? `Removed ${pc10.green(removedSkills.toString())} deleted skill${removedSkills !== 1 ? "s" : ""}` : `Removed ${pc10.green(removedSkills.toString())} deleted skill${removedSkills !== 1 ? "s" : ""} (${removedInstances} installations)`;
3005
+ p9.log.success(summaryMsg);
3006
+ }
3007
+ if (removalFailed > 0) {
3008
+ p9.log.error(
3009
+ `Failed to remove ${pc10.red(removalFailed.toString())} deleted skill${removalFailed !== 1 ? "s" : ""}`
3010
+ );
3011
+ for (const error of removalErrors) {
3012
+ console.log(` ${pc10.red("\u2022")} ${error}`);
3013
+ }
3014
+ }
2926
3015
  p9.outro(pc10.dim("Done"));
2927
3016
  }
2928
3017
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillstogether",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "description": "CLI tool to install skills",
5
5
  "keywords": [
6
6
  "cli",