@@ -5,6 +5,8 @@ const { execSync } = require("child_process");
55const {
66 parseSource,
77 getGitHubAssets,
8+ getWebsiteAssets,
9+ trySmartDownload,
810 downloadFromUrl,
911 findInstallScripts,
1012 hasHighPriorityInstallScript,
@@ -78,6 +80,26 @@ const performInstallation = async (args, isUpdate = false) => {
7880 case "url" :
7981 selected = await handleUrlSource ( source , log ) ;
8082 break ;
83+ case "smart_url" :
84+ const smartResult = await handleSmartUrlSource (
85+ source ,
86+ platformInfo ,
87+ capabilities ,
88+ log
89+ ) ;
90+ selected = smartResult . selected ;
91+ releaseInfo = smartResult . releaseInfo ;
92+ break ;
93+ case "website" :
94+ const websiteResult = await handleWebsiteSource (
95+ source ,
96+ platformInfo ,
97+ capabilities ,
98+ log
99+ ) ;
100+ selected = websiteResult . selected ;
101+ releaseInfo = websiteResult . releaseInfo ;
102+ break ;
81103 case "github" :
82104 const result = await handleGitHubSource (
83105 source ,
@@ -176,6 +198,128 @@ const handleUrlSource = async (source, log) => {
176198 } ;
177199} ;
178200
201+ const handleSmartUrlSource = async (
202+ source ,
203+ platformInfo ,
204+ capabilities ,
205+ log
206+ ) => {
207+ log . debug ( `Attempting smart download from: ${ source . url } ` ) ;
208+
209+ const result = await trySmartDownload ( source . url , log ) ;
210+
211+ if ( result . type === "direct_download" ) {
212+ // It was a direct download
213+ log . debug ( `Direct download: ${ result . filename } (${ result . size } bytes)` ) ;
214+
215+ // Write the buffer to a temporary file
216+ const tempFilename = path . join ( tmpdir , result . filename ) ;
217+ fs . writeFileSync ( tempFilename , result . buffer ) ;
218+
219+ const extension = require ( "./sources" ) . getExtension ( result . filename ) ;
220+
221+ return {
222+ selected : {
223+ name : result . filename ,
224+ size : result . size ,
225+ extension : extension ,
226+ browser_download_url : result . url ,
227+ localPath : tempFilename ,
228+ } ,
229+ releaseInfo : { body : `Direct download of ${ result . filename } ` } ,
230+ } ;
231+ } else if ( result . type === "scraped_assets" ) {
232+ // It was HTML, so we scraped it for assets
233+ log . debug ( `Found ${ result . assets . length } potential assets from HTML` ) ;
234+
235+ if ( result . assets . length > 0 ) {
236+ log . debug ( "Assets found:" ) ;
237+ result . assets . forEach ( ( asset , index ) => {
238+ log . debug (
239+ ` ${ index + 1 } . ${ asset . name } (ext: ${
240+ asset . extension || "none"
241+ } , url: ${ asset . browser_download_url } )`
242+ ) ;
243+ } ) ;
244+ }
245+
246+ // Try to find a suitable asset using the same logic as GitHub
247+ const selected = selectBestAsset ( result . assets , platformInfo , capabilities ) ;
248+
249+ if ( ! selected ) {
250+ // List available assets to help user
251+ log . log ( "No compatible assets found. Available downloads:" ) ;
252+ result . assets . forEach ( ( asset , index ) => {
253+ log . log (
254+ ` ${ index + 1 } . ${ asset . name } (${
255+ asset . extension || "no extension"
256+ } ) - ${ asset . browser_download_url } `
257+ ) ;
258+ } ) ;
259+
260+ throw new Error (
261+ `Couldn't find a compatible download for ${ platformInfo . platform } /${ platformInfo . arch } . ` +
262+ `Check manually: ${ source . url } `
263+ ) ;
264+ }
265+
266+ log . debug ( `Selected asset: ${ selected . name } (${ selected . extension } )` ) ;
267+
268+ return {
269+ selected,
270+ releaseInfo : { body : result . body } ,
271+ } ;
272+ }
273+
274+ throw new Error ( "Unexpected result from smart download" ) ;
275+ } ;
276+
277+ const handleWebsiteSource = async ( source , platformInfo , capabilities , log ) => {
278+ log . debug ( `Scraping website for downloadable assets: ${ source . url } ` ) ;
279+
280+ const { assets, body } = await getWebsiteAssets ( source . url ) ;
281+
282+ log . debug ( `Found ${ assets . length } potential assets` ) ;
283+
284+ if ( assets . length > 0 ) {
285+ log . debug ( "Assets found:" ) ;
286+ assets . forEach ( ( asset , index ) => {
287+ log . debug (
288+ ` ${ index + 1 } . ${ asset . name } (ext: ${
289+ asset . extension || "none"
290+ } , url: ${ asset . browser_download_url } )`
291+ ) ;
292+ } ) ;
293+ }
294+
295+ // Try to find a suitable asset using the same logic as GitHub
296+ const selected = selectBestAsset ( assets , platformInfo , capabilities ) ;
297+
298+ if ( ! selected ) {
299+ // List available assets to help user
300+ log . log ( "No compatible assets found. Available downloads:" ) ;
301+ assets . forEach ( ( asset , index ) => {
302+ log . log (
303+ ` ${ index + 1 } . ${ asset . name } (${
304+ asset . extension || "no extension"
305+ } ) - ${ asset . browser_download_url } `
306+ ) ;
307+ } ) ;
308+
309+ throw new Error (
310+ `Couldn't find a compatible download for ${ platformInfo . platform } /${ platformInfo . arch } . ` +
311+ `Check manually: ${ source . url } `
312+ ) ;
313+ }
314+
315+ log . debug ( `Selected asset: ${ selected . name } (${ selected . extension } )` ) ;
316+
317+ return {
318+ selected,
319+ releaseInfo : { body } ,
320+ } ;
321+ } ;
322+
179323const displayScriptPreview = ( script , log ) => {
180324 const { code, source, score } = script ;
181325 log . debug (
0 commit comments