mirror of
https://github.com/ggml-org/llama.cpp.git
synced 2026-07-30 14:40:48 -05:00
* ui: fix MCP server display name conflicts in tools lists Tool groups were keyed by display label so two servers reporting the same name broke the keyed each blocks and only one was visible. Key rendering, expand state and toggles by the stable server id instead, and suffix duplicate labels with a counter in config order. * ui: customizable MCP server display name with autofill Add a display name field to the MCP server form, add and edit alike. The custom name takes precedence over the server-reported one, so two servers reporting the same name can be told apart; clearing the field returns to the automatic label. In the add dialog a debounced preview handshake prefills the field with the server-reported name: a manual edit freezes the autofill, stale responses are discarded, failures stay silent, and an unedited prefill is not persisted so the label keeps following the server. * ui: fix recursive fetch passthrough in the client test setup The original fetch was captured inside beforeEach, where it is the previous test's spy since vi.spyOn returns the existing one, so the default passthrough recursed on itself for any URL outside the mocked set. Capture the real fetch once at module load.
85 lines
2.3 KiB
TypeScript
85 lines
2.3 KiB
TypeScript
/// <reference types="@vitest/browser/matchers" />
|
|
/// <reference types="@vitest/browser/providers/playwright" />
|
|
|
|
import { beforeEach, vi } from 'vitest';
|
|
|
|
// Mock fetch for API calls during client tests.
|
|
// In test environment there is no backend server, so we intercept
|
|
// the specific endpoints the app uses and return valid mock data.
|
|
// The passthrough target is captured once at module load: capturing it
|
|
// inside beforeEach grabs the previous test's spy (vi.spyOn returns the
|
|
// existing spy), making the default branch recurse on itself as soon as
|
|
// a test fetches a URL outside the mocked set.
|
|
const originalFetch = globalThis.fetch.bind(globalThis);
|
|
|
|
beforeEach(() => {
|
|
vi.spyOn(globalThis, 'fetch').mockImplementation(
|
|
async (input: RequestInfo | URL, init?: RequestInit) => {
|
|
const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;
|
|
|
|
// Mock server props endpoint
|
|
if (url.includes('/server')) {
|
|
return new Response(
|
|
JSON.stringify({
|
|
mode: 'router',
|
|
version: 'test',
|
|
git_commit: 'test',
|
|
git_branch: 'test'
|
|
}),
|
|
{ status: 200, headers: { 'Content-Type': 'application/json' } }
|
|
);
|
|
}
|
|
|
|
// Mock models list endpoint
|
|
if (/\/v1\/models|\/models\b/.test(url)) {
|
|
return new Response(
|
|
JSON.stringify({
|
|
object: 'list',
|
|
data: [
|
|
{
|
|
id: 'test-model.gguf',
|
|
object: 'model',
|
|
owned_by: 'llamacpp',
|
|
created: 0,
|
|
in_cache: false,
|
|
path: 'models/test-model.gguf',
|
|
status: { value: 'unloaded' },
|
|
meta: {}
|
|
}
|
|
],
|
|
models: [
|
|
{
|
|
model: 'test-model.gguf',
|
|
name: 'Test Model',
|
|
details: {}
|
|
}
|
|
]
|
|
}),
|
|
{ status: 200, headers: { 'Content-Type': 'application/json' } }
|
|
);
|
|
}
|
|
|
|
// Mock /props endpoint (used for modalities)
|
|
if (url.includes('/props')) {
|
|
return new Response(
|
|
JSON.stringify({
|
|
default_generation_settings: { n_ctx: 2048 }
|
|
}),
|
|
{ status: 200, headers: { 'Content-Type': 'application/json' } }
|
|
);
|
|
}
|
|
|
|
// Mock /tools endpoint (used for built-in tools list)
|
|
if (url.includes('/tools')) {
|
|
return new Response(JSON.stringify([]), {
|
|
status: 200,
|
|
headers: { 'Content-Type': 'application/json' }
|
|
});
|
|
}
|
|
|
|
// Default: use real fetch
|
|
return originalFetch(input, init);
|
|
}
|
|
);
|
|
});
|