feat: Add custom headers support

This commit is contained in:
n4ze3m 2024-06-30 00:21:43 +05:30
parent 86296c96b6
commit 52f9a2953a
14 changed files with 2126 additions and 1902 deletions

View File

@ -229,6 +229,18 @@
"label": "Custom Origin URL", "label": "Custom Origin URL",
"placeholder": "Enter Custom Origin URL" "placeholder": "Enter Custom Origin URL"
}, },
"headers": {
"label": "Custom Headers",
"add": "Add Header",
"key": {
"label": "Header Key",
"placeholder": "Authorization"
},
"value": {
"label": "Header Value",
"placeholder": "Bearer token"
}
},
"help": "If you have connection issues with Ollama on Page Assist, you can configure a custom origin URL. To learn more about the configuration, <anchor>click here</anchor>." "help": "If you have connection issues with Ollama on Page Assist, you can configure a custom origin URL. To learn more about the configuration, <anchor>click here</anchor>."
} }
} }

View File

@ -229,6 +229,18 @@
"label": "URL Personalizada", "label": "URL Personalizada",
"placeholder": "Ingresar URL Personalizada" "placeholder": "Ingresar URL Personalizada"
}, },
"headers": {
"label": "Encabezados Personalizados",
"add": "Agregar Encabezado",
"key": {
"label": "Clave del Encabezado",
"placeholder": "Autorización"
},
"value": {
"label": "Valor del Encabezado",
"placeholder": "Token Bearer"
}
},
"help": "Si tenes problemas de conexión con Ollama en Page Assist, podes configurar una URL de personalizada. Para saber más sobre la configuración, <anchor>click aqui</anchor>." "help": "Si tenes problemas de conexión con Ollama en Page Assist, podes configurar una URL de personalizada. Para saber más sobre la configuración, <anchor>click aqui</anchor>."
} }
} }

View File

@ -229,6 +229,18 @@
"label": "URL d'origine personnalisée", "label": "URL d'origine personnalisée",
"placeholder": "Entrez l'URL d'origine personnalisée" "placeholder": "Entrez l'URL d'origine personnalisée"
}, },
"headers": {
"label": "En-têtes Personnalisés",
"add": "Ajouter En-tête",
"key": {
"label": "Clé de l'En-tête",
"placeholder": "Autorisation"
},
"value": {
"label": "Valeur de l'En-tête",
"placeholder": "Jeton Bearer"
}
},
"help": "Si vous avez des problèmes de connexion avec OLLAMA sur Page Assist, vous pouvez configurer une URL d'origine personnalisée. Pour en savoir plus sur la configuration, <anchor>cliquez ici</anchor>." "help": "Si vous avez des problèmes de connexion avec OLLAMA sur Page Assist, vous pouvez configurer une URL d'origine personnalisée. Pour en savoir plus sur la configuration, <anchor>cliquez ici</anchor>."
} }
} }

View File

@ -229,6 +229,18 @@
"label": "URL di Origine Personalizzato", "label": "URL di Origine Personalizzato",
"placeholder": "Inserisci URL di Origine Personalizzato" "placeholder": "Inserisci URL di Origine Personalizzato"
}, },
"headers": {
"label": "Intestazioni Personalizzate",
"add": "Aggiungi Intestazione",
"key": {
"label": "Chiave dell'Intestazione",
"placeholder": "Autorizzazione"
},
"value": {
"label": "Valore dell'Intestazione",
"placeholder": "Token Bearer"
}
},
"help": "Se hai problemi di connessione con Ollama su Page Assist, puoi configurare un URL di origine personalizzato. Per saperne di più sulla configurazione, <anchor>clicca qui</anchor>." "help": "Se hai problemi di connessione con Ollama su Page Assist, puoi configurare un URL di origine personalizzato. Per saperne di più sulla configurazione, <anchor>clicca qui</anchor>."
} }
} }

View File

@ -232,6 +232,18 @@
"label": "カスタムOriginのURL", "label": "カスタムOriginのURL",
"placeholder": "カスタムOriginのURLを入力" "placeholder": "カスタムOriginのURLを入力"
}, },
"headers": {
"label": "カスタムヘッダー",
"add": "ヘッダーを追加",
"key": {
"label": "ヘッダーキー",
"placeholder": "認証"
},
"value": {
"label": "ヘッダー値",
"placeholder": "ベアラートークン"
}
},
"help": "PageAssistでOllamaに接続の問題がある場合は、カスタムOriginのURLを設定できます。設定の詳細については、<anchor>ここをクリック</anchor>してください。" "help": "PageAssistでOllamaに接続の問題がある場合は、カスタムOriginのURLを設定できます。設定の詳細については、<anchor>ここをクリック</anchor>してください。"
} }
} }

View File

@ -232,6 +232,18 @@
"label": "Custom Origin URL", "label": "Custom Origin URL",
"placeholder": "Enter Custom Origin URL" "placeholder": "Enter Custom Origin URL"
}, },
"headers": {
"label": "കസ്റ്റം തലക്കെട്ടുകൾ",
"add": "തലക്കെട്ട് ചേർക്കുക",
"key": {
"label": "തലക്കെട്ട് കീ",
"placeholder": "അധികൃതപെടുത്തൽ"
},
"value": {
"label": "തലക്കെട്ട് മൂല്യം",
"placeholder": "ബെയറർ ടോക്കൺ"
}
},
"help": "ഏജ് അസിസ്റ്റന്റിൽ Ollama-യുമായി ബന്ധപ്പെടുമ്പോൾ ബന്ധതടസ്സം ഉണ്ടെങ്കിൽ, നിങ്ങൾക്ക് ഒരു വ്യക്തിഗത അസ്ഥിരത്വം URL കോൺഫിഗർ ചെയ്യാം. കോൺഫിഗറേഷനെക്കുറിച്ച് കൂടുതലറിയാൻ, <anchor>ഇവിടെ ക്ലിക്കുചെയ്യുക</anchor>." "help": "ഏജ് അസിസ്റ്റന്റിൽ Ollama-യുമായി ബന്ധപ്പെടുമ്പോൾ ബന്ധതടസ്സം ഉണ്ടെങ്കിൽ, നിങ്ങൾക്ക് ഒരു വ്യക്തിഗത അസ്ഥിരത്വം URL കോൺഫിഗർ ചെയ്യാം. കോൺഫിഗറേഷനെക്കുറിച്ച് കൂടുതലറിയാൻ, <anchor>ഇവിടെ ക്ലിക്കുചെയ്യുക</anchor>."
} }
} }

View File

@ -229,6 +229,18 @@
"label": "URL de Origem Personalizada", "label": "URL de Origem Personalizada",
"placeholder": "Insira a URL de Origem Personalizada" "placeholder": "Insira a URL de Origem Personalizada"
}, },
"headers": {
"label": "Cabeçalhos Personalizados",
"add": "Adicionar Cabeçalho",
"key": {
"label": "Chave do Cabeçalho",
"placeholder": "Autorização"
},
"value": {
"label": "Valor do Cabeçalho",
"placeholder": "Token Bearer"
}
},
"help": "Se você tiver problemas de conexão com o Ollama no Page Assist, você pode configurar uma URL de origem personalizada. Para saber mais sobre a configuração, <anchor>clique aqui</anchor>." "help": "Se você tiver problemas de conexão com o Ollama no Page Assist, você pode configurar uma URL de origem personalizada. Para saber mais sobre a configuração, <anchor>clique aqui</anchor>."
} }
} }

View File

@ -230,6 +230,18 @@
"label": "Пользовательский исходный URL", "label": "Пользовательский исходный URL",
"placeholder": "Введите пользовательский исходный URL" "placeholder": "Введите пользовательский исходный URL"
}, },
"headers": {
"label": "Пользовательские Заголовки",
"add": "Добавить Заголовок",
"key": {
"label": "Ключ Заголовка",
"placeholder": "Авторизация"
},
"value": {
"label": "Значение Заголовка",
"placeholder": "Токен Bearer"
}
},
"help": "Если у вас возникают проблемы с подключением к Ollama на странице помощника, вы можете настроить пользовательский исходный URL. Чтобы узнать больше о конфигурации, <anchor>нажмите здесь</anchor>." "help": "Если у вас возникают проблемы с подключением к Ollama на странице помощника, вы можете настроить пользовательский исходный URL. Чтобы узнать больше о конфигурации, <anchor>нажмите здесь</anchor>."
} }
} }

View File

@ -234,6 +234,18 @@
"label": "自定义来源 URL", "label": "自定义来源 URL",
"placeholder": "输入自定义来源 URL" "placeholder": "输入自定义来源 URL"
}, },
"headers": {
"label": "自定义头部",
"add": "添加头部",
"key": {
"label": "头部键",
"placeholder": "授权"
},
"value": {
"label": "头部值",
"placeholder": "承载令牌"
}
},
"help": "如果您在 Page Assist 上与 Ollama 有连接问题,您可以配置自定义来源 URL。要了解更多关于配置的信息,<anchor>点击此处</anchor>。" "help": "如果您在 Page Assist 上与 Ollama 有连接问题,您可以配置自定义来源 URL。要了解更多关于配置的信息,<anchor>点击此处</anchor>。"
} }
} }

View File

@ -1,49 +1,132 @@
import { useStorage } from "@plasmohq/storage/hook" import { Divider, Input, Switch } from "antd"
import { Input, Switch } from "antd"
import { useTranslation } from "react-i18next" import { useTranslation } from "react-i18next"
import { Form } from "antd"
import React from "react"
import {
customOllamaHeaders,
getRewriteUrl,
isUrlRewriteEnabled,
setCustomOllamaHeaders,
setRewriteUrl,
setUrlRewriteEnabled
} from "@/services/app"
import { Trash2Icon } from "lucide-react"
import { SaveButton } from "../SaveButton"
export const AdvanceOllamaSettings = () => { export const AdvanceOllamaSettings = () => {
const [urlRewriteEnabled, setUrlRewriteEnabled] = useStorage( const [form] = Form.useForm()
"urlRewriteEnabled", const watchUrlRewriteEnabled = Form.useWatch("urlRewriteEnabled", form)
false
) const fetchAdvancedData = async () => {
const [urlRewriteEnabled, rewriteUrl, headers] = await Promise.all([
isUrlRewriteEnabled(),
getRewriteUrl(),
customOllamaHeaders()
])
form.setFieldsValue({ urlRewriteEnabled, rewriteUrl, headers })
}
React.useEffect(() => {
fetchAdvancedData()
}, [])
const [rewriteUrl, setRewriteUrl] = useStorage(
"rewriteUrl",
"http://127.0.0.1:11434"
)
const { t } = useTranslation("settings") const { t } = useTranslation("settings")
return ( return (
<div className="space-y-4"> <Form
<div className="flex sm:flex-row flex-col space-y-4 sm:space-y-0 sm:justify-between"> onFinish={(e) => {
<span className="text-gray-700 dark:text-neutral-50 "> const headers = e?.headers?.filter(
{t("ollamaSettings.settings.advanced.urlRewriteEnabled.label")} (header: { key: string; value: string }) => header.key && header.value
</span> )
<div> setUrlRewriteEnabled(e.urlRewriteEnabled)
<Switch setRewriteUrl(e.rewriteUrl)
className="mt-4 sm:mt-0" setCustomOllamaHeaders(headers)
checked={urlRewriteEnabled} }}
onChange={(checked) => setUrlRewriteEnabled(checked)} form={form}
/> layout="vertical"
</div> className="space-y-4">
</div> <Form.Item
<div className="flex flex-col space-y-4 sm:space-y-0 sm:justify-between"> name="urlRewriteEnabled"
<span className="text-gray-700 dark:text-neutral-50 mb-3"> label={t("ollamaSettings.settings.advanced.urlRewriteEnabled.label")}>
{t("ollamaSettings.settings.advanced.rewriteUrl.label")} <Switch />
</span> </Form.Item>
<div> <Form.Item
required={watchUrlRewriteEnabled}
name="rewriteUrl"
label={t("ollamaSettings.settings.advanced.rewriteUrl.label")}>
<Input <Input
disabled={!watchUrlRewriteEnabled}
className="w-full" className="w-full"
value={rewriteUrl}
disabled={!urlRewriteEnabled}
placeholder={t( placeholder={t(
"ollamaSettings.settings.advanced.rewriteUrl.placeholder" "ollamaSettings.settings.advanced.rewriteUrl.placeholder"
)} )}
onChange={(e) => setRewriteUrl(e.target.value)}
/> />
</Form.Item>
<Form.List name="headers">
{(fields, { add, remove }) => (
<div className="flex flex-col ">
<div className="flex justify-between items-center">
<h3 className="text-md font-semibold">
{t("ollamaSettings.settings.advanced.headers.label")}
</h3>
<button
type="button"
className="dark:bg-white dark:text-black text-white bg-black p-1.5 text-xs rounded-md"
onClick={() => {
add()
}}>
{t("ollamaSettings.settings.advanced.headers.add")}
</button>
</div> </div>
{fields.map((field, index) => (
<div key={field.key} className="flex items-center w-full">
<div className="flex-grow flex space-x-4">
<Form.Item
label={t(
"ollamaSettings.settings.advanced.headers.key.label"
)}
name={[field.name, "key"]}
className="flex-1 mb-0">
<Input
className="w-full"
placeholder={t(
"ollamaSettings.settings.advanced.headers.key.placeholder"
)}
/>
</Form.Item>
<Form.Item
label={t(
"ollamaSettings.settings.advanced.headers.value.label"
)}
name={[field.name, "value"]}
className="flex-1 mb-0">
<Input
className="w-full"
placeholder={t(
"ollamaSettings.settings.advanced.headers.value.placeholder"
)}
/>
</Form.Item>
</div> </div>
<button
type="button"
onClick={() => {
remove(field.name)
}}
className="shrink-0 ml-2 text-red-500 dark:text-red-400">
<Trash2Icon className="w-5 h-5" />
</button>
</div> </div>
))}
</div>
)}
</Form.List>
<Divider />
<Form.Item className="flex justify-end">
<SaveButton btnType="submit" />
</Form.Item>
</Form>
) )
} }

View File

@ -50,6 +50,14 @@ export const SettingsOllama = () => {
className="w-full p-2 border border-gray-300 rounded-md dark:bg-[#262626] dark:text-gray-100" className="w-full p-2 border border-gray-300 rounded-md dark:bg-[#262626] dark:text-gray-100"
/> />
</div> </div>
<div className="flex justify-end mb-3">
<SaveButton
onClick={() => {
saveOllamaURL(ollamaURL)
}}
className="mt-2"
/>
</div>
<Collapse <Collapse
size="small" size="small"
items={[ items={[
@ -79,15 +87,6 @@ export const SettingsOllama = () => {
} }
]} ]}
/> />
<div className="flex justify-end">
<SaveButton
onClick={() => {
saveOllamaURL(ollamaURL)
}}
className="mt-2"
/>
</div>
</div> </div>
<ModelSettings /> <ModelSettings />

View File

@ -1,6 +1,7 @@
import { Embeddings, EmbeddingsParams } from "@langchain/core/embeddings" import { Embeddings, EmbeddingsParams } from "@langchain/core/embeddings"
import type { StringWithAutocomplete } from "@langchain/core/utils/types" import type { StringWithAutocomplete } from "@langchain/core/utils/types"
import { parseKeepAlive } from "./utils/ollama" import { parseKeepAlive } from "./utils/ollama"
import { getCustomOllamaHeaders } from "@/services/app"
export interface OllamaInput { export interface OllamaInput {
embeddingOnly?: boolean embeddingOnly?: boolean
@ -213,12 +214,14 @@ export class OllamaEmbeddingsPageAssist extends Embeddings {
"http://127.0.0.1:" "http://127.0.0.1:"
) )
} }
const customHeaders = await getCustomOllamaHeaders()
const response = await fetch(`${formattedBaseUrl}/api/embeddings`, { const response = await fetch(`${formattedBaseUrl}/api/embeddings`, {
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
...this.headers ...this.headers,
...customHeaders
}, },
body: JSON.stringify({ body: JSON.stringify({
prompt, prompt,

View File

@ -1,184 +1,189 @@
import { IterableReadableStream } from "@langchain/core/utils/stream"; import { IterableReadableStream } from "@langchain/core/utils/stream"
import type { StringWithAutocomplete } from "@langchain/core/utils/types"; import type { StringWithAutocomplete } from "@langchain/core/utils/types"
import { BaseLanguageModelCallOptions } from "@langchain/core/language_models/base"; import { BaseLanguageModelCallOptions } from "@langchain/core/language_models/base"
import { getCustomOllamaHeaders } from "@/services/app"
export interface OllamaInput { export interface OllamaInput {
embeddingOnly?: boolean; embeddingOnly?: boolean
f16KV?: boolean; f16KV?: boolean
frequencyPenalty?: number; frequencyPenalty?: number
headers?: Record<string, string>; headers?: Record<string, string>
keepAlive?: any; keepAlive?: any
logitsAll?: boolean; logitsAll?: boolean
lowVram?: boolean; lowVram?: boolean
mainGpu?: number; mainGpu?: number
model?: string; model?: string
baseUrl?: string; baseUrl?: string
mirostat?: number; mirostat?: number
mirostatEta?: number; mirostatEta?: number
mirostatTau?: number; mirostatTau?: number
numBatch?: number; numBatch?: number
numCtx?: number; numCtx?: number
numGpu?: number; numGpu?: number
numGqa?: number; numGqa?: number
numKeep?: number; numKeep?: number
numPredict?: number; numPredict?: number
numThread?: number; numThread?: number
penalizeNewline?: boolean; penalizeNewline?: boolean
presencePenalty?: number; presencePenalty?: number
repeatLastN?: number; repeatLastN?: number
repeatPenalty?: number; repeatPenalty?: number
ropeFrequencyBase?: number; ropeFrequencyBase?: number
ropeFrequencyScale?: number; ropeFrequencyScale?: number
temperature?: number; temperature?: number
stop?: string[]; stop?: string[]
tfsZ?: number; tfsZ?: number
topK?: number; topK?: number
topP?: number; topP?: number
typicalP?: number; typicalP?: number
useMLock?: boolean; useMLock?: boolean
useMMap?: boolean; useMMap?: boolean
vocabOnly?: boolean; vocabOnly?: boolean
seed?: number; seed?: number
format?: StringWithAutocomplete<"json">; format?: StringWithAutocomplete<"json">
} }
export interface OllamaRequestParams { export interface OllamaRequestParams {
model: string; model: string
format?: StringWithAutocomplete<"json">; format?: StringWithAutocomplete<"json">
images?: string[]; images?: string[]
options: { options: {
embedding_only?: boolean; embedding_only?: boolean
f16_kv?: boolean; f16_kv?: boolean
frequency_penalty?: number; frequency_penalty?: number
logits_all?: boolean; logits_all?: boolean
low_vram?: boolean; low_vram?: boolean
main_gpu?: number; main_gpu?: number
mirostat?: number; mirostat?: number
mirostat_eta?: number; mirostat_eta?: number
mirostat_tau?: number; mirostat_tau?: number
num_batch?: number; num_batch?: number
num_ctx?: number; num_ctx?: number
num_gpu?: number; num_gpu?: number
num_gqa?: number; num_gqa?: number
num_keep?: number; num_keep?: number
num_thread?: number; num_thread?: number
num_predict?: number; num_predict?: number
penalize_newline?: boolean; penalize_newline?: boolean
presence_penalty?: number; presence_penalty?: number
repeat_last_n?: number; repeat_last_n?: number
repeat_penalty?: number; repeat_penalty?: number
rope_frequency_base?: number; rope_frequency_base?: number
rope_frequency_scale?: number; rope_frequency_scale?: number
temperature?: number; temperature?: number
stop?: string[]; stop?: string[]
tfs_z?: number; tfs_z?: number
top_k?: number; top_k?: number
top_p?: number; top_p?: number
typical_p?: number; typical_p?: number
use_mlock?: boolean; use_mlock?: boolean
use_mmap?: boolean; use_mmap?: boolean
vocab_only?: boolean; vocab_only?: boolean
}; }
} }
export type OllamaMessage = { export type OllamaMessage = {
role: StringWithAutocomplete<"user" | "assistant" | "system">; role: StringWithAutocomplete<"user" | "assistant" | "system">
content: string; content: string
images?: string[]; images?: string[]
}; }
export interface OllamaGenerateRequestParams extends OllamaRequestParams { export interface OllamaGenerateRequestParams extends OllamaRequestParams {
prompt: string; prompt: string
} }
export interface OllamaChatRequestParams extends OllamaRequestParams { export interface OllamaChatRequestParams extends OllamaRequestParams {
messages: OllamaMessage[]; messages: OllamaMessage[]
} }
export type BaseOllamaGenerationChunk = { export type BaseOllamaGenerationChunk = {
model: string; model: string
created_at: string; created_at: string
done: boolean; done: boolean
total_duration?: number; total_duration?: number
load_duration?: number; load_duration?: number
prompt_eval_count?: number; prompt_eval_count?: number
prompt_eval_duration?: number; prompt_eval_duration?: number
eval_count?: number; eval_count?: number
eval_duration?: number; eval_duration?: number
}; }
export type OllamaGenerationChunk = BaseOllamaGenerationChunk & { export type OllamaGenerationChunk = BaseOllamaGenerationChunk & {
response: string; response: string
}; }
export type OllamaChatGenerationChunk = BaseOllamaGenerationChunk & { export type OllamaChatGenerationChunk = BaseOllamaGenerationChunk & {
message: OllamaMessage; message: OllamaMessage
}; }
export type OllamaCallOptions = BaseLanguageModelCallOptions & { export type OllamaCallOptions = BaseLanguageModelCallOptions & {
headers?: Record<string, string>; headers?: Record<string, string>
}; }
async function* createOllamaStream( async function* createOllamaStream(
url: string, url: string,
params: OllamaRequestParams, params: OllamaRequestParams,
options: OllamaCallOptions options: OllamaCallOptions
) { ) {
let formattedUrl = url; let formattedUrl = url
if (formattedUrl.startsWith("http://localhost:")) { if (formattedUrl.startsWith("http://localhost:")) {
// Node 18 has issues with resolving "localhost" // Node 18 has issues with resolving "localhost"
// See https://github.com/node-fetch/node-fetch/issues/1624 // See https://github.com/node-fetch/node-fetch/issues/1624
formattedUrl = formattedUrl.replace( formattedUrl = formattedUrl.replace(
"http://localhost:", "http://localhost:",
"http://127.0.0.1:" "http://127.0.0.1:"
); )
} }
const customHeaders = await getCustomOllamaHeaders()
const response = await fetch(formattedUrl, { const response = await fetch(formattedUrl, {
method: "POST", method: "POST",
body: JSON.stringify(params), body: JSON.stringify(params),
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
...options.headers, ...options.headers,
...customHeaders
}, },
signal: options.signal, signal: options.signal
}); })
if (!response.ok) { if (!response.ok) {
let error; let error
const responseText = await response.text(); const responseText = await response.text()
try { try {
const json = JSON.parse(responseText); const json = JSON.parse(responseText)
error = new Error( error = new Error(
`Ollama call failed with status code ${response.status}: ${json.error}` `Ollama call failed with status code ${response.status}: ${json.error}`
); )
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (e: any) { } catch (e: any) {
error = new Error( error = new Error(
`Ollama call failed with status code ${response.status}: ${responseText}` `Ollama call failed with status code ${response.status}: ${responseText}`
); )
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
(error as any).response = response; ;(error as any).response = response
throw error; throw error
} }
if (!response.body) { if (!response.body) {
throw new Error( throw new Error(
"Could not begin Ollama stream. Please check the given URL and try again." "Could not begin Ollama stream. Please check the given URL and try again."
); )
} }
const stream = IterableReadableStream.fromReadableStream(response.body); const stream = IterableReadableStream.fromReadableStream(response.body)
const decoder = new TextDecoder(); const decoder = new TextDecoder()
let extra = ""; let extra = ""
for await (const chunk of stream) { for await (const chunk of stream) {
const decoded = extra + decoder.decode(chunk); const decoded = extra + decoder.decode(chunk)
const lines = decoded.split("\n"); const lines = decoded.split("\n")
extra = lines.pop() || ""; extra = lines.pop() || ""
for (const line of lines) { for (const line of lines) {
try { try {
yield JSON.parse(line); yield JSON.parse(line)
} catch (e) { } catch (e) {
console.warn(`Received a non-JSON parseable chunk: ${line}`); console.warn(`Received a non-JSON parseable chunk: ${line}`)
} }
} }
} }
@ -189,7 +194,7 @@ export async function* createOllamaGenerateStream(
params: OllamaGenerateRequestParams, params: OllamaGenerateRequestParams,
options: OllamaCallOptions options: OllamaCallOptions
): AsyncGenerator<OllamaGenerationChunk> { ): AsyncGenerator<OllamaGenerationChunk> {
yield* createOllamaStream(`${baseUrl}/api/generate`, params, options); yield* createOllamaStream(`${baseUrl}/api/generate`, params, options)
} }
export async function* createOllamaChatStream( export async function* createOllamaChatStream(
@ -197,10 +202,9 @@ export async function* createOllamaChatStream(
params: OllamaChatRequestParams, params: OllamaChatRequestParams,
options: OllamaCallOptions options: OllamaCallOptions
): AsyncGenerator<OllamaChatGenerationChunk> { ): AsyncGenerator<OllamaChatGenerationChunk> {
yield* createOllamaStream(`${baseUrl}/api/chat`, params, options); yield* createOllamaStream(`${baseUrl}/api/chat`, params, options)
} }
export const parseKeepAlive = (keepAlive: any) => { export const parseKeepAlive = (keepAlive: any) => {
if (keepAlive === "-1") { if (keepAlive === "-1") {
return -1 return -1

View File

@ -5,10 +5,10 @@ const DEFAULT_URL_REWRITE_URL = "http://127.0.0.1:11434"
export const isUrlRewriteEnabled = async () => { export const isUrlRewriteEnabled = async () => {
const enabled = await storage.get<boolean | undefined>("urlRewriteEnabled") const enabled = await storage.get<boolean | undefined>("urlRewriteEnabled")
return enabled return enabled ?? false
} }
export const setUrlRewriteEnabled = async (enabled: boolean) => { export const setUrlRewriteEnabled = async (enabled: boolean) => {
await storage.set("urlRewriteEnabled", enabled ? "true" : "false") await storage.set("urlRewriteEnabled", enabled)
} }
export const getRewriteUrl = async () => { export const getRewriteUrl = async () => {
@ -35,12 +35,10 @@ export const getAdvancedOllamaSettings = async () => {
} }
} }
export const copilotResumeLastChat = async () => { export const copilotResumeLastChat = async () => {
return await storage.get<boolean>("copilotResumeLastChat") return await storage.get<boolean>("copilotResumeLastChat")
} }
export const defaultSidebarOpen = async () => { export const defaultSidebarOpen = async () => {
const sidebarOpen = await storage.get("sidebarOpen") const sidebarOpen = await storage.get("sidebarOpen")
if (!sidebarOpen || sidebarOpen === "") { if (!sidebarOpen || sidebarOpen === "") {
@ -49,7 +47,36 @@ export const defaultSidebarOpen = async () => {
return sidebarOpen return sidebarOpen
} }
export const setSidebarOpen = async (sidebarOpen: string) => { export const setSidebarOpen = async (sidebarOpen: string) => {
await storage.set("sidebarOpen", sidebarOpen) await storage.set("sidebarOpen", sidebarOpen)
} }
export const customOllamaHeaders = async (): Promise<
{ key: string; value: string }[]
> => {
const headers = await storage.get<
{ key: string; value: string }[] | undefined
>("customOllamaHeaders")
if (!headers) {
return []
}
return headers
}
export const setCustomOllamaHeaders = async (headers: string[]) => {
await storage.set("customOllamaHeaders", headers)
}
export const getCustomOllamaHeaders = async (): Promise<
Record<string, string>
> => {
const headers = await customOllamaHeaders()
const headerMap: Record<string, string> = {}
for (const header of headers) {
headerMap[header.key] = header.value
}
return headerMap
}