diff --git a/core/http/react-ui/e2e/agent-kb-models.spec.js b/core/http/react-ui/e2e/agent-kb-models.spec.js new file mode 100644 index 000000000..b2573937a --- /dev/null +++ b/core/http/react-ui/e2e/agent-kb-models.spec.js @@ -0,0 +1,45 @@ +import { test, expect } from './coverage-fixtures.js' + +test('agent knowledge-base selectors filter models and save their selections', async ({ page }) => { + await page.route('**/api/agents/config/metadata', route => route.fulfill({ + json: { Fields: [ + { name: 'name', label: 'Name', type: 'text', required: true, tags: { section: 'BasicInfo' } }, + { name: 'model', label: 'Reasoning Model', type: 'text', defaultValue: 'chat-model', tags: { section: 'ModelSettings' } }, + { name: 'embedding_model', label: 'Embedding Model', type: 'text', tags: { section: 'ModelSettings' } }, + { name: 'reranker_model', label: 'Reranker Model', type: 'text', tags: { section: 'ModelSettings' } }, + ] }, + })) + await page.route('**/api/models/capabilities', route => route.fulfill({ + json: { data: [ + { id: 'chat-model', capabilities: ['FLAG_CHAT'] }, + { id: 'embed-model', capabilities: ['FLAG_EMBEDDINGS'] }, + { id: 'rank-model', capabilities: ['FLAG_RERANK'] }, + ] }, + })) + await page.route('**/api/agents', route => route.fulfill({ + json: route.request().method() === 'POST' ? {} : { agents: [], statuses: {} }, + })) + + await page.goto('/app/agents/new') + await page.locator('#field-name').fill('research') + await page.locator('.agent-wizard-nav-item').filter({ hasText: 'Model Settings' }).click() + + const embedding = page.locator('.form-row').filter({ has: page.getByText('Embedding Model', { exact: true }) }) + const reranker = page.locator('.form-row').filter({ has: page.getByText('Reranker Model', { exact: true }) }) + await expect(embedding.locator('input')).toHaveValue('') + await expect(reranker.locator('input')).toHaveValue('') + + await embedding.locator('input').click() + await expect(embedding.getByRole('option')).toHaveCount(1) + await embedding.getByRole('option', { name: /embed-model/ }).click() + await reranker.locator('input').click() + await expect(reranker.getByRole('option')).toHaveCount(1) + await reranker.getByRole('option', { name: /rank-model/ }).click() + + const saved = page.waitForRequest(request => request.method() === 'POST' && new URL(request.url()).pathname === '/api/agents') + await page.getByRole('button', { name: 'Create Agent', exact: true }).click() + expect((await saved).postDataJSON()).toMatchObject({ + name: 'research', model: 'chat-model', embedding_model: 'embed-model', reranker_model: 'rank-model', + }) + await expect(page).toHaveURL(/\/app\/agents$/) +}) diff --git a/go.mod b/go.mod index 1d4025b89..464fd1756 100644 --- a/go.mod +++ b/go.mod @@ -549,3 +549,6 @@ require ( howett.net/plist v1.0.2-0.20250314012144-ee69052608d9 // indirect lukechampine.com/blake3 v1.4.1 // indirect ) + +// Pending https://github.com/mudler/LocalAGI/pull/499; use upstream after merge. +replace github.com/mudler/LocalAGI => github.com/localai-org-maint-bot/LocalAGI v0.0.0-20260919143320-0a1d3326f4ed diff --git a/go.sum b/go.sum index 891a60d05..da5431785 100644 --- a/go.sum +++ b/go.sum @@ -917,6 +917,8 @@ github.com/libp2p/zeroconf/v2 v2.2.0 h1:Cup06Jv6u81HLhIj1KasuNM/RHHrJ8T7wOTS4+Tv github.com/libp2p/zeroconf/v2 v2.2.0/go.mod h1:fuJqLnUwZTshS3U/bMRJ3+ow/v9oid1n0DmyYyNO1Xs= github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4= github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4= +github.com/localai-org-maint-bot/LocalAGI v0.0.0-20260919143320-0a1d3326f4ed h1:yNQVhHGzpqZqv/PfdyAKhg9Y/TwdX50nRqU60pqiK6A= +github.com/localai-org-maint-bot/LocalAGI v0.0.0-20260919143320-0a1d3326f4ed/go.mod h1:Wo2UItZdZZd2PkMvhDT19a9MPyiwC+8gnk2nLZniVcY= github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag= github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 h1:PpXWgLPs+Fqr325bN2FD2ISlRRztXibcX6e8f5FR5Dc=