@@ -13,6 +13,7 @@ import (
1313 "strconv"
1414 "strings"
1515
16+ "github.com/google/go-containerregistry/pkg/v1/tarball"
1617 ocispec "github.com/opencontainers/image-spec/specs-go/v1"
1718
1819 "github.com/mudler/LocalAI/pkg/oci"
@@ -25,6 +26,7 @@ const (
2526 HuggingFacePrefix1 = "hf://"
2627 HuggingFacePrefix2 = "hf.co/"
2728 OCIPrefix = "oci://"
29+ OCIFilePrefix = "ocifile://"
2830 OllamaPrefix = "ollama://"
2931 HTTPPrefix = "http://"
3032 HTTPSPrefix = "https://"
@@ -137,8 +139,18 @@ func (u URI) LooksLikeURL() bool {
137139 strings .HasPrefix (string (u ), GithubURI2 )
138140}
139141
142+ func (u URI ) LooksLikeHTTPURL () bool {
143+ return strings .HasPrefix (string (u ), HTTPPrefix ) ||
144+ strings .HasPrefix (string (u ), HTTPSPrefix )
145+ }
146+
140147func (s URI ) LooksLikeOCI () bool {
141- return strings .HasPrefix (string (s ), OCIPrefix ) || strings .HasPrefix (string (s ), OllamaPrefix )
148+ return strings .HasPrefix (string (s ), "quay.io" ) ||
149+ strings .HasPrefix (string (s ), OCIPrefix ) ||
150+ strings .HasPrefix (string (s ), OllamaPrefix ) ||
151+ strings .HasPrefix (string (s ), OCIFilePrefix ) ||
152+ strings .HasPrefix (string (s ), "ghcr.io" ) ||
153+ strings .HasPrefix (string (s ), "docker.io" )
142154}
143155
144156func (s URI ) ResolveURL () string {
@@ -234,6 +246,13 @@ func (uri URI) checkSeverSupportsRangeHeader() (bool, error) {
234246func (uri URI ) DownloadFile (filePath , sha string , fileN , total int , downloadStatus func (string , string , string , float64 )) error {
235247 url := uri .ResolveURL ()
236248 if uri .LooksLikeOCI () {
249+
250+ // Only Ollama wants to download to the file, for the rest, we want to download to the directory
251+ // so we check if filepath has any extension, otherwise we assume it's a directory
252+ if filepath .Ext (filePath ) != "" && ! strings .HasPrefix (url , OllamaPrefix ) {
253+ filePath = filepath .Dir (filePath )
254+ }
255+
237256 progressStatus := func (desc ocispec.Descriptor ) io.Writer {
238257 return & progressWriter {
239258 fileName : filePath ,
@@ -245,18 +264,32 @@ func (uri URI) DownloadFile(filePath, sha string, fileN, total int, downloadStat
245264 }
246265 }
247266
248- if strings .HasPrefix (url , OllamaPrefix ) {
249- url = strings .TrimPrefix (url , OllamaPrefix )
267+ if url , ok := strings .CutPrefix (url , OllamaPrefix ); ok {
250268 return oci .OllamaFetchModel (url , filePath , progressStatus )
251269 }
252270
271+ if url , ok := strings .CutPrefix (url , OCIFilePrefix ); ok {
272+ // Open the tarball
273+ img , err := tarball .ImageFromPath (url , nil )
274+ if err != nil {
275+ return fmt .Errorf ("failed to open tarball: %s" , err .Error ())
276+ }
277+
278+ return oci .ExtractOCIImage (img , url , filePath , downloadStatus )
279+ }
280+
253281 url = strings .TrimPrefix (url , OCIPrefix )
254282 img , err := oci .GetImage (url , "" , nil , nil )
255283 if err != nil {
256284 return fmt .Errorf ("failed to get image %q: %v" , url , err )
257285 }
258286
259- return oci .ExtractOCIImage (img , url , filepath .Dir (filePath ), downloadStatus )
287+ return oci .ExtractOCIImage (img , url , filePath , downloadStatus )
288+ }
289+
290+ // We need to check if url looks like an URL or bail out
291+ if ! uri .LooksLikeHTTPURL () {
292+ return fmt .Errorf ("url %q does not look like an HTTP URL" , url )
260293 }
261294
262295 // Check if the file already exists
0 commit comments