# Agents

Módulo de gestión del Agente AI (`Module.AGENTS`). Permite administrar la base de conocimiento y la configuración del agente de IA de la empresa.

---

## Rutas

| Ruta | Componente | Descripción |
|---|---|---|
| `/agents` | `AgentsLayout` | Redirige automáticamente a `/agents/knowledge-base` |
| `/agents/knowledge-base` | `KnowledgeBase` | Lista raíz de archivos y carpetas |
| `/agents/knowledge-base/:path` | `KnowledgeBase` | Vista de carpeta específica. `path` es el path de carpeta URL-encoded (ej. `encodeURIComponent("policies/general/")`) |
| `/agents/settings` | `AgentsSettings` | Configuración general del agente AI |
| `/agents/knowledge-base/upload-file` | `UploadFile` | Carga de archivos multi-paso (página completa, sin layout ni sidebar). Acepta `?folderpath=<encoded>` como query param. |

> **Importante:** La ruta `/agents/knowledge-base/upload-file` está registrada **fuera** del `AgentsLayout` en el router para que se renderice como pantalla completa. Está también excluida explícitamente del sidebar y la navbar mediante regex en `src/utils/sidebar.ts` y `src/utils/navbar.ts`.

---

## Estructura de archivos

```
Agents/
├── index.tsx                   # Layout con tabs ("Base de conocimiento" | "Configuración")
├── routes.ts                   # Path factories centralizados
├── router.tsx                  # Config de rutas del módulo (importado en src/routes.tsx)
├── constants.ts                # LAYOUT_SX
├── README.md
│
├── KnowledgeBase/
│   ├── index.tsx               # Página: lista de archivos/carpetas (root o dentro de una carpeta)
│   ├── types.ts                # Todos los tipos API y UI (ver sección Tipos)
│   ├── constants.ts            # KNOWLEDGE_BASE_STATUS_PILL_TYPE, KNOWLEDGE_BASE_STATUS_KEY, KNOWLEDGE_BASE_NAME_MAX_LENGTH
│   ├── services.ts             # CRUD completo (ver sección API)
│   ├── queries.ts              # knowledgeBaseKeys (query key factories)
│   │
│   ├── hooks/
│   │   ├── useGetKnowledgeBaseFiles.tsx     # useInfiniteQuery: transforma API → UI (folders primero)
│   │   ├── useDeleteKnowledgeBaseItems.tsx  # Mutations: deleteFile, deleteFiles, deleteFolder
│   │   ├── useCreateKnowledgeBaseFolder.tsx # Mutation: crea carpeta + invalidación
│   │   ├── useUpdateKnowledgeBaseItem.tsx   # Mutations: updateFile, updateFolder (renombrar/mover)
│   │   ├── useKnowledgeBaseAudience.tsx     # Calcula totalCount de audiencia vía getAudiencesCount
│   │   └── useEditAudienceForm.tsx          # Form wrapper: transforma segmentation form → tags/userIds
│   │
│   ├── UploadFile/
│   │   ├── index.tsx           # Página full-screen multi-paso (FILE → AUDIENCE)
│   │   ├── types.ts            # UploadFormValues, UploadStep (enum), UploadKnowledgeBaseFileResponse
│   │   ├── services.ts         # uploadKnowledgeBaseFile(filename, formData) → PUT ai-agent/files/:filename
│   │   ├── constants.ts        # UPLOAD_FIELDS, UPLOAD_DEFAULT_VALUES, MAX_FILE_SIZE_MB/BYTES
│   │   ├── utils.ts            # getFileName, buildSegmentationTags
│   │   └── hooks/
│   │       └── useUploadKnowledgeBaseFile.tsx
│   │   └── components/
│   │       ├── UploadFileStep/         # Step 1: selector de archivos
│   │       ├── UploadFileAudienceStep/ # Step 2: selector de audiencia/segmentación
│   │       ├── UploadFileHeader/
│   │       ├── UploadFileFooter/
│   │       ├── UploadFileExitDialog/   # Confirma salida sin guardar
│   │       └── UploadFileConfirmDialog/ # Confirma envío
│   │
│   └── components/
│       ├── KnowledgeBaseHeader/
│       │   └── index.tsx       # Breadcrumbs + botones "Subir archivos" y "Nueva carpeta/subcarpeta"
│       │
│       ├── KnowledgeBaseContent/
│       │   ├── index.tsx                    # Orquestador: fetching, estado, search, bulk actions (0 props)
│       │   ├── KnowledgeBaseTable.tsx       # Display puro: tabla + loader + estados vacíos
│       │   ├── KnowledgeBaseTableHeader.tsx # Encabezado con checkbox "seleccionar todo" (solo archivos)
│       │   ├── KnowledgeBaseTableRow.tsx    # Fila individual (archivo o carpeta)
│       │   └── KnowledgeBaseTableState.tsx  # Estados vacío / error / networkError / emptySearch
│       │
│       ├── KnowledgeBaseBreadcrumbs/
│       │   └── index.tsx       # Breadcrumbs derivados de los segmentos del path (decodeURIComponent)
│       │
│       ├── KnowledgeBaseBulkActionsBar/
│       │   └── index.tsx       # Barra animada de acciones en bulk (Editar audiencia | Eliminar)
│       │
│       ├── KnowledgeBaseAudienceSelector/
│       │   └── index.tsx       # Selector de tipo de audiencia (Todos / Segmentado)
│       │
│       ├── KnowledgeBaseSegmentation/
│       │   └── index.tsx       # Selector de grupos de segmentación (FormSegmentationGroupSelector)
│       │
│       ├── KnowledgeBaseAudienceAlert/
│       │   └── index.tsx       # Alerta informativa sobre la audiencia configurada
│       │
│       ├── KnowledgeBaseAudienceCollaboratorsDrawer/
│       │   └── index.tsx       # Drawer que lista los colaboradores de la audiencia actual
│       │
│       ├── EditAudienceDrawer/
│       │   ├── index.tsx               # Drawer principal de edición de audiencia
│       │   └── EditAudienceDrawerBody.tsx
│       │
│       ├── EditAudienceConfirmDialog/
│       │   └── index.tsx       # Dialog de confirmación antes de guardar cambios de audiencia
│       │
│       ├── MoveItemDrawer/
│       │   └── index.tsx       # Drawer para mover un archivo o carpeta a otra ubicación
│       │
│       ├── NewFolderDialog/
│       │   └── index.tsx       # Dialog con formulario para crear una carpeta
│       │
│       ├── EditNameDialog/
│       │   └── index.tsx       # Dialog para renombrar un archivo o carpeta
│       │
│       └── DeleteConfirmDialog/
│           └── index.tsx       # Dialog de confirmación para eliminar items seleccionados
│
├── Settings/
│   ├── index.tsx               # Página: formulario de configuración del agente (con skeleton)
│   ├── types.ts                # AgentConfig, UpdateAgentConfigPayload, AgentSettingsFormValues
│   ├── queries.ts              # agentConfigKeys (query key factories)
│   ├── services.ts             # getAgentConfig, updateAgentConfig
│   ├── constants.ts            # SETTINGS_FIELDS, GOAL_MAX_LENGTH, INSTRUCTIONS_MAX_LENGTH
│   │
│   ├── hooks/
│   │   ├── useGetAgentConfig.ts    # useQuery wrapper para GET ai-agent/config
│   │   └── useUpdateAgentConfig.ts # useMutation con invalidación y snackbar
│   │
│   └── components/
│       ├── GeneralSection.tsx  # Sección: nombre, descripción, identidad, objetivo, instrucciones
│       ├── MessagesSection.tsx # Sección: mensaje inicial, de inactividad y filtro de audiencia
│       ├── ModulesSection.tsx  # Sección: módulos conectados (switchers — próximamente)
│       └── SettingsSkeleton.tsx # Skeleton de carga del formulario
```

---

## Tipos principales

### `KnowledgeBase/types.ts` — tipos de API

```ts
type AgentFileStatus = 'queued' | 'processing' | 'ready' | 'failed';

type SegmentationTag = {
  groupId: number;
  itemId: number;
  groupName: string;
  itemName: string;
};

type AgentFileRow = {
  name: string;
  id: string | null;
  size: number;
  status: AgentFileStatus;
  segmentationId: string | null;
  segmentationTags: SegmentationTag[];
  segmentationUserIds: number[];
  uploadedBy: { id: number; fullName: string } | null;
  updatedAt: string | null;
  downloadUrl: string;
};

type AgentFolderRow = {
  path: string;           // termina con "/"
  fileCount: number;
  statuses: AgentFileStatus[];
  segmentationTags: SegmentationTag[];
  segmentationUserIds: number[];
};

type KnowledgeBaseFilesResponse = {
  folder: string;
  files: AgentFileRow[];
  folders: AgentFolderRow[];
  total: number;
  hasMore: boolean;
};
```

### `KnowledgeBase/types.ts` — tipos UI

```ts
enum KnowledgeBaseItemType { FILE = 'FILE', FOLDER = 'FOLDER' }

type KnowledgeBaseItem = {
  name: string;
  path: string;
  parentPath: string | null;
  type: KnowledgeBaseItemType;
  extension: string | null;
  uploadedBy: { id: number; fullName: string } | null;
  updatedAt: string;
  size?: string;
  status?: AgentFileStatus;
  segmentationTags: SegmentationTag[];
  segmentationUserIds: number[];
  itemCount?: number;
  downloadUrl: string;
};

type UpdateKnowledgeBaseFilePayload = { newName?: string; newFolder?: string };
type UpdateKnowledgeBaseFolderPayload = { newName?: string; newParent?: string };

type EditKnowledgeBaseAudiencePayload = {
  documents: string[];
  tags: SegmentationTag[];
  userIds: number[];
};

type KnowledgeBaseListParams = {
  folder?: string;
  limit?: number;
  offset?: number;
  search?: string;
};

enum KnowledgeBaseAudienceType { ALL = 'all', SEGMENTED = 'segmented' }

type KnowledgeBaseAudienceSegmentation = Record<number, Set<number>>;
type KnowledgeBaseAudienceForm = {
  audienceType: KnowledgeBaseAudienceType | null;
  segmentation: KnowledgeBaseAudienceSegmentation;
};
```

### `Settings/types.ts`

```ts
type AgentConfig = {
  id: string;
  name: string;
  description: string;
  identity: string;
  goal: string;
  instructions: string;
  helloMessage: string;
  inactivityMessage: string;
  inactivityEnabled: boolean;
  inactivityTimeoutSec: number;
  audienceFilterEnabled: boolean;
};

type UpdateAgentConfigPayload = Partial<AgentConfig>;
type AgentSettingsFormValues = Partial<AgentConfig>;
```

### `KnowledgeBase/UploadFile/types.ts`

```ts
type UploadFormValues = KnowledgeBaseAudienceForm & {
  files: FileCardType[];
  folderPath: string;
};

enum UploadStep { FILE = 0, AUDIENCE = 1 }

type UploadKnowledgeBaseFileResponse = {
  filename: string;
  segmentationId: string;
  segmentationApplied: boolean | null;
};
```

---

## Integración con el sistema

### `src/routes.tsx`
El módulo se integra con spread: `...agentsRouterConfig`. La ruta de upload-file queda fuera del `AgentsLayout` y está envuelta en `PermissionsGuard`.

### `src/components/DashboardLayout/DashboardSidebar/index.tsx`
El módulo aparece en el sidebar como:
- `key: Module.AGENTS`
- Título: `t('backoffice_only:dashboard_sidebar.agents')`
- Icono: `IconSparkles`
- Path: `agentsRoutes.knowledgeBase.base()` → `/agents/knowledge-base`

### `src/utils/sidebar.ts` y `src/utils/navbar.ts`
La ruta `/agents/knowledge-base/upload-file` está excluida del sidebar y navbar vía regex:
```ts
/\/agents\/knowledge-base\/upload-file/
```

### `src/types/modules.ts`
```ts
Module.AI_AGENTS = 'AI_AGENTS'
```

---

## Integración con API

### Endpoints

| Endpoint | Función en services.ts | Descripción |
|---|---|---|
| `GET ai-agent/files` | `getKnowledgeBaseFiles(params)` | Lista paginada de archivos y carpetas |
| `GET ai-agent/files/:filename` | `getKnowledgeBaseFile(filename)` | Detalle de un archivo individual |
| `DELETE ai-agent/files/:filename` | `deleteKnowledgeBaseFile(filename)` | Eliminar un archivo |
| `DELETE ai-agent/files` | `deleteKnowledgeBaseFiles(filenames[])` | Eliminar archivos en bulk |
| `DELETE ai-agent/folders/:path` | `deleteKnowledgeBaseFolder(path)` | Eliminar una carpeta |
| `POST ai-agent/folders` | `createKnowledgeBaseFolder(path)` | Crear una carpeta |
| `PATCH ai-agent/files/:filename` | `updateKnowledgeBaseFile(filename, payload)` | Renombrar o mover un archivo |
| `PATCH ai-agent/folders/:path` | `updateKnowledgeBaseFolder(path, payload)` | Renombrar o mover una carpeta |
| `PUT ai-agent/segmentations` | `editKnowledgeBaseAudience(payload)` | Editar audiencia de items seleccionados |
| `PUT ai-agent/files/:filename` | `uploadKnowledgeBaseFile(filename, formData)` | Subir un archivo |
| `GET ai-agent/config` | `getAgentConfig()` | Obtener configuración del agente |
| `PUT ai-agent/config` | `updateAgentConfig(payload)` | Guardar configuración del agente |

> El `baseURL` del cliente `api` ya incluye `/backoffice`, por lo que las rutas no llevan ese prefijo.

### Hook: `useGetKnowledgeBaseFiles`

```ts
const { items, total, isLoading, isSuccess, isError, fetchNextPage, isFetchingNextPage } =
  useGetKnowledgeBaseFiles({ folderPath, search, limit, offset });
```

Usa `useInfiniteQuery`. Las carpetas aparecen primero, seguidas de los archivos. Internamente transforma `AgentFileRow[]` + `AgentFolderRow[]` → `KnowledgeBaseItem[]`.

---

## Navegación por carpetas

La misma página `KnowledgeBase` maneja raíz y subcarpetas. El `path` en la URL es el **path de carpeta URL-encoded**:

- Navegar a carpeta: `navigate(agentsRoutes.knowledgeBase.folder(encodeURIComponent(folder.path)))`
- Leer en página: `const folderPath = decodeURIComponent(params.path ?? '')`
- Los breadcrumbs se derivan de los segmentos del path: `"policies/general/"` → `["policies", "general"]`

---

## Traducciones

Namespace: `agents`
Ubicación: `node_modules/@humanddev/hu-translations/locale/es/agents.json`

Claves relevantes para Knowledge Base:

| Clave | Uso |
|---|---|
| `knowledge_base.table.audience` | Header columna Alcance |
| `knowledge_base.status.loading` | Pill para `queued` y `processing` |
| `knowledge_base.status.ready` | Pill para `ready` |
| `knowledge_base.status.error` | Pill para `failed` |

---

## Patrones y convenciones usadas

### Layers (drawers y dialogs)
Todos los drawers y dialogs usan el patrón de capas del proyecto:
- **Drawers:** `useDrawerLayer()` → `openDrawer({ content: <Componente /> })`
- **Dialogs:** `useDialogLayer()` → `openDialog({ content: <Componente /> }, DIALOG_ID)` / `closeDialog(DIALOG_ID)`

### Formularios
- Se usa `react-hook-form` con `FormProvider` + `useForm`.
- Las constantes de campos se tipan con `Record<keyof FormValues, keyof FormValues>` para evitar strings sueltos.

### Animaciones
- Se usa `appearFromBottom` de `@material-hu/utils/animations` para la entrada de páginas/tablas.
- `fadeIn` se usa en filas individuales de la tabla.

### Columna Alcance
- `segmentationTags.length === 0 && segmentationUserIds.length === 0` → `"Todos"`, si no → `"Segmentado N"`.
- Aplica igual para archivos y carpetas.

### Checkboxes en tabla
- Las **carpetas** tienen checkbox **disabled** — no participan en bulk actions.
- "Seleccionar todo" solo selecciona archivos (excluye carpetas del conteo).

### Status de carpetas
El status visible de una carpeta se deriva de su array `statuses`:
- Si contiene `failed` → pill error
- Si contiene `queued` o `processing` → pill warning
- Si todos son `ready` → pill success
- Array vacío → sin pill

### HuGoTheme
Las páginas principales (`AgentsLayout`, `UploadFile`) wrappean su contenido con `useHuGoTheme()` para asegurar el tema correcto del design system.

### Snackbars
Se usa `useHuSnackbar()` → `enqueueSnackbar({ title, variant })` para feedback de acciones.

---

## Estado actual

| Ítem | Estado | Detalle |
|---|---|---|
| KnowledgeBase UI | ✅ Listo | Layout, tabla, selección, búsqueda, carpetas, columna Alcance |
| Breadcrumbs | ✅ Listo | Navegación anidada funcional basada en path |
| Bulk actions bar | ✅ Listo | Editar audiencia y Eliminar con animación |
| NewFolderDialog | ✅ Listo | Crea carpeta con API integrada |
| EditNameDialog | ✅ Listo | Renombra archivos y carpetas con API integrada |
| MoveItemDrawer | ✅ Listo | Mueve archivos y carpetas con API integrada |
| DeleteConfirmDialog | ✅ Listo | Confirma y ejecuta eliminación vía API |
| EditAudienceDrawer | ✅ Listo | Edita audiencia de items seleccionados (bulk) |
| Upload page | ✅ Listo | Flujo multi-paso (archivo → audiencia) con API integrada |
| Settings form | ✅ Listo | General + Mensajes + Módulos (próximamente); con API integrada |
| Capa de servicios KB | ✅ Lista | CRUD completo en `services.ts` + hooks por operación |
| Integración con API real | ✅ Activa | Todos los hooks consumen la API directamente |
| Menú de acciones individuales por fila | ✅ Listo | Acciones por fila implementadas |
| `uploadedBy` → nombre de usuario | ✅ Resuelto | La API devuelve `{ id, fullName }` directamente |
| Guard de permisos / `Module.AGENTS` | ✅ Implementado | El router usa `PermissionsGuard` |
| Módulos conectados (Settings) | ⏳ Próximamente | Switchers actualmente deshabilitados |
