@mutmutco/hub 4.6.35 → 4.6.37

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 +30 -1
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -2964,6 +2964,28 @@ function sameTree(source, target) {
2964
2964
  return false;
2965
2965
  }
2966
2966
  }
2967
+ function skillIdentity(folder) {
2968
+ try {
2969
+ const text = (0, import_node_fs17.readFileSync)((0, import_node_path12.join)(folder, "SKILL.md"), "utf8").replace(/^\uFEFF/, "");
2970
+ const block = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/.exec(text);
2971
+ if (!block) return null;
2972
+ const field = (key) => {
2973
+ const line = new RegExp(`^${key}[ \\t]*:[ \\t]*(\\S.*?)[ \\t]*$`, "m").exec(block[1]);
2974
+ return line ? line[1] : null;
2975
+ };
2976
+ const name = field("name");
2977
+ const description = field("description");
2978
+ return name && description ? { name, description } : null;
2979
+ } catch {
2980
+ return null;
2981
+ }
2982
+ }
2983
+ function isStoreCopy(shipped, installed) {
2984
+ const mine = skillIdentity(shipped);
2985
+ if (!mine) return false;
2986
+ const theirs = skillIdentity(installed);
2987
+ return !!theirs && theirs.name === mine.name && theirs.description === mine.description;
2988
+ }
2967
2989
  function packageSkillNames(packageRoot) {
2968
2990
  try {
2969
2991
  return (0, import_node_fs17.readdirSync)((0, import_node_path12.join)(packageRoot, "skills"), { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith("_")).map((entry) => entry.name).sort();
@@ -2979,7 +3001,13 @@ function materializeOpenBotWorkspace(workspace, packageRoot, target) {
2979
3001
  const owned = readOwnership(workspace);
2980
3002
  const ownedNames = new Set(owned?.skills ?? []);
2981
3003
  const source = (0, import_node_path12.join)(packageRoot, "skills");
2982
- const conflicts = names.filter((name) => (0, import_node_fs17.existsSync)((0, import_node_path12.join)(root, name)) && !ownedNames.has(name));
3004
+ const conflicts = [];
3005
+ const adopted = [];
3006
+ for (const name of names) {
3007
+ if (!(0, import_node_fs17.existsSync)((0, import_node_path12.join)(root, name)) || ownedNames.has(name)) continue;
3008
+ if (isStoreCopy((0, import_node_path12.join)(source, name), (0, import_node_path12.join)(root, name))) adopted.push(name);
3009
+ else conflicts.push(name);
3010
+ }
2983
3011
  const retired = [...ownedNames].filter((name) => !names.includes(name) && (0, import_node_fs17.existsSync)((0, import_node_path12.join)(root, name)));
2984
3012
  const writable = names.filter((name) => !conflicts.includes(name));
2985
3013
  const current = writable.every((name) => sameTree((0, import_node_path12.join)(source, name), (0, import_node_path12.join)(root, name)));
@@ -3023,6 +3051,7 @@ function materializeOpenBotWorkspace(workspace, packageRoot, target) {
3023
3051
  }
3024
3052
  const detail = [
3025
3053
  `provisioned ${installed.length} skills to ${root}`,
3054
+ adopted.length ? `adopted ${adopted.length} store ${adopted.length === 1 ? "copy" : "copies"}: ${adopted.join(", ")}` : "",
3026
3055
  retired.length ? `retired ${retired.length}` : "",
3027
3056
  conflicts.length ? `${conflicts.length} NOT installed (not MMI-owned): ${conflicts.join(", ")}` : ""
3028
3057
  ].filter(Boolean).join("; ");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/hub",
3
- "version": "4.6.35",
3
+ "version": "4.6.37",
4
4
  "description": "Install and maintain the MMI CLI and every present host surface from one release-gated Hub command.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",