@drawcall/market 0.1.27 → 0.1.28

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 (49) hide show
  1. package/dist/asset-implementation.d.ts +1 -0
  2. package/dist/asset-implementation.d.ts.map +1 -1
  3. package/dist/cli.js +8 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/upload.d.ts +18 -0
  6. package/dist/commands/upload.d.ts.map +1 -1
  7. package/dist/commands/upload.js +67 -3
  8. package/dist/commands/upload.js.map +1 -1
  9. package/dist/contract.d.ts +3 -0
  10. package/dist/contract.d.ts.map +1 -1
  11. package/dist/contract.js.map +1 -1
  12. package/dist/index.d.ts +1 -1
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +1 -1
  15. package/dist/index.js.map +1 -1
  16. package/dist/install.d.ts +11 -2
  17. package/dist/install.d.ts.map +1 -1
  18. package/dist/install.js +63 -11
  19. package/dist/install.js.map +1 -1
  20. package/dist/output.d.ts.map +1 -1
  21. package/dist/output.js +6 -0
  22. package/dist/output.js.map +1 -1
  23. package/dist/resolve.d.ts +2 -0
  24. package/dist/resolve.d.ts.map +1 -1
  25. package/dist/resolve.js +28 -1
  26. package/dist/resolve.js.map +1 -1
  27. package/dist/schemas.d.ts +2 -0
  28. package/dist/schemas.d.ts.map +1 -1
  29. package/dist/schemas.js +5 -0
  30. package/dist/schemas.js.map +1 -1
  31. package/dist/skill.d.ts +1 -1
  32. package/dist/skill.d.ts.map +1 -1
  33. package/dist/skill.js +4 -1
  34. package/dist/skill.js.map +1 -1
  35. package/package.json +1 -1
  36. package/src/asset-implementation.ts +1 -0
  37. package/src/cli.ts +18 -1
  38. package/src/commands/upload.ts +79 -3
  39. package/src/contract.ts +2 -0
  40. package/src/index.ts +1 -0
  41. package/src/install.ts +89 -12
  42. package/src/output.ts +9 -0
  43. package/src/resolve.ts +36 -2
  44. package/src/schemas.ts +6 -0
  45. package/src/skill.ts +4 -1
  46. package/tests/install-layout.test.ts +60 -2
  47. package/tests/output.test.ts +18 -0
  48. package/tests/resolve-skills.test.ts +87 -0
  49. package/tests/upload-deps.test.ts +44 -0
package/dist/resolve.js CHANGED
@@ -46,11 +46,13 @@ export async function resolve(client, requests, opts = {}) {
46
46
  }
47
47
  const npmDeps = parseDependencies(meta.npmDependencies, assetName, 'npm');
48
48
  const assetDeps = parseDependencies(meta.assetDependencies, assetName, 'asset');
49
+ const skillDeps = parseDependencies(meta.skillDependencies, assetName, 'skill');
49
50
  resolved.set(assetName, {
50
51
  name: assetName,
51
52
  version: meta.latestVersion,
52
53
  npmDependencies: npmDeps,
53
54
  assetDependencies: assetDeps,
55
+ skillDependencies: skillDeps,
54
56
  });
55
57
  for (const [depName, depRange] of Object.entries(assetDeps)) {
56
58
  addConstraint(constraints, depName, depRange, `${assetName}@${meta.latestVersion}`);
@@ -69,13 +71,38 @@ export async function resolve(client, requests, opts = {}) {
69
71
  }
70
72
  }
71
73
  }
72
- // Merge npm dependencies across all resolved assets
74
+ // Merge npm and skill dependencies across all resolved assets
73
75
  const mergedNpm = mergeNpmDependencies(Array.from(resolved.values()));
76
+ const mergedSkills = mergeSkillDependencies(Array.from(resolved.values()));
74
77
  return {
75
78
  assets: Array.from(resolved.values()),
76
79
  npmDependencies: mergedNpm,
80
+ skillDependencies: mergedSkills,
77
81
  };
78
82
  }
83
+ /**
84
+ * Merge skill dependencies from all resolved assets. Skills are not versioned
85
+ * by the resolver — each entry is a label mapped to a `skills add` source — so
86
+ * the merge is a simple union. The same label declared by two assets must point
87
+ * at the same source; otherwise installing one would silently shadow the other.
88
+ */
89
+ function mergeSkillDependencies(assets) {
90
+ const merged = {};
91
+ const origin = {};
92
+ for (const asset of assets) {
93
+ const from = `${asset.name}@${asset.version}`;
94
+ for (const [label, source] of Object.entries(asset.skillDependencies)) {
95
+ if (label in merged && merged[label] !== source) {
96
+ throw new ResolutionError(`skill dependency conflict for "${label}":\n` +
97
+ ` ${merged[label]} (from ${origin[label]})\n` +
98
+ ` ${source} (from ${from})`);
99
+ }
100
+ merged[label] = source;
101
+ origin[label] = from;
102
+ }
103
+ }
104
+ return merged;
105
+ }
79
106
  function parseDependencies(value, assetName, kind) {
80
107
  try {
81
108
  const parsed = JSON.parse(value || '{}');
@@ -1 +1 @@
1
- {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAA;AAqBhC,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACxC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAA;IAC/B,CAAC;CACF;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,MAA6B,EAC7B,QAAwB,EACxB,OAAwC,EAAE;IAE1C,MAAM,WAAW,GAAG,IAAI,GAAG,EAA6C,CAAA;IACxE,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAyB,CAAA;IACjD,MAAM,SAAS,GAAG,IAAI,GAAG,EAA6B,CAAA;IAEtD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,aAAa,CAAC,WAAW,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;IACnE,CAAC;IAED,IAAI,UAAU,GAAG,aAAa,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAA;IACrD,OAAO,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,iBAAiB,IAAI,KAAK,CAAC,CAAA;YAC3F,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,MAAM,IAAI,eAAe,CAAC,UAAU,SAAS,cAAc,CAAC,CAAA;YAC9D,CAAC;YAED,IAAI,CAAC,IAAI,CAAC,iBAAiB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAC9C,MAAM,IAAI,eAAe,CAAC,UAAU,SAAS,6BAA6B,CAAC,CAAA;YAC7E,CAAC;YAED,qEAAqE;YACrE,oEAAoE;YACpE,oEAAoE;YACpE,gDAAgD;YAChD,MAAM,gBAAgB,GAAG,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,CAAA;YACzD,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;gBAClF,MAAM,cAAc,GAAG,gBAAgB;qBACpC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,IAAI,GAAG,CAAC;qBAC3C,IAAI,CAAC,IAAI,CAAC,CAAA;gBACb,MAAM,IAAI,eAAe,CACvB,aAAa,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,gBAAgB,SAAS,IAAI;oBACjF,IAAI,IAAI,CAAC,aAAa,wCAAwC,cAAc,EAAE,CACjF,CAAA;YACH,CAAC;YAED,MAAM,OAAO,GAAG,iBAAiB,CAAC,IAAI,CAAC,eAAe,EAAE,SAAS,EAAE,KAAK,CAAC,CAAA;YACzE,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,iBAAiB,EAAE,SAAS,EAAE,OAAO,CAAC,CAAA;YAE/E,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE;gBACtB,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,IAAI,CAAC,aAAa;gBAC3B,eAAe,EAAE,OAAO;gBACxB,iBAAiB,EAAE,SAAS;aAC7B,CAAC,CAAA;YAEF,KAAK,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC5D,aAAa,CAAC,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,SAAS,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC,CAAA;YACrF,CAAC;QACH,CAAC;QAED,UAAU,GAAG,aAAa,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAA;IACnD,CAAC;IAED,0EAA0E;IAC1E,8DAA8D;IAC9D,KAAK,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,QAAQ,EAAE,CAAC;QAC1C,MAAM,gBAAgB,GAAG,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,CAAA;QACzD,KAAK,MAAM,CAAC,IAAI,gBAAgB,EAAE,CAAC;YACjC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC9C,MAAM,IAAI,eAAe,CACvB,cAAc,SAAS,IAAI,KAAK,CAAC,OAAO,qBAAqB;oBAC3D,GAAG,CAAC,CAAC,KAAK,iBAAiB,CAAC,CAAC,IAAI,IAAI,CACxC,CAAA;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,oDAAoD;IACpD,MAAM,SAAS,GAAG,oBAAoB,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;IAErE,OAAO;QACL,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;QACrC,eAAe,EAAE,SAAS;KAC3B,CAAA;AACH,CAAC;AAED,SAAS,iBAAiB,CACxB,KAAa,EACb,SAAiB,EACjB,IAAqB;IAErB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,IAAI,CAAY,CAAA;QACnD,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACnE,OAAO,MAAgC,CAAA;QACzC,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,sCAAsC;IACxC,CAAC;IACD,MAAM,IAAI,eAAe,CAAC,UAAU,SAAS,mBAAmB,IAAI,uBAAuB,CAAC,CAAA;AAC9F,CAAC;AAED,SAAS,aAAa,CACpB,WAA2D,EAC3D,IAAY,EACZ,KAAa,EACb,IAAY;IAEZ,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAA;IAC5C,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IAC9B,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;AACjC,CAAC;AAED,SAAS,aAAa,CACpB,WAA2D,EAC3D,QAAoC;IAEpC,OAAO,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAA;AAC7E,CAAC;AAED,KAAK,UAAU,SAAS,CACtB,MAA6B,EAC7B,KAAqC,EACrC,IAAY,EACZ,iBAA0B;IAE1B,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAE,CAAA;IAC5C,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;QAC9B,IAAI;QACJ,iBAAiB;KAClB,CAAC,CAAA;IACF,IAAI,IAAI;QAAE,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;IAC/B,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;;;GAKG;AACH,SAAS,oBAAoB,CAAC,MAAuB;IACnD,iCAAiC;IACjC,MAAM,YAAY,GAAmD,IAAI,GAAG,EAAE,CAAA;IAE9E,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,eAAe,CAAC,EAAE,CAAC;YACjE,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAA;YAC5C,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC,CAAA;YAChE,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;QACjC,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAA2B,EAAE,CAAA;IAEzC,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,YAAY,EAAE,CAAC;QACzC,+BAA+B;QAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACvC,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3C,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;oBACzD,MAAM,IAAI,eAAe,CACvB,gCAAgC,GAAG,MAAM;wBACvC,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,UAAU,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK;wBACjD,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,UAAU,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAClD,CAAA;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,0EAA0E;QAC1E,wEAAwE;QACxE,2EAA2E;QAC3E,wEAAwE;QACxE,4EAA4E;QAC5E,uDAAuD;QACvD,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAC1C,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CACrE,CAAA;QACD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,eAAe,CACvB,8BAA8B,GAAG,yDAAyD;gBACxF,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAChE,CAAA;QACH,CAAC;QAED,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,KAAK,CAAA;IAC/B,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC"}
1
+ {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"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"}
package/dist/schemas.d.ts CHANGED
@@ -16,6 +16,7 @@ export declare const semverSchema: z.ZodString;
16
16
  export declare const assetNameSchema: z.ZodString;
17
17
  export declare const npmDependenciesSchema: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
18
18
  export declare const assetDependenciesSchema: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
19
+ export declare const skillDependenciesSchema: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
19
20
  export declare const updateProfileSchema: z.ZodObject<{
20
21
  name: z.ZodOptional<z.ZodString>;
21
22
  image: z.ZodOptional<z.ZodString>;
@@ -71,6 +72,7 @@ export declare const uploadZipSchema: z.ZodObject<{
71
72
  description: z.ZodOptional<z.ZodString>;
72
73
  npmDependencies: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
73
74
  assetDependencies: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
75
+ skillDependencies: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
74
76
  tags: z.ZodDefault<z.ZodArray<z.ZodString>>;
75
77
  }, z.core.$strip>;
76
78
  export declare const downloadZipSchema: z.ZodObject<{
@@ -1 +1 @@
1
- {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,WAAW,sIASd,CAAA;AACV,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAA;AAEpD,eAAO,MAAM,eAAe;;;;;;;;;EAAsB,CAAA;AAElD,eAAO,MAAM,yBAAyB,QAAqB,CAAA;AAE3D,eAAO,MAAM,YAAY,aAKtB,CAAA;AAEH,eAAO,MAAM,eAAe,aAUxB,CAAA;AAEJ,eAAO,MAAM,qBAAqB,qDAA+C,CAAA;AAEjF,eAAO,MAAM,uBAAuB,qDAA+C,CAAA;AAEnF,eAAO,MAAM,mBAAmB;;;iBAG9B,CAAA;AAEF,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;iBAO3B,CAAA;AAEF,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;iBAI3B,CAAA;AAEF,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;iBAQ1B,CAAA;AAEF,eAAO,MAAM,iBAAiB;;;iBAG5B,CAAA;AAEF,eAAO,MAAM,mBAAmB;;;;;;;;;;;;iBAG9B,CAAA"}
1
+ {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,WAAW,sIASd,CAAA;AACV,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAA;AAEpD,eAAO,MAAM,eAAe;;;;;;;;;EAAsB,CAAA;AAElD,eAAO,MAAM,yBAAyB,QAAqB,CAAA;AAE3D,eAAO,MAAM,YAAY,aAKtB,CAAA;AAEH,eAAO,MAAM,eAAe,aAUxB,CAAA;AAEJ,eAAO,MAAM,qBAAqB,qDAA+C,CAAA;AAEjF,eAAO,MAAM,uBAAuB,qDAA+C,CAAA;AAKnF,eAAO,MAAM,uBAAuB,qDAA+C,CAAA;AAEnF,eAAO,MAAM,mBAAmB;;;iBAG9B,CAAA;AAEF,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;iBAO3B,CAAA;AAEF,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;iBAI3B,CAAA;AAEF,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;iBAS1B,CAAA;AAEF,eAAO,MAAM,iBAAiB;;;iBAG5B,CAAA;AAEF,eAAO,MAAM,mBAAmB;;;;;;;;;;;;iBAG9B,CAAA"}
package/dist/schemas.js CHANGED
@@ -24,6 +24,10 @@ export const assetNameSchema = z
24
24
  });
25
25
  export const npmDependenciesSchema = z.record(z.string(), z.string()).default({});
26
26
  export const assetDependenciesSchema = z.record(z.string(), z.string()).default({});
27
+ // Maps a skill label to a `skills add` source: a remote ref (owner/repo,
28
+ // git/HTTP URL, tree/<branch>/<subpath>) or a local path to a skill directory
29
+ // shipped inside the asset.
30
+ export const skillDependenciesSchema = z.record(z.string(), z.string()).default({});
27
31
  export const updateProfileSchema = z.object({
28
32
  name: z.string().min(1).max(100).optional(),
29
33
  image: z.string().url().optional(),
@@ -48,6 +52,7 @@ export const uploadZipSchema = z.object({
48
52
  description: z.string().max(1000).optional(),
49
53
  npmDependencies: npmDependenciesSchema,
50
54
  assetDependencies: assetDependenciesSchema,
55
+ skillDependencies: skillDependenciesSchema,
51
56
  tags: z.array(z.string()).default([]),
52
57
  });
53
58
  export const downloadZipSchema = z.object({
@@ -1 +1 @@
1
- {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"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"}
package/dist/skill.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const marketSkill = "---\nname: market\ndescription: Find, preview, install, generate, and publish Drawcall Market assets from a coding agent.\n---\n\n# Drawcall Market\n\nUse the `market` CLI. Keep commands short and read the summary lines.\n\n## Quick Start\n\n```sh\nmarket search \"wooden chair\" --type model --limit 3\nmarket install wooden-chair --cwd \"$PWD\"\nmarket preview wooden-chair --out /tmp/wooden-chair.png\n```\n\n## Workflow\n\n1. Search first unless the user already gave an exact asset name. `search` requires `--type`; use `model` unless the user names another supported type: `humanoid-model`, `texture`, `humanoid-animation`, `template`, `sound-effect`, `background-music`, or `environment`.\n2. Use `--limit 1` for lookup, `--limit 3` for choice. Search caps at 5. Add `--verbose` only when the one-line descriptions are not enough.\n3. `install` takes one or more exact asset names (optionally `name@range`); it does not search or generate. Find names with `search` first. No `--type` is needed \u2014 asset names are unique.\n4. `preview <name>` saves the preview image; no `--type` is needed. Not every type has previews (e.g. `humanoid-animation`, `template`, `sound-effect`, `background-music`); the CLI reports when one is unavailable.\n5. Use `--unapproved` only when the user asks for unapproved/private/admin assets. Do not install unapproved assets without explicit acceptance.\n6. `generate --type <type> \"<prompt>\"` creates a new asset; it requires login and a type that supports generation. No asset type currently supports generation.\n7. Upload only when publishing is requested: `market upload <name> <zip> \"<description>\" --type <type>`.\n8. Installed `environment` assets contain `public/environment/<name>.hdr` for Three.js IBL lighting and `public/environment/<name>-background.webp` for the visible equirectangular background. Use `market preview` to fetch the preview image separately.\n\n## Output\n\nCommands print concise, line-oriented summaries:\n\n```text\nResults: 2/8 query=\"wooden chair\" type=model approval=approved\n- wooden-chair@1.0.0 | model | approved | Low-poly wooden chair\nInstalled:\n- wooden-chair@1.0.0 (asset)\n files:\n public/model\n \u2514\u2500 wooden-chair.glb\n- three@^0.178.0 (npm)\nSaved preview for wooden-chair@1.0.0: /tmp/wooden-chair.png\n```\n\nIf search returns no results, try one broader noun phrase. If a command returns `Error: Not logged in...`, ask before running `market login`.\n";
1
+ export declare const marketSkill = "---\nname: market\ndescription: Find, preview, install, generate, and publish Drawcall Market assets from a coding agent.\n---\n\n# Drawcall Market\n\nUse the `market` CLI. Keep commands short and read the summary lines.\n\n## Quick Start\n\n```sh\nmarket search \"wooden chair\" --type model --limit 3\nmarket install wooden-chair --cwd \"$PWD\"\nmarket preview wooden-chair --out /tmp/wooden-chair.png\n```\n\n## Workflow\n\n1. Search first unless the user already gave an exact asset name. `search` requires `--type`; use `model` unless the user names another supported type: `humanoid-model`, `texture`, `humanoid-animation`, `template`, `sound-effect`, `background-music`, or `environment`.\n2. Use `--limit 1` for lookup, `--limit 3` for choice. Search caps at 5. Add `--verbose` only when the one-line descriptions are not enough.\n3. `install` takes one or more exact asset names (optionally `name@range`); it does not search or generate. Find names with `search` first. No `--type` is needed \u2014 asset names are unique.\n4. `preview <name>` saves the preview image; no `--type` is needed. Not every type has previews (e.g. `humanoid-animation`, `template`, `sound-effect`, `background-music`); the CLI reports when one is unavailable.\n5. Use `--unapproved` only when the user asks for unapproved/private/admin assets. Do not install unapproved assets without explicit acceptance.\n6. `generate --type <type> \"<prompt>\"` creates a new asset; it requires login and a type that supports generation. No asset type currently supports generation.\n7. Upload only when publishing is requested: `market upload <name> <zip> \"<description>\" --type <type>`. Declare dependencies with repeatable flags: `--npm name@range`, `--asset name@range`, `--skill label=source` (source is a GitHub/git ref or a local path to a skill directory inside the zip). Example: `market upload my-scene scene.zip \"A scene\" --type model --npm three@^0.178.0 --skill web-design=vercel-labs/agent-skills`.\n8. Installed `environment` assets contain `public/environment/<name>.hdr` for Three.js IBL lighting and `public/environment/<name>-background.webp` for the visible equirectangular background. Use `market preview` to fetch the preview image separately.\n\n## Output\n\nCommands print concise, line-oriented summaries:\n\n```text\nResults: 2/8 query=\"wooden chair\" type=model approval=approved\n- wooden-chair@1.0.0 | model | approved | Low-poly wooden chair\nInstalled:\n- wooden-chair@1.0.0 (asset)\n files:\n public/model\n \u2514\u2500 wooden-chair.glb\n- three@^0.178.0 (npm)\n- web-design-guidelines \u2190 vercel-labs/agent-skills/tree/main/skills/web-design-guidelines (skill)\nSaved preview for wooden-chair@1.0.0: /tmp/wooden-chair.png\n```\n\nAssets may also declare `skill` dependencies, installed for you via the `skills` CLI (`skills add`) during `install`. Sources are either a GitHub/git ref or a local path to a skill directory shipped inside the asset. This requires `npx` to be available.\n\nIf search returns no results, try one broader noun phrase. If a command returns `Error: Not logged in...`, ask before running `market login`.\n";
2
2
  //# sourceMappingURL=skill.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../src/skill.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,s6EA6CvB,CAAA"}
1
+ {"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../src/skill.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,qlGAgDvB,CAAA"}
package/dist/skill.js CHANGED
@@ -23,7 +23,7 @@ market preview wooden-chair --out /tmp/wooden-chair.png
23
23
  4. \`preview <name>\` saves the preview image; no \`--type\` is needed. Not every type has previews (e.g. \`humanoid-animation\`, \`template\`, \`sound-effect\`, \`background-music\`); the CLI reports when one is unavailable.
24
24
  5. Use \`--unapproved\` only when the user asks for unapproved/private/admin assets. Do not install unapproved assets without explicit acceptance.
25
25
  6. \`generate --type <type> "<prompt>"\` creates a new asset; it requires login and a type that supports generation. No asset type currently supports generation.
26
- 7. Upload only when publishing is requested: \`market upload <name> <zip> "<description>" --type <type>\`.
26
+ 7. Upload only when publishing is requested: \`market upload <name> <zip> "<description>" --type <type>\`. Declare dependencies with repeatable flags: \`--npm name@range\`, \`--asset name@range\`, \`--skill label=source\` (source is a GitHub/git ref or a local path to a skill directory inside the zip). Example: \`market upload my-scene scene.zip "A scene" --type model --npm three@^0.178.0 --skill web-design=vercel-labs/agent-skills\`.
27
27
  8. Installed \`environment\` assets contain \`public/environment/<name>.hdr\` for Three.js IBL lighting and \`public/environment/<name>-background.webp\` for the visible equirectangular background. Use \`market preview\` to fetch the preview image separately.
28
28
 
29
29
  ## Output
@@ -39,9 +39,12 @@ Installed:
39
39
  public/model
40
40
  └─ wooden-chair.glb
41
41
  - three@^0.178.0 (npm)
42
+ - web-design-guidelines ← vercel-labs/agent-skills/tree/main/skills/web-design-guidelines (skill)
42
43
  Saved preview for wooden-chair@1.0.0: /tmp/wooden-chair.png
43
44
  \`\`\`
44
45
 
46
+ Assets may also declare \`skill\` dependencies, installed for you via the \`skills\` CLI (\`skills add\`) during \`install\`. Sources are either a GitHub/git ref or a local path to a skill directory shipped inside the asset. This requires \`npx\` to be available.
47
+
45
48
  If search returns no results, try one broader noun phrase. If a command returns \`Error: Not logged in...\`, ask before running \`market login\`.
46
49
  `;
47
50
  //# sourceMappingURL=skill.js.map
package/dist/skill.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"skill.js","sourceRoot":"","sources":["../src/skill.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6C1B,CAAA"}
1
+ {"version":3,"file":"skill.js","sourceRoot":"","sources":["../src/skill.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgD1B,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drawcall/market",
3
- "version": "0.1.27",
3
+ "version": "0.1.28",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/drawcall-ai/market",
@@ -28,6 +28,7 @@ export interface AssetUploadZipInput {
28
28
  description?: string
29
29
  npmDependencies: Record<string, string>
30
30
  assetDependencies: Record<string, string>
31
+ skillDependencies: Record<string, string>
31
32
  tags: string[]
32
33
  zip: File
33
34
  }
package/src/cli.ts CHANGED
@@ -24,6 +24,9 @@ const DEFAULT_BASE_URL = 'https://api.market.drawcall.ai'
24
24
  const AUTH_ISSUER_URL = 'https://auth.drawcall.ai/api/auth'
25
25
  const DEVICE_CLIENT_ID = 'market-cli'
26
26
 
27
+ /** Accumulate a repeatable option into an array. */
28
+ const collect = (value: string, previous: string[]): string[] => previous.concat(value)
29
+
27
30
  const typeOption = new Option('--type <type>', 'Asset type').choices([...ASSET_TYPES])
28
31
  const apiOption = new Option('--api <url>', 'API URL').default(
29
32
  process.env.MARKET_API_URL,
@@ -126,12 +129,23 @@ program
126
129
  .addOption(apiOption)
127
130
  .option('--version <version>', 'Explicit semver version')
128
131
  .option('--cwd <dir>', 'Project directory')
132
+ .option('--npm <dep>', 'npm dependency name@range (repeatable)', collect, [])
133
+ .option('--asset <dep>', 'asset dependency name@range (repeatable)', collect, [])
134
+ .option('--skill <dep>', 'skill dependency label=source (repeatable)', collect, [])
129
135
  .action(
130
136
  async (
131
137
  name: string,
132
138
  zipFilter: string,
133
139
  description: string,
134
- opts: { type?: AssetType; api?: string; version?: string; cwd?: string },
140
+ opts: {
141
+ type?: AssetType
142
+ api?: string
143
+ version?: string
144
+ cwd?: string
145
+ npm: string[]
146
+ asset: string[]
147
+ skill: string[]
148
+ },
135
149
  ) => {
136
150
  requireType(opts.type, 'Upload')
137
151
  await uploadCommand(name, zipFilter, description, {
@@ -139,6 +153,9 @@ program
139
153
  version: opts.version,
140
154
  baseUrl: opts.api,
141
155
  cwd: opts.cwd,
156
+ npm: opts.npm,
157
+ asset: opts.asset,
158
+ skill: opts.skill,
142
159
  })
143
160
  },
144
161
  )
@@ -12,6 +12,12 @@ export interface UploadCommandOptions {
12
12
  version?: string
13
13
  cwd?: string
14
14
  baseUrl?: string
15
+ /** npm dependencies, each `name@range` (range defaults to `*`). */
16
+ npm?: string[]
17
+ /** asset dependencies, each `name@range` (range defaults to `*`). */
18
+ asset?: string[]
19
+ /** skill dependencies, each `label=source` passed to `skills add`. */
20
+ skill?: string[]
15
21
  }
16
22
 
17
23
  export async function uploadCommand(
@@ -29,6 +35,10 @@ export async function uploadCommand(
29
35
  try {
30
36
  const parsedName = assetNameSchema.parse(name)
31
37
  const parsedVersion = opts.version ? semverSchema.parse(opts.version) : undefined
38
+ // Parse dep flags before any network work so a malformed spec fails fast.
39
+ const npmDependencies = parseVersionedDeps(opts.npm ?? [], 'npm')
40
+ const assetDependencies = parseVersionedDeps(opts.asset ?? [], 'asset')
41
+ const skillDependencies = parseSkillDeps(opts.skill ?? [])
32
42
  const cwd = opts.cwd ?? process.cwd()
33
43
  const type = opts.type
34
44
  const zipFile = await resolveOneZipFile(cwd, zipFilter)
@@ -58,7 +68,13 @@ export async function uploadCommand(
58
68
  version: existing.latestVersion,
59
69
  })
60
70
  const latestBytes = new Uint8Array(await latestZip.arrayBuffer())
61
- if (existing.description === description && bytesEqual(latestBytes, zip)) {
71
+ if (
72
+ existing.description === description &&
73
+ depsEqual(existing.npmDependencies, npmDependencies) &&
74
+ depsEqual(existing.assetDependencies, assetDependencies) &&
75
+ depsEqual(existing.skillDependencies, skillDependencies) &&
76
+ bytesEqual(latestBytes, zip)
77
+ ) {
62
78
  spinner.stop()
63
79
  console.log(unchangedUploadResult(parsedName, existing.latestVersion))
64
80
  return
@@ -72,8 +88,9 @@ export async function uploadCommand(
72
88
  type,
73
89
  version,
74
90
  description,
75
- npmDependencies: {},
76
- assetDependencies: {},
91
+ npmDependencies,
92
+ assetDependencies,
93
+ skillDependencies,
77
94
  tags: [],
78
95
  zip: new File([toArrayBuffer(zip)], `${parsedName}-${version}.zip`, {
79
96
  type: 'application/zip',
@@ -88,6 +105,65 @@ export async function uploadCommand(
88
105
  }
89
106
  }
90
107
 
108
+ /**
109
+ * Parse `name@range` specs (npm or asset deps) into a name→range record. The
110
+ * range is optional and defaults to `*`. A leading `@` is treated as a scope
111
+ * marker, so `@scope/pkg@^1.0.0` splits into `@scope/pkg` and `^1.0.0`.
112
+ */
113
+ export function parseVersionedDeps(specs: string[], kind: 'npm' | 'asset'): Record<string, string> {
114
+ const out: Record<string, string> = {}
115
+ for (const spec of specs) {
116
+ const at = spec.lastIndexOf('@')
117
+ const hasRange = at > 0
118
+ const name = hasRange ? spec.slice(0, at) : spec
119
+ const range = hasRange ? spec.slice(at + 1) : '*'
120
+ if (!name || !range) {
121
+ throw new Error(`Invalid ${kind} dependency "${spec}". Use name@range (e.g. three@^0.178.0).`)
122
+ }
123
+ if (name in out) {
124
+ throw new Error(`Duplicate ${kind} dependency "${name}".`)
125
+ }
126
+ out[name] = range
127
+ }
128
+ return out
129
+ }
130
+
131
+ /**
132
+ * Parse `label=source` specs into a label→source record. The source is passed
133
+ * verbatim to `skills add` (a GitHub/git ref or a local path), so only the
134
+ * first `=` is treated as the separator.
135
+ */
136
+ export function parseSkillDeps(specs: string[]): Record<string, string> {
137
+ const out: Record<string, string> = {}
138
+ for (const spec of specs) {
139
+ const eq = spec.indexOf('=')
140
+ if (eq <= 0 || eq === spec.length - 1) {
141
+ throw new Error(
142
+ `Invalid skill dependency "${spec}". Use label=source ` +
143
+ `(e.g. web-design=vercel-labs/agent-skills).`,
144
+ )
145
+ }
146
+ const label = spec.slice(0, eq)
147
+ if (label in out) {
148
+ throw new Error(`Duplicate skill dependency "${label}".`)
149
+ }
150
+ out[label] = spec.slice(eq + 1)
151
+ }
152
+ return out
153
+ }
154
+
155
+ /** Compare a stored dependency JSON string against a freshly parsed record. */
156
+ function depsEqual(storedJson: string, next: Record<string, string>): boolean {
157
+ let stored: Record<string, string>
158
+ try {
159
+ stored = JSON.parse(storedJson || '{}') as Record<string, string>
160
+ } catch {
161
+ return false
162
+ }
163
+ const keys = Object.keys(stored)
164
+ return keys.length === Object.keys(next).length && keys.every((key) => stored[key] === next[key])
165
+ }
166
+
91
167
  async function resolveOneZipFile(cwd: string, zipFilter: string): Promise<string> {
92
168
  const absolute = path.resolve(cwd, zipFilter)
93
169
  const stat = await maybeStat(absolute)
package/src/contract.ts CHANGED
@@ -17,6 +17,7 @@ export interface AssetVersion {
17
17
  approved: boolean
18
18
  npmDependencies: string
19
19
  assetDependencies: string
20
+ skillDependencies: string
20
21
  sourceKey: string
21
22
  createdAt: Date
22
23
  }
@@ -43,6 +44,7 @@ export interface AssetSearchResult {
43
44
  approved: boolean
44
45
  npmDependencies: string
45
46
  assetDependencies: string
47
+ skillDependencies: string
46
48
  }
47
49
 
48
50
  export interface PaginatedList<T> {
package/src/index.ts CHANGED
@@ -43,6 +43,7 @@ export {
43
43
  assetNameSchema,
44
44
  npmDependenciesSchema,
45
45
  assetDependenciesSchema,
46
+ skillDependenciesSchema,
46
47
  uploadZipSchema,
47
48
  downloadZipSchema,
48
49
  exactAssetSchema,
package/src/install.ts CHANGED
@@ -4,11 +4,13 @@
4
4
  * 1. Downloads public asset files into ./public/... via the oRPC client.
5
5
  * 2. Merges npm dependencies into package.json.
6
6
  * 3. Runs the package manager to install npm deps.
7
+ * 4. Installs skill dependencies via the `skills` CLI (`skills add <source>`).
7
8
  *
8
- * NOTE: This module uses Node.js APIs (fs, path, nypm) and is only
9
- * used by the CLI binary; it is NOT exported from the package index.
9
+ * NOTE: This module uses Node.js APIs (fs, path, nypm, child_process) and is
10
+ * only used by the CLI binary; it is NOT exported from the package index.
10
11
  */
11
12
 
13
+ import { execFile } from 'child_process'
12
14
  import * as fs from 'fs/promises'
13
15
  import * as path from 'path'
14
16
  import { unzipSync } from 'fflate'
@@ -28,6 +30,12 @@ export interface InstallOptions {
28
30
  cwd?: string
29
31
  /** Log progress */
30
32
  onProgress?: (message: string) => void
33
+ /**
34
+ * Override how a single resolved skill source is installed. The default
35
+ * shells out to `npx skills add <source> -y`. Exposed for tests and for
36
+ * callers that want to drive a different skills runner.
37
+ */
38
+ runSkillAdd?: (source: string, cwd: string) => Promise<void>
31
39
  }
32
40
 
33
41
  export interface InstalledAsset {
@@ -39,6 +47,8 @@ export interface InstalledAsset {
39
47
  export interface InstallResult {
40
48
  assets: InstalledAsset[]
41
49
  npmDependencies: Record<string, string>
50
+ /** Installed skills, keyed by label, with the source passed to `skills add`. */
51
+ skillDependencies: Record<string, string>
42
52
  }
43
53
 
44
54
  export async function install(
@@ -54,28 +64,34 @@ export async function install(
54
64
  installNpmDeps(resolution, installRoot, log),
55
65
  ])
56
66
 
67
+ // Skills are installed after asset files land on disk: a skill source may be
68
+ // a local path pointing at a skill directory shipped inside an installed
69
+ // asset, which only exists once downloadAssets has completed.
70
+ const skillDependencies = await installSkills(
71
+ resolution,
72
+ installRoot,
73
+ log,
74
+ opts.runSkillAdd ?? defaultRunSkillAdd,
75
+ )
76
+
57
77
  return {
58
78
  assets,
59
79
  npmDependencies: resolution.npmDependencies,
80
+ skillDependencies,
60
81
  }
61
82
  }
62
83
 
63
84
  export async function findInstallRoot(cwd: string = process.cwd()): Promise<string> {
64
85
  const start = path.resolve(cwd)
65
- let packageRoot: string | null = null
66
86
 
67
- let dir = start
68
- while (true) {
87
+ for (let dir = start; ; dir = path.dirname(dir)) {
69
88
  if (await isFile(path.join(dir, 'package.json'))) {
70
- packageRoot = dir
89
+ return dir
90
+ }
91
+ if (path.dirname(dir) === dir) {
92
+ return start
71
93
  }
72
-
73
- const parent = path.dirname(dir)
74
- if (parent === dir) break
75
- dir = parent
76
94
  }
77
-
78
- return packageRoot ?? start
79
95
  }
80
96
 
81
97
  async function downloadAssets(
@@ -165,3 +181,64 @@ async function installNpmDeps(
165
181
  await installDependencies({ cwd: projectRoot, packageManager: { name: pmName, command: pmName } })
166
182
  log('npm dependencies installed.')
167
183
  }
184
+
185
+ async function installSkills(
186
+ resolution: ResolveResult,
187
+ projectRoot: string,
188
+ log: (msg: string) => void,
189
+ runSkillAdd: (source: string, cwd: string) => Promise<void>,
190
+ ): Promise<Record<string, string>> {
191
+ const skills = resolution.skillDependencies ?? {}
192
+ const entries = Object.entries(skills)
193
+ if (entries.length === 0) return {}
194
+
195
+ for (const [label, source] of entries) {
196
+ const resolvedSource = resolveSkillSource(source, projectRoot)
197
+ log(`Installing skill ${label} (${source})...`)
198
+ await runSkillAdd(resolvedSource, projectRoot)
199
+ }
200
+
201
+ log(`Skills installed: ${entries.map(([label]) => label).join(', ')}`)
202
+ return skills
203
+ }
204
+
205
+ /**
206
+ * Resolve a skill source to the argument passed to `skills add`. Local paths
207
+ * (`./`, `../`, `.`, `..`, or absolute) are resolved against the install root
208
+ * so they point at a skill directory shipped inside an installed asset; every
209
+ * other form (GitHub shorthand, git/HTTP(S) URL, `tree/<branch>/<subpath>`) is
210
+ * a remote ref and is passed through untouched.
211
+ */
212
+ function resolveSkillSource(source: string, projectRoot: string): string {
213
+ return isLocalSkillPath(source) ? path.resolve(projectRoot, source) : source
214
+ }
215
+
216
+ function isLocalSkillPath(source: string): boolean {
217
+ return (
218
+ path.isAbsolute(source) ||
219
+ source === '.' ||
220
+ source === '..' ||
221
+ source.startsWith('./') ||
222
+ source.startsWith('../') ||
223
+ /^[a-zA-Z]:[/\\]/.test(source)
224
+ )
225
+ }
226
+
227
+ /**
228
+ * Install one skill via `npx skills add <source> -y`. When run inside a coding
229
+ * agent the `skills` CLI auto-detects the agent and installs non-interactively;
230
+ * `-y` keeps it non-interactive everywhere else. npx resolves (and caches) the
231
+ * `skills` package on first use.
232
+ */
233
+ function defaultRunSkillAdd(source: string, cwd: string): Promise<void> {
234
+ return new Promise((resolve, reject) => {
235
+ execFile('npx', ['--yes', 'skills', 'add', source, '-y'], { cwd }, (error, _stdout, stderr) => {
236
+ if (error) {
237
+ const detail = stderr.trim() || error.message
238
+ reject(new Error(`Failed to install skill "${source}": ${detail}`))
239
+ return
240
+ }
241
+ resolve()
242
+ })
243
+ })
244
+ }
package/src/output.ts CHANGED
@@ -57,6 +57,15 @@ export function installResult(result: InstallResult): string {
57
57
  )
58
58
  }
59
59
 
60
+ const skillDependencies = Object.entries(result.skillDependencies ?? {})
61
+ if (skillDependencies.length > 0) {
62
+ lines.push(
63
+ ...skillDependencies
64
+ .sort(([a], [b]) => a.localeCompare(b))
65
+ .map(([label, source]) => `- ${label} ← ${source} (skill)`),
66
+ )
67
+ }
68
+
60
69
  return lines.join('\n')
61
70
  }
62
71
 
package/src/resolve.ts CHANGED
@@ -18,11 +18,13 @@ export interface ResolvedAsset {
18
18
  version: string
19
19
  npmDependencies: Record<string, string>
20
20
  assetDependencies: Record<string, string>
21
+ skillDependencies: Record<string, string>
21
22
  }
22
23
 
23
24
  export interface ResolveResult {
24
25
  assets: ResolvedAsset[]
25
26
  npmDependencies: Record<string, string>
27
+ skillDependencies: Record<string, string>
26
28
  }
27
29
 
28
30
  interface AssetRequest {
@@ -79,12 +81,14 @@ export async function resolve(
79
81
 
80
82
  const npmDeps = parseDependencies(meta.npmDependencies, assetName, 'npm')
81
83
  const assetDeps = parseDependencies(meta.assetDependencies, assetName, 'asset')
84
+ const skillDeps = parseDependencies(meta.skillDependencies, assetName, 'skill')
82
85
 
83
86
  resolved.set(assetName, {
84
87
  name: assetName,
85
88
  version: meta.latestVersion,
86
89
  npmDependencies: npmDeps,
87
90
  assetDependencies: assetDeps,
91
+ skillDependencies: skillDeps,
88
92
  })
89
93
 
90
94
  for (const [depName, depRange] of Object.entries(assetDeps)) {
@@ -109,19 +113,49 @@ export async function resolve(
109
113
  }
110
114
  }
111
115
 
112
- // Merge npm dependencies across all resolved assets
116
+ // Merge npm and skill dependencies across all resolved assets
113
117
  const mergedNpm = mergeNpmDependencies(Array.from(resolved.values()))
118
+ const mergedSkills = mergeSkillDependencies(Array.from(resolved.values()))
114
119
 
115
120
  return {
116
121
  assets: Array.from(resolved.values()),
117
122
  npmDependencies: mergedNpm,
123
+ skillDependencies: mergedSkills,
118
124
  }
119
125
  }
120
126
 
127
+ /**
128
+ * Merge skill dependencies from all resolved assets. Skills are not versioned
129
+ * by the resolver — each entry is a label mapped to a `skills add` source — so
130
+ * the merge is a simple union. The same label declared by two assets must point
131
+ * at the same source; otherwise installing one would silently shadow the other.
132
+ */
133
+ function mergeSkillDependencies(assets: ResolvedAsset[]): Record<string, string> {
134
+ const merged: Record<string, string> = {}
135
+ const origin: Record<string, string> = {}
136
+
137
+ for (const asset of assets) {
138
+ const from = `${asset.name}@${asset.version}`
139
+ for (const [label, source] of Object.entries(asset.skillDependencies)) {
140
+ if (label in merged && merged[label] !== source) {
141
+ throw new ResolutionError(
142
+ `skill dependency conflict for "${label}":\n` +
143
+ ` ${merged[label]} (from ${origin[label]})\n` +
144
+ ` ${source} (from ${from})`,
145
+ )
146
+ }
147
+ merged[label] = source
148
+ origin[label] = from
149
+ }
150
+ }
151
+
152
+ return merged
153
+ }
154
+
121
155
  function parseDependencies(
122
156
  value: string,
123
157
  assetName: string,
124
- kind: 'npm' | 'asset',
158
+ kind: 'npm' | 'asset' | 'skill',
125
159
  ): Record<string, string> {
126
160
  try {
127
161
  const parsed = JSON.parse(value || '{}') as unknown