mirror of
https://github.com/mudler/LocalAI.git
synced 2026-11-06 04:23:15 -05:00
fix(studio): stop the web tools group title from matching an add-on name
The provider guard flags any core string that contains the name of a shipped add-on that provides a generic role. The web add-on has the id and title "Web", so the built-in tools group titled "Web" in the tools picker (and the schema example for it) failed the guard on master. Rename the group title to "Look things up online", which matches its "cannot look anything up online" off-state text. Update the schema example and the Playwright fixtures and specs that read the title. Assisted-by: Claude:claude-sonnet-5-5 go test eslint
This commit is contained in:
7 files changed
+22
-12
No files matched your search
+1
-1
@@ -101,7 +101,7 @@ const BODIES = { citations: 'Cite every claim.\n\n1. Number the sources.\n2. Lis
|
||||
export const DRAFT_TOOLS = {
|
||||
builtins: [
|
||||
{ group: 'files', tools: ['read_file'], off: false, usable: true, provider: 'builtin', providers: { read_file: 'builtin' }, title: 'Your files', description: 'The model can list, read, write, edit, move, delete and search your files, and read documents.', when_off: 'The model cannot see or change your files.' },
|
||||
{ group: 'web', tools: ['web_search', 'web_fetch'], off: false, usable: true, provider: 'builtin', providers: { web_search: 'builtin', web_fetch: 'builtin' }, title: 'Web', description: 'The model can search the web and read a public page by its address.', when_off: 'The model cannot look anything up online.' },
|
||||
{ group: 'web', tools: ['web_search', 'web_fetch'], off: false, usable: true, provider: 'builtin', providers: { web_search: 'builtin', web_fetch: 'builtin' }, title: 'Look things up online', description: 'The model can search the web and read a public page by its address.', when_off: 'The model cannot look anything up online.' },
|
||||
{ group: 'saved_agents', tools: ['list_agents'], off: true, opt_in: true, usable: true, provider: 'builtin', providers: { list_agents: 'builtin' }, title: 'Saved agents', description: 'The model can list your saved agents and start one as a sub-agent.', when_off: 'The model cannot see or start your saved agents.' },
|
||||
{ group: 'triggers', tools: ['propose_trigger'], off: false, usable: true, provider: 'builtin', providers: { propose_trigger: 'builtin' }, title: 'Triggers', description: 'The model can propose, list, change and delete triggers; a new one waits for your confirmation.', when_off: 'The model cannot create or manage triggers.' },
|
||||
{ group: 'changes', tools: ['propose_change'], off: false, usable: true, provider: 'builtin', providers: { propose_change: 'builtin' }, title: 'Memory and profile changes', description: 'The model can propose an edit to your memory notes; nothing changes until you confirm.', when_off: 'The model cannot propose edits to your memory.' },
|
||||
|
||||
@@ -66,7 +66,7 @@ test.describe('Chat tools menu: the Triggers group', () => {
|
||||
await open(page)
|
||||
await page.getByTestId('chat-tools-none').click()
|
||||
await expect(sw(page, 'Triggers')).toHaveAttribute('aria-checked', 'false')
|
||||
await expect(sw(page, 'Web')).toHaveAttribute('aria-checked', 'false')
|
||||
await expect(sw(page, 'Look things up online')).toHaveAttribute('aria-checked', 'false')
|
||||
await expect.poll(() => state.puts).toEqual([{ off: ['triggers', 'web'] }])
|
||||
await page.getByTestId('chat-tools-all').click()
|
||||
await expect(sw(page, 'Triggers')).toHaveAttribute('aria-checked', 'true')
|
||||
|
||||
@@ -631,7 +631,7 @@ test.describe('Chat tools menu: MCP', () => {
|
||||
let web = { group: 'web', tools: ['web_search', 'web_fetch'], off: false, provider: 'builtin', providers: { web_search: 'builtin', web_fetch: 'builtin' } }
|
||||
await page.route('**/api/chats/c1/addons', route => route.fulfill({ json: { addons: [] } }))
|
||||
await page.route('**/api/chats/c1/tools', route => route.fulfill({ json: { builtins: [web], addons: [], servers: [], connectors: [], off: [] } }))
|
||||
const row = () => page.getByTestId('chat-tools-item').filter({ has: page.getByRole('switch', { name: 'Web' }) })
|
||||
const row = () => page.getByTestId('chat-tools-item').filter({ has: page.getByRole('switch', { name: 'Look things up online' }) })
|
||||
const open = async () => {
|
||||
await page.goto('/app/chats/c1')
|
||||
await page.getByTestId('chat-tools-button').click()
|
||||
@@ -685,7 +685,7 @@ test.describe('Chat tools menu: built-in groups', () => {
|
||||
})
|
||||
await page.goto('/app/chats/c1')
|
||||
await page.getByTestId('chat-tools-button').click()
|
||||
await expect(page.getByRole('switch', { name: 'Web' })).toBeChecked()
|
||||
await expect(page.getByRole('switch', { name: 'Look things up online' })).toBeChecked()
|
||||
await expect(page.getByRole('switch', { name: 'Saved agents' })).not.toBeChecked()
|
||||
await page.getByRole('switch', { name: 'Saved agents' }).check()
|
||||
await expect.poll(() => calls.at(-1)).toEqual({ off: [], on: ['saved_agents'] })
|
||||
@@ -765,7 +765,7 @@ test.describe('Chat tools menu: every group of built-in tools', () => {
|
||||
await stubGroups(page)
|
||||
await open(page)
|
||||
const names = await page.getByTestId('chat-tools-group-builtins').locator('.swl-row__name').allTextContents()
|
||||
expect(names).toEqual(['Run commands', 'Your files', 'Web', 'Images and audio', 'Collections', 'Sub-agents', 'Triggers'])
|
||||
expect(names).toEqual(['Run commands', 'Your files', 'Look things up online', 'Images and audio', 'Collections', 'Sub-agents', 'Triggers'])
|
||||
await expect(row(page, 'Run commands').getByTestId('chat-tools-note')).toHaveText(['Served by add-on sandbox', 'Commands run isolated'])
|
||||
await expect(row(page, 'Your files')).toHaveAttribute('title', 'list_files, read_file, write_file · built-in')
|
||||
await expect(sw(page, 'Collections')).toBeDisabled()
|
||||
@@ -791,8 +791,8 @@ test.describe('Chat tools menu: every group of built-in tools', () => {
|
||||
const n = await rows.count()
|
||||
expect(n).toBe(10)
|
||||
for (let i = 0; i < n; i++) await expect(rows.nth(i).getByTestId('chat-tools-blurb')).not.toBeEmpty()
|
||||
await sw(page, 'Web').click()
|
||||
await expect(row(page, 'Web')).toContainText('The model cannot look anything up online.')
|
||||
await sw(page, 'Look things up online').click()
|
||||
await expect(row(page, 'Look things up online')).toContainText('The model cannot look anything up online.')
|
||||
})
|
||||
|
||||
test('switching a group off and on sends the list of groups that are off', async ({ page }) => {
|
||||
@@ -908,7 +908,7 @@ test.describe('Chat tools menu: switches and bulk actions', () => {
|
||||
await expect(manual).toHaveAttribute('aria-checked', 'false')
|
||||
await expect(manual).toHaveAccessibleDescription('the model does not use this server unless a saved agent names it')
|
||||
// The add-on that serves the web tools is a chip next to the name.
|
||||
const web = page.getByTestId('chat-tools-item').filter({ has: sw(page, 'Web') })
|
||||
const web = page.getByTestId('chat-tools-item').filter({ has: sw(page, 'Look things up online') })
|
||||
await expect(web.getByTestId('chat-tools-note')).toHaveText('Served by add-on searx')
|
||||
await expect(web.locator('.ui-chip')).toBeVisible()
|
||||
// The opt-in row says that Select all leaves it.
|
||||
|
||||
@@ -148,7 +148,7 @@ test.describe('Home composer', () => {
|
||||
await ready(page)
|
||||
await page.getByTestId('chat-tools-button').click()
|
||||
const tools = page.getByTestId('chat-tools-menu')
|
||||
for (const name of ['Your files', 'Web', 'Images and audio', 'Sub-agents']) {
|
||||
for (const name of ['Your files', 'Look things up online', 'Images and audio', 'Sub-agents']) {
|
||||
await expect(tools.getByRole('switch', { name, exact: true })).toHaveAttribute('aria-checked', 'true')
|
||||
}
|
||||
await tools.getByRole('switch', { name: 'Your files', exact: true }).click()
|
||||
|
||||
@@ -65,7 +65,17 @@ var _ = Describe("Chats built-in web tools endpoints", func() {
|
||||
Expect(panel.Code).To(Equal(http.StatusOK), panel.Body.String())
|
||||
// The panel lists more groups (shell, saved agents): the order is the
|
||||
// registry's, so the spec finds the web group by name.
|
||||
Expect(groupOf(decodeJSON(panel), "web")).To(Equal(map[string]any{
|
||||
web := groupOf(decodeJSON(panel), "web")
|
||||
// The picker texts come from the group info; the spec pins the title
|
||||
// and only requires the other two to be present, so rewording the
|
||||
// description does not break the routing check.
|
||||
Expect(web).To(HaveKeyWithValue("title", "Look things up online"))
|
||||
Expect(web["description"]).NotTo(BeEmpty())
|
||||
Expect(web["when_off"]).NotTo(BeEmpty())
|
||||
delete(web, "title")
|
||||
delete(web, "description")
|
||||
delete(web, "when_off")
|
||||
Expect(web).To(Equal(map[string]any{
|
||||
"group": "web", "tools": []any{"web_search", "web_fetch"}, "off": false, "usable": true, "provider": "builtin",
|
||||
"providers": map[string]any{"web_search": "builtin", "web_fetch": "builtin"},
|
||||
}))
|
||||
|
||||
@@ -1664,7 +1664,7 @@ type ChatsBuiltinGroup struct {
|
||||
// Title and Description say what the group is and what the model can do
|
||||
// when its switch is on; WhenOff says what it cannot do when it is off.
|
||||
// They are English; the interface may translate them by group.
|
||||
Title string `json:"title,omitempty" example:"Web"`
|
||||
Title string `json:"title,omitempty" example:"Look things up online"`
|
||||
Description string `json:"description,omitempty" example:"The model can search the web and read a public page by its address."`
|
||||
WhenOff string `json:"when_off,omitempty" example:"The model cannot look anything up online."`
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ func (s *Service) describeGroups() {
|
||||
WhenOff: "The model cannot see or change your files.",
|
||||
},
|
||||
builtins.GroupWeb: {
|
||||
Title: "Web",
|
||||
Title: "Look things up online",
|
||||
Description: "The model can search the web and read a public page by its address. Addresses inside your network are refused unless an administrator allows them.",
|
||||
WhenOff: "The model cannot look anything up online.",
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user