mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-18 21:16:47 +00:00
fix(llm-parse): the local model list and pull send the saved api key to an ollama behind an auth proxy
The admin screen's model list (/api/tags) and pull (/api/pull) went out without the Authorization header that the extraction and /api/show already send, so an Ollama behind a Bearer proxy answered 401 and the list came back as a 502. The controller now adds the key saved with the local provider, read server side through LlmConfigResolver.readLocalServerAccess, and only when the requested base URL reaches the same server root as the saved one, so another address in the form never receives it. A 401 or 403 now says whether the key was rejected or none is saved for that address, and the admin form shows the server's reason instead of the axios status line. A server without /api/tags (LM Studio, vLLM) is asked for its OpenAI-compatible /v1/models instead, and the list body is read with a size cap and checked before use. Refs #2649
This commit is contained in:
@@ -5,7 +5,7 @@ import { adminApi } from '../../../api/client';
|
||||
import { type Addon, DEFAULT_OLLAMA_URL, MASKED } from './addonModel';
|
||||
import { useLlmParsingConfig } from './useLlmParsingConfig';
|
||||
|
||||
// FE-HOOK-LLMCFG-001 to FE-HOOK-LLMCFG-010
|
||||
// FE-HOOK-LLMCFG-001 to FE-HOOK-LLMCFG-011
|
||||
|
||||
const toast = vi.hoisted(() => ({ success: vi.fn(), error: vi.fn() }));
|
||||
vi.mock('../../shared/Toast', () => ({ useToast: () => toast }));
|
||||
@@ -74,6 +74,15 @@ describe('useLlmParsingConfig', () => {
|
||||
expect(result.current.modelsErr).toBe('Could not reach the local LLM server');
|
||||
});
|
||||
|
||||
it("FE-HOOK-LLMCFG-011: a refused list shows the server's reason, not the status line (#2649)", async () => {
|
||||
const refused = Object.assign(new Error('Request failed with status code 502'), {
|
||||
response: { status: 502, data: { error: 'Local LLM server rejected the API key (401)' } },
|
||||
});
|
||||
vi.mocked(adminApi.llmLocalModels).mockRejectedValue(refused);
|
||||
const { result } = renderHook(() => useLlmParsingConfig(llm({ provider: 'local' })));
|
||||
await waitFor(() => expect(result.current.modelsErr).toBe('Local LLM server rejected the API key (401)'));
|
||||
});
|
||||
|
||||
it('FE-HOOK-LLMCFG-005: a pull reports progress, selects the model and lists again', async () => {
|
||||
let progress!: (p: { status?: string; total?: number; completed?: number; error?: string }) => void;
|
||||
let finish!: () => void;
|
||||
|
||||
@@ -2,6 +2,7 @@ import { type LlmVision, asLlmVision } from '@trek/shared';
|
||||
import { useEffect, useEffectEvent, useState } from 'react';
|
||||
|
||||
import { adminApi } from '../../../api/client';
|
||||
import { getApiErrorMessage } from '../../../types';
|
||||
import { useToast } from '../../shared/Toast';
|
||||
import { type Addon, DEFAULT_OLLAMA_URL } from './addonModel';
|
||||
|
||||
@@ -40,7 +41,8 @@ export function useLlmParsingConfig(addon: Addon) {
|
||||
const res = await adminApi.llmLocalModels(effectiveUrl);
|
||||
setInstalled(res.models.map((m) => m.name));
|
||||
} catch (e: unknown) {
|
||||
setModelsErr(e instanceof Error ? e.message : 'Could not reach the local LLM server');
|
||||
// The server says why (unreachable, key refused); axios' own status line does not.
|
||||
setModelsErr(getApiErrorMessage(e, 'Could not reach the local LLM server'));
|
||||
setInstalled([]);
|
||||
} finally {
|
||||
setLoadingModels(false);
|
||||
|
||||
Reference in New Issue
Block a user