diff --git a/core/http/react-ui/e2e/agents-edit.spec.js b/core/http/react-ui/e2e/agents-edit.spec.js
index 6d52a32ec9..365bb035b7 100644
--- a/core/http/react-ui/e2e/agents-edit.spec.js
+++ b/core/http/react-ui/e2e/agents-edit.spec.js
@@ -541,7 +541,8 @@ test('create uses the chat picker, filters unusable models and persists the alia
await chip.click()
const options = page.getByRole('listbox').getByRole('option')
await expect(options.locator('code')).toHaveText(['Any model (the chat picks one)', 'production', 'alternate'])
- await expect(options.locator('small')).toHaveText(['not loaded', 'not loaded'])
+ // The agent picker now draws the rich row (state and capabilities), so the state is the bold line.
+ await expect(options.locator('.home-menu__state b')).toHaveText(['not loaded', 'not loaded'])
await options.filter({ has: page.getByText('production', { exact: true }) }).click()
await page.getByRole('button', { name: 'Create Agent' }).first().click()
await expect(page).toHaveURL(/\/app\/agents$/)
diff --git a/core/http/react-ui/e2e/agents-editor-levels.spec.js b/core/http/react-ui/e2e/agents-editor-levels.spec.js
new file mode 100644
index 0000000000..591858c1e8
--- /dev/null
+++ b/core/http/react-ui/e2e/agents-editor-levels.spec.js
@@ -0,0 +1,156 @@
+import { test, expect } from './coverage-fixtures.js'
+import { installAgents, DRAFT_TOOLS } from './agents-fixtures.js'
+
+// The agent editor, part 2: tool levels and templates that can be undone, the
+// Connections section, the model picker with search and capabilities, and the
+// two layout fixes of part 1 (Advanced collapses, the phone nav sticks).
+
+const MODELS = [
+ { id: 'qwen3-8b', capabilities: ['FLAG_CHAT', 'FLAG_COMPLETION'] },
+ { id: 'gemma-3-12b-it', capabilities: ['FLAG_CHAT', 'FLAG_VISION'] },
+ { id: 'phi-4-mini', capabilities: ['FLAG_CHAT'] },
+]
+const WORK = { id: 'b1', name: 'Work account' }
+const HOME = { id: 'b2', name: 'Home account' }
+
+async function open(page, url = '/app/agents/new', { bindings = [] } = {}) {
+ const s = await installAgents(page, { models: MODELS, bindings })
+ await page.route('**/api/chats/draft/tools*', route => route.fulfill({
+ json: {
+ ...DRAFT_TOOLS, servers: [], off: [], connectors: [],
+ addons: [{ id: 'tracker', tools: 14, off: false, title: 'Tracker', credentialed: true, connections: [WORK, HOME], enabled_connections: [] }, ...DRAFT_TOOLS.addons],
+ },
+ }))
+ await page.goto(url)
+ await expect(page.getByTestId('agent-edit')).toBeVisible()
+ return s
+}
+
+const tools = (page) => page.getByTestId('agent-tools-panel')
+
+test.describe('Tool levels', () => {
+ test('a level sets the switches, says so, and can be undone before saving', async ({ page }) => {
+ const s = await open(page)
+ const files = tools(page).getByRole('switch', { name: /Your files/ })
+ await expect(files).toBeChecked()
+ await expect(page.getByTestId('agent-preset-state')).toContainText('Custom mix')
+
+ await page.getByTestId('agent-preset-readonly').click()
+ await expect(files).not.toBeChecked()
+ await expect(page.getByTestId('agent-preset-readonly').locator('input')).toBeChecked()
+ await expect(page.getByTestId('agent-preset-state')).toContainText('Level: Look only')
+ const note = page.getByTestId('agent-preset-applied')
+ await expect(note).toContainText('Applied the Look only level')
+ await expect(note).toContainText('Nothing is saved until you save')
+
+ await page.getByTestId('agent-preset-applied-undo').click()
+ await expect(note).toHaveCount(0)
+ await expect(files).toBeChecked()
+ await expect(page.getByTestId('agent-preset-state')).toContainText('Custom mix')
+ expect(s.calls.some(c => c.method === 'POST' || c.method === 'PUT')).toBe(false)
+ })
+
+ test('a level is sent as the stored switches and grants, and a change by hand makes it custom', async ({ page }) => {
+ const s = await open(page)
+ await page.getByTestId('agent-preset-assistant').click()
+ await expect(page.getByTestId('agent-preset-state')).toContainText('Level: Assistant')
+ await tools(page).getByRole('switch', { name: /Look things up online/ }).click()
+ await expect(page.getByTestId('agent-preset-state')).toContainText('Custom mix')
+ await page.getByTestId('agent-preset-assistant').click()
+ await page.getByLabel('Name', { exact: false }).first().fill('Helper')
+ await page.getByRole('button', { name: 'Create Agent' }).first().click()
+ await expect(page).toHaveURL(/\/app\/agents$/)
+ const body = s.calls.find(c => c.method === 'POST').body
+ expect(body.builtins_off).toContain('files')
+ expect(body.builtins_off).not.toContain('web')
+ expect(body.builtins_on).toContain('saved_agents')
+ expect(body.builtins).toEqual(expect.arrayContaining(['triggers.propose', 'memory.write']))
+ })
+})
+
+test.describe('Templates', () => {
+ test('a template fills the identity and starts at a level, and one click takes it back', async ({ page }) => {
+ await open(page)
+ const name = page.getByLabel('Name', { exact: false }).first()
+ await page.locator('[data-template="researcher"]').click()
+ await expect(name).toHaveValue('research-assistant')
+ await expect(page.locator('[data-template="researcher"]')).toHaveAttribute('aria-pressed', 'true')
+ await expect(page.getByTestId('agent-template-applied')).toContainText('Started from Research assistant')
+ await expect(page.getByTestId('agent-preset-state')).toContainText('Level: Look only')
+ await page.getByTestId('agent-template-applied-undo').click()
+ await expect(name).toHaveValue('')
+ await expect(page.getByLabel('Instructions')).toHaveValue('')
+ await expect(page.getByTestId('agent-preset-state')).toContainText('Custom mix')
+ })
+})
+
+test.describe('Connections', () => {
+ test('the section names the connections an add-on may use, and lists where the agent is connected', async ({ page }) => {
+ const bindings = [{ id: 'b9', name: 'Team', kind: 'slack', agent_id: 'a1', enabled: true, caps: ['triggers.propose', 'memory.write'] }]
+ const s = await open(page, '/app/agents/a1/edit', { bindings })
+ const section = page.locator('#aed-sec-connections')
+ await expect(section.getByTestId('agent-connections-hint')).toContainText('each chat chooses its own')
+ await section.getByLabel('Home account').check()
+ await expect(section.getByTestId('agent-connections-hint')).toContainText('only the ticked connections')
+ await expect(section.getByTestId('agent-connections-messaging')).toContainText('Slack Team')
+ await expect(section.getByTestId('agent-connections-messaging')).toContainText('allows 2 rights')
+ // The choice is drawn here and not a second time in the Tools list.
+ await expect(tools(page).getByTestId('agent-tools-pick')).toHaveCount(0)
+ await page.getByRole('button', { name: 'Save Changes' }).first().click()
+ await expect(page).toHaveURL(/\/app\/agents$/)
+ expect(s.calls.find(c => c.method === 'PUT').body.connections).toEqual({ tracker: ['b2'] })
+ })
+
+ test('with nothing to connect the section says so', async ({ page }) => {
+ await installAgents(page, { models: MODELS })
+ await page.goto('/app/agents/new')
+ const section = page.locator('#aed-sec-connections')
+ await expect(section.getByTestId('agent-connections-addons-empty')).toBeVisible()
+ await expect(section.getByTestId('agent-connections-messaging-empty')).toBeVisible()
+ })
+})
+
+test.describe('Model picker', () => {
+ test('the list can be searched and each model shows what it can do', async ({ page }) => {
+ await open(page, '/app/agents/a1/edit')
+ await expect(page.getByTestId('agent-model-caps')).toContainText('Chat')
+ await page.getByTestId('home-model-chip').first().click()
+ const filter = page.getByRole('combobox', { name: 'Filter models' })
+ await expect(filter).toBeVisible()
+ await expect(page.getByRole('option', { name: /qwen3-8b/ })).toContainText('completion')
+ await expect(page.getByRole('option', { name: /gemma-3-12b-it/ }).locator('[data-icon="eye"]')).toHaveCount(1)
+ await filter.fill('gemma')
+ await expect(page.getByRole('option', { name: /phi-4-mini/ })).toHaveCount(0)
+ await page.getByRole('option', { name: /gemma-3-12b-it/ }).click()
+ await expect(page.getByTestId('agent-model-caps')).toContainText('Understands images')
+ })
+})
+
+test.describe('Layout', () => {
+ test('Advanced collapses and opens again, and a jump from the nav opens it', async ({ page }) => {
+ await open(page, '/app/agents/a1/edit')
+ const toggle = page.getByTestId('agent-toggle-advanced')
+ await expect(toggle).toHaveAttribute('aria-expanded', 'true')
+ await expect(page.getByTestId('agent-mcp')).toBeVisible()
+ await toggle.click()
+ await expect(toggle).toHaveAttribute('aria-expanded', 'false')
+ await expect(page.getByTestId('agent-mcp')).toBeHidden()
+ await page.getByTestId('agent-nav-advanced').click()
+ await expect(toggle).toHaveAttribute('aria-expanded', 'true')
+ await expect(page.getByTestId('agent-mcp')).toBeVisible()
+ })
+
+ test('on a phone the section nav stays under the header while the page scrolls', async ({ page }) => {
+ await page.setViewportSize({ width: 375, height: 800 })
+ await open(page, '/app/agents/a1/edit')
+ await page.evaluate(() => window.scrollTo(0, 1400))
+ await page.waitForTimeout(200)
+ const box = async (sel) => page.locator(sel).evaluate(el => { const r = el.getBoundingClientRect(); return { top: r.top, bottom: r.bottom } })
+ const bar = await box('.aed-bar')
+ const nav = await box('.aed-nav')
+ expect(bar.top).toBeGreaterThanOrEqual(-1)
+ expect(bar.top).toBeLessThanOrEqual(1)
+ expect(nav.top).toBeGreaterThanOrEqual(bar.bottom - 3)
+ expect(nav.top).toBeLessThanOrEqual(bar.bottom + 3)
+ })
+})
diff --git a/core/http/react-ui/e2e/chats-connection.spec.js b/core/http/react-ui/e2e/chats-connection.spec.js
index bc8e5b91ea..ff13207b12 100644
--- a/core/http/react-ui/e2e/chats-connection.spec.js
+++ b/core/http/react-ui/e2e/chats-connection.spec.js
@@ -140,13 +140,15 @@ test.describe('The connections an agent names', () => {
}))
await page.goto('/app/agents/new')
await page.getByLabel('Name', { exact: false }).first().fill('Reviewer')
+ // The agent form draws this choice in its Connections section.
const panel = page.getByTestId('agent-tools-panel')
- const group = panel.getByRole('group', { name: 'Connections for chats of this agent' })
+ const section = page.getByTestId('agent-connections')
+ const group = section.getByRole('group', { name: 'Connections for Tracker' })
await expect(group).toBeVisible()
- await expect(panel.getByTestId('agent-tools-pick-hint')).toContainText('each chat chooses its own')
+ await expect(section.getByTestId('agent-connections-hint')).toContainText('each chat chooses its own')
await group.getByLabel('Home').check()
await group.getByLabel('Play').check()
- await expect(panel.getByTestId('agent-tools-pick-hint')).toContainText('cannot change them')
+ await expect(section.getByTestId('agent-connections-hint')).toContainText('only the ticked connections')
await panel.getByRole('switch', { name: /Tracker/ }).click()
await page.getByRole('button', { name: 'Create Agent' }).first().click()
await expect(page).toHaveURL(/\/app\/agents$/)
diff --git a/core/http/react-ui/e2e/no-horizontal-overflow.spec.js b/core/http/react-ui/e2e/no-horizontal-overflow.spec.js
index 47ffbd4100..80ddf52be0 100644
--- a/core/http/react-ui/e2e/no-horizontal-overflow.spec.js
+++ b/core/http/react-ui/e2e/no-horizontal-overflow.spec.js
@@ -14,11 +14,13 @@ import { mockLedger, GALLERY } from './ledger-fixtures.js'
// that is meant to scroll (code, a table) does so inside its own box; the
// allowlist names those.
-const WIDTHS = [390, 768]
+const WIDTHS = [360, 390, 768]
// Boxes that scroll on their own, by selector.
// The strips are one row of tabs or chips that scroll on a phone by design
-// (the Settings tabs outgrow 390 px with a wider font).
-const SCROLLS_INSIDE = ['pre', 'code', 'table', '.ag-pre', '.wk-shortcuts__chips', '.st-groups', '.dk-hubtabs']
+// (the Settings tabs outgrow 390 px with a wider font). The agent editor nav
+// is one row of chips that scrolls inside itself on a phone, and so is the
+// add-ons tab strip (it first overflowed at 360, the width added here).
+const SCROLLS_INSIDE = ['pre', 'code', 'table', '.ag-pre', '.wk-shortcuts__chips', '.st-groups', '.dk-hubtabs', '.aed-nav', '.ad-tabs']
const join = (n, s) => Array.from({ length: n }, (_, i) => `${s}${i}`).join('_')
const WORD = join(9, 'unbroken_name_segment')
@@ -193,7 +195,8 @@ const plainBindings = [
{ id: 'b2', name: 'Personal', kind: 'telegram', agent_id: 'a2', enabled: true, caps: plainCaps.filter(c => c !== 'triggers.run') },
]
-for (const width of [1280, 1100, 390]) {
+// 320 is the narrowest phone the editor supports; 360 is the common one.
+for (const width of [1280, 1100, 390, 360, 320]) {
for (const collapsed of [false, true]) {
test.describe(`plain agent editor at ${width}px, sidebar ${collapsed ? 'collapsed' : 'open'}`, () => {
test.use({ viewport: { width, height: 900 } })
diff --git a/core/http/react-ui/public/locales/de/agents.json b/core/http/react-ui/public/locales/de/agents.json
index 067122b0e4..b4f25c341d 100644
--- a/core/http/react-ui/public/locales/de/agents.json
+++ b/core/http/react-ui/public/locales/de/agents.json
@@ -82,7 +82,8 @@
"export": "Export",
"Files": "Dateien",
"Tools": "Werkzeuge",
- "Notes": "Gedächtnis"
+ "Notes": "Gedächtnis",
+ "Connections": "Verbindungen"
},
"name": "Name",
"description": "Description",
@@ -157,13 +158,15 @@
"identity": "Identität",
"capabilities": "Fähigkeiten",
"memory": "Gedächtnis und Wissen",
- "advanced": "Erweitert"
+ "advanced": "Erweitert",
+ "connections": "Verbindungen"
},
"lead": {
"identity": "Wer der Agent ist und wie er sich verhält.",
"capabilities": "Was der Agent nutzen und erreichen darf.",
"memory": "Woran sich der Agent erinnert und was er nachschlagen kann.",
- "advanced": "Zusätzliche Server und Export."
+ "advanced": "Zusätzliche Server und Export.",
+ "connections": "Welche Verbindungen dieser Agent nutzen darf."
},
"header": {
"unnamed": "Unbenannter Agent",
@@ -175,6 +178,54 @@
"clean": "Keine ungespeicherten Änderungen",
"new": "Noch nicht erstellt",
"unsaved": "Ungespeicherte Änderungen ({{count}})"
+ },
+ "preset": {
+ "label": "Werkzeugstufe",
+ "loading": "Werkzeugliste wird geladen",
+ "current": "Stufe: {{name}}. Ändern Sie unten einen Schalter, wird daraus eine eigene Mischung.",
+ "custom": "Eigene Mischung von Schaltern. Wählen Sie eine Stufe, um sie zu ersetzen.",
+ "applied": "Stufe {{name}} angewendet",
+ "appliedBody": "Die Schalter unten haben sich geändert. Nichts wird gespeichert, bis Sie speichern.",
+ "readonly": {
+ "title": "Nur nachsehen",
+ "body": "Sucht im Internet und in Ihren Sammlungen. Keine Dateien, keine Befehle, keine Trigger."
+ },
+ "assistant": {
+ "title": "Assistent",
+ "body": "Fügt gespeicherte Agenten, Trigger und vorgeschlagene Änderungen hinzu. Keine Dateien, keine Befehle."
+ },
+ "full": {
+ "title": "Voll",
+ "body": "Jedes Werkzeug, das der Server auflistet. Sensible Rechte bleiben aus."
+ }
+ },
+ "tpl": {
+ "applied": "Gestartet mit {{name}}",
+ "appliedBody": "Name, Beschreibung, Anweisungen und Werkzeuge haben sich geändert. Nichts wird gespeichert, bis Sie speichern.",
+ "tools": "Werkzeuge: {{level}}",
+ "noTools": "Werkzeuge: unverändert"
+ },
+ "undo": "Rückgängig",
+ "keep": "Behalten",
+ "modelCaps": "Was dieses Modell kann",
+ "modelChat": "Chat",
+ "connections": {
+ "addonsTitle": "Add-ons mit Verbindung",
+ "addonsNone": "Kein Add-on braucht eine Verbindung.",
+ "messagingTitle": "Wo dieser Agent verbunden ist",
+ "messagingNone": "Noch keine Messaging-Verbindung nutzt diesen Agenten. Speichern Sie den Agenten und fügen Sie dann eine hinzu.",
+ "messagingHelp": "Messaging-Verbindungen werden auf ihrer eigenen Seite eingestellt.",
+ "allows_one": "erlaubt {{count}} Recht",
+ "allows_other": "erlaubt {{count}} Rechte",
+ "open": "Öffnen",
+ "addonOff": "aus",
+ "noneYet": "Noch keine Verbindung.",
+ "add": "Verbindung hinzufügen",
+ "groupLabel": "Verbindungen für {{name}}",
+ "chosenHelp": "Chats dieses Agenten dürfen nur die angehakten Verbindungen nutzen.",
+ "perChat": "Nichts angehakt: Jeder Chat wählt selbst.",
+ "summary_one": "{{count}} Verbindung",
+ "summary_other": "{{count}} Verbindungen"
}
},
"run": {
@@ -538,5 +589,19 @@
"effectiveWrite": "Liegt in einem Ordner, der geändert werden kann, daher kann auch dieser geändert werden.",
"notMounted": "{{n}} geteilte Ordner passen nicht in das Zugriffslimit eines Chats und sind nicht eingebunden.",
"exportNoteMany": "Die Datei nennt {{n}} Ordner. Beim Import erhält der Agent die Ordner mit diesen Pfaden, die es gibt, und bittet dich, die anderen zu wählen."
+ },
+ "templates": {
+ "researcher": {
+ "description": "Sucht, liest Quellen und schreibt kurze Berichte."
+ },
+ "reviewer": {
+ "description": "Prüft eine Änderung und nennt zuerst, was zu beheben ist."
+ },
+ "digest": {
+ "description": "Sammelt Neues zu einem Thema und fasst es zusammen."
+ },
+ "blank": {
+ "description": "Leer. Von Null beginnen."
+ }
}
}
diff --git a/core/http/react-ui/public/locales/en/agents.json b/core/http/react-ui/public/locales/en/agents.json
index 6fa19b1bc7..d207aff8b2 100644
--- a/core/http/react-ui/public/locales/en/agents.json
+++ b/core/http/react-ui/public/locales/en/agents.json
@@ -112,16 +112,20 @@
},
"templates": {
"researcher": {
- "label": "Research assistant"
+ "label": "Research assistant",
+ "description": "Searches, reads sources and writes short briefs."
},
"reviewer": {
- "label": "Code reviewer"
+ "label": "Code reviewer",
+ "description": "Reviews a change and lists what to fix first."
},
"digest": {
- "label": "Daily digest"
+ "label": "Daily digest",
+ "description": "Collects what is new on a topic and summarises it."
},
"blank": {
- "label": "Blank"
+ "label": "Blank",
+ "description": "Empty. Start from scratch."
}
},
"agent": {
@@ -191,7 +195,8 @@
"export": "Export",
"Files": "Files",
"Tools": "Tools",
- "Notes": "Memory"
+ "Notes": "Memory",
+ "Connections": "Connections"
},
"grantsNoticeTitle": "Some messaging features will turn off.",
"grantsNotice": "This agent had no permission list, so it kept these on its messaging connections: {{grants}}. They stop working until you tick them here.",
@@ -260,13 +265,15 @@
"identity": "Identity",
"capabilities": "Capabilities",
"memory": "Memory and knowledge",
- "advanced": "Advanced"
+ "advanced": "Advanced",
+ "connections": "Connections"
},
"lead": {
"identity": "Who the agent is and how it behaves.",
"capabilities": "What the agent may use and reach.",
"memory": "What the agent remembers and what it can look up.",
- "advanced": "Extra servers and export."
+ "advanced": "Extra servers and export.",
+ "connections": "Which connections this agent may use."
},
"header": {
"unnamed": "Unnamed agent",
@@ -278,6 +285,54 @@
"clean": "No unsaved changes",
"new": "Not created yet",
"unsaved": "Unsaved changes ({{count}})"
+ },
+ "preset": {
+ "label": "Tool level",
+ "loading": "Loading the tool list",
+ "current": "Level: {{name}}. Change a switch below and it becomes a custom mix.",
+ "custom": "Custom mix of switches. Pick a level to replace it.",
+ "applied": "Applied the {{name}} level",
+ "appliedBody": "The switches below changed. Nothing is saved until you save.",
+ "readonly": {
+ "title": "Look only",
+ "body": "Searches the web and your collections. No files, no commands, no triggers."
+ },
+ "assistant": {
+ "title": "Assistant",
+ "body": "Adds saved agents, triggers and suggested changes. No files, no commands."
+ },
+ "full": {
+ "title": "Full",
+ "body": "Every tool the server lists. Sensitive rights stay off."
+ }
+ },
+ "tpl": {
+ "applied": "Started from {{name}}",
+ "appliedBody": "The name, description, instructions and tools changed. Nothing is saved until you save.",
+ "tools": "Tools: {{level}}",
+ "noTools": "Tools: as they are"
+ },
+ "undo": "Undo",
+ "keep": "Keep",
+ "modelCaps": "What this model can do",
+ "modelChat": "Chat",
+ "connections": {
+ "addonsTitle": "Add-ons that use a connection",
+ "addonsNone": "No add-on needs a connection.",
+ "messagingTitle": "Where this agent is connected",
+ "messagingNone": "No messaging connection uses this agent yet. Save the agent, then add one.",
+ "messagingHelp": "Messaging connections are set on their own page.",
+ "allows_one": "allows {{count}} right",
+ "allows_other": "allows {{count}} rights",
+ "open": "Open",
+ "addonOff": "off",
+ "noneYet": "No connection yet.",
+ "add": "Add a connection",
+ "groupLabel": "Connections for {{name}}",
+ "chosenHelp": "Chats of this agent may use only the ticked connections.",
+ "perChat": "None ticked: each chat chooses its own.",
+ "summary_one": "{{count}} connection",
+ "summary_other": "{{count}} connections"
}
},
"status": {
diff --git a/core/http/react-ui/public/locales/es/agents.json b/core/http/react-ui/public/locales/es/agents.json
index ab2d8ec9be..6daab5e07a 100644
--- a/core/http/react-ui/public/locales/es/agents.json
+++ b/core/http/react-ui/public/locales/es/agents.json
@@ -82,7 +82,8 @@
"export": "Export",
"Files": "Archivos",
"Tools": "Herramientas",
- "Notes": "Memoria"
+ "Notes": "Memoria",
+ "Connections": "Conexiones"
},
"name": "Name",
"description": "Description",
@@ -157,13 +158,15 @@
"identity": "Identidad",
"capabilities": "Capacidades",
"memory": "Memoria y conocimiento",
- "advanced": "Avanzado"
+ "advanced": "Avanzado",
+ "connections": "Conexiones"
},
"lead": {
"identity": "Quién es el agente y cómo se comporta.",
"capabilities": "Lo que el agente puede usar y alcanzar.",
"memory": "Lo que el agente recuerda y lo que puede consultar.",
- "advanced": "Servidores adicionales y exportación."
+ "advanced": "Servidores adicionales y exportación.",
+ "connections": "Qué conexiones puede usar este agente."
},
"header": {
"unnamed": "Agente sin nombre",
@@ -175,6 +178,54 @@
"clean": "Sin cambios sin guardar",
"new": "Aún no creado",
"unsaved": "Cambios sin guardar ({{count}})"
+ },
+ "preset": {
+ "label": "Nivel de herramientas",
+ "loading": "Cargando la lista de herramientas",
+ "current": "Nivel: {{name}}. Si cambia un interruptor de abajo, pasa a ser una mezcla propia.",
+ "custom": "Mezcla propia de interruptores. Elija un nivel para sustituirla.",
+ "applied": "Nivel {{name}} aplicado",
+ "appliedBody": "Los interruptores de abajo han cambiado. No se guarda nada hasta que guarde.",
+ "readonly": {
+ "title": "Solo consultar",
+ "body": "Busca en la web y en sus colecciones. Sin archivos, sin comandos, sin disparadores."
+ },
+ "assistant": {
+ "title": "Asistente",
+ "body": "Añade agentes guardados, disparadores y cambios sugeridos. Sin archivos, sin comandos."
+ },
+ "full": {
+ "title": "Completo",
+ "body": "Todas las herramientas que lista el servidor. Los permisos sensibles siguen desactivados."
+ }
+ },
+ "tpl": {
+ "applied": "Empezado desde {{name}}",
+ "appliedBody": "El nombre, la descripción, las instrucciones y las herramientas han cambiado. No se guarda nada hasta que guarde.",
+ "tools": "Herramientas: {{level}}",
+ "noTools": "Herramientas: sin cambios"
+ },
+ "undo": "Deshacer",
+ "keep": "Conservar",
+ "modelCaps": "Qué puede hacer este modelo",
+ "modelChat": "Chat",
+ "connections": {
+ "addonsTitle": "Complementos que usan una conexión",
+ "addonsNone": "Ningún complemento necesita una conexión.",
+ "messagingTitle": "Dónde está conectado este agente",
+ "messagingNone": "Ninguna conexión de mensajería usa todavía este agente. Guarde el agente y añada una.",
+ "messagingHelp": "Las conexiones de mensajería se configuran en su propia página.",
+ "allows_one": "permite {{count}} permiso",
+ "allows_other": "permite {{count}} permisos",
+ "open": "Abrir",
+ "addonOff": "desactivado",
+ "noneYet": "Aún no hay ninguna conexión.",
+ "add": "Añadir una conexión",
+ "groupLabel": "Conexiones para {{name}}",
+ "chosenHelp": "Los chats de este agente solo pueden usar las conexiones marcadas.",
+ "perChat": "Ninguna marcada: cada chat elige la suya.",
+ "summary_one": "{{count}} conexión",
+ "summary_other": "{{count}} conexiones"
}
},
"run": {
@@ -538,5 +589,19 @@
"effectiveWrite": "Está dentro de una carpeta que se puede cambiar, así que esta también se puede cambiar.",
"notMounted": "{{n}} carpetas compartidas no caben en el límite de acceso de un chat y no se montan.",
"exportNoteMany": "El archivo nombra {{n}} carpetas. Donde lo importes, el agente recibe las carpetas con esas rutas que existan y te pide elegir las demás."
+ },
+ "templates": {
+ "researcher": {
+ "description": "Busca, lee fuentes y escribe resúmenes breves."
+ },
+ "reviewer": {
+ "description": "Revisa un cambio y lista primero lo que hay que corregir."
+ },
+ "digest": {
+ "description": "Reúne las novedades de un tema y las resume."
+ },
+ "blank": {
+ "description": "Vacío. Empiece desde cero."
+ }
}
}
diff --git a/core/http/react-ui/public/locales/fr/agents.json b/core/http/react-ui/public/locales/fr/agents.json
index ae08a81df0..6bb9f17550 100644
--- a/core/http/react-ui/public/locales/fr/agents.json
+++ b/core/http/react-ui/public/locales/fr/agents.json
@@ -82,7 +82,8 @@
"export": "Export",
"Files": "Fichiers",
"Tools": "Outils",
- "Notes": "Mémoire"
+ "Notes": "Mémoire",
+ "Connections": "Connexions"
},
"name": "Name",
"description": "Description",
@@ -157,13 +158,15 @@
"identity": "Identité",
"capabilities": "Capacités",
"memory": "Mémoire et connaissances",
- "advanced": "Avancé"
+ "advanced": "Avancé",
+ "connections": "Connexions"
},
"lead": {
"identity": "Qui est l'agent et comment il se comporte.",
"capabilities": "Ce que l'agent peut utiliser et atteindre.",
"memory": "Ce dont l'agent se souvient et ce qu'il peut consulter.",
- "advanced": "Serveurs supplémentaires et export."
+ "advanced": "Serveurs supplémentaires et export.",
+ "connections": "Les connexions que cet agent peut utiliser."
},
"header": {
"unnamed": "Agent sans nom",
@@ -175,6 +178,54 @@
"clean": "Aucune modification non enregistrée",
"new": "Pas encore créé",
"unsaved": "Modifications non enregistrées ({{count}})"
+ },
+ "preset": {
+ "label": "Niveau d'outils",
+ "loading": "Chargement de la liste d'outils",
+ "current": "Niveau : {{name}}. Si vous changez un interrupteur ci-dessous, cela devient un mélange personnalisé.",
+ "custom": "Mélange personnalisé d'interrupteurs. Choisissez un niveau pour le remplacer.",
+ "applied": "Niveau {{name}} appliqué",
+ "appliedBody": "Les interrupteurs ci-dessous ont changé. Rien n'est enregistré avant que vous enregistriez.",
+ "readonly": {
+ "title": "Consultation seule",
+ "body": "Cherche sur le web et dans vos collections. Pas de fichiers, pas de commandes, pas de déclencheurs."
+ },
+ "assistant": {
+ "title": "Assistant",
+ "body": "Ajoute les agents enregistrés, les déclencheurs et les modifications suggérées. Pas de fichiers, pas de commandes."
+ },
+ "full": {
+ "title": "Complet",
+ "body": "Tous les outils que le serveur liste. Les droits sensibles restent désactivés."
+ }
+ },
+ "tpl": {
+ "applied": "Démarré depuis {{name}}",
+ "appliedBody": "Le nom, la description, les instructions et les outils ont changé. Rien n'est enregistré avant que vous enregistriez.",
+ "tools": "Outils : {{level}}",
+ "noTools": "Outils : inchangés"
+ },
+ "undo": "Annuler",
+ "keep": "Garder",
+ "modelCaps": "Ce que ce modèle sait faire",
+ "modelChat": "Chat",
+ "connections": {
+ "addonsTitle": "Modules qui utilisent une connexion",
+ "addonsNone": "Aucun module n'a besoin d'une connexion.",
+ "messagingTitle": "Où cet agent est connecté",
+ "messagingNone": "Aucune connexion de messagerie n'utilise encore cet agent. Enregistrez l'agent, puis ajoutez-en une.",
+ "messagingHelp": "Les connexions de messagerie se règlent sur leur propre page.",
+ "allows_one": "autorise {{count}} droit",
+ "allows_other": "autorise {{count}} droits",
+ "open": "Ouvrir",
+ "addonOff": "désactivé",
+ "noneYet": "Aucune connexion pour l'instant.",
+ "add": "Ajouter une connexion",
+ "groupLabel": "Connexions pour {{name}}",
+ "chosenHelp": "Les discussions de cet agent ne peuvent utiliser que les connexions cochées.",
+ "perChat": "Aucune cochée : chaque discussion choisit la sienne.",
+ "summary_one": "{{count}} connexion",
+ "summary_other": "{{count}} connexions"
}
},
"run": {
@@ -538,5 +589,19 @@
"effectiveWrite": "Dans un dossier modifiable : celui-ci peut aussi être modifié.",
"notMounted": "{{n}} dossiers partagés ne tiennent pas dans la limite d'accès d'un chat et ne sont pas montés.",
"exportNoteMany": "Le fichier nomme {{n}} dossiers. Là où vous l'importez, l'agent reçoit les dossiers de ces chemins qui existent et vous demande de choisir les autres."
+ },
+ "templates": {
+ "researcher": {
+ "description": "Cherche, lit des sources et rédige de courtes synthèses."
+ },
+ "reviewer": {
+ "description": "Examine une modification et liste d'abord ce qu'il faut corriger."
+ },
+ "digest": {
+ "description": "Réunit les nouveautés d'un sujet et les résume."
+ },
+ "blank": {
+ "description": "Vide. Partez de zéro."
+ }
}
}
diff --git a/core/http/react-ui/public/locales/id/agents.json b/core/http/react-ui/public/locales/id/agents.json
index e1a85b8f98..7e7322bfff 100644
--- a/core/http/react-ui/public/locales/id/agents.json
+++ b/core/http/react-ui/public/locales/id/agents.json
@@ -82,7 +82,8 @@
"export": "Export",
"Files": "File",
"Tools": "Alat",
- "Notes": "Memori"
+ "Notes": "Memori",
+ "Connections": "Koneksi"
},
"name": "Name",
"description": "Description",
@@ -157,13 +158,15 @@
"identity": "Identitas",
"capabilities": "Kemampuan",
"memory": "Memori dan pengetahuan",
- "advanced": "Lanjutan"
+ "advanced": "Lanjutan",
+ "connections": "Koneksi"
},
"lead": {
"identity": "Siapa agen ini dan bagaimana ia bersikap.",
"capabilities": "Apa yang boleh digunakan dan dijangkau agen.",
"memory": "Apa yang diingat agen dan apa yang bisa dicarinya.",
- "advanced": "Server tambahan dan ekspor."
+ "advanced": "Server tambahan dan ekspor.",
+ "connections": "Koneksi mana yang boleh dipakai agen ini."
},
"header": {
"unnamed": "Agen tanpa nama",
@@ -175,6 +178,54 @@
"clean": "Tidak ada perubahan yang belum disimpan",
"new": "Belum dibuat",
"unsaved": "Perubahan belum disimpan ({{count}})"
+ },
+ "preset": {
+ "label": "Tingkat alat",
+ "loading": "Memuat daftar alat",
+ "current": "Tingkat: {{name}}. Ubah satu sakelar di bawah dan jadilah campuran kustom.",
+ "custom": "Campuran sakelar kustom. Pilih satu tingkat untuk menggantinya.",
+ "applied": "Tingkat {{name}} diterapkan",
+ "appliedBody": "Sakelar di bawah berubah. Tidak ada yang disimpan sampai Anda menyimpan.",
+ "readonly": {
+ "title": "Hanya melihat",
+ "body": "Mencari di web dan koleksi Anda. Tanpa berkas, tanpa perintah, tanpa pemicu."
+ },
+ "assistant": {
+ "title": "Asisten",
+ "body": "Menambahkan agen tersimpan, pemicu, dan perubahan yang disarankan. Tanpa berkas, tanpa perintah."
+ },
+ "full": {
+ "title": "Penuh",
+ "body": "Semua alat yang didaftarkan server. Hak sensitif tetap mati."
+ }
+ },
+ "tpl": {
+ "applied": "Dimulai dari {{name}}",
+ "appliedBody": "Nama, deskripsi, instruksi, dan alat berubah. Tidak ada yang disimpan sampai Anda menyimpan.",
+ "tools": "Alat: {{level}}",
+ "noTools": "Alat: tidak berubah"
+ },
+ "undo": "Urungkan",
+ "keep": "Pertahankan",
+ "modelCaps": "Apa yang bisa dilakukan model ini",
+ "modelChat": "Obrolan",
+ "connections": {
+ "addonsTitle": "Add-on yang memakai koneksi",
+ "addonsNone": "Tidak ada add-on yang butuh koneksi.",
+ "messagingTitle": "Tempat agen ini terhubung",
+ "messagingNone": "Belum ada koneksi pesan yang memakai agen ini. Simpan agen, lalu tambahkan satu.",
+ "messagingHelp": "Koneksi pesan diatur di halamannya sendiri.",
+ "allows_one": "mengizinkan {{count}} hak",
+ "allows_other": "mengizinkan {{count}} hak",
+ "open": "Buka",
+ "addonOff": "mati",
+ "noneYet": "Belum ada koneksi.",
+ "add": "Tambah koneksi",
+ "groupLabel": "Koneksi untuk {{name}}",
+ "chosenHelp": "Obrolan agen ini hanya boleh memakai koneksi yang dicentang.",
+ "perChat": "Tidak ada yang dicentang: tiap obrolan memilih sendiri.",
+ "summary_one": "{{count}} koneksi",
+ "summary_other": "{{count}} koneksi"
}
},
"run": {
@@ -538,5 +589,19 @@
"effectiveWrite": "Ada di dalam folder yang bisa diubah, jadi folder ini juga bisa diubah.",
"notMounted": "{{n}} folder bersama tidak muat dalam batas akses sebuah chat dan tidak dipasang.",
"exportNoteMany": "File ini menyebut {{n}} folder. Di tempat Anda mengimpornya, agen mendapat folder dengan path itu yang ada, dan meminta Anda memilih sisanya."
+ },
+ "templates": {
+ "researcher": {
+ "description": "Mencari, membaca sumber, dan menulis ringkasan singkat."
+ },
+ "reviewer": {
+ "description": "Meninjau perubahan dan mendaftar yang perlu diperbaiki lebih dulu."
+ },
+ "digest": {
+ "description": "Mengumpulkan yang baru pada suatu topik dan merangkumnya."
+ },
+ "blank": {
+ "description": "Kosong. Mulai dari nol."
+ }
}
}
diff --git a/core/http/react-ui/public/locales/it/agents.json b/core/http/react-ui/public/locales/it/agents.json
index c9510a0d87..91bd094769 100644
--- a/core/http/react-ui/public/locales/it/agents.json
+++ b/core/http/react-ui/public/locales/it/agents.json
@@ -82,7 +82,8 @@
"export": "Export",
"Files": "File",
"Tools": "Strumenti",
- "Notes": "Memoria"
+ "Notes": "Memoria",
+ "Connections": "Connessioni"
},
"name": "Name",
"description": "Description",
@@ -157,13 +158,15 @@
"identity": "Identità",
"capabilities": "Capacità",
"memory": "Memoria e conoscenza",
- "advanced": "Avanzate"
+ "advanced": "Avanzate",
+ "connections": "Connessioni"
},
"lead": {
"identity": "Chi è l'agente e come si comporta.",
"capabilities": "Cosa può usare e raggiungere l'agente.",
"memory": "Cosa ricorda l'agente e cosa può consultare.",
- "advanced": "Server aggiuntivi ed esportazione."
+ "advanced": "Server aggiuntivi ed esportazione.",
+ "connections": "Quali connessioni può usare questo agente."
},
"header": {
"unnamed": "Agente senza nome",
@@ -175,6 +178,54 @@
"clean": "Nessuna modifica non salvata",
"new": "Non ancora creato",
"unsaved": "Modifiche non salvate ({{count}})"
+ },
+ "preset": {
+ "label": "Livello degli strumenti",
+ "loading": "Caricamento dell'elenco degli strumenti",
+ "current": "Livello: {{name}}. Se cambi un interruttore qui sotto diventa una combinazione personalizzata.",
+ "custom": "Combinazione personalizzata di interruttori. Scegli un livello per sostituirla.",
+ "applied": "Livello {{name}} applicato",
+ "appliedBody": "Gli interruttori qui sotto sono cambiati. Non viene salvato nulla finché non salvi.",
+ "readonly": {
+ "title": "Solo consultazione",
+ "body": "Cerca sul web e nelle tue raccolte. Niente file, niente comandi, niente trigger."
+ },
+ "assistant": {
+ "title": "Assistente",
+ "body": "Aggiunge agenti salvati, trigger e modifiche suggerite. Niente file, niente comandi."
+ },
+ "full": {
+ "title": "Completo",
+ "body": "Tutti gli strumenti elencati dal server. I permessi sensibili restano disattivati."
+ }
+ },
+ "tpl": {
+ "applied": "Partito da {{name}}",
+ "appliedBody": "Nome, descrizione, istruzioni e strumenti sono cambiati. Non viene salvato nulla finché non salvi.",
+ "tools": "Strumenti: {{level}}",
+ "noTools": "Strumenti: invariati"
+ },
+ "undo": "Annulla",
+ "keep": "Mantieni",
+ "modelCaps": "Cosa sa fare questo modello",
+ "modelChat": "Chat",
+ "connections": {
+ "addonsTitle": "Add-on che usano una connessione",
+ "addonsNone": "Nessun add-on ha bisogno di una connessione.",
+ "messagingTitle": "Dove è connesso questo agente",
+ "messagingNone": "Nessuna connessione di messaggistica usa ancora questo agente. Salva l'agente, poi aggiungine una.",
+ "messagingHelp": "Le connessioni di messaggistica si impostano nella loro pagina.",
+ "allows_one": "consente {{count}} permesso",
+ "allows_other": "consente {{count}} permessi",
+ "open": "Apri",
+ "addonOff": "disattivato",
+ "noneYet": "Ancora nessuna connessione.",
+ "add": "Aggiungi una connessione",
+ "groupLabel": "Connessioni per {{name}}",
+ "chosenHelp": "Le chat di questo agente possono usare solo le connessioni selezionate.",
+ "perChat": "Nessuna selezionata: ogni chat sceglie la sua.",
+ "summary_one": "{{count}} connessione",
+ "summary_other": "{{count}} connessioni"
}
},
"run": {
@@ -538,5 +589,19 @@
"effectiveWrite": "È dentro una cartella modificabile, quindi anche questa si può modificare.",
"notMounted": "{{n}} cartelle condivise non rientrano nel limite di accesso di una chat e non sono montate.",
"exportNoteMany": "Il file nomina {{n}} cartelle. Dove lo importi, l'agente riceve le cartelle con quei percorsi che esistono e ti chiede di scegliere le altre."
+ },
+ "templates": {
+ "researcher": {
+ "description": "Cerca, legge le fonti e scrive brevi sintesi."
+ },
+ "reviewer": {
+ "description": "Esamina una modifica ed elenca prima ciò che va corretto."
+ },
+ "digest": {
+ "description": "Raccoglie le novità su un argomento e le riassume."
+ },
+ "blank": {
+ "description": "Vuoto. Parti da zero."
+ }
}
}
diff --git a/core/http/react-ui/public/locales/ko/agents.json b/core/http/react-ui/public/locales/ko/agents.json
index d2ad5d7f94..bcbfbbb2e4 100644
--- a/core/http/react-ui/public/locales/ko/agents.json
+++ b/core/http/react-ui/public/locales/ko/agents.json
@@ -82,7 +82,8 @@
"export": "Export",
"Files": "파일",
"Tools": "도구",
- "Notes": "메모리"
+ "Notes": "메모리",
+ "Connections": "연결"
},
"name": "Name",
"description": "Description",
@@ -157,13 +158,15 @@
"identity": "정체성",
"capabilities": "기능",
"memory": "메모리와 지식",
- "advanced": "고급"
+ "advanced": "고급",
+ "connections": "연결"
},
"lead": {
"identity": "에이전트가 누구이고 어떻게 행동하는지 정합니다.",
"capabilities": "에이전트가 사용하고 접근할 수 있는 것을 정합니다.",
"memory": "에이전트가 기억하는 것과 찾아볼 수 있는 것을 정합니다.",
- "advanced": "추가 서버와 내보내기."
+ "advanced": "추가 서버와 내보내기.",
+ "connections": "이 에이전트가 사용할 수 있는 연결입니다."
},
"header": {
"unnamed": "이름 없는 에이전트",
@@ -175,6 +178,54 @@
"clean": "저장하지 않은 변경 사항 없음",
"new": "아직 만들지 않음",
"unsaved": "저장하지 않은 변경 사항 ({{count}})"
+ },
+ "preset": {
+ "label": "도구 수준",
+ "loading": "도구 목록을 불러오는 중",
+ "current": "수준: {{name}}. 아래 스위치를 바꾸면 사용자 지정 조합이 됩니다.",
+ "custom": "사용자 지정 스위치 조합입니다. 수준을 고르면 바뀝니다.",
+ "applied": "{{name}} 수준을 적용했습니다",
+ "appliedBody": "아래 스위치가 바뀌었습니다. 저장하기 전에는 아무것도 저장되지 않습니다.",
+ "readonly": {
+ "title": "보기만",
+ "body": "웹과 컬렉션을 검색합니다. 파일, 명령, 트리거는 없습니다."
+ },
+ "assistant": {
+ "title": "어시스턴트",
+ "body": "저장된 에이전트, 트리거, 제안된 변경을 더합니다. 파일과 명령은 없습니다."
+ },
+ "full": {
+ "title": "전체",
+ "body": "서버가 나열하는 모든 도구입니다. 민감한 권한은 꺼진 채로 둡니다."
+ }
+ },
+ "tpl": {
+ "applied": "{{name}}에서 시작함",
+ "appliedBody": "이름, 설명, 지침, 도구가 바뀌었습니다. 저장하기 전에는 아무것도 저장되지 않습니다.",
+ "tools": "도구: {{level}}",
+ "noTools": "도구: 그대로"
+ },
+ "undo": "실행 취소",
+ "keep": "유지",
+ "modelCaps": "이 모델이 할 수 있는 일",
+ "modelChat": "채팅",
+ "connections": {
+ "addonsTitle": "연결을 쓰는 애드온",
+ "addonsNone": "연결이 필요한 애드온이 없습니다.",
+ "messagingTitle": "이 에이전트가 연결된 곳",
+ "messagingNone": "이 에이전트를 쓰는 메시징 연결이 아직 없습니다. 에이전트를 저장한 뒤 추가하세요.",
+ "messagingHelp": "메시징 연결은 해당 페이지에서 설정합니다.",
+ "allows_one": "권한 {{count}}개 허용",
+ "allows_other": "권한 {{count}}개 허용",
+ "open": "열기",
+ "addonOff": "꺼짐",
+ "noneYet": "아직 연결이 없습니다.",
+ "add": "연결 추가",
+ "groupLabel": "{{name}}의 연결",
+ "chosenHelp": "이 에이전트의 채팅은 선택한 연결만 쓸 수 있습니다.",
+ "perChat": "선택 없음: 채팅마다 직접 고릅니다.",
+ "summary_one": "연결 {{count}}개",
+ "summary_other": "연결 {{count}}개"
}
},
"run": {
@@ -538,5 +589,19 @@
"effectiveWrite": "변경할 수 있는 폴더 안에 있어서 이 폴더도 변경할 수 있습니다.",
"notMounted": "공유 폴더 {{n}}개가 채팅의 접근 한도에 맞지 않아 마운트되지 않았습니다.",
"exportNoteMany": "이 파일에는 폴더 {{n}}개가 적혀 있습니다. 가져오는 곳에서는 해당 경로에 실제로 있는 폴더가 에이전트에 지정되고, 나머지는 직접 고르라고 안내합니다."
+ },
+ "templates": {
+ "researcher": {
+ "description": "검색하고 출처를 읽어 짧은 요약을 씁니다."
+ },
+ "reviewer": {
+ "description": "변경 사항을 검토하고 먼저 고칠 것을 나열합니다."
+ },
+ "digest": {
+ "description": "주제의 새 소식을 모아 요약합니다."
+ },
+ "blank": {
+ "description": "비어 있음. 처음부터 시작합니다."
+ }
}
}
diff --git a/core/http/react-ui/public/locales/pt-BR/agents.json b/core/http/react-ui/public/locales/pt-BR/agents.json
index c6e3e2915d..e473dda4c9 100644
--- a/core/http/react-ui/public/locales/pt-BR/agents.json
+++ b/core/http/react-ui/public/locales/pt-BR/agents.json
@@ -82,7 +82,8 @@
"export": "Export",
"Files": "Arquivos",
"Tools": "Ferramentas",
- "Notes": "Memória"
+ "Notes": "Memória",
+ "Connections": "Conexões"
},
"name": "Name",
"description": "Description",
@@ -157,13 +158,15 @@
"identity": "Identidade",
"capabilities": "Capacidades",
"memory": "Memória e conhecimento",
- "advanced": "Avançado"
+ "advanced": "Avançado",
+ "connections": "Conexões"
},
"lead": {
"identity": "Quem é o agente e como ele se comporta.",
"capabilities": "O que o agente pode usar e alcançar.",
"memory": "O que o agente lembra e o que ele pode consultar.",
- "advanced": "Servidores extras e exportação."
+ "advanced": "Servidores extras e exportação.",
+ "connections": "Quais conexões este agente pode usar."
},
"header": {
"unnamed": "Agente sem nome",
@@ -175,6 +178,54 @@
"clean": "Nenhuma alteração não salva",
"new": "Ainda não criado",
"unsaved": "Alterações não salvas ({{count}})"
+ },
+ "preset": {
+ "label": "Nível de ferramentas",
+ "loading": "Carregando a lista de ferramentas",
+ "current": "Nível: {{name}}. Se você mudar uma chave abaixo, vira uma combinação própria.",
+ "custom": "Combinação própria de chaves. Escolha um nível para substituí-la.",
+ "applied": "Nível {{name}} aplicado",
+ "appliedBody": "As chaves abaixo mudaram. Nada é salvo até você salvar.",
+ "readonly": {
+ "title": "Só consulta",
+ "body": "Pesquisa na web e nas suas coleções. Sem arquivos, sem comandos, sem gatilhos."
+ },
+ "assistant": {
+ "title": "Assistente",
+ "body": "Adiciona agentes salvos, gatilhos e mudanças sugeridas. Sem arquivos, sem comandos."
+ },
+ "full": {
+ "title": "Completo",
+ "body": "Todas as ferramentas que o servidor lista. Os direitos sensíveis continuam desligados."
+ }
+ },
+ "tpl": {
+ "applied": "Iniciado a partir de {{name}}",
+ "appliedBody": "Nome, descrição, instruções e ferramentas mudaram. Nada é salvo até você salvar.",
+ "tools": "Ferramentas: {{level}}",
+ "noTools": "Ferramentas: como estão"
+ },
+ "undo": "Desfazer",
+ "keep": "Manter",
+ "modelCaps": "O que este modelo sabe fazer",
+ "modelChat": "Chat",
+ "connections": {
+ "addonsTitle": "Complementos que usam uma conexão",
+ "addonsNone": "Nenhum complemento precisa de uma conexão.",
+ "messagingTitle": "Onde este agente está conectado",
+ "messagingNone": "Nenhuma conexão de mensagens usa este agente ainda. Salve o agente e adicione uma.",
+ "messagingHelp": "As conexões de mensagens são definidas na página própria.",
+ "allows_one": "permite {{count}} direito",
+ "allows_other": "permite {{count}} direitos",
+ "open": "Abrir",
+ "addonOff": "desligado",
+ "noneYet": "Ainda não há conexão.",
+ "add": "Adicionar uma conexão",
+ "groupLabel": "Conexões para {{name}}",
+ "chosenHelp": "Os chats deste agente só podem usar as conexões marcadas.",
+ "perChat": "Nenhuma marcada: cada chat escolhe a sua.",
+ "summary_one": "{{count}} conexão",
+ "summary_other": "{{count}} conexões"
}
},
"run": {
@@ -538,5 +589,19 @@
"effectiveWrite": "Está dentro de uma pasta que pode ser alterada, então esta também pode ser alterada.",
"notMounted": "{{n}} pastas compartilhadas não cabem no limite de acesso de um chat e não são montadas.",
"exportNoteMany": "O arquivo cita {{n}} pastas. Onde você importar, o agente recebe as pastas com esses caminhos que existirem e pede que você escolha as outras."
+ },
+ "templates": {
+ "researcher": {
+ "description": "Pesquisa, lê fontes e escreve resumos curtos."
+ },
+ "reviewer": {
+ "description": "Revisa uma mudança e lista primeiro o que corrigir."
+ },
+ "digest": {
+ "description": "Reúne as novidades de um tema e as resume."
+ },
+ "blank": {
+ "description": "Vazio. Comece do zero."
+ }
}
}
diff --git a/core/http/react-ui/public/locales/zh-CN/agents.json b/core/http/react-ui/public/locales/zh-CN/agents.json
index 1e8aa280fe..c13ed91516 100644
--- a/core/http/react-ui/public/locales/zh-CN/agents.json
+++ b/core/http/react-ui/public/locales/zh-CN/agents.json
@@ -82,7 +82,8 @@
"export": "Export",
"Files": "文件",
"Tools": "工具",
- "Notes": "记忆"
+ "Notes": "记忆",
+ "Connections": "连接"
},
"name": "Name",
"description": "Description",
@@ -157,13 +158,15 @@
"identity": "身份",
"capabilities": "能力",
"memory": "记忆与知识",
- "advanced": "高级"
+ "advanced": "高级",
+ "connections": "连接"
},
"lead": {
"identity": "智能体是谁,以及它如何行事。",
"capabilities": "智能体可以使用和访问的内容。",
"memory": "智能体记住什么,以及可以查找什么。",
- "advanced": "额外的服务器和导出。"
+ "advanced": "额外的服务器和导出。",
+ "connections": "此代理可以使用哪些连接。"
},
"header": {
"unnamed": "未命名的智能体",
@@ -175,6 +178,54 @@
"clean": "没有未保存的更改",
"new": "尚未创建",
"unsaved": "未保存的更改({{count}})"
+ },
+ "preset": {
+ "label": "工具级别",
+ "loading": "正在加载工具列表",
+ "current": "级别:{{name}}。更改下方任一开关后,它就成为自定义组合。",
+ "custom": "自定义开关组合。选择一个级别可替换它。",
+ "applied": "已应用{{name}}级别",
+ "appliedBody": "下方的开关已更改。保存之前不会存储任何内容。",
+ "readonly": {
+ "title": "仅查看",
+ "body": "搜索网页和你的集合。没有文件、命令和触发器。"
+ },
+ "assistant": {
+ "title": "助手",
+ "body": "加入已保存的代理、触发器和建议的更改。没有文件和命令。"
+ },
+ "full": {
+ "title": "完整",
+ "body": "服务器列出的所有工具。敏感权限保持关闭。"
+ }
+ },
+ "tpl": {
+ "applied": "从{{name}}开始",
+ "appliedBody": "名称、描述、指令和工具已更改。保存之前不会存储任何内容。",
+ "tools": "工具:{{level}}",
+ "noTools": "工具:保持不变"
+ },
+ "undo": "撤销",
+ "keep": "保留",
+ "modelCaps": "此模型能做什么",
+ "modelChat": "聊天",
+ "connections": {
+ "addonsTitle": "使用连接的附加组件",
+ "addonsNone": "没有附加组件需要连接。",
+ "messagingTitle": "此代理连接到哪里",
+ "messagingNone": "还没有消息连接使用此代理。请先保存代理,再添加连接。",
+ "messagingHelp": "消息连接在各自的页面中设置。",
+ "allows_one": "允许 {{count}} 项权限",
+ "allows_other": "允许 {{count}} 项权限",
+ "open": "打开",
+ "addonOff": "已关闭",
+ "noneYet": "还没有连接。",
+ "add": "添加连接",
+ "groupLabel": "{{name}}的连接",
+ "chosenHelp": "此代理的聊天只能使用已勾选的连接。",
+ "perChat": "未勾选:每个聊天自行选择。",
+ "summary_one": "{{count}} 个连接",
+ "summary_other": "{{count}} 个连接"
}
},
"run": {
@@ -538,5 +589,19 @@
"effectiveWrite": "位于可修改的文件夹内,因此这个文件夹也可以修改。",
"notMounted": "有 {{n}} 个共享文件夹超出了聊天的访问上限,未挂载。",
"exportNoteMany": "文件列出了 {{n}} 个文件夹。导入时,智能体会使用这些路径中存在的文件夹,并请你为其余的重新选择。"
+ },
+ "templates": {
+ "researcher": {
+ "description": "搜索、阅读来源并撰写简短摘要。"
+ },
+ "reviewer": {
+ "description": "审阅一项更改,并先列出需要修复的内容。"
+ },
+ "digest": {
+ "description": "收集某个主题的新内容并加以总结。"
+ },
+ "blank": {
+ "description": "空白。从头开始。"
+ }
}
}
diff --git a/core/http/react-ui/src/components/ModelPicker.jsx b/core/http/react-ui/src/components/ModelPicker.jsx
index 00d63b043d..7b0338b562 100644
--- a/core/http/react-ui/src/components/ModelPicker.jsx
+++ b/core/http/react-ui/src/components/ModelPicker.jsx
@@ -27,6 +27,7 @@ const FILTER_FROM = 8
// models, loading the list is already held by the caller, so no second fetch
// grouped, loadedIds, showWarm, describe, onOpen, footer, labels
// defaultChoice, defaultSelected, onChooseDefault a first row for "use the default"
+// describe(name, warm) -> { size, vision, caps: [label], fit } a richer row; caps are small tags
const ModelPicker = forwardRef(function ModelPicker(
{
value, onChange, capability, loadedIds, disabled = false, placeholder,
@@ -291,10 +292,11 @@ const ModelPicker = forwardRef(function ModelPicker(
{name === null ? defaultChoice : name}
{badges(name)}
- {(info.size || info.vision) && (
+ {(info.size || info.vision || info.caps?.length > 0) && (
{info.size && {info.size}}
{info.vision &&
{t('create.connections.addonsNone')}
+ : ( +{t('create.connections.messagingNone')}
+ : ( +{t('create.connections.messagingHelp')}
++ {t('create.connections.noneYet')}{' '} + {t('create.connections.add')} +
+ ) : ( +{t('create.preset.label')}
++ {ready ? (active ? t('create.preset.current', { name: t(`create.preset.${active}.title`) }) : t('create.preset.custom')) : t('create.preset.loading')} +
+{t('create.modelCaps')}
+{t('create.modelHelp')}
) @@ -383,9 +464,13 @@ export default function AgentCreate() { > ) + case 'Connections': + return{t('create.toolsHelp')}
{memoryUser.settings && memoryUser.settings.enabled === false && (