@@ -116,36 +116,84 @@ async function fetchLatestDownloadUrl(
116116 try {
117117 let apiPlatform = platform ;
118118 let isSystemVersion = false ;
119+ let isUserVersion = false ;
119120
120- // Handle system version URLs
121+ // Handle system/user version URLs
121122 if ( platform . endsWith ( "-system" ) ) {
122123 apiPlatform = platform . replace ( "-system" , "" ) ;
123124 isSystemVersion = true ;
125+ } else if ( platform . endsWith ( "-user" ) ) {
126+ isUserVersion = true ;
127+ }
128+ let downloadUrl : string | null = null ;
129+
130+ // Prefer new prerelease update endpoint for all platforms
131+ let normalizedPlatform : string | null = null ;
132+ if ( apiPlatform . includes ( "win32-x64" ) ) normalizedPlatform = "win32-x64" ;
133+ else if ( apiPlatform . includes ( "win32-arm64" ) ) normalizedPlatform = "win32-arm64" ;
134+ else if ( apiPlatform . includes ( "darwin-universal" ) ) normalizedPlatform = "darwin-universal" ;
135+ else if ( apiPlatform . includes ( "darwin-arm64" ) ) normalizedPlatform = "darwin-arm64" ;
136+ else if ( apiPlatform . includes ( "darwin-x64" ) ) normalizedPlatform = "darwin-x64" ;
137+ else if ( apiPlatform . includes ( "linux-x64" ) ) normalizedPlatform = "linux-x64" ;
138+ else if ( apiPlatform . includes ( "linux-arm64" ) ) normalizedPlatform = "linux-arm64" ;
139+
140+ if ( normalizedPlatform ) {
141+ const prereleaseUrl = `https://api2.cursor.sh/updates/api/update/${ normalizedPlatform } /cursor/1.0.0/hash/prerelease` ;
142+ try {
143+ const preResp = await fetch ( prereleaseUrl , {
144+ headers : {
145+ "Accept" : "application/json" ,
146+ "User-Agent" :
147+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" ,
148+ "Cache-Control" : "no-cache" ,
149+ } ,
150+ } ) ;
151+ if ( preResp . ok ) {
152+ const preData = ( await preResp . json ( ) ) as unknown as {
153+ url ?: string ;
154+ downloadUrl ?: string ;
155+ } ;
156+ downloadUrl = preData . url || preData . downloadUrl || null ;
157+ }
158+ } catch ( e ) {
159+ // Silently fall back to legacy endpoint below
160+ }
124161 }
125162
126- const response = await fetch (
127- `https://www.cursor.com/api/download?platform=${ apiPlatform } &releaseTrack=latest` ,
128- {
129- headers : {
130- "User-Agent" :
131- "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" ,
132- "Cache-Control" : "no-cache" ,
163+ // Fallback to legacy latest endpoint if prerelease not available or for non-Windows
164+ if ( ! downloadUrl ) {
165+ const response = await fetch (
166+ `https://www.cursor.com/api/download?platform=${ apiPlatform } &releaseTrack=latest` ,
167+ {
168+ headers : {
169+ "User-Agent" :
170+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" ,
171+ "Cache-Control" : "no-cache" ,
172+ } ,
133173 } ,
134- } ,
135- ) ;
174+ ) ;
136175
137- if ( ! response . ok ) {
138- throw new Error ( `HTTP error! status: ${ response . status } ` ) ;
139- }
176+ if ( ! response . ok ) {
177+ throw new Error ( `HTTP error! status: ${ response . status } ` ) ;
178+ }
140179
141- const data = ( await response . json ( ) ) as DownloadResponse ;
142- let downloadUrl = data . downloadUrl ;
180+ const data = ( await response . json ( ) ) as DownloadResponse ;
181+ downloadUrl = data . downloadUrl ;
182+ }
143183
144- if ( isSystemVersion ) {
145- downloadUrl = downloadUrl . replace (
146- "user-setup/CursorUserSetup" ,
147- "system-setup/CursorSetup" ,
148- ) ;
184+ // Ensure correct variant (system/user) according to requested platform
185+ if ( downloadUrl ) {
186+ if ( isSystemVersion ) {
187+ downloadUrl = downloadUrl . replace (
188+ "user-setup/CursorUserSetup" ,
189+ "system-setup/CursorSetup" ,
190+ ) ;
191+ } else if ( isUserVersion ) {
192+ downloadUrl = downloadUrl . replace (
193+ "system-setup/CursorSetup" ,
194+ "user-setup/CursorUserSetup" ,
195+ ) ;
196+ }
149197 }
150198
151199 return downloadUrl ;
0 commit comments