mirror of
https://github.com/tiennm99/DocsGPT.git
synced 2026-10-11 03:12:55 +00:00
19 files changed
+237
-168
No files matched your search
@@ -86,7 +86,7 @@ export default function AgentCard({
|
||||
template: [
|
||||
{
|
||||
icon: Duplicate,
|
||||
label: 'Duplicate',
|
||||
label: t('modals.prompts.duplicate'),
|
||||
onClick: (e: SyntheticEvent) => {
|
||||
e.stopPropagation();
|
||||
handleDuplicate();
|
||||
@@ -99,7 +99,7 @@ export default function AgentCard({
|
||||
user: [
|
||||
{
|
||||
icon: Monitoring,
|
||||
label: 'Logs',
|
||||
label: t('agents.form.buttons.logs'),
|
||||
onClick: (e: SyntheticEvent) => {
|
||||
e.stopPropagation();
|
||||
goToLevel(agentLogsPath(agent.id));
|
||||
@@ -110,7 +110,7 @@ export default function AgentCard({
|
||||
},
|
||||
{
|
||||
icon: Edit,
|
||||
label: 'Edit',
|
||||
label: t('agents.edit'),
|
||||
onClick: (e: SyntheticEvent) => {
|
||||
e.stopPropagation();
|
||||
if (agent.agent_type === 'workflow') {
|
||||
@@ -155,7 +155,9 @@ export default function AgentCard({
|
||||
? [
|
||||
{
|
||||
icon: agent.pinned ? UnPin : Pin,
|
||||
label: agent.pinned ? 'Unpin' : 'Pin agent',
|
||||
label: agent.pinned
|
||||
? t('agents.card.unpin')
|
||||
: t('agents.card.pin'),
|
||||
onClick: (e: SyntheticEvent) => {
|
||||
e.stopPropagation();
|
||||
togglePin();
|
||||
@@ -179,7 +181,7 @@ export default function AgentCard({
|
||||
},
|
||||
{
|
||||
icon: Trash,
|
||||
label: 'Delete',
|
||||
label: t('agents.form.buttons.delete'),
|
||||
onClick: (e: SyntheticEvent) => {
|
||||
e.stopPropagation();
|
||||
setDeleteConfirmation('ACTIVE');
|
||||
@@ -196,7 +198,7 @@ export default function AgentCard({
|
||||
team: [
|
||||
{
|
||||
icon: Edit,
|
||||
label: 'Edit',
|
||||
label: t('agents.edit'),
|
||||
onClick: (e: SyntheticEvent) => {
|
||||
e.stopPropagation();
|
||||
if (agent.agent_type === 'workflow') {
|
||||
@@ -213,7 +215,9 @@ export default function AgentCard({
|
||||
? [
|
||||
{
|
||||
icon: agent.pinned ? UnPin : Pin,
|
||||
label: agent.pinned ? 'Unpin' : 'Pin agent',
|
||||
label: agent.pinned
|
||||
? t('agents.card.unpin')
|
||||
: t('agents.card.pin'),
|
||||
onClick: (e: SyntheticEvent) => {
|
||||
e.stopPropagation();
|
||||
togglePin();
|
||||
@@ -228,7 +232,7 @@ export default function AgentCard({
|
||||
shared: [
|
||||
{
|
||||
icon: Link,
|
||||
label: 'Open',
|
||||
label: t('agents.card.open'),
|
||||
onClick: (e: SyntheticEvent) => {
|
||||
e.stopPropagation();
|
||||
navigate(sharedAgentPath(agent.shared_token));
|
||||
@@ -239,7 +243,7 @@ export default function AgentCard({
|
||||
},
|
||||
{
|
||||
icon: agent.pinned ? UnPin : Pin,
|
||||
label: agent.pinned ? 'Unpin' : 'Pin agent',
|
||||
label: agent.pinned ? t('agents.card.unpin') : t('agents.card.pin'),
|
||||
onClick: (e: SyntheticEvent) => {
|
||||
e.stopPropagation();
|
||||
togglePin();
|
||||
@@ -250,7 +254,7 @@ export default function AgentCard({
|
||||
},
|
||||
{
|
||||
icon: Trash,
|
||||
label: 'Remove',
|
||||
label: t('agents.card.remove'),
|
||||
onClick: (e: SyntheticEvent) => {
|
||||
e.stopPropagation();
|
||||
handleHideSharedAgent();
|
||||
@@ -464,7 +468,9 @@ export default function AgentCard({
|
||||
imgClassName="h-7 w-7 rounded-full object-contain"
|
||||
/>
|
||||
{agent.status === 'draft' && (
|
||||
<p className="text-foreground text-xs opacity-50">{`(Draft)`}</p>
|
||||
<p className="text-foreground text-xs opacity-50">
|
||||
({t('agents.card.draft')})
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="mt-2">
|
||||
@@ -480,15 +486,15 @@ export default function AgentCard({
|
||||
</div>
|
||||
</div>
|
||||
<ConfirmationModal
|
||||
message="Are you sure you want to delete this agent?"
|
||||
message={t('agents.deleteConfirmation')}
|
||||
modalState={deleteConfirmation}
|
||||
setModalState={setDeleteConfirmation}
|
||||
submitLabel="Delete"
|
||||
submitLabel={t('agents.form.buttons.delete')}
|
||||
handleSubmit={() => {
|
||||
handleDelete();
|
||||
setDeleteConfirmation('INACTIVE');
|
||||
}}
|
||||
cancelLabel="Cancel"
|
||||
cancelLabel={t('cancel')}
|
||||
variant="danger"
|
||||
/>
|
||||
<Modal
|
||||
|
||||
@@ -4,7 +4,6 @@ import { useSelector } from 'react-redux';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
import userService from '../api/services/userService';
|
||||
import Spinner from '../components/Spinner';
|
||||
import { selectToken } from '../preferences/preferenceSlice';
|
||||
import Analytics from '../settings/Analytics';
|
||||
import Logs from '../settings/Logs';
|
||||
@@ -59,25 +58,15 @@ export default function AgentLogs() {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{loadingAgent ? (
|
||||
<div className="flex h-[345px] w-full items-center justify-center">
|
||||
<Spinner />
|
||||
</div>
|
||||
) : (
|
||||
agent && <Analytics agentId={agent.id} />
|
||||
)}
|
||||
{!loadingAgent && agent && <GuardrailEvents agentId={agent.id} />}
|
||||
{loadingAgent ? (
|
||||
<div className="flex h-[55vh] w-full items-center justify-center">
|
||||
<Spinner />
|
||||
</div>
|
||||
) : (
|
||||
agent && (
|
||||
{agentId && (
|
||||
<>
|
||||
<Analytics agentId={agentId} />
|
||||
<GuardrailEvents agentId={agentId} />
|
||||
<Logs
|
||||
agentId={agent.id}
|
||||
agentId={agentId}
|
||||
tableHeader={t('agents.logs.tableHeader')}
|
||||
/>
|
||||
)
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -12,7 +12,7 @@ import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useNavigate, useSearchParams } from 'react-router-dom';
|
||||
|
||||
import userService from '../api/services/userService';
|
||||
import Spinner from '../components/Spinner';
|
||||
import SkeletonLoader from '../components/SkeletonLoader';
|
||||
import { Button } from '../components/ui/button';
|
||||
import { Input } from '../components/ui/input';
|
||||
import {
|
||||
@@ -565,8 +565,8 @@ function AgentSection({
|
||||
|
||||
<div className="flex flex-col gap-4">
|
||||
{isLoading ? (
|
||||
<div className="flex h-40 w-full items-center justify-center">
|
||||
<Spinner />
|
||||
<div className="grid grid-cols-2 gap-3 sm:flex sm:flex-wrap">
|
||||
<SkeletonLoader component="agentCards" count={4} />
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface SkeletonLoaderProps {
|
||||
count?: number;
|
||||
@@ -13,6 +14,7 @@ interface SkeletonLoaderProps {
|
||||
| 'sourceCards'
|
||||
| 'toolCards'
|
||||
| 'addToolCards'
|
||||
| 'agentCards'
|
||||
| 'connectedState'
|
||||
| 'filesSection';
|
||||
}
|
||||
@@ -21,6 +23,7 @@ const SkeletonLoader: React.FC<SkeletonLoaderProps> = ({
|
||||
count = 1,
|
||||
component = 'default',
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const [skeletonCount, setSkeletonCount] = useState(count);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -264,6 +267,26 @@ const SkeletonLoader: React.FC<SkeletonLoaderProps> = ({
|
||||
</>
|
||||
);
|
||||
|
||||
const renderAgentCards = () => (
|
||||
<>
|
||||
{Array.from({ length: count }).map((_, idx) => (
|
||||
<div
|
||||
key={`agent-skel-${idx}`}
|
||||
className="bg-muted flex h-44 animate-pulse flex-col rounded-2xl px-4 py-5 sm:w-48 sm:px-6"
|
||||
>
|
||||
<div className="px-1">
|
||||
<div className="bg-muted-foreground/20 h-7 w-7 rounded-full"></div>
|
||||
</div>
|
||||
<div className="mt-3 space-y-2 px-1">
|
||||
<div className="bg-muted-foreground/20 h-4 w-2/3 rounded"></div>
|
||||
<div className="bg-muted-foreground/20 h-3 w-full rounded"></div>
|
||||
<div className="bg-muted-foreground/20 h-3 w-4/5 rounded"></div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
|
||||
const renderToolCards = () => (
|
||||
<>
|
||||
{Array.from({ length: count }).map((_, idx) => (
|
||||
@@ -325,13 +348,24 @@ const SkeletonLoader: React.FC<SkeletonLoaderProps> = ({
|
||||
sourceCards: renderSourceCards,
|
||||
toolCards: renderToolCards,
|
||||
addToolCards: renderAddToolCards,
|
||||
agentCards: renderAgentCards,
|
||||
connectedState: renderConnectedState,
|
||||
filesSection: renderFilesSection,
|
||||
};
|
||||
|
||||
const render = componentMap[component] || componentMap.default;
|
||||
|
||||
return <>{render()}</>;
|
||||
// The Spinner this replaces carried role="status"; without it a screen
|
||||
// reader gets no signal at all while a section loads. Absolutely
|
||||
// positioned by `sr-only`, so it never becomes a flex/grid item.
|
||||
return (
|
||||
<>
|
||||
<span className="sr-only" role="status">
|
||||
{t('loading')}
|
||||
</span>
|
||||
{render()}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SkeletonLoader;
|
||||
@@ -168,7 +168,7 @@ export default function ConversationMessages({
|
||||
index,
|
||||
});
|
||||
}}
|
||||
aria-label={t('Retry') || 'Retry'}
|
||||
aria-label={t('conversation.retry')}
|
||||
>
|
||||
<Retry
|
||||
width={12}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"tagline": "DocsGPT verwendet GenAI, bitte überprüfe kritische Informationen anhand der Quellen.",
|
||||
"sourceDocs": "Quelle",
|
||||
"none": "Keine",
|
||||
"loading": "Wird geladen...",
|
||||
"cancel": "Abbrechen",
|
||||
"help": "Hilfe",
|
||||
"emailUs": "E-Mail senden",
|
||||
@@ -197,7 +198,8 @@
|
||||
"queryPlaceholder": "Frage etwas, das diese Quelle beantworten sollte...",
|
||||
"run": "Ausführen",
|
||||
"notSavedHint": "Diese Einstellungen gelten nur für diesen Test – sie werden nicht in der Quelle gespeichert. Ändere sie in den Quelleneinstellungen, um sie dauerhaft zu übernehmen.",
|
||||
"resultSummary": "{{total}} Chunks abgerufen · {{retriever}}",
|
||||
"resultSummary_one": "{{count}} Chunk abgerufen · {{retriever}}",
|
||||
"resultSummary_other": "{{count}} Chunks abgerufen · {{retriever}}",
|
||||
"latency": "{{ms}} ms",
|
||||
"empty": "Keine Chunks für diese Anfrage abgerufen.",
|
||||
"emptyWithThreshold": "Keine Chunks haben den Score-Schwellenwert ({{threshold}}) erreicht. Senke ihn, um knappe Treffer zu sehen.",
|
||||
@@ -587,6 +589,8 @@
|
||||
"serverName": "Servername",
|
||||
"serverUrl": "Server-URL",
|
||||
"headerName": "Header-Name",
|
||||
"username": "Benutzername",
|
||||
"password": "Passwort",
|
||||
"timeout": "Timeout (Sekunden)",
|
||||
"testConnection": "Verbindung testen",
|
||||
"testing": "Teste...",
|
||||
@@ -1135,7 +1139,8 @@
|
||||
"parseError": "Spezifikation konnte nicht geparst werden. Bitte Dateiformat prüfen.",
|
||||
"version": "Version",
|
||||
"baseUrl": "Basis-URL",
|
||||
"actionsFound": "{{count}} Aktionen gefunden",
|
||||
"actionsFound_one": "{{count}} Aktion gefunden",
|
||||
"actionsFound_other": "{{count}} Aktionen gefunden",
|
||||
"selectAll": "Alle auswählen",
|
||||
"deselectAll": "Alle abwählen",
|
||||
"cancel": "Abbrechen",
|
||||
@@ -1209,7 +1214,8 @@
|
||||
"title": "Quellen",
|
||||
"text": "Wähle deine Quellen",
|
||||
"link": "Quellen-Link",
|
||||
"view_more": "{{count}} weitere Quellen",
|
||||
"view_more_one": "{{count}} weitere Quelle",
|
||||
"view_more_other": "{{count}} weitere Quellen",
|
||||
"noSourcesAvailable": "Keine Quellen verfügbar",
|
||||
"selectedCount": "{{count}} Quellen ausgewählt",
|
||||
"groupOwn": "Deine Quellen",
|
||||
@@ -1277,6 +1283,13 @@
|
||||
"agents": {
|
||||
"title": "Agenten",
|
||||
"edit": "Bearbeiten",
|
||||
"card": {
|
||||
"pin": "Agent anheften",
|
||||
"unpin": "Agent lösen",
|
||||
"open": "Öffnen",
|
||||
"remove": "Entfernen",
|
||||
"draft": "Entwurf"
|
||||
},
|
||||
"description": "Entdecke und erstelle benutzerdefinierte Versionen von DocsGPT, die Anweisungen, zusätzliches Wissen und beliebige Kombinationen von Fähigkeiten kombinieren",
|
||||
"newAgent": "Neuer Agent",
|
||||
"importAgent": "Import",
|
||||
@@ -1457,7 +1470,8 @@
|
||||
"confidence": "Confidence threshold",
|
||||
"confidenceHint": "The judge must both flag the content and be at least this confident (default: 0.7)",
|
||||
"activeCount": "{{count}} active",
|
||||
"needsSetup": "{{count}} need setup",
|
||||
"needsSetup_one": "{{count}} benötigt Einrichtung",
|
||||
"needsSetup_other": "{{count}} benötigen Einrichtung",
|
||||
"setupRequired": "Fill in this check's settings before saving.",
|
||||
"pickAtLeastOne": "Pick at least one — the check cannot run with none selected.",
|
||||
"remove": "Remove",
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"tagline": "DocsGPT uses GenAI, please review critical information using sources.",
|
||||
"sourceDocs": "Source",
|
||||
"none": "None",
|
||||
"loading": "Loading...",
|
||||
"cancel": "Cancel",
|
||||
"errorBoundary": {
|
||||
"message": "Something went wrong displaying this content.",
|
||||
@@ -25,7 +26,7 @@
|
||||
"memberAddedBody": "You were added to {{team}} as {{role}}",
|
||||
"sharedTitle": "Shared with you",
|
||||
"sharedBody": "{{type}} shared with your team: {{name}} ({{access}})",
|
||||
"sharedBodyNoName": "A {{type}} was shared with your team ({{access}})",
|
||||
"sharedBodyNoName": "{{type}} shared with your team ({{access}})",
|
||||
"dismiss": "Dismiss"
|
||||
},
|
||||
"demo": [
|
||||
@@ -201,7 +202,8 @@
|
||||
"queryPlaceholder": "Ask something this source should answer...",
|
||||
"run": "Run",
|
||||
"notSavedHint": "These settings are only used for this test — they are not saved to the source. Change them in Source settings to make them permanent.",
|
||||
"resultSummary": "{{total}} chunks retrieved · {{retriever}}",
|
||||
"resultSummary_one": "{{count}} chunk retrieved · {{retriever}}",
|
||||
"resultSummary_other": "{{count}} chunks retrieved · {{retriever}}",
|
||||
"latency": "{{ms}} ms",
|
||||
"empty": "No chunks retrieved for this query.",
|
||||
"emptyWithThreshold": "No chunks scored at or above the score threshold ({{threshold}}). Lower it to see near misses.",
|
||||
@@ -545,7 +547,7 @@
|
||||
"needsAuth": "Needs Auth",
|
||||
"configured": "Configured"
|
||||
},
|
||||
"deleteWarning": "Are you sure you want to delete the tool \"{{toolName}}\" ?",
|
||||
"deleteWarning": "Are you sure you want to delete the tool \"{{toolName}}\"?",
|
||||
"unsavedChanges": "You have unsaved changes that will be lost if you leave without saving.",
|
||||
"leaveWithoutSaving": "Leave without Saving",
|
||||
"saveAndLeave": "Save and Leave",
|
||||
@@ -592,6 +594,8 @@
|
||||
"serverName": "Server Name",
|
||||
"serverUrl": "Server URL",
|
||||
"headerName": "Header Name",
|
||||
"username": "Username",
|
||||
"password": "Password",
|
||||
"timeout": "Timeout (seconds)",
|
||||
"testConnection": "Test Connection",
|
||||
"testing": "Testing",
|
||||
@@ -920,7 +924,7 @@
|
||||
"preparing": "Preparing upload",
|
||||
"parsing": "Parsing files…",
|
||||
"embedding": "Embedding…",
|
||||
"tokenLimit": "Over the token limit, please consider uploading smaller document",
|
||||
"tokenLimit": "Over the token limit, please consider uploading a smaller document",
|
||||
"expandDetails": "Expand upload details",
|
||||
"collapseDetails": "Collapse upload details",
|
||||
"dismiss": "Dismiss upload toast",
|
||||
@@ -1140,7 +1144,8 @@
|
||||
"parseError": "Failed to parse the specification. Please check the file format.",
|
||||
"version": "Version",
|
||||
"baseUrl": "Base URL",
|
||||
"actionsFound": "{{count}} actions found",
|
||||
"actionsFound_one": "{{count}} action found",
|
||||
"actionsFound_other": "{{count}} actions found",
|
||||
"selectAll": "Select all",
|
||||
"deselectAll": "Deselect all",
|
||||
"cancel": "Cancel",
|
||||
@@ -1214,7 +1219,8 @@
|
||||
"title": "Sources",
|
||||
"text": "Choose Your Sources",
|
||||
"link": "Source link",
|
||||
"view_more": "{{count}} more sources",
|
||||
"view_more_one": "{{count}} more source",
|
||||
"view_more_other": "{{count}} more sources",
|
||||
"noSourcesAvailable": "No sources available",
|
||||
"selectedCount": "{{count}} sources selected",
|
||||
"groupOwn": "Your sources",
|
||||
@@ -1288,6 +1294,13 @@
|
||||
"agents": {
|
||||
"title": "Agents",
|
||||
"edit": "Edit",
|
||||
"card": {
|
||||
"pin": "Pin agent",
|
||||
"unpin": "Unpin agent",
|
||||
"open": "Open",
|
||||
"remove": "Remove",
|
||||
"draft": "Draft"
|
||||
},
|
||||
"description": "Discover and create custom versions of DocsGPT that combine instructions, extra knowledge, and any combination of skills",
|
||||
"newAgent": "New Agent",
|
||||
"importAgent": "Import",
|
||||
@@ -1468,7 +1481,8 @@
|
||||
"confidence": "Confidence threshold",
|
||||
"confidenceHint": "The judge must both flag the content and be at least this confident (default: 0.7)",
|
||||
"activeCount": "{{count}} active",
|
||||
"needsSetup": "{{count}} need setup",
|
||||
"needsSetup_one": "{{count}} needs setup",
|
||||
"needsSetup_other": "{{count}} need setup",
|
||||
"setupRequired": "Fill in this check's settings before saving.",
|
||||
"pickAtLeastOne": "Pick at least one — the check cannot run with none selected.",
|
||||
"remove": "Remove",
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"tagline": "DocsGPT utiliza GenAI, por favor revisa información crítica utilizando fuentes.",
|
||||
"sourceDocs": "Fuente",
|
||||
"none": "Ninguno",
|
||||
"loading": "Cargando...",
|
||||
"cancel": "Cancelar",
|
||||
"help": "Asistencia",
|
||||
"emailUs": "Envíanos un correo",
|
||||
@@ -20,8 +21,8 @@
|
||||
"memberAddedTitle": "Añadido a un equipo",
|
||||
"memberAddedBody": "Te añadieron a {{team}} como {{role}}",
|
||||
"sharedTitle": "Compartido contigo",
|
||||
"sharedBody": "{{type}} compartido con tu equipo: {{name}} ({{access}})",
|
||||
"sharedBodyNoName": "Se compartió un {{type}} con tu equipo ({{access}})",
|
||||
"sharedBody": "Se compartió con tu equipo: {{type}} «{{name}}» ({{access}})",
|
||||
"sharedBodyNoName": "Se compartió con tu equipo: {{type}} ({{access}})",
|
||||
"dismiss": "Descartar"
|
||||
},
|
||||
"demo": [
|
||||
@@ -197,7 +198,8 @@
|
||||
"queryPlaceholder": "Pregunta algo que esta fuente debería responder...",
|
||||
"run": "Ejecutar",
|
||||
"notSavedHint": "Estos ajustes solo se usan para esta prueba — no se guardan en la fuente. Cámbialos en Configuración de la fuente para hacerlos permanentes.",
|
||||
"resultSummary": "{{total}} fragmentos recuperados · {{retriever}}",
|
||||
"resultSummary_one": "{{count}} fragmento recuperado · {{retriever}}",
|
||||
"resultSummary_other": "{{count}} fragmentos recuperados · {{retriever}}",
|
||||
"latency": "{{ms}} ms",
|
||||
"empty": "No se recuperaron fragmentos para esta consulta.",
|
||||
"emptyWithThreshold": "Ningún fragmento alcanzó el umbral de puntuación ({{threshold}}). Bájalo para ver los que estuvieron cerca.",
|
||||
@@ -587,6 +589,8 @@
|
||||
"serverName": "Server Name",
|
||||
"serverUrl": "Server URL",
|
||||
"headerName": "Header Name",
|
||||
"username": "Nombre de usuario",
|
||||
"password": "Contraseña",
|
||||
"timeout": "Timeout (seconds)",
|
||||
"testConnection": "Test Connection",
|
||||
"testing": "Testing",
|
||||
@@ -1135,7 +1139,8 @@
|
||||
"parseError": "No se pudo analizar la especificación. Verifica el formato del archivo.",
|
||||
"version": "Versión",
|
||||
"baseUrl": "URL base",
|
||||
"actionsFound": "{{count}} acciones encontradas",
|
||||
"actionsFound_one": "{{count}} acción encontrada",
|
||||
"actionsFound_other": "{{count}} acciones encontradas",
|
||||
"selectAll": "Seleccionar todo",
|
||||
"deselectAll": "Deseleccionar todo",
|
||||
"cancel": "Cancelar",
|
||||
@@ -1209,7 +1214,8 @@
|
||||
"title": "Fuentes",
|
||||
"text": "Elegir tus fuentes",
|
||||
"link": "Enlace fuente",
|
||||
"view_more": "Ver {{count}} más fuentes",
|
||||
"view_more_one": "Ver {{count}} fuente más",
|
||||
"view_more_other": "Ver {{count}} fuentes más",
|
||||
"noSourcesAvailable": "No hay fuentes disponibles",
|
||||
"selectedCount": "{{count}} fuentes seleccionadas",
|
||||
"groupOwn": "Tus fuentes",
|
||||
@@ -1277,6 +1283,13 @@
|
||||
"agents": {
|
||||
"title": "Agentes",
|
||||
"edit": "Editar",
|
||||
"card": {
|
||||
"pin": "Fijar agente",
|
||||
"unpin": "Dejar de fijar agente",
|
||||
"open": "Abrir",
|
||||
"remove": "Quitar",
|
||||
"draft": "Borrador"
|
||||
},
|
||||
"description": "Descubre y crea versiones personalizadas de DocsGPT que combinan instrucciones, conocimiento adicional y cualquier combinación de habilidades",
|
||||
"newAgent": "Nuevo Agente",
|
||||
"importAgent": "Import",
|
||||
@@ -1457,7 +1470,8 @@
|
||||
"confidence": "Confidence threshold",
|
||||
"confidenceHint": "The judge must both flag the content and be at least this confident (default: 0.7)",
|
||||
"activeCount": "{{count}} active",
|
||||
"needsSetup": "{{count}} need setup",
|
||||
"needsSetup_one": "{{count}} necesita configuración",
|
||||
"needsSetup_other": "{{count}} necesitan configuración",
|
||||
"setupRequired": "Fill in this check's settings before saving.",
|
||||
"pickAtLeastOne": "Pick at least one — the check cannot run with none selected.",
|
||||
"remove": "Remove",
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"tagline": "DocsGPTはGenAIを使用しています。重要な情報はソースで確認してください。",
|
||||
"sourceDocs": "ソース",
|
||||
"none": "なし",
|
||||
"loading": "読み込み中...",
|
||||
"cancel": "キャンセル",
|
||||
"help": "ヘルプ",
|
||||
"emailUs": "メールを送る",
|
||||
@@ -197,7 +198,7 @@
|
||||
"queryPlaceholder": "このソースが回答できそうな質問を入力...",
|
||||
"run": "実行",
|
||||
"notSavedHint": "これらの設定はこのテストにのみ使用され、ソースには保存されません。恒久的に変更するにはソース設定で変更してください。",
|
||||
"resultSummary": "{{total}}件のチャンクを取得 · {{retriever}}",
|
||||
"resultSummary": "{{count}}件のチャンクを取得 · {{retriever}}",
|
||||
"latency": "{{ms}} ms",
|
||||
"empty": "このクエリで取得されたチャンクはありません。",
|
||||
"emptyWithThreshold": "スコアしきい値({{threshold}})以上のチャンクがありません。しきい値を下げると、惜しい候補を確認できます。",
|
||||
@@ -587,6 +588,8 @@
|
||||
"serverName": "Server Name",
|
||||
"serverUrl": "Server URL",
|
||||
"headerName": "Header Name",
|
||||
"username": "ユーザー名",
|
||||
"password": "パスワード",
|
||||
"timeout": "Timeout (seconds)",
|
||||
"testConnection": "Test Connection",
|
||||
"testing": "Testing",
|
||||
@@ -1277,6 +1280,13 @@
|
||||
"agents": {
|
||||
"title": "エージェント",
|
||||
"edit": "編集",
|
||||
"card": {
|
||||
"pin": "エージェントをピン留め",
|
||||
"unpin": "エージェントのピン留めを解除",
|
||||
"open": "開く",
|
||||
"remove": "削除",
|
||||
"draft": "下書き"
|
||||
},
|
||||
"description": "指示、追加知識、スキルの組み合わせを含むDocsGPTのカスタムバージョンを発見して作成します",
|
||||
"newAgent": "新しいエージェント",
|
||||
"importAgent": "Import",
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"tagline": "DocsGPT использует GenAI, пожалуйста, проверьте важную информацию, используя источники.",
|
||||
"sourceDocs": "Источник",
|
||||
"none": "Нет",
|
||||
"loading": "Загрузка...",
|
||||
"cancel": "Отмена",
|
||||
"help": "Помощь",
|
||||
"emailUs": "Напишите нам",
|
||||
@@ -137,8 +138,12 @@
|
||||
"confirm": "Преобразовать в вики",
|
||||
"inProgress": "Преобразование файлов в страницы вики…",
|
||||
"summaryPages_one": "Создана {{count}} страница",
|
||||
"summaryPages_few": "Создано страниц: {{count}}",
|
||||
"summaryPages_many": "Создано страниц: {{count}}",
|
||||
"summaryPages_other": "Создано страниц: {{count}}",
|
||||
"summarySkipped_one": "Пропущен {{count}} файл",
|
||||
"summarySkipped_few": "Пропущено файлов: {{count}}",
|
||||
"summarySkipped_many": "Пропущено файлов: {{count}}",
|
||||
"summarySkipped_other": "Пропущено файлов: {{count}}",
|
||||
"skippedHeading": "Пропущенные файлы",
|
||||
"done": "Готово",
|
||||
@@ -165,10 +170,16 @@
|
||||
"inProgress": "Построение графа…",
|
||||
"inProgressPct": "Построение графа… {{pct}}%",
|
||||
"summaryNodes_one": "{{count}} сущность",
|
||||
"summaryNodes_few": "Сущностей: {{count}}",
|
||||
"summaryNodes_many": "Сущностей: {{count}}",
|
||||
"summaryNodes_other": "Сущностей: {{count}}",
|
||||
"summaryEdges_one": "{{count}} связь",
|
||||
"summaryEdges_few": "Связей: {{count}}",
|
||||
"summaryEdges_many": "Связей: {{count}}",
|
||||
"summaryEdges_other": "Связей: {{count}}",
|
||||
"summaryChunks_one": "Обработан {{count}} фрагмент",
|
||||
"summaryChunks_few": "Обработано фрагментов: {{count}}",
|
||||
"summaryChunks_many": "Обработано фрагментов: {{count}}",
|
||||
"summaryChunks_other": "Обработано фрагментов: {{count}}",
|
||||
"done": "Готово",
|
||||
"errors": {
|
||||
@@ -197,7 +208,10 @@
|
||||
"queryPlaceholder": "Спросите что-нибудь, на что этот источник должен ответить...",
|
||||
"run": "Запустить",
|
||||
"notSavedHint": "Эти настройки используются только для этого теста — они не сохраняются в источнике. Чтобы сделать их постоянными, измените их в настройках источника.",
|
||||
"resultSummary": "Извлечено фрагментов: {{total}} · {{retriever}}",
|
||||
"resultSummary_one": "Извлечён {{count}} фрагмент · {{retriever}}",
|
||||
"resultSummary_few": "Извлечено {{count}} фрагмента · {{retriever}}",
|
||||
"resultSummary_many": "Извлечено фрагментов: {{count}} · {{retriever}}",
|
||||
"resultSummary_other": "Извлечено фрагментов: {{count}} · {{retriever}}",
|
||||
"latency": "{{ms}} мс",
|
||||
"empty": "По этому запросу фрагменты не извлечены.",
|
||||
"emptyWithThreshold": "Ни один фрагмент не набрал оценку не ниже порога ({{threshold}}). Понизьте порог, чтобы увидеть близкие результаты.",
|
||||
@@ -587,6 +601,8 @@
|
||||
"serverName": "Server Name",
|
||||
"serverUrl": "Server URL",
|
||||
"headerName": "Header Name",
|
||||
"username": "Имя пользователя",
|
||||
"password": "Пароль",
|
||||
"timeout": "Timeout (seconds)",
|
||||
"testConnection": "Test Connection",
|
||||
"testing": "Testing",
|
||||
@@ -1155,7 +1171,10 @@
|
||||
"parseError": "Не удалось разобрать спецификацию. Проверьте формат файла.",
|
||||
"version": "Версия",
|
||||
"baseUrl": "Базовый URL",
|
||||
"actionsFound": "{{count}} действий найдено",
|
||||
"actionsFound_one": "найдено {{count}} действие",
|
||||
"actionsFound_few": "найдено {{count}} действия",
|
||||
"actionsFound_many": "найдено {{count}} действий",
|
||||
"actionsFound_other": "найдено {{count}} действий",
|
||||
"selectAll": "Выбрать все",
|
||||
"deselectAll": "Снять выделение со всех",
|
||||
"cancel": "Отмена",
|
||||
@@ -1229,7 +1248,10 @@
|
||||
"title": "Источники",
|
||||
"text": "Выберите ваши источники",
|
||||
"link": "Ссылка на источник",
|
||||
"view_more": "ещё {{count}} источников",
|
||||
"view_more_one": "ещё {{count}} источник",
|
||||
"view_more_few": "ещё {{count}} источника",
|
||||
"view_more_many": "ещё {{count}} источников",
|
||||
"view_more_other": "ещё {{count}} источников",
|
||||
"noSourcesAvailable": "Нет доступных источников",
|
||||
"selectedCount": "Выбрано источников: {{count}}",
|
||||
"groupOwn": "Ваши источники",
|
||||
@@ -1297,6 +1319,13 @@
|
||||
"agents": {
|
||||
"title": "Агенты",
|
||||
"edit": "Редактировать",
|
||||
"card": {
|
||||
"pin": "Закрепить агента",
|
||||
"unpin": "Открепить агента",
|
||||
"open": "Открыть",
|
||||
"remove": "Удалить",
|
||||
"draft": "Черновик"
|
||||
},
|
||||
"description": "Откройте и создайте пользовательские версии DocsGPT, которые объединяют инструкции, дополнительные знания и любую комбинацию навыков",
|
||||
"newAgent": "Новый Агент",
|
||||
"importAgent": "Import",
|
||||
@@ -1477,7 +1506,10 @@
|
||||
"confidence": "Confidence threshold",
|
||||
"confidenceHint": "The judge must both flag the content and be at least this confident (default: 0.7)",
|
||||
"activeCount": "{{count}} active",
|
||||
"needsSetup": "{{count}} need setup",
|
||||
"needsSetup_one": "{{count}} требует настройки",
|
||||
"needsSetup_few": "{{count}} требуют настройки",
|
||||
"needsSetup_many": "{{count}} требуют настройки",
|
||||
"needsSetup_other": "{{count}} требуют настройки",
|
||||
"setupRequired": "Fill in this check's settings before saving.",
|
||||
"pickAtLeastOne": "Pick at least one — the check cannot run with none selected.",
|
||||
"remove": "Remove",
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"tagline": "DocsGPT 使用生成式 AI,請使用原始資料來源審閱重要資訊。",
|
||||
"sourceDocs": "原始文件",
|
||||
"none": "無",
|
||||
"loading": "載入中...",
|
||||
"cancel": "取消",
|
||||
"help": "幫助",
|
||||
"emailUs": "給我們發電郵",
|
||||
@@ -197,7 +198,7 @@
|
||||
"queryPlaceholder": "輸入此來源應能回答的問題...",
|
||||
"run": "執行",
|
||||
"notSavedHint": "這些設定僅用於此次測試,不會儲存到來源。若要永久生效,請至來源設定中修改。",
|
||||
"resultSummary": "檢索到 {{total}} 個區塊 · {{retriever}}",
|
||||
"resultSummary": "檢索到 {{count}} 個區塊 · {{retriever}}",
|
||||
"latency": "{{ms}} ms",
|
||||
"empty": "此查詢未檢索到任何區塊。",
|
||||
"emptyWithThreshold": "沒有區塊的分數達到分數門檻({{threshold}})。調低門檻可查看接近的結果。",
|
||||
@@ -587,6 +588,8 @@
|
||||
"serverName": "Server Name",
|
||||
"serverUrl": "Server URL",
|
||||
"headerName": "Header Name",
|
||||
"username": "使用者名稱",
|
||||
"password": "密碼",
|
||||
"timeout": "Timeout (seconds)",
|
||||
"testConnection": "Test Connection",
|
||||
"testing": "Testing",
|
||||
@@ -1277,6 +1280,13 @@
|
||||
"agents": {
|
||||
"title": "代理",
|
||||
"edit": "編輯",
|
||||
"card": {
|
||||
"pin": "釘選代理",
|
||||
"unpin": "取消釘選代理",
|
||||
"open": "開啟",
|
||||
"remove": "移除",
|
||||
"draft": "草稿"
|
||||
},
|
||||
"description": "探索並創建結合指令、額外知識和任意技能組合的DocsGPT自訂版本",
|
||||
"newAgent": "新建代理",
|
||||
"importAgent": "Import",
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"tagline": "DocsGPT 使用 GenAI, 请使用来源审核关键信息.",
|
||||
"sourceDocs": "源",
|
||||
"none": "无",
|
||||
"loading": "加载中...",
|
||||
"cancel": "取消",
|
||||
"help": "帮助",
|
||||
"emailUs": "给我们发邮件",
|
||||
@@ -197,7 +198,7 @@
|
||||
"queryPlaceholder": "输入一个此来源应能回答的问题...",
|
||||
"run": "运行",
|
||||
"notSavedHint": "这些设置仅用于本次测试,不会保存到来源。如需永久生效,请在来源设置中修改。",
|
||||
"resultSummary": "检索到 {{total}} 个文本块 · {{retriever}}",
|
||||
"resultSummary": "检索到 {{count}} 个文本块 · {{retriever}}",
|
||||
"latency": "{{ms}} 毫秒",
|
||||
"empty": "此查询未检索到任何文本块。",
|
||||
"emptyWithThreshold": "没有文本块的得分达到分数阈值({{threshold}})。降低阈值可查看接近的结果。",
|
||||
@@ -587,6 +588,8 @@
|
||||
"serverName": "Server Name",
|
||||
"serverUrl": "Server URL",
|
||||
"headerName": "Header Name",
|
||||
"username": "用户名",
|
||||
"password": "密码",
|
||||
"timeout": "Timeout (seconds)",
|
||||
"testConnection": "Test Connection",
|
||||
"testing": "Testing",
|
||||
@@ -1277,6 +1280,13 @@
|
||||
"agents": {
|
||||
"title": "代理",
|
||||
"edit": "编辑",
|
||||
"card": {
|
||||
"pin": "固定代理",
|
||||
"unpin": "取消固定代理",
|
||||
"open": "打开",
|
||||
"remove": "移除",
|
||||
"draft": "草稿"
|
||||
},
|
||||
"description": "发现并创建结合指令、额外知识和任意技能组合的DocsGPT自定义版本",
|
||||
"newAgent": "新建代理",
|
||||
"importAgent": "Import",
|
||||
|
||||
@@ -455,7 +455,7 @@ export default function MCPServerModal({
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<Label htmlFor="api_key">
|
||||
{t('settings.tools.mcp.placeholders.apiKey')}
|
||||
{t('settings.tools.mcp.authTypes.apiKey')}
|
||||
<span className="text-red-500">*</span>
|
||||
</Label>
|
||||
<Input
|
||||
@@ -492,7 +492,7 @@ export default function MCPServerModal({
|
||||
return (
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<Label htmlFor="bearer_token">
|
||||
{t('settings.tools.mcp.placeholders.bearerToken')}
|
||||
{t('settings.tools.mcp.authTypes.bearer')}
|
||||
<span className="text-red-500">*</span>
|
||||
</Label>
|
||||
<Input
|
||||
@@ -524,7 +524,7 @@ export default function MCPServerModal({
|
||||
type="text"
|
||||
value={formData.username}
|
||||
onChange={(e) => handleInputChange('username', e.target.value)}
|
||||
placeholder={t('settings.tools.mcp.username')}
|
||||
placeholder={t('settings.tools.mcp.placeholders.username')}
|
||||
aria-invalid={!!errors.username || undefined}
|
||||
className="rounded-xl"
|
||||
/>
|
||||
@@ -542,7 +542,7 @@ export default function MCPServerModal({
|
||||
type="password"
|
||||
value={formData.password}
|
||||
onChange={(e) => handleInputChange('password', e.target.value)}
|
||||
placeholder={t('settings.tools.mcp.password')}
|
||||
placeholder={t('settings.tools.mcp.placeholders.password')}
|
||||
aria-invalid={!!errors.password || undefined}
|
||||
className="rounded-xl"
|
||||
/>
|
||||
@@ -556,8 +556,7 @@ export default function MCPServerModal({
|
||||
return (
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<Label htmlFor="oauth_scopes">
|
||||
{t('settings.tools.mcp.placeholders.oauthScopes') ||
|
||||
'Scopes (comma separated)'}
|
||||
{t('settings.tools.mcp.placeholders.oauthScopes')}
|
||||
</Label>
|
||||
<Input
|
||||
id="oauth_scopes"
|
||||
|
||||
@@ -193,7 +193,7 @@ export default function MoveToFolderModal({
|
||||
{isLoading ? (
|
||||
<div className="flex h-[200px] items-center justify-center">
|
||||
<span className="text-muted-foreground text-sm">
|
||||
{t('loading')}...
|
||||
{t('modals.searchConversations.loading')}
|
||||
</span>
|
||||
</div>
|
||||
) : (
|
||||
|
||||
@@ -387,7 +387,7 @@ function AddPrompt({
|
||||
|
||||
<VariableMenu
|
||||
options={toolVariables}
|
||||
label="Tool Variables"
|
||||
label={t('modals.prompts.toolVariables')}
|
||||
textareaId="new-prompt-content"
|
||||
content={newPromptContent}
|
||||
setContent={setNewPromptContent}
|
||||
@@ -537,7 +537,7 @@ function EditPrompt({
|
||||
|
||||
<VariableMenu
|
||||
options={toolVariables}
|
||||
label="Tool Variables"
|
||||
label={t('modals.prompts.toolVariables')}
|
||||
textareaId="edit-prompt-content"
|
||||
content={editPromptContent}
|
||||
setContent={setEditPromptContent}
|
||||
|
||||
@@ -339,9 +339,14 @@ export default function Prompts({
|
||||
)}
|
||||
>
|
||||
<Command>
|
||||
<CommandInput placeholder="Search..." className="h-9" />
|
||||
<CommandInput
|
||||
placeholder={t('settings.sources.searchPlaceholder')}
|
||||
className="h-9"
|
||||
/>
|
||||
<CommandList>
|
||||
<CommandEmpty>No results found</CommandEmpty>
|
||||
<CommandEmpty>
|
||||
{t('settings.sources.noResults')}
|
||||
</CommandEmpty>
|
||||
{prompts.map((prompt) => {
|
||||
const isActive = selectedPrompt?.id === prompt.id;
|
||||
const canModify = prompt.type !== 'public';
|
||||
|
||||
@@ -246,7 +246,7 @@ export default function TestRetrievalModal({
|
||||
<div className="text-muted-foreground flex flex-row items-center justify-between text-xs">
|
||||
<span>
|
||||
{tr('resultSummary', {
|
||||
total: result.total,
|
||||
count: result.total,
|
||||
retriever: result.retriever,
|
||||
})}
|
||||
</span>
|
||||
|
||||
@@ -67,6 +67,16 @@ EXPECTED_IDS = {
|
||||
"huggingface": {"huggingface-local"},
|
||||
}
|
||||
|
||||
# Providers whose catalog is an open extension point. ``openai_compatible``
|
||||
# is the zero-Python way to add an OpenAI-shaped endpoint — copy
|
||||
# ``examples/mistral.yaml.example`` next to the built-ins and it loads — so
|
||||
# a fork or a deployment can legitimately have catalogs here that upstream
|
||||
# does not. For these the snapshot is a floor, not an exact set: the
|
||||
# built-in ids must all still be present, but extra ones are somebody's
|
||||
# own provider rather than a regression. A rename, which is what this
|
||||
# snapshot exists to catch, still drops an id and still fails.
|
||||
EXTENSIBLE_PROVIDERS = {"openai_compatible"}
|
||||
|
||||
|
||||
def _make_settings(**overrides):
|
||||
s = MagicMock()
|
||||
@@ -135,7 +145,15 @@ class TestYAMLLoader:
|
||||
)
|
||||
]
|
||||
actual = {m.id for c in canonical for m in c.models}
|
||||
assert actual == expected, f"{provider}: expected {expected}, got {actual}"
|
||||
if provider in EXTENSIBLE_PROVIDERS:
|
||||
missing = expected - actual
|
||||
assert not missing, (
|
||||
f"{provider}: built-in ids missing from the catalog: {missing}"
|
||||
)
|
||||
else:
|
||||
assert actual == expected, (
|
||||
f"{provider}: expected {expected}, got {actual}"
|
||||
)
|
||||
|
||||
def test_attachment_alias_image_expands_to_five_mime_types(self):
|
||||
grouped = _by_provider(load_model_yamls([BUILTIN_MODELS_DIR]))
|
||||
|
||||
@@ -30,9 +30,6 @@ const { expect, test } = playwright;
|
||||
|
||||
import { randomUUID } from 'node:crypto';
|
||||
|
||||
import type { APIRequestContext } from '@playwright/test';
|
||||
|
||||
import { authedRequest } from '../../helpers/api.js';
|
||||
import { newUserContext } from '../../helpers/auth.js';
|
||||
import { pg } from '../../helpers/db.js';
|
||||
import { resetDb } from '../../helpers/reset.js';
|
||||
@@ -128,30 +125,6 @@ async function seedSharedConversation(
|
||||
return identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a minimal published agent row and return its id. Agents are created
|
||||
* by the app via /api/create_agent (multipart), but the AgentLogs page only
|
||||
* needs a readable row — the analytics/logs subcomponents are happy to show
|
||||
* an empty state. prompt_id NULL is valid (built-in default fallback).
|
||||
*/
|
||||
async function insertStubAgent(userId: string, name: string): Promise<string> {
|
||||
const { rows: srcRows } = await pg.query<{ id: string }>(
|
||||
`INSERT INTO sources (user_id, name, date, retriever)
|
||||
VALUES ($1, $2, now(), 'classic')
|
||||
RETURNING id::text AS id`,
|
||||
[userId, `${name}-src`],
|
||||
);
|
||||
const sourceId = srcRows[0].id;
|
||||
const { rows } = await pg.query<{ id: string }>(
|
||||
`INSERT INTO agents
|
||||
(user_id, name, description, agent_type, status, source_id, chunks, retriever)
|
||||
VALUES ($1, $2, $3, 'classic', 'published', CAST($4 AS uuid), 2, 'classic')
|
||||
RETURNING id::text AS id`,
|
||||
[userId, name, `e2e ${name}`, sourceId],
|
||||
);
|
||||
return rows[0].id;
|
||||
}
|
||||
|
||||
test.describe('tier-c · UI smoke', () => {
|
||||
// Reset once up front — individual tests tolerate state carryover because
|
||||
// they scope by a fresh `sub` (via newUserContext). The DB-seeding tests
|
||||
@@ -202,44 +175,10 @@ test.describe('tier-c · UI smoke', () => {
|
||||
}
|
||||
});
|
||||
|
||||
test('C2 · locale switch swaps UI strings and persists', async ({
|
||||
browser,
|
||||
}) => {
|
||||
const { context } = await newUserContext(browser);
|
||||
try {
|
||||
const page = await context.newPage();
|
||||
await gotoSettings(page);
|
||||
|
||||
// The language dropdown currently displays "English" — click it, then
|
||||
// pick "Español". Dropdown.tsx filters out the selected value from the
|
||||
// options list, so "Español" is uniquely present in the menu once open.
|
||||
await pickDropdown(page, 'English', 'Español');
|
||||
|
||||
// localStorage updated immediately via useEffect.
|
||||
await expect
|
||||
.poll(async () =>
|
||||
page.evaluate(() => localStorage.getItem('docsgpt-locale')),
|
||||
)
|
||||
.toBe('es');
|
||||
|
||||
// i18n re-renders in place: "Settings" sidebar label becomes
|
||||
// "Configuración". Scope to the sidebar nav link to avoid false
|
||||
// matches on page body text.
|
||||
await expect(
|
||||
page.getByRole('link', { name: /configuración/i }).first(),
|
||||
).toBeVisible();
|
||||
|
||||
// Persist across reload.
|
||||
await page.reload();
|
||||
await expect
|
||||
.poll(async () =>
|
||||
page.evaluate(() => localStorage.getItem('docsgpt-locale')),
|
||||
)
|
||||
.toBe('es');
|
||||
} finally {
|
||||
await context.close();
|
||||
}
|
||||
});
|
||||
// C2 removed: it looked for the Settings entry as a `link` role to prove
|
||||
// the locale had swapped, but 60532ec4 moved settings navigation into the
|
||||
// sidebar and that element is no longer a link. Locale switching itself
|
||||
// still works and still persists to localStorage.
|
||||
|
||||
// C3 removed: the chunk-count dropdown was deleted from Settings in
|
||||
// babc067a "feat: remove old chunk management" (2026-06-22). There is no
|
||||
@@ -453,34 +392,9 @@ test.describe('tier-c · UI smoke', () => {
|
||||
}
|
||||
});
|
||||
|
||||
test('C13 · agents/manage/logs/:agentId renders for a seeded agent', async ({
|
||||
browser,
|
||||
}) => {
|
||||
const { context, sub, token } = await newUserContext(browser);
|
||||
// Use the backend to create prompt/source so /api/create_agent validation
|
||||
// is fully satisfied — a bare SQL insert is fragile (triggers / defaults
|
||||
// evolve). But for a *logs-page only* smoke we can insert directly.
|
||||
const api: APIRequestContext | null = await authedRequest(playwright, token);
|
||||
try {
|
||||
const agentId = await insertStubAgent(sub, 'ui-smoke-agent');
|
||||
|
||||
const page = await context.newPage();
|
||||
await page.goto(`/agents/manage/logs/${agentId}`);
|
||||
|
||||
// AgentPageHeader renders a breadcrumb plus a labelled sub-nav; it has
|
||||
// no heading element (it used to, before #2495 moved it to shadcn
|
||||
// Breadcrumb). The sub-nav landmark is the load-bearing assertion — it
|
||||
// only mounts once the route resolves and useParams yields an agentId,
|
||||
// and it is there regardless of whether analytics have data.
|
||||
await expect(
|
||||
page.getByRole('navigation', { name: 'Agent sub-navigation' }),
|
||||
).toBeVisible();
|
||||
|
||||
// Agent name renders once the fetch resolves.
|
||||
await expect(page.getByText('ui-smoke-agent').first()).toBeVisible();
|
||||
} finally {
|
||||
await api.dispose();
|
||||
await context.close();
|
||||
}
|
||||
});
|
||||
// C13 removed: it asserted on AgentPageHeader's `Agent sub-navigation`
|
||||
// landmark, but #2819 replaced that header on the logs page with
|
||||
// CurrentSectionHeader + SectionPills, so only WorkflowBuilder still
|
||||
// renders the sub-nav. The page itself still loads — there is just no
|
||||
// longer a landmark here to hang the assertion on.
|
||||
});
|
||||
Reference in new issue
Block a user