11import { lstat , readFile , realpath , readdir } from "node:fs/promises" ;
22import { basename , dirname , relative , resolve } from "node:path" ;
33
4- import { SkillOsError , containedPath , sha256 , slash , stableName , utf8Compare } from "./common.mjs" ;
4+ import { SkillOsError , containedPath , portableResourceBytes , sha256 , slash , stableName , utf8Compare } from "./common.mjs" ;
55
66const BODY_LIMIT = 96 * 1024 ;
77const REFERENCE_LIMIT = 256 * 1024 ;
@@ -112,7 +112,8 @@ async function resourceFiles(skillRoot, folder, limit) {
112112 if ( ( folder === "references" || folder === "scripts" || folder === "agents" ) && bytes . includes ( 0 ) ) {
113113 fail ( "SKILL_STRUCTURE_INVALID" , `text resource contains NUL: ${ relativePath } ` ) ;
114114 }
115- output . push ( Object . freeze ( { path : relativePath , bytes : bytes . byteLength , sha256 : sha256 ( bytes ) } ) ) ;
115+ const portable = portableResourceBytes ( relativePath , bytes ) ;
116+ output . push ( Object . freeze ( { path : relativePath , bytes : portable . byteLength , sha256 : sha256 ( portable ) } ) ) ;
116117 }
117118 }
118119 }
@@ -131,6 +132,7 @@ export async function parseSkill(skillPath, { skillsRoot = dirname(skillPath) }
131132 try { text = TEXT_DECODER . decode ( bytes ) ; }
132133 catch { fail ( "SKILL_STRUCTURE_INVALID" , "SKILL.md is not valid UTF-8" ) ; }
133134 text = text . replaceAll ( "\r\n" , "\n" ) . replaceAll ( "\r" , "\n" ) ;
135+ const portable = Buffer . from ( text ) ;
134136 const frontmatter = parseFrontmatter ( text ) ;
135137 if ( ! stableName ( frontmatter . name ) ) fail ( "SKILL_FRONTMATTER_INVALID" , `invalid skill name: ${ frontmatter . name } ` ) ;
136138 if ( frontmatter . name !== basename ( directory ) ) fail ( "SKILL_NAME_MISMATCH" , `${ frontmatter . name } does not match ${ basename ( directory ) } ` ) ;
@@ -149,8 +151,8 @@ export async function parseSkill(skillPath, { skillsRoot = dirname(skillPath) }
149151 ] ) ;
150152 if ( references . length > 8 ) fail ( "SKILL_RESOURCE_LIMIT" , "a skill may declare at most eight direct references" ) ;
151153 return Object . freeze ( { name : frontmatter . name , description : frontmatter . description ,
152- path : slash ( relative ( resolve ( skillsRoot ) , path ) ) , sourcePath : path , bytes : bytes . byteLength ,
153- sha256 : sha256 ( bytes ) , normalizedSha256 : sha256 ( Buffer . from ( text ) ) , headings,
154+ path : slash ( relative ( resolve ( skillsRoot ) , path ) ) , sourcePath : path , bytes : portable . byteLength ,
155+ sha256 : sha256 ( portable ) , normalizedSha256 : sha256 ( portable ) , headings,
154156 references, scripts, assets, agents } ) ;
155157}
156158
0 commit comments