Add onlyRetrieveFromCache option to Glide RequestOptions

<|original_code|>
    ResourceCallback cb = mock(ResourceCallback.class);
    @SuppressWarnings("rawtypes")
    EngineResource resource = mock(EngineResource.class);
    Map<Key, EngineJob<?>> jobs = new HashMap<>();
    Map<Key, WeakReference<EngineResource<?>>> activeResources = new HashMap<>();

    int width = 100;
    int height = 100;

    Object model = new Object();
    MemoryCache cache = mock(MemoryCache.class);
    EngineJob<?> job;
    Engine engine;
    Engine.EngineJobFactory engineJobFactory = mock(Engine.EngineJobFactory.class);
    Engine.DecodeJobFactory decodeJobFactory = mock(Engine.DecodeJobFactory.class);
    ResourceRecycler resourceRecycler = mock(ResourceRecycler.class);
    Key signature = mock(Key.class);
    Map<Class<?>, Transformation<?>> transformations = new HashMap<>();
    Options options = new Options();
    GlideContext glideContext = mock(GlideContext.class);
    boolean isMemoryCacheable = true;
    boolean useUnlimitedSourceGeneratorPool = false;

    public EngineTestHarness() {
      when(keyFactory.buildKey(eq(model), eq(signature), anyInt(), anyInt(), eq(transformations),
          eq(Object.class), eq(Object.class), eq(options))).thenReturn(cacheKey);

      job = mock(EngineJob.class);

      engine = new Engine(cache, mock(DiskCache.Factory.class),
          GlideExecutor.newDiskCacheExecutor(),
          MockGlideExecutor.newMainThreadExecutor(),
          MockGlideExecutor.newMainThreadUnlimitedExecutor(),
          jobs, keyFactory, activeResources,
          engineJobFactory, decodeJobFactory, resourceRecycler);
    }

    public Engine.LoadStatus doLoad() {
      when(engineJobFactory.build(eq(cacheKey), anyBoolean(), anyBoolean()))
          .thenReturn((EngineJob<Object>) job);
      return engine.load(glideContext,
          model,
          signature,
          width,
          height,
          Object.class /*resourceClass*/,
          Object.class /*transcodeClass*/,
          Priority.HIGH,
          DiskCacheStrategy.ALL,
          transformations,
          false /*isTransformationRequired*/,
          options,
          isMemoryCacheable,
          useUnlimitedSourceGeneratorPool,
          cb);
    }
  }
}

<|edits_diff|>
--- library/src/test/java/com/bumptech/glide/load/engine/EngineTest.java
+++ library/src/test/java/com/bumptech/glide/load/engine/EngineTest.java
@@ -20,6 +20,7 @@
     GlideContext glideContext = mock(GlideContext.class);
     boolean isMemoryCacheable = true;
     boolean useUnlimitedSourceGeneratorPool = false;
+    boolean onlyRetrieveFromCache = false;

     public EngineTestHarness() {
       when(keyFactory.buildKey(eq(model), eq(signature), anyInt(), anyInt(), eq(transformations),
<|current_version|>
    ResourceCallback cb = mock(ResourceCallback.class);
    @SuppressWarnings("rawtypes")
    EngineResource resource = mock(EngineResource.class);
    Map<Key, EngineJob<?>> jobs = new HashMap<>();
    Map<Key, WeakReference<EngineResource<?>>> activeResources = new HashMap<>();

    int width = 100;
    int height = 100;

    Object model = new Object();
    MemoryCache cache = mock(MemoryCache.class);
    EngineJob<?> job;
    Engine engine;
    Engine.EngineJobFactory engineJobFactory = mock(Engine.EngineJobFactory.class);
    Engine.DecodeJobFactory decodeJobFactory = mock(Engine.DecodeJobFactory.class);
    ResourceRecycler resourceRecycler = mock(ResourceRecycler.class);
    Key signature = mock(Key.class);
    Map<Class<?>, Transformation<?>> transformations = new HashMap<>();
    Options options = new Options();
    GlideContext glideContext = mock(GlideContext.class);
    boolean isMemoryCacheable = true;
    boolean useUnlimitedSourceGeneratorPool = false;
    boolean onlyRetrieveFromCache = false;

    public EngineTestHarness() {
      when(keyFactory.buildKey(eq(model), eq(signature), anyInt(), anyInt(), eq(transformations),
          eq(Object.class), eq(Object.class), eq(options))).thenReturn(cacheKey);

      job = mock(EngineJob.class);

      engine = new Engine(cache, mock(DiskCache.Factory.class),
          GlideExecutor.newDiskCacheExecutor(),
          MockGlideExecutor.newMainThreadExecutor(),
          MockGlideExecutor.newMainThreadUnlimitedExecutor(),
          jobs, keyFactory, activeResources,
          engineJobFactory, decodeJobFactory, resourceRecycler);
    }

    public Engine.LoadStatus doLoad() {
      when(engineJobFactory.build(eq(cacheKey), anyBoolean(), anyBoolean()))
          .thenReturn((EngineJob<Object>) job);
      return engine.load(glideContext,
          model,
          signature,
          width,
          height,
          Object.class /*resourceClass*/,
          Object.class /*transcodeClass*/,
          Priority.HIGH,
          DiskCacheStrategy.ALL,
          transformations,
          false /*isTransformationRequired*/,
          options,
          isMemoryCacheable,
          useUnlimitedSourceGeneratorPool,
          cb);
    }
  }
}

<|next_version|>
    ResourceCallback cb = mock(ResourceCallback.class);
    @SuppressWarnings("rawtypes")
    EngineResource resource = mock(EngineResource.class);
    Map<Key, EngineJob<?>> jobs = new HashMap<>();
    Map<Key, WeakReference<EngineResource<?>>> activeResources = new HashMap<>();

    int width = 100;
    int height = 100;

    Object model = new Object();
    MemoryCache cache = mock(MemoryCache.class);
    EngineJob<?> job;
    Engine engine;
    Engine.EngineJobFactory engineJobFactory = mock(Engine.EngineJobFactory.class);
    Engine.DecodeJobFactory decodeJobFactory = mock(Engine.DecodeJobFactory.class);
    ResourceRecycler resourceRecycler = mock(ResourceRecycler.class);
    Key signature = mock(Key.class);
    Map<Class<?>, Transformation<?>> transformations = new HashMap<>();
    Options options = new Options();
    GlideContext glideContext = mock(GlideContext.class);
    boolean isMemoryCacheable = true;
    boolean useUnlimitedSourceGeneratorPool = false;
    boolean onlyRetrieveFromCache = false;

    public EngineTestHarness() {
      when(keyFactory.buildKey(eq(model), eq(signature), anyInt(), anyInt(), eq(transformations),
          eq(Object.class), eq(Object.class), eq(options))).thenReturn(cacheKey);

      job = mock(EngineJob.class);

      engine = new Engine(cache, mock(DiskCache.Factory.class),
          GlideExecutor.newDiskCacheExecutor(),
          MockGlideExecutor.newMainThreadExecutor(),
          MockGlideExecutor.newMainThreadUnlimitedExecutor(),
          jobs, keyFactory, activeResources,
          engineJobFactory, decodeJobFactory, resourceRecycler);
    }

    public Engine.LoadStatus doLoad() {
      when(engineJobFactory.build(eq(cacheKey), anyBoolean(), anyBoolean()))
          .thenReturn((EngineJob<Object>) job);
      return engine.load(glideContext,
          model,
          signature,
          width,
          height,
          Object.class /*resourceClass*/,
          Object.class /*transcodeClass*/,
          Priority.HIGH,
          DiskCacheStrategy.ALL,
          transformations,
          false /*isTransformationRequired*/,
          options,
          isMemoryCacheable,
          useUnlimitedSourceGeneratorPool,
          onlyRetrieveFromCache,
          cb);
    }
  }
}


Add Load/Decode paths.

<|original_code|>
package com.bumptech.glide.load.data;

import java.util.HashMap;
import java.util.Map;

public class DataRewinderRegistry {
    private final Map<Class, DataRewinder.Factory> rewinders = new HashMap<Class, DataRewinder.Factory>();
    private static final DataRewinder.Factory DEFAULT_FACTORY = new DataRewinder.Factory<Object>() {
        @Override
        public DataRewinder<Object> build(Object data) {
            return new DefaultRewinder(data);
        }

        @Override
        public Class getDataClass() {
            throw new UnsupportedOperationException("Not implemented");
        }
    };

    public synchronized void register(DataRewinder.Factory factory) {
        rewinders.put(factory.getDataClass(), factory);
    }

    @SuppressWarnings("unchecked")
    public synchronized <T> DataRewinder<T> build(T data) {
        DataRewinder.Factory result = rewinders.get(data.getClass());
        if (result == null) {
            for (DataRewinder.Factory<?> registeredFactory : rewinders.values()) {
                if (registeredFactory.getDataClass().isAssignableFrom(data.getClass())) {
                    result = registeredFactory;
                    break;
                }
            }
        }

        if (result == null) {
            result = DEFAULT_FACTORY;
        }
        return result.build(data);
    }

    private static class DefaultRewinder implements DataRewinder<Object> {
        private Object data;

        public DefaultRewinder(Object data) {
            this.data = data;
        }

        @Override
<|edits_diff|>
--- library/src/main/java/com/bumptech/glide/load/data/DataRewinderRegistry.java
+++ library/src/main/java/com/bumptech/glide/load/data/DataRewinderRegistry.java
@@ -1,4 +1,6 @@
 package com.bumptech.glide.load.data;
+
+import com.bumptech.glide.util.Preconditions;

 import java.util.HashMap;
 import java.util.Map;
<|current_version|>
package com.bumptech.glide.load.data;

import com.bumptech.glide.util.Preconditions;

import java.util.HashMap;
import java.util.Map;

public class DataRewinderRegistry {
    private final Map<Class, DataRewinder.Factory> rewinders = new HashMap<Class, DataRewinder.Factory>();
    private static final DataRewinder.Factory DEFAULT_FACTORY = new DataRewinder.Factory<Object>() {
        @Override
        public DataRewinder<Object> build(Object data) {
            return new DefaultRewinder(data);
        }

        @Override
        public Class getDataClass() {
            throw new UnsupportedOperationException("Not implemented");
        }
    };

    public synchronized void register(DataRewinder.Factory factory) {
        rewinders.put(factory.getDataClass(), factory);
    }

    @SuppressWarnings("unchecked")
    public synchronized <T> DataRewinder<T> build(T data) {
        DataRewinder.Factory result = rewinders.get(data.getClass());
        if (result == null) {
            for (DataRewinder.Factory<?> registeredFactory : rewinders.values()) {
                if (registeredFactory.getDataClass().isAssignableFrom(data.getClass())) {
                    result = registeredFactory;
                    break;
                }
            }
        }

        if (result == null) {
            result = DEFAULT_FACTORY;
        }
        return result.build(data);
    }

    private static class DefaultRewinder implements DataRewinder<Object> {
        private Object data;

        public DefaultRewinder(Object data) {
            this.data = data;
        }

        @Override
<|next_version|>
package com.bumptech.glide.load.data;

import com.bumptech.glide.util.Preconditions;

import java.util.HashMap;
import java.util.Map;

public class DataRewinderRegistry {
    private final Map<Class, DataRewinder.Factory> rewinders = new HashMap<Class, DataRewinder.Factory>();
    private static final DataRewinder.Factory DEFAULT_FACTORY = new DataRewinder.Factory<Object>() {
        @Override
        public DataRewinder<Object> build(Object data) {
            return new DefaultRewinder(data);
        }

        @Override
        public Class getDataClass() {
            throw new UnsupportedOperationException("Not implemented");
        }
    };

    public synchronized void register(DataRewinder.Factory factory) {
        rewinders.put(factory.getDataClass(), factory);
    }

    @SuppressWarnings("unchecked")
    public synchronized <T> DataRewinder<T> build(T data) {
        Preconditions.checkNotNull(data);
        DataRewinder.Factory result = rewinders.get(data.getClass());
        if (result == null) {
            for (DataRewinder.Factory<?> registeredFactory : rewinders.values()) {
                if (registeredFactory.getDataClass().isAssignableFrom(data.getClass())) {
                    result = registeredFactory;
                    break;
                }
            }
        }

        if (result == null) {
            result = DEFAULT_FACTORY;
        }
        return result.build(data);
    }

    private static class DefaultRewinder implements DataRewinder<Object> {
        private Object data;

        public DefaultRewinder(Object data) {
            this.data = data;
        }

        @Override


Explicitly set JUnit4 runner for junit tests.

<|original_code|>
package com.bumptech.glide.load;

import com.bumptech.glide.load.engine.Resource;
import org.junit.Test;

import java.util.ArrayList;

import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

public class MultiTransformationTest {
    @Test
    public void testReturnsConcatenatedTransformationIds() {
        String firstId = "firstId";
        Transformation first = mock(Transformation.class);
        when(first.getId()).thenReturn(firstId);
        String secondId = "secondId";
        Transformation second = mock(Transformation.class);
        when(second.getId()).thenReturn(secondId);
        String thirdId = "thirdId";
        Transformation third = mock(Transformation.class);
        when(third.getId()).thenReturn(thirdId);

        MultiTransformation transformation = new MultiTransformation(first, second, third);

        final String expected = firstId + secondId + thirdId;
        assertEquals(expected, transformation.getId());

        ArrayList<Transformation> transformations = new ArrayList<Transformation>();
        transformations.add(first);
        transformations.add(second);
        transformations.add(third);

        transformation = new MultiTransformation(transformations);
<|edits_diff|>
--- library/src/androidTest/java/com/bumptech/glide/load/MultiTransformationTest.java
+++ library/src/androidTest/java/com/bumptech/glide/load/MultiTransformationTest.java
@@ -2,6 +2,8 @@

 import com.bumptech.glide.load.engine.Resource;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;

 import java.util.ArrayList;

<|current_version|>
package com.bumptech.glide.load;

import com.bumptech.glide.load.engine.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

import java.util.ArrayList;

import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

public class MultiTransformationTest {
    @Test
    public void testReturnsConcatenatedTransformationIds() {
        String firstId = "firstId";
        Transformation first = mock(Transformation.class);
        when(first.getId()).thenReturn(firstId);
        String secondId = "secondId";
        Transformation second = mock(Transformation.class);
        when(second.getId()).thenReturn(secondId);
        String thirdId = "thirdId";
        Transformation third = mock(Transformation.class);
        when(third.getId()).thenReturn(thirdId);

        MultiTransformation transformation = new MultiTransformation(first, second, third);

        final String expected = firstId + secondId + thirdId;
        assertEquals(expected, transformation.getId());

        ArrayList<Transformation> transformations = new ArrayList<Transformation>();
        transformations.add(first);
        transformations.add(second);
        transformations.add(third);

        transformation = new MultiTransformation(transformations);
<|next_version|>
package com.bumptech.glide.load;

import com.bumptech.glide.load.engine.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

import java.util.ArrayList;

import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@RunWith(JUnit4.class)
public class MultiTransformationTest {
    @Test
    public void testReturnsConcatenatedTransformationIds() {
        String firstId = "firstId";
        Transformation first = mock(Transformation.class);
        when(first.getId()).thenReturn(firstId);
        String secondId = "secondId";
        Transformation second = mock(Transformation.class);
        when(second.getId()).thenReturn(secondId);
        String thirdId = "thirdId";
        Transformation third = mock(Transformation.class);
        when(third.getId()).thenReturn(thirdId);

        MultiTransformation transformation = new MultiTransformation(first, second, third);

        final String expected = firstId + secondId + thirdId;
        assertEquals(expected, transformation.getId());

        ArrayList<Transformation> transformations = new ArrayList<Transformation>();
        transformations.add(first);
        transformations.add(second);
        transformations.add(third);

        transformation = new MultiTransformation(transformations);


Avoid NPE loading null or empty urls.

<|original_code|>
package com.bumptech.glide.load.model;

import android.text.TextUtils;

import java.net.MalformedURLException;
import java.net.URL;

/**
 * This is a simple wrapper for strings representing http/https URLs. new URL() is an excessively expensive operation
 * that may be unnecessary if the class loading the image from the URL doesn't actually require a URL object.
 *
 * Users wishing to replace the class for handling URLs must register a factory using GlideUrl.
 */
public class GlideUrl {
    private String stringUrl;
    private URL url;

    public GlideUrl(URL url) {
        this.url = url;
        stringUrl = null;
    }

    public GlideUrl(String url) {
        this.stringUrl = url;
        this.url = null;
    }

    public URL toURL() throws MalformedURLException {
        if (url == null) {
            url = new URL(stringUrl);
        }
        return url;
    }

    @Override
    public String toString() {
        if (TextUtils.isEmpty(stringUrl)) {
            stringUrl = url.toString();
        }
        return stringUrl;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
<|edits_diff|>
--- library/src/main/java/com/bumptech/glide/load/model/GlideUrl.java
+++ library/src/main/java/com/bumptech/glide/load/model/GlideUrl.java
@@ -16,6 +16,9 @@
     private URL url;

     public GlideUrl(URL url) {
+        if (url == null) {
+            throw new IllegalArgumentException("URL must not be null!");
+        }
         this.url = url;
         stringUrl = null;
     }
<|current_version|>
package com.bumptech.glide.load.model;

import android.text.TextUtils;

import java.net.MalformedURLException;
import java.net.URL;

/**
 * This is a simple wrapper for strings representing http/https URLs. new URL() is an excessively expensive operation
 * that may be unnecessary if the class loading the image from the URL doesn't actually require a URL object.
 *
 * Users wishing to replace the class for handling URLs must register a factory using GlideUrl.
 */
public class GlideUrl {
    private String stringUrl;
    private URL url;

    public GlideUrl(URL url) {
        if (url == null) {
            throw new IllegalArgumentException("URL must not be null!");
        }
        this.url = url;
        stringUrl = null;
    }

    public GlideUrl(String url) {
        this.stringUrl = url;
        this.url = null;
    }

    public URL toURL() throws MalformedURLException {
        if (url == null) {
            url = new URL(stringUrl);
        }
        return url;
    }

    @Override
    public String toString() {
        if (TextUtils.isEmpty(stringUrl)) {
            stringUrl = url.toString();
        }
        return stringUrl;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
<|next_version|>
package com.bumptech.glide.load.model;

import android.text.TextUtils;

import java.net.MalformedURLException;
import java.net.URL;

/**
 * This is a simple wrapper for strings representing http/https URLs. new URL() is an excessively expensive operation
 * that may be unnecessary if the class loading the image from the URL doesn't actually require a URL object.
 *
 * Users wishing to replace the class for handling URLs must register a factory using GlideUrl.
 */
public class GlideUrl {
    private String stringUrl;
    private URL url;

    public GlideUrl(URL url) {
        if (url == null) {
            throw new IllegalArgumentException("URL must not be null!");
        }
        this.url = url;
        stringUrl = null;
    }

    public GlideUrl(String url) {
        if (TextUtils.isEmpty(url)) {
            throw new IllegalArgumentException("String url must not be empty or null: " + url);
        }
        this.stringUrl = url;
        this.url = null;
    }

    public URL toURL() throws MalformedURLException {
        if (url == null) {
            url = new URL(stringUrl);
        }
        return url;
    }

    @Override
    public String toString() {
        if (TextUtils.isEmpty(stringUrl)) {
            stringUrl = url.toString();
        }
        return stringUrl;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }


increase default context length to 4096 (#10364)

<|original_code|>
		}

		checkChatResponse(t, w.Body, "test", "Hi!")
	})

	w = createRequest(t, s.CreateHandler, api.CreateRequest{
		Model:  "test-system",
		From:   "test",
		System: "You are a helpful assistant.",
	})

	if w.Code != http.StatusOK {
		t.Fatalf("expected status 200, got %d", w.Code)
	}

	t.Run("messages with model system", func(t *testing.T) {
		w := createRequest(t, s.ChatHandler, api.ChatRequest{
			Model: "test-system",
			Messages: []api.Message{
				{Role: "user", Content: "Hello!"},
			},
			Stream: &stream,
		})

		if w.Code != http.StatusOK {
			t.Errorf("expected status 200, got %d", w.Code)
		}

		if diff := cmp.Diff(mock.CompletionRequest.Prompt, "system: You are a helpful assistant.\nuser: Hello!\n"); diff != "" {
			t.Errorf("mismatch (-got +want):\n%s", diff)
		}

		checkChatResponse(t, w.Body, "test-system", "Hi!")
	})

	mock.CompletionResponse.Content = "Abra kadabra!"
	t.Run("messages with system", func(t *testing.T) {
		w := createRequest(t, s.ChatHandler, api.ChatRequest{
			Model: "test-system",
			Messages: []api.Message{
				{Role: "system", Content: "You can perform magic tricks."},
				{Role: "user", Content: "Hello!"},
			},
			Stream: &stream,
		})

		if w.Code != http.StatusOK {
			t.Errorf("expected status 200, got %d", w.Code)
		}

		if diff := cmp.Diff(mock.CompletionRequest.Prompt, "system: You can perform magic tricks.\nuser: Hello!\n"); diff != "" {
			t.Errorf("mismatch (-got +want):\n%s", diff)
		}

		checkChatResponse(t, w.Body, "test-system", "Abra kadabra!")
	})

	t.Run("messages with interleaved system", func(t *testing.T) {
		w := createRequest(t, s.ChatHandler, api.ChatRequest{
			Model: "test-system",
			Messages: []api.Message{
				{Role: "user", Content: "Hello!"},
				{Role: "assistant", Content: "I can help you with that."},
				{Role: "system", Content: "You can perform magic tricks."},
				{Role: "user", Content: "Help me write tests."},
			},
			Stream: &stream,
		})

		if w.Code != http.StatusOK {
			t.Errorf("expected status 200, got %d", w.Code)
		}

		if diff := cmp.Diff(mock.CompletionRequest.Prompt, "system: You are a helpful assistant.\nuser: Hello!\nassistant: I can help you with that.\nsystem: You can perform magic tricks.\nuser: Help me write tests.\n"); diff != "" {
			t.Errorf("mismatch (-got +want):\n%s", diff)
		}

		checkChatResponse(t, w.Body, "test-system", "Abra kadabra!")
	})

	t.Run("messages with tools (non-streaming)", func(t *testing.T) {
		if w.Code != http.StatusOK {
			t.Fatalf("failed to create test-system model: %d", w.Code)
		}

		tools := []api.Tool{
			{
				Type: "function",
				Function: api.ToolFunction{
					Name:        "get_weather",
					Description: "Get the current weather",
<|edits_diff|>
--- server/routes_generate_test.go
+++ server/routes_generate_test.go
@@ -20,6 +20,9 @@
 				{Role: "user", Content: "Hello!"},
 			},
 			Stream: &stream,
+			Options: map[string]any{
+				"num_ctx": 1024,
+			},
 		})

 		if w.Code != http.StatusOK {
@@ -42,6 +45,9 @@
 				{Role: "user", Content: "Hello!"},
 			},
 			Stream: &stream,
+			Options: map[string]any{
+				"num_ctx": 1024,
+			},
 		})

 		if w.Code != http.StatusOK {
<|current_version|>
		}

		checkChatResponse(t, w.Body, "test", "Hi!")
	})

	w = createRequest(t, s.CreateHandler, api.CreateRequest{
		Model:  "test-system",
		From:   "test",
		System: "You are a helpful assistant.",
	})

	if w.Code != http.StatusOK {
		t.Fatalf("expected status 200, got %d", w.Code)
	}

	t.Run("messages with model system", func(t *testing.T) {
		w := createRequest(t, s.ChatHandler, api.ChatRequest{
			Model: "test-system",
			Messages: []api.Message{
				{Role: "user", Content: "Hello!"},
			},
			Stream: &stream,
			Options: map[string]any{
				"num_ctx": 1024,
			},
		})

		if w.Code != http.StatusOK {
			t.Errorf("expected status 200, got %d", w.Code)
		}

		if diff := cmp.Diff(mock.CompletionRequest.Prompt, "system: You are a helpful assistant.\nuser: Hello!\n"); diff != "" {
			t.Errorf("mismatch (-got +want):\n%s", diff)
		}

		checkChatResponse(t, w.Body, "test-system", "Hi!")
	})

	mock.CompletionResponse.Content = "Abra kadabra!"
	t.Run("messages with system", func(t *testing.T) {
		w := createRequest(t, s.ChatHandler, api.ChatRequest{
			Model: "test-system",
			Messages: []api.Message{
				{Role: "system", Content: "You can perform magic tricks."},
				{Role: "user", Content: "Hello!"},
			},
			Stream: &stream,
			Options: map[string]any{
				"num_ctx": 1024,
			},
		})

		if w.Code != http.StatusOK {
			t.Errorf("expected status 200, got %d", w.Code)
		}

		if diff := cmp.Diff(mock.CompletionRequest.Prompt, "system: You can perform magic tricks.\nuser: Hello!\n"); diff != "" {
			t.Errorf("mismatch (-got +want):\n%s", diff)
		}

		checkChatResponse(t, w.Body, "test-system", "Abra kadabra!")
	})

	t.Run("messages with interleaved system", func(t *testing.T) {
		w := createRequest(t, s.ChatHandler, api.ChatRequest{
			Model: "test-system",
			Messages: []api.Message{
				{Role: "user", Content: "Hello!"},
				{Role: "assistant", Content: "I can help you with that."},
				{Role: "system", Content: "You can perform magic tricks."},
				{Role: "user", Content: "Help me write tests."},
			},
			Stream: &stream,
		})

		if w.Code != http.StatusOK {
			t.Errorf("expected status 200, got %d", w.Code)
		}

		if diff := cmp.Diff(mock.CompletionRequest.Prompt, "system: You are a helpful assistant.\nuser: Hello!\nassistant: I can help you with that.\nsystem: You can perform magic tricks.\nuser: Help me write tests.\n"); diff != "" {
			t.Errorf("mismatch (-got +want):\n%s", diff)
		}

		checkChatResponse(t, w.Body, "test-system", "Abra kadabra!")
	})

	t.Run("messages with tools (non-streaming)", func(t *testing.T) {
		if w.Code != http.StatusOK {
			t.Fatalf("failed to create test-system model: %d", w.Code)
		}

		tools := []api.Tool{
			{
				Type: "function",
				Function: api.ToolFunction{
					Name:        "get_weather",
					Description: "Get the current weather",
<|next_version|>
		}

		checkChatResponse(t, w.Body, "test", "Hi!")
	})

	w = createRequest(t, s.CreateHandler, api.CreateRequest{
		Model:  "test-system",
		From:   "test",
		System: "You are a helpful assistant.",
	})

	if w.Code != http.StatusOK {
		t.Fatalf("expected status 200, got %d", w.Code)
	}

	t.Run("messages with model system", func(t *testing.T) {
		w := createRequest(t, s.ChatHandler, api.ChatRequest{
			Model: "test-system",
			Messages: []api.Message{
				{Role: "user", Content: "Hello!"},
			},
			Stream: &stream,
			Options: map[string]any{
				"num_ctx": 1024,
			},
		})

		if w.Code != http.StatusOK {
			t.Errorf("expected status 200, got %d", w.Code)
		}

		if diff := cmp.Diff(mock.CompletionRequest.Prompt, "system: You are a helpful assistant.\nuser: Hello!\n"); diff != "" {
			t.Errorf("mismatch (-got +want):\n%s", diff)
		}

		checkChatResponse(t, w.Body, "test-system", "Hi!")
	})

	mock.CompletionResponse.Content = "Abra kadabra!"
	t.Run("messages with system", func(t *testing.T) {
		w := createRequest(t, s.ChatHandler, api.ChatRequest{
			Model: "test-system",
			Messages: []api.Message{
				{Role: "system", Content: "You can perform magic tricks."},
				{Role: "user", Content: "Hello!"},
			},
			Stream: &stream,
			Options: map[string]any{
				"num_ctx": 1024,
			},
		})

		if w.Code != http.StatusOK {
			t.Errorf("expected status 200, got %d", w.Code)
		}

		if diff := cmp.Diff(mock.CompletionRequest.Prompt, "system: You can perform magic tricks.\nuser: Hello!\n"); diff != "" {
			t.Errorf("mismatch (-got +want):\n%s", diff)
		}

		checkChatResponse(t, w.Body, "test-system", "Abra kadabra!")
	})

	t.Run("messages with interleaved system", func(t *testing.T) {
		w := createRequest(t, s.ChatHandler, api.ChatRequest{
			Model: "test-system",
			Messages: []api.Message{
				{Role: "user", Content: "Hello!"},
				{Role: "assistant", Content: "I can help you with that."},
				{Role: "system", Content: "You can perform magic tricks."},
				{Role: "user", Content: "Help me write tests."},
			},
			Stream: &stream,
			Options: map[string]any{
				"num_ctx": 1024,
			},
		})

		if w.Code != http.StatusOK {
			t.Errorf("expected status 200, got %d", w.Code)
		}

		if diff := cmp.Diff(mock.CompletionRequest.Prompt, "system: You are a helpful assistant.\nuser: Hello!\nassistant: I can help you with that.\nsystem: You can perform magic tricks.\nuser: Help me write tests.\n"); diff != "" {
			t.Errorf("mismatch (-got +want):\n%s", diff)
		}

		checkChatResponse(t, w.Body, "test-system", "Abra kadabra!")
	})

	t.Run("messages with tools (non-streaming)", func(t *testing.T) {
		if w.Code != http.StatusOK {
			t.Fatalf("failed to create test-system model: %d", w.Code)
		}

		tools := []api.Tool{
			{
				Type: "function",
				Function: api.ToolFunction{
					Name:        "get_weather",
					Description: "Get the current weather",


ggml: Log filesystem errors

<|original_code|>
	g.SetLimit(runtime.GOMAXPROCS(0))
	for _, t := range meta.Tensors().Items() {
		g.Go(func() error {
			tts := make([]*C.struct_ggml_tensor, max(1, len(targets[t.Name])))
			for i := range tts {
				target := targets[t.Name][i]
				if target == "" {
					target = t.Name
				}

				tt, ok := tensors[target]
				if !ok {
					return fmt.Errorf("unassigned tensor: %s", t.Name)
				}

				tts[i] = tt
			}

			// Create a new FD for each goroutine so that each FD is read sequentially, rather than
			// seeking around within an FD shared between all goroutines.
			file, err := os.Open(r.Name())
			if err != nil {
				return err
			}
			defer file.Close()
			sr := io.NewSectionReader(file, int64(meta.Tensors().Offset+t.Offset), int64(t.Size()))
			bts := make([]byte, 128*format.KibiByte)

			var s uint64
			for s < t.Size() {
				n, err := io.ReadFull(sr, bts[:min(len(bts), int(t.Size()-s))])
				if err != nil {
					return err
				}

				for _, tt := range tts {
					C.ggml_backend_tensor_set(tt, unsafe.Pointer(&bts[0]), C.size_t(s), C.size_t(n))
				}

				s += uint64(n)

				if params.Progress != nil {
					done := doneBytes.Add(uint64(n))
					params.Progress(float32(done) / float32(totalBytes))
				}
			}

			return nil
		})
	}

	// start a goroutine to cancel the errgroup if the parent context is done
	go func() {
		<-ctx.Done()
		g.Go(func() error {
			return ctx.Err()
<|edits_diff|>
--- ml/backend/ggml/ggml.go
+++ ml/backend/ggml/ggml.go
@@ -20,6 +20,7 @@
 			// seeking around within an FD shared between all goroutines.
 			file, err := os.Open(r.Name())
 			if err != nil {
+				slog.Warn("file open error", "file", r.Name(), "error", err)
 				return err
 			}
 			defer file.Close()
<|current_version|>
	g.SetLimit(runtime.GOMAXPROCS(0))
	for _, t := range meta.Tensors().Items() {
		g.Go(func() error {
			tts := make([]*C.struct_ggml_tensor, max(1, len(targets[t.Name])))
			for i := range tts {
				target := targets[t.Name][i]
				if target == "" {
					target = t.Name
				}

				tt, ok := tensors[target]
				if !ok {
					return fmt.Errorf("unassigned tensor: %s", t.Name)
				}

				tts[i] = tt
			}

			// Create a new FD for each goroutine so that each FD is read sequentially, rather than
			// seeking around within an FD shared between all goroutines.
			file, err := os.Open(r.Name())
			if err != nil {
				slog.Warn("file open error", "file", r.Name(), "error", err)
				return err
			}
			defer file.Close()
			sr := io.NewSectionReader(file, int64(meta.Tensors().Offset+t.Offset), int64(t.Size()))
			bts := make([]byte, 128*format.KibiByte)

			var s uint64
			for s < t.Size() {
				n, err := io.ReadFull(sr, bts[:min(len(bts), int(t.Size()-s))])
				if err != nil {
					return err
				}

				for _, tt := range tts {
					C.ggml_backend_tensor_set(tt, unsafe.Pointer(&bts[0]), C.size_t(s), C.size_t(n))
				}

				s += uint64(n)

				if params.Progress != nil {
					done := doneBytes.Add(uint64(n))
					params.Progress(float32(done) / float32(totalBytes))
				}
			}

			return nil
		})
	}

	// start a goroutine to cancel the errgroup if the parent context is done
	go func() {
		<-ctx.Done()
		g.Go(func() error {
			return ctx.Err()
<|next_version|>
	g.SetLimit(runtime.GOMAXPROCS(0))
	for _, t := range meta.Tensors().Items() {
		g.Go(func() error {
			tts := make([]*C.struct_ggml_tensor, max(1, len(targets[t.Name])))
			for i := range tts {
				target := targets[t.Name][i]
				if target == "" {
					target = t.Name
				}

				tt, ok := tensors[target]
				if !ok {
					return fmt.Errorf("unassigned tensor: %s", t.Name)
				}

				tts[i] = tt
			}

			// Create a new FD for each goroutine so that each FD is read sequentially, rather than
			// seeking around within an FD shared between all goroutines.
			file, err := os.Open(r.Name())
			if err != nil {
				slog.Warn("file open error", "file", r.Name(), "error", err)
				return err
			}
			defer file.Close()
			sr := io.NewSectionReader(file, int64(meta.Tensors().Offset+t.Offset), int64(t.Size()))
			bts := make([]byte, 128*format.KibiByte)

			var s uint64
			for s < t.Size() {
				n, err := io.ReadFull(sr, bts[:min(len(bts), int(t.Size()-s))])
				if err != nil {
					slog.Warn("file read error", "file", r.Name(), "error", err)
					return err
				}

				for _, tt := range tts {
					C.ggml_backend_tensor_set(tt, unsafe.Pointer(&bts[0]), C.size_t(s), C.size_t(n))
				}

				s += uint64(n)

				if params.Progress != nil {
					done := doneBytes.Add(uint64(n))
					params.Progress(float32(done) / float32(totalBytes))
				}
			}

			return nil
		})
	}

	// start a goroutine to cancel the errgroup if the parent context is done
	go func() {
		<-ctx.Done()
		g.Go(func() error {
			return ctx.Err()


fix: show correct bool value for kv in verbose show information (#9928)

<|original_code|>
    embedding length    0
    quantization        FP16

`
		if diff := cmp.Diff(expect, b.String()); diff != "" {
			t.Errorf("unexpected output (-want +got):\n%s", diff)
		}
	})

	t.Run("verbose model", func(t *testing.T) {
		var b bytes.Buffer
		if err := showInfo(&api.ShowResponse{
			Details: api.ModelDetails{
				Family:            "test",
				ParameterSize:     "8B",
				QuantizationLevel: "FP16",
			},
			Parameters: `
			stop up`,
			ModelInfo: map[string]any{
				"general.architecture":    "test",
				"general.parameter_count": float64(8_000_000_000),
				"test.context_length":     float64(1000),
				"test.embedding_length":   float64(11434),
			},
			Tensors: []api.Tensor{
				{Name: "blk.0.attn_k.weight", Type: "BF16", Shape: []uint64{42, 3117}},
				{Name: "blk.0.attn_q.weight", Type: "FP16", Shape: []uint64{3117, 42}},
			},
		}, true, &b); err != nil {
			t.Fatal(err)
		}

		expect := `  Model
    architecture        test
    parameters          8B
    context length      1000
    embedding length    11434
    quantization        FP16

  Parameters
    stop    up

  Metadata
    general.architecture       test
    general.parameter_count    8e+09
    test.context_length        1000
    test.embedding_length      11434

  Tensors
    blk.0.attn_k.weight    BF16    [42 3117]
    blk.0.attn_q.weight    FP16    [3117 42]

`
		if diff := cmp.Diff(expect, b.String()); diff != "" {
			t.Errorf("unexpected output (-want +got):\n%s", diff)
		}
	})

	t.Run("parameters", func(t *testing.T) {
		var b bytes.Buffer
		if err := showInfo(&api.ShowResponse{
			Details: api.ModelDetails{
				Family:            "test",
				ParameterSize:     "7B",
				QuantizationLevel: "FP16",
			},
			Parameters: `
			stop never
			stop gonna
<|edits_diff|>
--- cmd/cmd_test.go
+++ cmd/cmd_test.go
@@ -20,6 +20,8 @@
 			ModelInfo: map[string]any{
 				"general.architecture":    "test",
 				"general.parameter_count": float64(8_000_000_000),
+				"some.true_bool":          true,
+				"some.false_bool":         false,
 				"test.context_length":     float64(1000),
 				"test.embedding_length":   float64(11434),
 			},
<|current_version|>
    embedding length    0
    quantization        FP16

`
		if diff := cmp.Diff(expect, b.String()); diff != "" {
			t.Errorf("unexpected output (-want +got):\n%s", diff)
		}
	})

	t.Run("verbose model", func(t *testing.T) {
		var b bytes.Buffer
		if err := showInfo(&api.ShowResponse{
			Details: api.ModelDetails{
				Family:            "test",
				ParameterSize:     "8B",
				QuantizationLevel: "FP16",
			},
			Parameters: `
			stop up`,
			ModelInfo: map[string]any{
				"general.architecture":    "test",
				"general.parameter_count": float64(8_000_000_000),
				"some.true_bool":          true,
				"some.false_bool":         false,
				"test.context_length":     float64(1000),
				"test.embedding_length":   float64(11434),
			},
			Tensors: []api.Tensor{
				{Name: "blk.0.attn_k.weight", Type: "BF16", Shape: []uint64{42, 3117}},
				{Name: "blk.0.attn_q.weight", Type: "FP16", Shape: []uint64{3117, 42}},
			},
		}, true, &b); err != nil {
			t.Fatal(err)
		}

		expect := `  Model
    architecture        test
    parameters          8B
    context length      1000
    embedding length    11434
    quantization        FP16

  Parameters
    stop    up

  Metadata
    general.architecture       test
    general.parameter_count    8e+09
    test.context_length        1000
    test.embedding_length      11434

  Tensors
    blk.0.attn_k.weight    BF16    [42 3117]
    blk.0.attn_q.weight    FP16    [3117 42]

`
		if diff := cmp.Diff(expect, b.String()); diff != "" {
			t.Errorf("unexpected output (-want +got):\n%s", diff)
		}
	})

	t.Run("parameters", func(t *testing.T) {
		var b bytes.Buffer
		if err := showInfo(&api.ShowResponse{
			Details: api.ModelDetails{
				Family:            "test",
				ParameterSize:     "7B",
				QuantizationLevel: "FP16",
			},
			Parameters: `
			stop never
			stop gonna
<|next_version|>
    embedding length    0
    quantization        FP16

`
		if diff := cmp.Diff(expect, b.String()); diff != "" {
			t.Errorf("unexpected output (-want +got):\n%s", diff)
		}
	})

	t.Run("verbose model", func(t *testing.T) {
		var b bytes.Buffer
		if err := showInfo(&api.ShowResponse{
			Details: api.ModelDetails{
				Family:            "test",
				ParameterSize:     "8B",
				QuantizationLevel: "FP16",
			},
			Parameters: `
			stop up`,
			ModelInfo: map[string]any{
				"general.architecture":    "test",
				"general.parameter_count": float64(8_000_000_000),
				"some.true_bool":          true,
				"some.false_bool":         false,
				"test.context_length":     float64(1000),
				"test.embedding_length":   float64(11434),
			},
			Tensors: []api.Tensor{
				{Name: "blk.0.attn_k.weight", Type: "BF16", Shape: []uint64{42, 3117}},
				{Name: "blk.0.attn_q.weight", Type: "FP16", Shape: []uint64{3117, 42}},
			},
		}, true, &b); err != nil {
			t.Fatal(err)
		}

		expect := `  Model
    architecture        test
    parameters          8B
    context length      1000
    embedding length    11434
    quantization        FP16

  Parameters
    stop    up

  Metadata
    general.architecture       test
    general.parameter_count    8e+09
    some.false_bool            false
    some.true_bool             true
    test.context_length        1000
    test.embedding_length      11434

  Tensors
    blk.0.attn_k.weight    BF16    [42 3117]
    blk.0.attn_q.weight    FP16    [3117 42]

`
		if diff := cmp.Diff(expect, b.String()); diff != "" {
			t.Errorf("unexpected output (-want +got):\n%s", diff)
		}
	})

	t.Run("parameters", func(t *testing.T) {
		var b bytes.Buffer
		if err := showInfo(&api.ShowResponse{
			Details: api.ModelDetails{
				Family:            "test",
				ParameterSize:     "7B",
				QuantizationLevel: "FP16",
			},
			Parameters: `
			stop never
			stop gonna


Enable index tracking for tools - openai api support (#7888)

<|original_code|>

type Completion struct {
	Id                string                `json:"id"`
	Object            string                `json:"object"`
	Created           int64                 `json:"created"`
	Model             string                `json:"model"`
	SystemFingerprint string                `json:"system_fingerprint"`
	Choices           []CompleteChunkChoice `json:"choices"`
	Usage             Usage                 `json:"usage,omitempty"`
}

type CompletionChunk struct {
	Id                string                `json:"id"`
	Object            string                `json:"object"`
	Created           int64                 `json:"created"`
	Choices           []CompleteChunkChoice `json:"choices"`
	Model             string                `json:"model"`
	SystemFingerprint string                `json:"system_fingerprint"`
}

type ToolCall struct {
	ID       string `json:"id"`
	Type     string `json:"type"`
	Function struct {
		Name      string `json:"name"`
		Arguments string `json:"arguments"`
	} `json:"function"`
}

type Model struct {
	Id      string `json:"id"`
	Object  string `json:"object"`
	Created int64  `json:"created"`
	OwnedBy string `json:"owned_by"`
}

type Embedding struct {
	Object    string    `json:"object"`
	Embedding []float32 `json:"embedding"`
	Index     int       `json:"index"`
}

type ListCompletion struct {
	Object string  `json:"object"`
	Data   []Model `json:"data"`
}

type EmbeddingList struct {
	Object string         `json:"object"`
	Data   []Embedding    `json:"data"`
	Model  string         `json:"model"`
	Usage  EmbeddingUsage `json:"usage,omitempty"`
}

type EmbeddingUsage struct {
	PromptTokens int `json:"prompt_tokens"`
	TotalTokens  int `json:"total_tokens"`
}

func NewError(code int, message string) ErrorResponse {
	var etype string
	switch code {
	case http.StatusBadRequest:
		etype = "invalid_request_error"
	case http.StatusNotFound:
		etype = "not_found_error"
	default:
		etype = "api_error"
	}

	return ErrorResponse{Error{Type: etype, Message: message}}
}

func toolCallId() string {
	const letterBytes = "abcdefghijklmnopqrstuvwxyz0123456789"
	b := make([]byte, 8)
	for i := range b {
		b[i] = letterBytes[rand.Intn(len(letterBytes))]
	}
	return "call_" + strings.ToLower(string(b))
}

func toToolCalls(tc []api.ToolCall) []ToolCall {
	toolCalls := make([]ToolCall, len(tc))
	for i, tc := range tc {
		toolCalls[i].ID = toolCallId()
		toolCalls[i].Type = "function"
		toolCalls[i].Function.Name = tc.Function.Name

		args, err := json.Marshal(tc.Function.Arguments)
		if err != nil {
			slog.Error("could not marshall function arguments to json", "error", err)
			continue
		}

		toolCalls[i].Function.Arguments = string(args)
	}
	return toolCalls
}

func toChatCompletion(id string, r api.ChatResponse) ChatCompletion {
	toolCalls := toToolCalls(r.Message.ToolCalls)
	return ChatCompletion{
		Id:                id,
		Object:            "chat.completion",
		Created:           r.CreatedAt.Unix(),
		Model:             r.Model,
		SystemFingerprint: "fp_ollama",
		Choices: []Choice{{
			Index:   0,
			Message: Message{Role: r.Message.Role, Content: r.Message.Content, ToolCalls: toolCalls},
			FinishReason: func(reason string) *string {
<|edits_diff|>
--- openai/openai.go
+++ openai/openai.go
@@ -20,6 +20,7 @@

 type ToolCall struct {
 	ID       string `json:"id"`
+	Index    int    `json:"index"`
 	Type     string `json:"type"`
 	Function struct {
 		Name      string `json:"name"`
<|current_version|>

type Completion struct {
	Id                string                `json:"id"`
	Object            string                `json:"object"`
	Created           int64                 `json:"created"`
	Model             string                `json:"model"`
	SystemFingerprint string                `json:"system_fingerprint"`
	Choices           []CompleteChunkChoice `json:"choices"`
	Usage             Usage                 `json:"usage,omitempty"`
}

type CompletionChunk struct {
	Id                string                `json:"id"`
	Object            string                `json:"object"`
	Created           int64                 `json:"created"`
	Choices           []CompleteChunkChoice `json:"choices"`
	Model             string                `json:"model"`
	SystemFingerprint string                `json:"system_fingerprint"`
}

type ToolCall struct {
	ID       string `json:"id"`
	Index    int    `json:"index"`
	Type     string `json:"type"`
	Function struct {
		Name      string `json:"name"`
		Arguments string `json:"arguments"`
	} `json:"function"`
}

type Model struct {
	Id      string `json:"id"`
	Object  string `json:"object"`
	Created int64  `json:"created"`
	OwnedBy string `json:"owned_by"`
}

type Embedding struct {
	Object    string    `json:"object"`
	Embedding []float32 `json:"embedding"`
	Index     int       `json:"index"`
}

type ListCompletion struct {
	Object string  `json:"object"`
	Data   []Model `json:"data"`
}

type EmbeddingList struct {
	Object string         `json:"object"`
	Data   []Embedding    `json:"data"`
	Model  string         `json:"model"`
	Usage  EmbeddingUsage `json:"usage,omitempty"`
}

type EmbeddingUsage struct {
	PromptTokens int `json:"prompt_tokens"`
	TotalTokens  int `json:"total_tokens"`
}

func NewError(code int, message string) ErrorResponse {
	var etype string
	switch code {
	case http.StatusBadRequest:
		etype = "invalid_request_error"
	case http.StatusNotFound:
		etype = "not_found_error"
	default:
		etype = "api_error"
	}

	return ErrorResponse{Error{Type: etype, Message: message}}
}

func toolCallId() string {
	const letterBytes = "abcdefghijklmnopqrstuvwxyz0123456789"
	b := make([]byte, 8)
	for i := range b {
		b[i] = letterBytes[rand.Intn(len(letterBytes))]
	}
	return "call_" + strings.ToLower(string(b))
}

func toToolCalls(tc []api.ToolCall) []ToolCall {
	toolCalls := make([]ToolCall, len(tc))
	for i, tc := range tc {
		toolCalls[i].ID = toolCallId()
		toolCalls[i].Type = "function"
		toolCalls[i].Function.Name = tc.Function.Name

		args, err := json.Marshal(tc.Function.Arguments)
		if err != nil {
			slog.Error("could not marshall function arguments to json", "error", err)
			continue
		}

		toolCalls[i].Function.Arguments = string(args)
	}
	return toolCalls
}

func toChatCompletion(id string, r api.ChatResponse) ChatCompletion {
	toolCalls := toToolCalls(r.Message.ToolCalls)
	return ChatCompletion{
		Id:                id,
		Object:            "chat.completion",
		Created:           r.CreatedAt.Unix(),
		Model:             r.Model,
		SystemFingerprint: "fp_ollama",
		Choices: []Choice{{
			Index:   0,
			Message: Message{Role: r.Message.Role, Content: r.Message.Content, ToolCalls: toolCalls},
			FinishReason: func(reason string) *string {
<|next_version|>

type Completion struct {
	Id                string                `json:"id"`
	Object            string                `json:"object"`
	Created           int64                 `json:"created"`
	Model             string                `json:"model"`
	SystemFingerprint string                `json:"system_fingerprint"`
	Choices           []CompleteChunkChoice `json:"choices"`
	Usage             Usage                 `json:"usage,omitempty"`
}

type CompletionChunk struct {
	Id                string                `json:"id"`
	Object            string                `json:"object"`
	Created           int64                 `json:"created"`
	Choices           []CompleteChunkChoice `json:"choices"`
	Model             string                `json:"model"`
	SystemFingerprint string                `json:"system_fingerprint"`
}

type ToolCall struct {
	ID       string `json:"id"`
	Index    int    `json:"index"`
	Type     string `json:"type"`
	Function struct {
		Name      string `json:"name"`
		Arguments string `json:"arguments"`
	} `json:"function"`
}

type Model struct {
	Id      string `json:"id"`
	Object  string `json:"object"`
	Created int64  `json:"created"`
	OwnedBy string `json:"owned_by"`
}

type Embedding struct {
	Object    string    `json:"object"`
	Embedding []float32 `json:"embedding"`
	Index     int       `json:"index"`
}

type ListCompletion struct {
	Object string  `json:"object"`
	Data   []Model `json:"data"`
}

type EmbeddingList struct {
	Object string         `json:"object"`
	Data   []Embedding    `json:"data"`
	Model  string         `json:"model"`
	Usage  EmbeddingUsage `json:"usage,omitempty"`
}

type EmbeddingUsage struct {
	PromptTokens int `json:"prompt_tokens"`
	TotalTokens  int `json:"total_tokens"`
}

func NewError(code int, message string) ErrorResponse {
	var etype string
	switch code {
	case http.StatusBadRequest:
		etype = "invalid_request_error"
	case http.StatusNotFound:
		etype = "not_found_error"
	default:
		etype = "api_error"
	}

	return ErrorResponse{Error{Type: etype, Message: message}}
}

func toolCallId() string {
	const letterBytes = "abcdefghijklmnopqrstuvwxyz0123456789"
	b := make([]byte, 8)
	for i := range b {
		b[i] = letterBytes[rand.Intn(len(letterBytes))]
	}
	return "call_" + strings.ToLower(string(b))
}

func toToolCalls(tc []api.ToolCall) []ToolCall {
	toolCalls := make([]ToolCall, len(tc))
	for i, tc := range tc {
		toolCalls[i].ID = toolCallId()
		toolCalls[i].Type = "function"
		toolCalls[i].Function.Name = tc.Function.Name
		toolCalls[i].Index = tc.Function.Index

		args, err := json.Marshal(tc.Function.Arguments)
		if err != nil {
			slog.Error("could not marshall function arguments to json", "error", err)
			continue
		}

		toolCalls[i].Function.Arguments = string(args)
	}
	return toolCalls
}

func toChatCompletion(id string, r api.ChatResponse) ChatCompletion {
	toolCalls := toToolCalls(r.Message.ToolCalls)
	return ChatCompletion{
		Id:                id,
		Object:            "chat.completion",
		Created:           r.CreatedAt.Unix(),
		Model:             r.Model,
		SystemFingerprint: "fp_ollama",
		Choices: []Choice{{
			Index:   0,
			Message: Message{Role: r.Message.Role, Content: r.Message.Content, ToolCalls: toolCalls},
			FinishReason: func(reason string) *string {


windows: Support alt install paths, fit and finish (#6967)

<|original_code|>
package lifecycle

import (
	"context"
	"errors"
	"fmt"
	"io"
	"log/slog"
	"os"
	"os/exec"
	"path/filepath"
	"time"

	"github.com/ollama/ollama/api"
)

func getCLIFullPath(command string) string {
	var cmdPath string
	appExe, err := os.Executable()
	if err == nil {
		cmdPath = filepath.Join(filepath.Dir(appExe), command)
		_, err := os.Stat(cmdPath)
		if err == nil {
			return cmdPath
		}
	}
	cmdPath, err = exec.LookPath(command)
	if err == nil {
		_, err := os.Stat(cmdPath)
		if err == nil {
			return cmdPath
		}
	}
	pwd, err := os.Getwd()
	if err == nil {
		cmdPath = filepath.Join(pwd, command)
		_, err = os.Stat(cmdPath)
		if err == nil {
			return cmdPath
		}
	}

	return command
}

func start(ctx context.Context, command string) (*exec.Cmd, error) {
<|edits_diff|>
--- app/lifecycle/server.go
+++ app/lifecycle/server.go
@@ -18,6 +18,7 @@
 	var cmdPath string
 	appExe, err := os.Executable()
 	if err == nil {
+		// Check both the same location as the tray app, as well as ./bin
 		cmdPath = filepath.Join(filepath.Dir(appExe), command)
 		_, err := os.Stat(cmdPath)
 		if err == nil {
<|current_version|>
package lifecycle

import (
	"context"
	"errors"
	"fmt"
	"io"
	"log/slog"
	"os"
	"os/exec"
	"path/filepath"
	"time"

	"github.com/ollama/ollama/api"
)

func getCLIFullPath(command string) string {
	var cmdPath string
	appExe, err := os.Executable()
	if err == nil {
		// Check both the same location as the tray app, as well as ./bin
		cmdPath = filepath.Join(filepath.Dir(appExe), command)
		_, err := os.Stat(cmdPath)
		if err == nil {
			return cmdPath
		}
	}
	cmdPath, err = exec.LookPath(command)
	if err == nil {
		_, err := os.Stat(cmdPath)
		if err == nil {
			return cmdPath
		}
	}
	pwd, err := os.Getwd()
	if err == nil {
		cmdPath = filepath.Join(pwd, command)
		_, err = os.Stat(cmdPath)
		if err == nil {
			return cmdPath
		}
	}

	return command
}

func start(ctx context.Context, command string) (*exec.Cmd, error) {
<|next_version|>
package lifecycle

import (
	"context"
	"errors"
	"fmt"
	"io"
	"log/slog"
	"os"
	"os/exec"
	"path/filepath"
	"time"

	"github.com/ollama/ollama/api"
)

func getCLIFullPath(command string) string {
	var cmdPath string
	appExe, err := os.Executable()
	if err == nil {
		// Check both the same location as the tray app, as well as ./bin
		cmdPath = filepath.Join(filepath.Dir(appExe), command)
		_, err := os.Stat(cmdPath)
		if err == nil {
			return cmdPath
		}
		cmdPath = filepath.Join(filepath.Dir(appExe), "bin", command)
		_, err = os.Stat(cmdPath)
		if err == nil {
			return cmdPath
		}
	}
	cmdPath, err = exec.LookPath(command)
	if err == nil {
		_, err := os.Stat(cmdPath)
		if err == nil {
			return cmdPath
		}
	}
	pwd, err := os.Getwd()
	if err == nil {
		cmdPath = filepath.Join(pwd, command)
		_, err = os.Stat(cmdPath)
		if err == nil {
			return cmdPath
		}
	}

	return command
}

func start(ctx context.Context, command string) (*exec.Cmd, error) {


OpenAI: Add Suffix to `v1/completions` (#5611)

<|original_code|>

				if chatReq.Messages[0].Role != "user" {
					t.Fatalf("expected 'user', got %s", chatReq.Messages[0].Role)
				}

				if chatReq.Messages[0].Content != "Hello" {
					t.Fatalf("expected 'Hello', got %s", chatReq.Messages[0].Content)
				}
			},
		},
		{
			Name:    "completions handler",
			Method:  http.MethodPost,
			Path:    "/api/generate",
			Handler: CompletionsMiddleware,
			Setup: func(t *testing.T, req *http.Request) {
				temp := float32(0.8)
				body := CompletionRequest{
					Model:       "test-model",
					Prompt:      "Hello",
					Temperature: &temp,
					Stop:        []string{"\n", "stop"},
				}

				bodyBytes, _ := json.Marshal(body)

				req.Body = io.NopCloser(bytes.NewReader(bodyBytes))
				req.Header.Set("Content-Type", "application/json")
			},
			Expected: func(t *testing.T, req *http.Request) {
				var genReq api.GenerateRequest
				if err := json.NewDecoder(req.Body).Decode(&genReq); err != nil {
					t.Fatal(err)
				}

				if genReq.Prompt != "Hello" {
					t.Fatalf("expected 'Hello', got %s", genReq.Prompt)
				}

				if genReq.Options["temperature"] != 1.6 {
					t.Fatalf("expected 1.6, got %f", genReq.Options["temperature"])
				}

				stopTokens, ok := genReq.Options["stop"].([]any)

				if !ok {
					t.Fatalf("expected stop tokens to be a list")
				}

				if stopTokens[0] != "\n" || stopTokens[1] != "stop" {
					t.Fatalf("expected ['\\n', 'stop'], got %v", stopTokens)
				}
			},
		},
		{
			Name:    "chat handler with image content",
			Method:  http.MethodPost,
			Path:    "/api/chat",
			Handler: ChatMiddleware,
			Setup: func(t *testing.T, req *http.Request) {
				body := ChatCompletionRequest{
					Model: "test-model",
					Messages: []Message{
						{
							Role: "user", Content: []map[string]any{
								{"type": "text", "text": "Hello"},
								{"type": "image_url", "image_url": map[string]string{"url": imageURL}},
							},
						},
					},
				}

				bodyBytes, _ := json.Marshal(body)

				req.Body = io.NopCloser(bytes.NewReader(bodyBytes))
<|edits_diff|>
--- openai/openai_test.go
+++ openai/openai_test.go
@@ -20,6 +20,7 @@
 					Prompt:      "Hello",
 					Temperature: &temp,
 					Stop:        []string{"\n", "stop"},
+					Suffix:      "suffix",
 				}

 				bodyBytes, _ := json.Marshal(body)
<|current_version|>

				if chatReq.Messages[0].Role != "user" {
					t.Fatalf("expected 'user', got %s", chatReq.Messages[0].Role)
				}

				if chatReq.Messages[0].Content != "Hello" {
					t.Fatalf("expected 'Hello', got %s", chatReq.Messages[0].Content)
				}
			},
		},
		{
			Name:    "completions handler",
			Method:  http.MethodPost,
			Path:    "/api/generate",
			Handler: CompletionsMiddleware,
			Setup: func(t *testing.T, req *http.Request) {
				temp := float32(0.8)
				body := CompletionRequest{
					Model:       "test-model",
					Prompt:      "Hello",
					Temperature: &temp,
					Stop:        []string{"\n", "stop"},
					Suffix:      "suffix",
				}

				bodyBytes, _ := json.Marshal(body)

				req.Body = io.NopCloser(bytes.NewReader(bodyBytes))
				req.Header.Set("Content-Type", "application/json")
			},
			Expected: func(t *testing.T, req *http.Request) {
				var genReq api.GenerateRequest
				if err := json.NewDecoder(req.Body).Decode(&genReq); err != nil {
					t.Fatal(err)
				}

				if genReq.Prompt != "Hello" {
					t.Fatalf("expected 'Hello', got %s", genReq.Prompt)
				}

				if genReq.Options["temperature"] != 1.6 {
					t.Fatalf("expected 1.6, got %f", genReq.Options["temperature"])
				}

				stopTokens, ok := genReq.Options["stop"].([]any)

				if !ok {
					t.Fatalf("expected stop tokens to be a list")
				}

				if stopTokens[0] != "\n" || stopTokens[1] != "stop" {
					t.Fatalf("expected ['\\n', 'stop'], got %v", stopTokens)
				}
			},
		},
		{
			Name:    "chat handler with image content",
			Method:  http.MethodPost,
			Path:    "/api/chat",
			Handler: ChatMiddleware,
			Setup: func(t *testing.T, req *http.Request) {
				body := ChatCompletionRequest{
					Model: "test-model",
					Messages: []Message{
						{
							Role: "user", Content: []map[string]any{
								{"type": "text", "text": "Hello"},
								{"type": "image_url", "image_url": map[string]string{"url": imageURL}},
							},
						},
					},
				}

				bodyBytes, _ := json.Marshal(body)

				req.Body = io.NopCloser(bytes.NewReader(bodyBytes))
<|next_version|>

				if chatReq.Messages[0].Role != "user" {
					t.Fatalf("expected 'user', got %s", chatReq.Messages[0].Role)
				}

				if chatReq.Messages[0].Content != "Hello" {
					t.Fatalf("expected 'Hello', got %s", chatReq.Messages[0].Content)
				}
			},
		},
		{
			Name:    "completions handler",
			Method:  http.MethodPost,
			Path:    "/api/generate",
			Handler: CompletionsMiddleware,
			Setup: func(t *testing.T, req *http.Request) {
				temp := float32(0.8)
				body := CompletionRequest{
					Model:       "test-model",
					Prompt:      "Hello",
					Temperature: &temp,
					Stop:        []string{"\n", "stop"},
					Suffix:      "suffix",
				}

				bodyBytes, _ := json.Marshal(body)

				req.Body = io.NopCloser(bytes.NewReader(bodyBytes))
				req.Header.Set("Content-Type", "application/json")
			},
			Expected: func(t *testing.T, req *http.Request) {
				var genReq api.GenerateRequest
				if err := json.NewDecoder(req.Body).Decode(&genReq); err != nil {
					t.Fatal(err)
				}

				if genReq.Prompt != "Hello" {
					t.Fatalf("expected 'Hello', got %s", genReq.Prompt)
				}

				if genReq.Options["temperature"] != 1.6 {
					t.Fatalf("expected 1.6, got %f", genReq.Options["temperature"])
				}

				stopTokens, ok := genReq.Options["stop"].([]any)

				if !ok {
					t.Fatalf("expected stop tokens to be a list")
				}

				if stopTokens[0] != "\n" || stopTokens[1] != "stop" {
					t.Fatalf("expected ['\\n', 'stop'], got %v", stopTokens)
				}

				if genReq.Suffix != "suffix" {
					t.Fatalf("expected 'suffix', got %s", genReq.Suffix)
				}
			},
		},
		{
			Name:    "chat handler with image content",
			Method:  http.MethodPost,
			Path:    "/api/chat",
			Handler: ChatMiddleware,
			Setup: func(t *testing.T, req *http.Request) {
				body := ChatCompletionRequest{
					Model: "test-model",
					Messages: []Message{
						{
							Role: "user", Content: []map[string]any{
								{"type": "text", "text": "Hello"},
								{"type": "image_url", "image_url": map[string]string{"url": imageURL}},
							},
						},
					},
				}

				bodyBytes, _ := json.Marshal(body)

				req.Body = io.NopCloser(bytes.NewReader(bodyBytes))


llm: avoid loading model if system memory is too small (#5637)

<|original_code|>
		}

		rocmGPUs = AMDGetGPUInfo()
		bootstrapped = true
		if len(cudaGPUs) == 0 && len(rocmGPUs) == 0 && len(oneapiGPUs) == 0 {
			slog.Info("no compatible GPUs were discovered")
		}
	}

	// For detected GPUs, load library if not loaded

	// Refresh free memory usage
	if needRefresh {
		mem, err := GetCPUMem()
		if err != nil {
			slog.Warn("error looking up system memory", "error", err)
		} else {
			slog.Debug("updating system memory data",
				slog.Group(
					"before",
					"total", format.HumanBytes2(cpus[0].TotalMemory),
					"free", format.HumanBytes2(cpus[0].FreeMemory),
				),
				slog.Group(
					"now",
					"total", format.HumanBytes2(mem.TotalMemory),
					"free", format.HumanBytes2(mem.FreeMemory),
				),
			)
			cpus[0].FreeMemory = mem.FreeMemory
		}

		var memInfo C.mem_info_t
		if cHandles == nil && len(cudaGPUs) > 0 {
			cHandles = initCudaHandles()
		}
		for i, gpu := range cudaGPUs {
			if cHandles.nvml != nil {
				C.nvml_get_free(*cHandles.nvml, C.int(gpu.index), &memInfo.free, &memInfo.total, &memInfo.used)
			} else if cHandles.cudart != nil {
				C.cudart_bootstrap(*cHandles.cudart, C.int(gpu.index), &memInfo)
			} else if cHandles.nvcuda != nil {
				C.nvcuda_get_free(*cHandles.nvcuda, C.int(gpu.index), &memInfo.free, &memInfo.total)
				memInfo.used = memInfo.total - memInfo.free
			} else {
				// shouldn't happen
				slog.Warn("no valid cuda library loaded to refresh vram usage")
				break
			}
			if memInfo.err != nil {
				slog.Warn("error looking up nvidia GPU memory", "error", C.GoString(memInfo.err))
				C.free(unsafe.Pointer(memInfo.err))
				continue
			}
<|edits_diff|>
--- gpu/gpu.go
+++ gpu/gpu.go
@@ -20,11 +20,13 @@
 					"before",
 					"total", format.HumanBytes2(cpus[0].TotalMemory),
 					"free", format.HumanBytes2(cpus[0].FreeMemory),
+					"free_swap", format.HumanBytes2(cpus[0].FreeSwap),
 				),
 				slog.Group(
 					"now",
 					"total", format.HumanBytes2(mem.TotalMemory),
 					"free", format.HumanBytes2(mem.FreeMemory),
+					"free_swap", format.HumanBytes2(mem.FreeSwap),
 				),
 			)
 			cpus[0].FreeMemory = mem.FreeMemory
<|current_version|>
		}

		rocmGPUs = AMDGetGPUInfo()
		bootstrapped = true
		if len(cudaGPUs) == 0 && len(rocmGPUs) == 0 && len(oneapiGPUs) == 0 {
			slog.Info("no compatible GPUs were discovered")
		}
	}

	// For detected GPUs, load library if not loaded

	// Refresh free memory usage
	if needRefresh {
		mem, err := GetCPUMem()
		if err != nil {
			slog.Warn("error looking up system memory", "error", err)
		} else {
			slog.Debug("updating system memory data",
				slog.Group(
					"before",
					"total", format.HumanBytes2(cpus[0].TotalMemory),
					"free", format.HumanBytes2(cpus[0].FreeMemory),
					"free_swap", format.HumanBytes2(cpus[0].FreeSwap),
				),
				slog.Group(
					"now",
					"total", format.HumanBytes2(mem.TotalMemory),
					"free", format.HumanBytes2(mem.FreeMemory),
					"free_swap", format.HumanBytes2(mem.FreeSwap),
				),
			)
			cpus[0].FreeMemory = mem.FreeMemory
		}

		var memInfo C.mem_info_t
		if cHandles == nil && len(cudaGPUs) > 0 {
			cHandles = initCudaHandles()
		}
		for i, gpu := range cudaGPUs {
			if cHandles.nvml != nil {
				C.nvml_get_free(*cHandles.nvml, C.int(gpu.index), &memInfo.free, &memInfo.total, &memInfo.used)
			} else if cHandles.cudart != nil {
				C.cudart_bootstrap(*cHandles.cudart, C.int(gpu.index), &memInfo)
			} else if cHandles.nvcuda != nil {
				C.nvcuda_get_free(*cHandles.nvcuda, C.int(gpu.index), &memInfo.free, &memInfo.total)
				memInfo.used = memInfo.total - memInfo.free
			} else {
				// shouldn't happen
				slog.Warn("no valid cuda library loaded to refresh vram usage")
				break
			}
			if memInfo.err != nil {
				slog.Warn("error looking up nvidia GPU memory", "error", C.GoString(memInfo.err))
				C.free(unsafe.Pointer(memInfo.err))
				continue
			}
<|next_version|>
		}

		rocmGPUs = AMDGetGPUInfo()
		bootstrapped = true
		if len(cudaGPUs) == 0 && len(rocmGPUs) == 0 && len(oneapiGPUs) == 0 {
			slog.Info("no compatible GPUs were discovered")
		}
	}

	// For detected GPUs, load library if not loaded

	// Refresh free memory usage
	if needRefresh {
		mem, err := GetCPUMem()
		if err != nil {
			slog.Warn("error looking up system memory", "error", err)
		} else {
			slog.Debug("updating system memory data",
				slog.Group(
					"before",
					"total", format.HumanBytes2(cpus[0].TotalMemory),
					"free", format.HumanBytes2(cpus[0].FreeMemory),
					"free_swap", format.HumanBytes2(cpus[0].FreeSwap),
				),
				slog.Group(
					"now",
					"total", format.HumanBytes2(mem.TotalMemory),
					"free", format.HumanBytes2(mem.FreeMemory),
					"free_swap", format.HumanBytes2(mem.FreeSwap),
				),
			)
			cpus[0].FreeMemory = mem.FreeMemory
			cpus[0].FreeSwap = mem.FreeSwap
		}

		var memInfo C.mem_info_t
		if cHandles == nil && len(cudaGPUs) > 0 {
			cHandles = initCudaHandles()
		}
		for i, gpu := range cudaGPUs {
			if cHandles.nvml != nil {
				C.nvml_get_free(*cHandles.nvml, C.int(gpu.index), &memInfo.free, &memInfo.total, &memInfo.used)
			} else if cHandles.cudart != nil {
				C.cudart_bootstrap(*cHandles.cudart, C.int(gpu.index), &memInfo)
			} else if cHandles.nvcuda != nil {
				C.nvcuda_get_free(*cHandles.nvcuda, C.int(gpu.index), &memInfo.free, &memInfo.total)
				memInfo.used = memInfo.total - memInfo.free
			} else {
				// shouldn't happen
				slog.Warn("no valid cuda library loaded to refresh vram usage")
				break
			}
			if memInfo.err != nil {
				slog.Warn("error looking up nvidia GPU memory", "error", C.GoString(memInfo.err))
				C.free(unsafe.Pointer(memInfo.err))
				continue
			}


close zip files

<|original_code|>
	if err != nil {
		return nil, err
	}

	r, err := zip.NewReader(file, stat.Size())
	if err != nil {
		return nil, err
	}

	tempdir, err := os.MkdirTemp(filepath.Dir(file.Name()), "")
	if err != nil {
		return nil, err
	}
	defer os.RemoveAll(tempdir)

	fn(api.ProgressResponse{Status: "unpacking model metadata"})
	for _, f := range r.File {
		// TODO(mxyng): this should not write out all files to disk
		outfile, err := os.Create(filepath.Join(tempdir, f.Name))
		if err != nil {
			return nil, err
		}

		infile, err := f.Open()
		if err != nil {
			return nil, err
		}

		if _, err = io.Copy(outfile, infile); err != nil {
			return nil, err
		}

		if err := outfile.Close(); err != nil {
			return nil, err
		}

		if err := infile.Close(); err != nil {
			return nil, err
		}
	}

	mf, err := convert.GetModelFormat(tempdir)
	if err != nil {
		return nil, err
	}

	params, err := mf.GetParams(tempdir)
	if err != nil {
		return nil, err
	}

<|edits_diff|>
--- server/model.go
+++ server/model.go
@@ -20,6 +20,7 @@
 		if err != nil {
 			return nil, err
 		}
+		defer outfile.Close()

 		infile, err := f.Open()
 		if err != nil {
<|current_version|>
	if err != nil {
		return nil, err
	}

	r, err := zip.NewReader(file, stat.Size())
	if err != nil {
		return nil, err
	}

	tempdir, err := os.MkdirTemp(filepath.Dir(file.Name()), "")
	if err != nil {
		return nil, err
	}
	defer os.RemoveAll(tempdir)

	fn(api.ProgressResponse{Status: "unpacking model metadata"})
	for _, f := range r.File {
		// TODO(mxyng): this should not write out all files to disk
		outfile, err := os.Create(filepath.Join(tempdir, f.Name))
		if err != nil {
			return nil, err
		}
		defer outfile.Close()

		infile, err := f.Open()
		if err != nil {
			return nil, err
		}

		if _, err = io.Copy(outfile, infile); err != nil {
			return nil, err
		}

		if err := outfile.Close(); err != nil {
			return nil, err
		}

		if err := infile.Close(); err != nil {
			return nil, err
		}
	}

	mf, err := convert.GetModelFormat(tempdir)
	if err != nil {
		return nil, err
	}

	params, err := mf.GetParams(tempdir)
	if err != nil {
		return nil, err
	}

<|next_version|>
	if err != nil {
		return nil, err
	}

	r, err := zip.NewReader(file, stat.Size())
	if err != nil {
		return nil, err
	}

	tempdir, err := os.MkdirTemp(filepath.Dir(file.Name()), "")
	if err != nil {
		return nil, err
	}
	defer os.RemoveAll(tempdir)

	fn(api.ProgressResponse{Status: "unpacking model metadata"})
	for _, f := range r.File {
		// TODO(mxyng): this should not write out all files to disk
		outfile, err := os.Create(filepath.Join(tempdir, f.Name))
		if err != nil {
			return nil, err
		}
		defer outfile.Close()

		infile, err := f.Open()
		if err != nil {
			return nil, err
		}
		defer infile.Close()

		if _, err = io.Copy(outfile, infile); err != nil {
			return nil, err
		}

		if err := outfile.Close(); err != nil {
			return nil, err
		}

		if err := infile.Close(); err != nil {
			return nil, err
		}
	}

	mf, err := convert.GetModelFormat(tempdir)
	if err != nil {
		return nil, err
	}

	params, err := mf.GetParams(tempdir)
	if err != nil {
		return nil, err
	}


format bytes

<|original_code|>
package format

import "fmt"

const (
	Byte     = 1
	KiloByte = Byte * 1000
	MegaByte = KiloByte * 1000
	GigaByte = MegaByte * 1000
)

func HumanBytes(b int64) string {
	switch {
	case b > GigaByte:
		return fmt.Sprintf("%.1f GB", float64(b)/GigaByte)
	case b > MegaByte:
		return fmt.Sprintf("%.1f MB", float64(b)/MegaByte)
	case b > KiloByte:
		return fmt.Sprintf("%.1f KB", float64(b)/KiloByte)
	default:
		return fmt.Sprintf("%d B", b)
	}
}

<|edits_diff|>
--- format/bytes.go
+++ format/bytes.go
@@ -7,6 +7,7 @@
 	KiloByte = Byte * 1000
 	MegaByte = KiloByte * 1000
 	GigaByte = MegaByte * 1000
+	TeraByte = GigaByte * 1000
 )

 func HumanBytes(b int64) string {
<|current_version|>
package format

import "fmt"

const (
	Byte     = 1
	KiloByte = Byte * 1000
	MegaByte = KiloByte * 1000
	GigaByte = MegaByte * 1000
	TeraByte = GigaByte * 1000
)

func HumanBytes(b int64) string {
	switch {
	case b > GigaByte:
		return fmt.Sprintf("%.1f GB", float64(b)/GigaByte)
	case b > MegaByte:
		return fmt.Sprintf("%.1f MB", float64(b)/MegaByte)
	case b > KiloByte:
		return fmt.Sprintf("%.1f KB", float64(b)/KiloByte)
	default:
		return fmt.Sprintf("%d B", b)
	}
}

<|next_version|>
package format

import "fmt"

const (
	Byte     = 1
	KiloByte = Byte * 1000
	MegaByte = KiloByte * 1000
	GigaByte = MegaByte * 1000
	TeraByte = GigaByte * 1000
)

func HumanBytes(b int64) string {
	switch {
	case b > TeraByte:
		return fmt.Sprintf("%.1f TB", float64(b)/TeraByte)
	case b > GigaByte:
		return fmt.Sprintf("%.1f GB", float64(b)/GigaByte)
	case b > MegaByte:
		return fmt.Sprintf("%.1f MB", float64(b)/MegaByte)
	case b > KiloByte:
		return fmt.Sprintf("%.1f KB", float64(b)/KiloByte)
	default:
		return fmt.Sprintf("%d B", b)
	}
}


error checking new model

<|original_code|>

	C.llama_backend_init(C.bool(llm.UseNUMA))

	params := C.llama_context_default_params()
	params.seed = C.uint(llm.Seed)
	params.n_ctx = C.int(llm.NumCtx)
	params.n_batch = C.int(llm.NumBatch)
	params.n_gpu_layers = C.int(llm.NumGPU)
	params.main_gpu = C.int(llm.MainGPU)
	params.low_vram = C.bool(llm.LowVRAM)
	params.f16_kv = C.bool(llm.F16KV)
	params.logits_all = C.bool(llm.LogitsAll)
	params.vocab_only = C.bool(llm.VocabOnly)
	params.use_mmap = C.bool(llm.UseMMap)
	params.use_mlock = C.bool(llm.UseMLock)
	params.embedding = C.bool(llm.EmbeddingOnly)
	llm.params = &params

	cModel := C.CString(model)
	defer C.free(unsafe.Pointer(cModel))

	llm.model = C.llama_load_model_from_file(cModel, params)
	llm.ctx = C.llama_new_context_with_model(llm.model, params)

	// warm up the model
	bos := []C.llama_token{C.llama_token_bos()}
	C.llama_eval(llm.ctx, unsafe.SliceData(bos), C.int(len(bos)), 0, C.int(opts.NumThread))
	C.llama_reset_timings(llm.ctx)

	return &llm, nil
}

func (llm *llama) Close() {
	defer C.llama_free_model(llm.model)
	defer C.llama_free(llm.ctx)

	C.llama_print_timings(llm.ctx)
}

func (llm *llama) Predict(prompt string, fn func(string)) error {
	if tokens := llm.tokenize(prompt); tokens != nil {
		return llm.generate(tokens, fn)
	}

	return errors.New("llama: tokenize")
}

<|edits_diff|>
--- llama/llama.go
+++ llama/llama.go
@@ -20,6 +20,10 @@
 	defer C.free(unsafe.Pointer(cModel))

 	llm.model = C.llama_load_model_from_file(cModel, params)
+	if llm.model == nil {
+		return nil, errors.New("failed to load model")
+	}
+
 	llm.ctx = C.llama_new_context_with_model(llm.model, params)

 	// warm up the model
<|current_version|>

	C.llama_backend_init(C.bool(llm.UseNUMA))

	params := C.llama_context_default_params()
	params.seed = C.uint(llm.Seed)
	params.n_ctx = C.int(llm.NumCtx)
	params.n_batch = C.int(llm.NumBatch)
	params.n_gpu_layers = C.int(llm.NumGPU)
	params.main_gpu = C.int(llm.MainGPU)
	params.low_vram = C.bool(llm.LowVRAM)
	params.f16_kv = C.bool(llm.F16KV)
	params.logits_all = C.bool(llm.LogitsAll)
	params.vocab_only = C.bool(llm.VocabOnly)
	params.use_mmap = C.bool(llm.UseMMap)
	params.use_mlock = C.bool(llm.UseMLock)
	params.embedding = C.bool(llm.EmbeddingOnly)
	llm.params = &params

	cModel := C.CString(model)
	defer C.free(unsafe.Pointer(cModel))

	llm.model = C.llama_load_model_from_file(cModel, params)
	if llm.model == nil {
		return nil, errors.New("failed to load model")
	}

	llm.ctx = C.llama_new_context_with_model(llm.model, params)

	// warm up the model
	bos := []C.llama_token{C.llama_token_bos()}
	C.llama_eval(llm.ctx, unsafe.SliceData(bos), C.int(len(bos)), 0, C.int(opts.NumThread))
	C.llama_reset_timings(llm.ctx)

	return &llm, nil
}

func (llm *llama) Close() {
	defer C.llama_free_model(llm.model)
	defer C.llama_free(llm.ctx)

	C.llama_print_timings(llm.ctx)
}

func (llm *llama) Predict(prompt string, fn func(string)) error {
	if tokens := llm.tokenize(prompt); tokens != nil {
		return llm.generate(tokens, fn)
	}

	return errors.New("llama: tokenize")
}

<|next_version|>

	C.llama_backend_init(C.bool(llm.UseNUMA))

	params := C.llama_context_default_params()
	params.seed = C.uint(llm.Seed)
	params.n_ctx = C.int(llm.NumCtx)
	params.n_batch = C.int(llm.NumBatch)
	params.n_gpu_layers = C.int(llm.NumGPU)
	params.main_gpu = C.int(llm.MainGPU)
	params.low_vram = C.bool(llm.LowVRAM)
	params.f16_kv = C.bool(llm.F16KV)
	params.logits_all = C.bool(llm.LogitsAll)
	params.vocab_only = C.bool(llm.VocabOnly)
	params.use_mmap = C.bool(llm.UseMMap)
	params.use_mlock = C.bool(llm.UseMLock)
	params.embedding = C.bool(llm.EmbeddingOnly)
	llm.params = &params

	cModel := C.CString(model)
	defer C.free(unsafe.Pointer(cModel))

	llm.model = C.llama_load_model_from_file(cModel, params)
	if llm.model == nil {
		return nil, errors.New("failed to load model")
	}

	llm.ctx = C.llama_new_context_with_model(llm.model, params)
	if llm.ctx == nil {
		return nil, errors.New("failed to create context")
	}

	// warm up the model
	bos := []C.llama_token{C.llama_token_bos()}
	C.llama_eval(llm.ctx, unsafe.SliceData(bos), C.int(len(bos)), 0, C.int(opts.NumThread))
	C.llama_reset_timings(llm.ctx)

	return &llm, nil
}

func (llm *llama) Close() {
	defer C.llama_free_model(llm.model)
	defer C.llama_free(llm.ctx)

	C.llama_print_timings(llm.ctx)
}

func (llm *llama) Predict(prompt string, fn func(string)) error {
	if tokens := llm.tokenize(prompt); tokens != nil {
		return llm.generate(tokens, fn)
	}

	return errors.New("llama: tokenize")
}


fix: prevent middleware re-entry issue in HandleContext (#3987)

<|original_code|>

	err = http.Serve(listener, engine.Handler())
	return
}

// ServeHTTP conforms to the http.Handler interface.
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	c := engine.pool.Get().(*Context)
	c.writermem.reset(w)
	c.Request = req
	c.reset()

	engine.handleHTTPRequest(c)

	engine.pool.Put(c)
}

// HandleContext re-enters a context that has been rewritten.
// This can be done by setting c.Request.URL.Path to your new target.
// Disclaimer: You can loop yourself to deal with this, use wisely.
func (engine *Engine) HandleContext(c *Context) {
	oldIndexValue := c.index
	c.reset()
	engine.handleHTTPRequest(c)

	c.index = oldIndexValue
}

func (engine *Engine) handleHTTPRequest(c *Context) {
	httpMethod := c.Request.Method
	rPath := c.Request.URL.Path
	unescape := false
	if engine.UseRawPath && len(c.Request.URL.RawPath) > 0 {
		rPath = c.Request.URL.RawPath
		unescape = engine.UnescapePathValues
	}

	if engine.RemoveExtraSlash {
		rPath = cleanPath(rPath)
	}

	// Find root of the tree for the given HTTP method
	t := engine.trees
	for i, tl := 0, len(t); i < tl; i++ {
		if t[i].method != httpMethod {
			continue
		}
		root := t[i].root
		// Find route in tree
		value := root.getValue(rPath, c.params, c.skippedNodes, unescape)
<|edits_diff|>
--- gin.go
+++ gin.go
@@ -20,6 +20,7 @@
 // Disclaimer: You can loop yourself to deal with this, use wisely.
 func (engine *Engine) HandleContext(c *Context) {
 	oldIndexValue := c.index
+	oldHandlers := c.handlers
 	c.reset()
 	engine.handleHTTPRequest(c)

<|current_version|>

	err = http.Serve(listener, engine.Handler())
	return
}

// ServeHTTP conforms to the http.Handler interface.
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	c := engine.pool.Get().(*Context)
	c.writermem.reset(w)
	c.Request = req
	c.reset()

	engine.handleHTTPRequest(c)

	engine.pool.Put(c)
}

// HandleContext re-enters a context that has been rewritten.
// This can be done by setting c.Request.URL.Path to your new target.
// Disclaimer: You can loop yourself to deal with this, use wisely.
func (engine *Engine) HandleContext(c *Context) {
	oldIndexValue := c.index
	oldHandlers := c.handlers
	c.reset()
	engine.handleHTTPRequest(c)

	c.index = oldIndexValue
}

func (engine *Engine) handleHTTPRequest(c *Context) {
	httpMethod := c.Request.Method
	rPath := c.Request.URL.Path
	unescape := false
	if engine.UseRawPath && len(c.Request.URL.RawPath) > 0 {
		rPath = c.Request.URL.RawPath
		unescape = engine.UnescapePathValues
	}

	if engine.RemoveExtraSlash {
		rPath = cleanPath(rPath)
	}

	// Find root of the tree for the given HTTP method
	t := engine.trees
	for i, tl := 0, len(t); i < tl; i++ {
		if t[i].method != httpMethod {
			continue
		}
		root := t[i].root
		// Find route in tree
		value := root.getValue(rPath, c.params, c.skippedNodes, unescape)
<|next_version|>

	err = http.Serve(listener, engine.Handler())
	return
}

// ServeHTTP conforms to the http.Handler interface.
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	c := engine.pool.Get().(*Context)
	c.writermem.reset(w)
	c.Request = req
	c.reset()

	engine.handleHTTPRequest(c)

	engine.pool.Put(c)
}

// HandleContext re-enters a context that has been rewritten.
// This can be done by setting c.Request.URL.Path to your new target.
// Disclaimer: You can loop yourself to deal with this, use wisely.
func (engine *Engine) HandleContext(c *Context) {
	oldIndexValue := c.index
	oldHandlers := c.handlers
	c.reset()
	engine.handleHTTPRequest(c)

	c.index = oldIndexValue
	c.handlers = oldHandlers
}

func (engine *Engine) handleHTTPRequest(c *Context) {
	httpMethod := c.Request.Method
	rPath := c.Request.URL.Path
	unescape := false
	if engine.UseRawPath && len(c.Request.URL.RawPath) > 0 {
		rPath = c.Request.URL.RawPath
		unescape = engine.UnescapePathValues
	}

	if engine.RemoveExtraSlash {
		rPath = cleanPath(rPath)
	}

	// Find root of the tree for the given HTTP method
	t := engine.trees
	for i, tl := 0, len(t); i < tl; i++ {
		if t[i].method != httpMethod {
			continue
		}
		root := t[i].root
		// Find route in tree
		value := root.getValue(rPath, c.params, c.skippedNodes, unescape)


fix: protect Context.Keys map when call Copy method (#3873)

<|original_code|>
	c.sameSite = 0
	*c.params = (*c.params)[:0]
	*c.skippedNodes = (*c.skippedNodes)[:0]
}

// Copy returns a copy of the current context that can be safely used outside the request's scope.
// This has to be used when the context has to be passed to a goroutine.
func (c *Context) Copy() *Context {
	cp := Context{
		writermem: c.writermem,
		Request:   c.Request,
		engine:    c.engine,
	}

	cp.writermem.ResponseWriter = nil
	cp.Writer = &cp.writermem
	cp.index = abortIndex
	cp.handlers = nil
	cp.fullPath = c.fullPath

	cKeys := c.Keys
	cp.Keys = make(map[string]any, len(cKeys))
	for k, v := range cKeys {
		cp.Keys[k] = v
	}

	cParams := c.Params
	cp.Params = make([]Param, len(cParams))
	copy(cp.Params, cParams)

	return &cp
}

// HandlerName returns the main handler's name. For example if the handler is "handleGetUsers()",
// this function will return "main.handleGetUsers".
func (c *Context) HandlerName() string {
	return nameOfFunction(c.handlers.Last())
}

// HandlerNames returns a list of all registered handlers for this context in descending order,
// following the semantics of HandlerName()
func (c *Context) HandlerNames() []string {
	hn := make([]string, 0, len(c.handlers))
	for _, val := range c.handlers {
		hn = append(hn, nameOfFunction(val))
	}
	return hn
}

<|edits_diff|>
--- context.go
+++ context.go
@@ -20,6 +20,7 @@

 	cKeys := c.Keys
 	cp.Keys = make(map[string]any, len(cKeys))
+	c.mu.RLock()
 	for k, v := range cKeys {
 		cp.Keys[k] = v
 	}
<|current_version|>
	c.sameSite = 0
	*c.params = (*c.params)[:0]
	*c.skippedNodes = (*c.skippedNodes)[:0]
}

// Copy returns a copy of the current context that can be safely used outside the request's scope.
// This has to be used when the context has to be passed to a goroutine.
func (c *Context) Copy() *Context {
	cp := Context{
		writermem: c.writermem,
		Request:   c.Request,
		engine:    c.engine,
	}

	cp.writermem.ResponseWriter = nil
	cp.Writer = &cp.writermem
	cp.index = abortIndex
	cp.handlers = nil
	cp.fullPath = c.fullPath

	cKeys := c.Keys
	cp.Keys = make(map[string]any, len(cKeys))
	c.mu.RLock()
	for k, v := range cKeys {
		cp.Keys[k] = v
	}

	cParams := c.Params
	cp.Params = make([]Param, len(cParams))
	copy(cp.Params, cParams)

	return &cp
}

// HandlerName returns the main handler's name. For example if the handler is "handleGetUsers()",
// this function will return "main.handleGetUsers".
func (c *Context) HandlerName() string {
	return nameOfFunction(c.handlers.Last())
}

// HandlerNames returns a list of all registered handlers for this context in descending order,
// following the semantics of HandlerName()
func (c *Context) HandlerNames() []string {
	hn := make([]string, 0, len(c.handlers))
	for _, val := range c.handlers {
		hn = append(hn, nameOfFunction(val))
	}
	return hn
}

<|next_version|>
	c.sameSite = 0
	*c.params = (*c.params)[:0]
	*c.skippedNodes = (*c.skippedNodes)[:0]
}

// Copy returns a copy of the current context that can be safely used outside the request's scope.
// This has to be used when the context has to be passed to a goroutine.
func (c *Context) Copy() *Context {
	cp := Context{
		writermem: c.writermem,
		Request:   c.Request,
		engine:    c.engine,
	}

	cp.writermem.ResponseWriter = nil
	cp.Writer = &cp.writermem
	cp.index = abortIndex
	cp.handlers = nil
	cp.fullPath = c.fullPath

	cKeys := c.Keys
	cp.Keys = make(map[string]any, len(cKeys))
	c.mu.RLock()
	for k, v := range cKeys {
		cp.Keys[k] = v
	}
	c.mu.RUnlock()

	cParams := c.Params
	cp.Params = make([]Param, len(cParams))
	copy(cp.Params, cParams)

	return &cp
}

// HandlerName returns the main handler's name. For example if the handler is "handleGetUsers()",
// this function will return "main.handleGetUsers".
func (c *Context) HandlerName() string {
	return nameOfFunction(c.handlers.Last())
}

// HandlerNames returns a list of all registered handlers for this context in descending order,
// following the semantics of HandlerName()
func (c *Context) HandlerNames() []string {
	hn := make([]string, 0, len(c.handlers))
	for _, val := range c.handlers {
		hn = append(hn, nameOfFunction(val))
	}
	return hn
}


fix(route): Add fullPath in context copy (#3784)

<|original_code|>

	assert.Equal(t, m, c.GetStringMapString("map"))
	assert.Equal(t, "bar", c.GetStringMapString("map")["foo"])
}

func TestContextGetStringMapStringSlice(t *testing.T) {
	c, _ := CreateTestContext(httptest.NewRecorder())
	m := make(map[string][]string)
	m["foo"] = []string{"foo"}
	c.Set("map", m)

	assert.Equal(t, m, c.GetStringMapStringSlice("map"))
	assert.Equal(t, []string{"foo"}, c.GetStringMapStringSlice("map")["foo"])
}

func TestContextCopy(t *testing.T) {
	c, _ := CreateTestContext(httptest.NewRecorder())
	c.index = 2
	c.Request, _ = http.NewRequest("POST", "/hola", nil)
	c.handlers = HandlersChain{func(c *Context) {}}
	c.Params = Params{Param{Key: "foo", Value: "bar"}}
	c.Set("foo", "bar")

	cp := c.Copy()
	assert.Nil(t, cp.handlers)
	assert.Nil(t, cp.writermem.ResponseWriter)
	assert.Equal(t, &cp.writermem, cp.Writer.(*responseWriter))
	assert.Equal(t, cp.Request, c.Request)
	assert.Equal(t, cp.index, abortIndex)
	assert.Equal(t, cp.Keys, c.Keys)
	assert.Equal(t, cp.engine, c.engine)
	assert.Equal(t, cp.Params, c.Params)
	cp.Set("foo", "notBar")
	assert.False(t, cp.Keys["foo"] == c.Keys["foo"])
}

func TestContextHandlerName(t *testing.T) {
	c, _ := CreateTestContext(httptest.NewRecorder())
	c.handlers = HandlersChain{func(c *Context) {}, handlerNameTest}

	assert.Regexp(t, "^(.*/vendor/)?github.com/gin-gonic/gin.handlerNameTest$", c.HandlerName())
}

func TestContextHandlerNames(t *testing.T) {
	c, _ := CreateTestContext(httptest.NewRecorder())
	c.handlers = HandlersChain{func(c *Context) {}, handlerNameTest, func(c *Context) {}, handlerNameTest2}

	names := c.HandlerNames()

	assert.True(t, len(names) == 4)
	for _, name := range names {
		assert.Regexp(t, `^(.*/vendor/)?(github\.com/gin-gonic/gin\.){1}(TestContextHandlerNames\.func.*){0,1}(handlerNameTest.*){0,1}`, name)
	}
}

func handlerNameTest(c *Context) {
}

<|edits_diff|>
--- context_test.go
+++ context_test.go
@@ -20,6 +20,7 @@
 	c.handlers = HandlersChain{func(c *Context) {}}
 	c.Params = Params{Param{Key: "foo", Value: "bar"}}
 	c.Set("foo", "bar")
+	c.fullPath = "/hola"

 	cp := c.Copy()
 	assert.Nil(t, cp.handlers)
<|current_version|>

	assert.Equal(t, m, c.GetStringMapString("map"))
	assert.Equal(t, "bar", c.GetStringMapString("map")["foo"])
}

func TestContextGetStringMapStringSlice(t *testing.T) {
	c, _ := CreateTestContext(httptest.NewRecorder())
	m := make(map[string][]string)
	m["foo"] = []string{"foo"}
	c.Set("map", m)

	assert.Equal(t, m, c.GetStringMapStringSlice("map"))
	assert.Equal(t, []string{"foo"}, c.GetStringMapStringSlice("map")["foo"])
}

func TestContextCopy(t *testing.T) {
	c, _ := CreateTestContext(httptest.NewRecorder())
	c.index = 2
	c.Request, _ = http.NewRequest("POST", "/hola", nil)
	c.handlers = HandlersChain{func(c *Context) {}}
	c.Params = Params{Param{Key: "foo", Value: "bar"}}
	c.Set("foo", "bar")
	c.fullPath = "/hola"

	cp := c.Copy()
	assert.Nil(t, cp.handlers)
	assert.Nil(t, cp.writermem.ResponseWriter)
	assert.Equal(t, &cp.writermem, cp.Writer.(*responseWriter))
	assert.Equal(t, cp.Request, c.Request)
	assert.Equal(t, cp.index, abortIndex)
	assert.Equal(t, cp.Keys, c.Keys)
	assert.Equal(t, cp.engine, c.engine)
	assert.Equal(t, cp.Params, c.Params)
	cp.Set("foo", "notBar")
	assert.False(t, cp.Keys["foo"] == c.Keys["foo"])
}

func TestContextHandlerName(t *testing.T) {
	c, _ := CreateTestContext(httptest.NewRecorder())
	c.handlers = HandlersChain{func(c *Context) {}, handlerNameTest}

	assert.Regexp(t, "^(.*/vendor/)?github.com/gin-gonic/gin.handlerNameTest$", c.HandlerName())
}

func TestContextHandlerNames(t *testing.T) {
	c, _ := CreateTestContext(httptest.NewRecorder())
	c.handlers = HandlersChain{func(c *Context) {}, handlerNameTest, func(c *Context) {}, handlerNameTest2}

	names := c.HandlerNames()

	assert.True(t, len(names) == 4)
	for _, name := range names {
		assert.Regexp(t, `^(.*/vendor/)?(github\.com/gin-gonic/gin\.){1}(TestContextHandlerNames\.func.*){0,1}(handlerNameTest.*){0,1}`, name)
	}
}

func handlerNameTest(c *Context) {
}

<|next_version|>

	assert.Equal(t, m, c.GetStringMapString("map"))
	assert.Equal(t, "bar", c.GetStringMapString("map")["foo"])
}

func TestContextGetStringMapStringSlice(t *testing.T) {
	c, _ := CreateTestContext(httptest.NewRecorder())
	m := make(map[string][]string)
	m["foo"] = []string{"foo"}
	c.Set("map", m)

	assert.Equal(t, m, c.GetStringMapStringSlice("map"))
	assert.Equal(t, []string{"foo"}, c.GetStringMapStringSlice("map")["foo"])
}

func TestContextCopy(t *testing.T) {
	c, _ := CreateTestContext(httptest.NewRecorder())
	c.index = 2
	c.Request, _ = http.NewRequest("POST", "/hola", nil)
	c.handlers = HandlersChain{func(c *Context) {}}
	c.Params = Params{Param{Key: "foo", Value: "bar"}}
	c.Set("foo", "bar")
	c.fullPath = "/hola"

	cp := c.Copy()
	assert.Nil(t, cp.handlers)
	assert.Nil(t, cp.writermem.ResponseWriter)
	assert.Equal(t, &cp.writermem, cp.Writer.(*responseWriter))
	assert.Equal(t, cp.Request, c.Request)
	assert.Equal(t, cp.index, abortIndex)
	assert.Equal(t, cp.Keys, c.Keys)
	assert.Equal(t, cp.engine, c.engine)
	assert.Equal(t, cp.Params, c.Params)
	cp.Set("foo", "notBar")
	assert.False(t, cp.Keys["foo"] == c.Keys["foo"])
	assert.Equal(t, cp.fullPath, c.fullPath)
}

func TestContextHandlerName(t *testing.T) {
	c, _ := CreateTestContext(httptest.NewRecorder())
	c.handlers = HandlersChain{func(c *Context) {}, handlerNameTest}

	assert.Regexp(t, "^(.*/vendor/)?github.com/gin-gonic/gin.handlerNameTest$", c.HandlerName())
}

func TestContextHandlerNames(t *testing.T) {
	c, _ := CreateTestContext(httptest.NewRecorder())
	c.handlers = HandlersChain{func(c *Context) {}, handlerNameTest, func(c *Context) {}, handlerNameTest2}

	names := c.HandlerNames()

	assert.True(t, len(names) == 4)
	for _, name := range names {
		assert.Regexp(t, `^(.*/vendor/)?(github\.com/gin-gonic/gin\.){1}(TestContextHandlerNames\.func.*){0,1}(handlerNameTest.*){0,1}`, name)
	}
}

func handlerNameTest(c *Context) {
}


Sync route tree to httprouter latest code (#2368)

<|original_code|>
	MIMEMultipartPOSTForm = binding.MIMEMultipartPOSTForm
	MIMEYAML              = binding.MIMEYAML
)

// BodyBytesKey indicates a default body bytes key.
const BodyBytesKey = "_gin-gonic/gin/bodybyteskey"

const abortIndex int8 = math.MaxInt8 / 2

// Context is the most important part of gin. It allows us to pass variables between middleware,
// manage the flow, validate the JSON of a request and render a JSON response for example.
type Context struct {
	writermem responseWriter
	Request   *http.Request
	Writer    ResponseWriter

	Params   Params
	handlers HandlersChain
	index    int8
	fullPath string

	engine *Engine

	// This mutex protect Keys map
	mu sync.RWMutex

	// Keys is a key/value pair exclusively for the context of each request.
	Keys map[string]interface{}

	// Errors is a list of errors attached to all the handlers/middlewares who used this context.
	Errors errorMsgs

	// Accepted defines a list of manually accepted formats for content negotiation.
	Accepted []string

	// queryCache use url.ParseQuery cached the param query result from c.Request.URL.Query()
	queryCache url.Values

	// formCache use url.ParseQuery cached PostForm contains the parsed form data from POST, PATCH,
	// or PUT body parameters.
	formCache url.Values

	// SameSite allows a server to define a cookie attribute making it impossible for
	// the browser to send this cookie along with cross-site requests.
	sameSite http.SameSite
}

/************************************/
/********** CONTEXT CREATION ********/
/************************************/

func (c *Context) reset() {
	c.Writer = &c.writermem
	c.Params = c.Params[0:0]
	c.handlers = nil
	c.index = -1

	c.fullPath = ""
	c.Keys = nil
	c.Errors = c.Errors[0:0]
	c.Accepted = nil
	c.queryCache = nil
	c.formCache = nil
}

// Copy returns a copy of the current context that can be safely used outside the request's scope.
// This has to be used when the context has to be passed to a goroutine.
func (c *Context) Copy() *Context {
	cp := Context{
		writermem: c.writermem,
		Request:   c.Request,
		Params:    c.Params,
		engine:    c.engine,
	}
	cp.writermem.ResponseWriter = nil
	cp.Writer = &cp.writermem
	cp.index = abortIndex
	cp.handlers = nil
	cp.Keys = map[string]interface{}{}
	for k, v := range c.Keys {
		cp.Keys[k] = v
	}
	paramCopy := make([]Param, len(cp.Params))
	copy(paramCopy, cp.Params)
	cp.Params = paramCopy
	return &cp
}
<|edits_diff|>
--- context.go
+++ context.go
@@ -20,6 +20,7 @@
 	fullPath string

 	engine *Engine
+	params *Params

 	// This mutex protect Keys map
 	mu sync.RWMutex
<|current_version|>
	MIMEMultipartPOSTForm = binding.MIMEMultipartPOSTForm
	MIMEYAML              = binding.MIMEYAML
)

// BodyBytesKey indicates a default body bytes key.
const BodyBytesKey = "_gin-gonic/gin/bodybyteskey"

const abortIndex int8 = math.MaxInt8 / 2

// Context is the most important part of gin. It allows us to pass variables between middleware,
// manage the flow, validate the JSON of a request and render a JSON response for example.
type Context struct {
	writermem responseWriter
	Request   *http.Request
	Writer    ResponseWriter

	Params   Params
	handlers HandlersChain
	index    int8
	fullPath string

	engine *Engine
	params *Params

	// This mutex protect Keys map
	mu sync.RWMutex

	// Keys is a key/value pair exclusively for the context of each request.
	Keys map[string]interface{}

	// Errors is a list of errors attached to all the handlers/middlewares who used this context.
	Errors errorMsgs

	// Accepted defines a list of manually accepted formats for content negotiation.
	Accepted []string

	// queryCache use url.ParseQuery cached the param query result from c.Request.URL.Query()
	queryCache url.Values

	// formCache use url.ParseQuery cached PostForm contains the parsed form data from POST, PATCH,
	// or PUT body parameters.
	formCache url.Values

	// SameSite allows a server to define a cookie attribute making it impossible for
	// the browser to send this cookie along with cross-site requests.
	sameSite http.SameSite
}

/************************************/
/********** CONTEXT CREATION ********/
/************************************/

func (c *Context) reset() {
	c.Writer = &c.writermem
	c.Params = c.Params[0:0]
	c.handlers = nil
	c.index = -1

	c.fullPath = ""
	c.Keys = nil
	c.Errors = c.Errors[0:0]
	c.Accepted = nil
	c.queryCache = nil
	c.formCache = nil
}

// Copy returns a copy of the current context that can be safely used outside the request's scope.
// This has to be used when the context has to be passed to a goroutine.
func (c *Context) Copy() *Context {
	cp := Context{
		writermem: c.writermem,
		Request:   c.Request,
		Params:    c.Params,
		engine:    c.engine,
	}
	cp.writermem.ResponseWriter = nil
	cp.Writer = &cp.writermem
	cp.index = abortIndex
	cp.handlers = nil
	cp.Keys = map[string]interface{}{}
	for k, v := range c.Keys {
		cp.Keys[k] = v
	}
	paramCopy := make([]Param, len(cp.Params))
	copy(paramCopy, cp.Params)
	cp.Params = paramCopy
	return &cp
}
<|next_version|>
	MIMEMultipartPOSTForm = binding.MIMEMultipartPOSTForm
	MIMEYAML              = binding.MIMEYAML
)

// BodyBytesKey indicates a default body bytes key.
const BodyBytesKey = "_gin-gonic/gin/bodybyteskey"

const abortIndex int8 = math.MaxInt8 / 2

// Context is the most important part of gin. It allows us to pass variables between middleware,
// manage the flow, validate the JSON of a request and render a JSON response for example.
type Context struct {
	writermem responseWriter
	Request   *http.Request
	Writer    ResponseWriter

	Params   Params
	handlers HandlersChain
	index    int8
	fullPath string

	engine *Engine
	params *Params

	// This mutex protect Keys map
	mu sync.RWMutex

	// Keys is a key/value pair exclusively for the context of each request.
	Keys map[string]interface{}

	// Errors is a list of errors attached to all the handlers/middlewares who used this context.
	Errors errorMsgs

	// Accepted defines a list of manually accepted formats for content negotiation.
	Accepted []string

	// queryCache use url.ParseQuery cached the param query result from c.Request.URL.Query()
	queryCache url.Values

	// formCache use url.ParseQuery cached PostForm contains the parsed form data from POST, PATCH,
	// or PUT body parameters.
	formCache url.Values

	// SameSite allows a server to define a cookie attribute making it impossible for
	// the browser to send this cookie along with cross-site requests.
	sameSite http.SameSite
}

/************************************/
/********** CONTEXT CREATION ********/
/************************************/

func (c *Context) reset() {
	c.Writer = &c.writermem
	c.Params = c.Params[0:0]
	c.handlers = nil
	c.index = -1

	c.fullPath = ""
	c.Keys = nil
	c.Errors = c.Errors[0:0]
	c.Accepted = nil
	c.queryCache = nil
	c.formCache = nil
	*c.params = (*c.params)[0:0]
}

// Copy returns a copy of the current context that can be safely used outside the request's scope.
// This has to be used when the context has to be passed to a goroutine.
func (c *Context) Copy() *Context {
	cp := Context{
		writermem: c.writermem,
		Request:   c.Request,
		Params:    c.Params,
		engine:    c.engine,
	}
	cp.writermem.ResponseWriter = nil
	cp.Writer = &cp.writermem
	cp.index = abortIndex
	cp.handlers = nil
	cp.Keys = map[string]interface{}{}
	for k, v := range c.Keys {
		cp.Keys[k] = v
	}
	paramCopy := make([]Param, len(cp.Params))
	copy(paramCopy, cp.Params)
	cp.Params = paramCopy
	return &cp
}