From 8a702a96b4cdb28b05a1345b7bd94f070e64b1fd Mon Sep 17 00:00:00 2001 From: ParthSareen Date: Thu, 7 Nov 2024 11:45:52 -0800 Subject: [PATCH 1/3] Allow users to passthrough custom headers Co-authored-by: Naveen <78990165+gnpaone@users.noreply.github.com> --- src/browser.ts | 30 +++++++++++++++++++++--------- src/interfaces.ts | 2 +- src/utils.ts | 18 +++++++++++++----- 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/src/browser.ts b/src/browser.ts index 7fa23cd..84af0aa 100644 --- a/src/browser.ts +++ b/src/browser.ts @@ -1,5 +1,5 @@ import * as utils from './utils.js' -import { AbortableAsyncIterator, parseJSON, post } from './utils.js' +import { AbortableAsyncIterator, parseJSON } from './utils.js' import 'whatwg-fetch' import type { @@ -34,15 +34,14 @@ export class Ollama { constructor(config?: Partial) { this.config = { host: '', + headers: config?.headers } + if (!config?.proxy) { this.config.host = utils.formatHost(config?.host ?? 'http://127.0.0.1:11434') } - this.fetch = fetch - if (config?.fetch != null) { - this.fetch = config.fetch - } + this.fetch = config?.fetch ?? fetch } // Abort any ongoing streamed requests to Ollama @@ -72,7 +71,7 @@ export class Ollama { const host = `${this.config.host}/api/${endpoint}` if (request.stream) { const abortController = new AbortController() - const response = await post(this.fetch, host, request, { + const response = await utils.post(this.fetch, host, request, { signal: abortController.signal, headers: this.config.headers }) @@ -238,6 +237,7 @@ async encodeImage(image: Uint8Array | string): Promise { async delete(request: DeleteRequest): Promise { await utils.del(this.fetch, `${this.config.host}/api/delete`, { name: request.model, + headers: this.config.headers }) return { status: 'success' } } @@ -249,7 +249,9 @@ async encodeImage(image: Uint8Array | string): Promise { * @returns {Promise} - The response object. */ async copy(request: CopyRequest): Promise { - await utils.post(this.fetch, `${this.config.host}/api/copy`, { ...request }) + await utils.post(this.fetch, `${this.config.host}/api/copy`, { ...request }, { + headers: this.config.headers + }) return { status: 'success' } } @@ -259,7 +261,9 @@ async encodeImage(image: Uint8Array | string): Promise { * @throws {Error} - If the response body is missing. */ async list(): Promise { - const response = await utils.get(this.fetch, `${this.config.host}/api/tags`) + const response = await utils.get(this.fetch, `${this.config.host}/api/tags`, { + headers: this.config.headers + }) return (await response.json()) as ListResponse } @@ -271,6 +275,8 @@ async encodeImage(image: Uint8Array | string): Promise { async show(request: ShowRequest): Promise { const response = await utils.post(this.fetch, `${this.config.host}/api/show`, { ...request, + }, { + headers: this.config.headers }) return (await response.json()) as ShowResponse } @@ -283,6 +289,8 @@ async encodeImage(image: Uint8Array | string): Promise { async embed(request: EmbedRequest): Promise { const response = await utils.post(this.fetch, `${this.config.host}/api/embed`, { ...request, + }, { + headers: this.config.headers }) return (await response.json()) as EmbedResponse } @@ -295,6 +303,8 @@ async encodeImage(image: Uint8Array | string): Promise { async embeddings(request: EmbeddingsRequest): Promise { const response = await utils.post(this.fetch, `${this.config.host}/api/embeddings`, { ...request, + }, { + headers: this.config.headers }) return (await response.json()) as EmbeddingsResponse } @@ -305,7 +315,9 @@ async encodeImage(image: Uint8Array | string): Promise { * @throws {Error} - If the response body is missing. */ async ps(): Promise { - const response = await utils.get(this.fetch, `${this.config.host}/api/ps`) + const response = await utils.get(this.fetch, `${this.config.host}/api/ps`, { + headers: this.config.headers + }) return (await response.json()) as ListResponse } } diff --git a/src/interfaces.ts b/src/interfaces.ts index 5b7b115..a5058f5 100644 --- a/src/interfaces.ts +++ b/src/interfaces.ts @@ -4,7 +4,7 @@ export interface Config { host: string fetch?: Fetch proxy?: boolean - headers?: Headers + headers?: HeadersInit } // request types diff --git a/src/utils.ts b/src/utils.ts index 7ab32d4..aecc505 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -115,15 +115,20 @@ const fetchWithHeaders = async ( 'Content-Type': 'application/json', Accept: 'application/json', 'User-Agent': `ollama-js/${version} (${getPlatform()})`, - } + } as HeadersInit if (!options.headers) { options.headers = {} } + // Filter out default headers from custom headers + const customHeaders = Object.fromEntries( + Object.entries(options.headers).filter(([key]) => !Object.keys(defaultHeaders).some(defaultKey => defaultKey.toLowerCase() === key.toLowerCase())) + ) + options.headers = { ...defaultHeaders, - ...options.headers, + ...customHeaders } return fetch(url, options) @@ -135,8 +140,10 @@ const fetchWithHeaders = async ( * @param host {string} - The host to fetch * @returns {Promise} - The fetch response */ -export const get = async (fetch: Fetch, host: string): Promise => { - const response = await fetchWithHeaders(fetch, host) +export const get = async (fetch: Fetch, host: string, options?: { headers?: HeadersInit }): Promise => { + const response = await fetchWithHeaders(fetch, host, { + headers: options?.headers + }) await checkOk(response) @@ -169,7 +176,7 @@ export const post = async ( fetch: Fetch, host: string, data?: Record | BodyInit, - options?: { signal?: AbortSignal, headers?: Headers }, + options?: { signal?: AbortSignal, headers?: HeadersInit }, ): Promise => { const isRecord = (input: any): input is Record => { return input !== null && typeof input === 'object' && !Array.isArray(input) @@ -199,6 +206,7 @@ export const del = async ( fetch: Fetch, host: string, data?: Record, + options?: { headers?: HeadersInit }, ): Promise => { const response = await fetchWithHeaders(fetch, host, { method: 'DELETE', From f01c1b3dd1ebac87eefb05202779068a18cd05d7 Mon Sep 17 00:00:00 2001 From: ParthSareen Date: Thu, 7 Nov 2024 12:08:59 -0800 Subject: [PATCH 2/3] Fix delete request with headers --- src/browser.ts | 10 ++++++---- src/utils.ts | 3 ++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/browser.ts b/src/browser.ts index 84af0aa..6d8dcc6 100644 --- a/src/browser.ts +++ b/src/browser.ts @@ -235,10 +235,12 @@ async encodeImage(image: Uint8Array | string): Promise { * @returns {Promise} - The response object. */ async delete(request: DeleteRequest): Promise { - await utils.del(this.fetch, `${this.config.host}/api/delete`, { - name: request.model, - headers: this.config.headers - }) + await utils.del( + this.fetch, + `${this.config.host}/api/delete`, + { name: request.model }, + { headers: this.config.headers } + ) return { status: 'success' } } diff --git a/src/utils.ts b/src/utils.ts index aecc505..d2ca82e 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -113,7 +113,7 @@ const fetchWithHeaders = async ( ): Promise => { const defaultHeaders = { 'Content-Type': 'application/json', - Accept: 'application/json', + Accept: 'application/json', 'User-Agent': `ollama-js/${version} (${getPlatform()})`, } as HeadersInit @@ -211,6 +211,7 @@ export const del = async ( const response = await fetchWithHeaders(fetch, host, { method: 'DELETE', body: JSON.stringify(data), + headers: options?.headers }) await checkOk(response) From 4133282a282c8cf918720a34c559d683d6275d90 Mon Sep 17 00:00:00 2001 From: Parth Sareen Date: Thu, 7 Nov 2024 13:20:51 -0800 Subject: [PATCH 3/3] Update src/utils.ts Co-authored-by: Bruce MacDonald --- src/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils.ts b/src/utils.ts index d2ca82e..76976bf 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -113,7 +113,7 @@ const fetchWithHeaders = async ( ): Promise => { const defaultHeaders = { 'Content-Type': 'application/json', - Accept: 'application/json', + Accept: 'application/json', 'User-Agent': `ollama-js/${version} (${getPlatform()})`, } as HeadersInit