diff --git a/orchestrator/src/components/NavEspacio.vue b/orchestrator/src/components/NavEspacio.vue new file mode 100644 index 0000000..704783b --- /dev/null +++ b/orchestrator/src/components/NavEspacio.vue @@ -0,0 +1,51 @@ + + + diff --git a/orchestrator/src/lib/api.js b/orchestrator/src/lib/api.js index 1bbcb94..d3fcedf 100644 --- a/orchestrator/src/lib/api.js +++ b/orchestrator/src/lib/api.js @@ -5,9 +5,12 @@ import { contexto } from './contexto.js' // PortalAuth() redirigen al login devolviendo HTML en vez de un 401 JSON — // fetch sigue ese redirect solo, así que lo detectamos por el content-type. async function request(path, options = {}) { + const esFormData = options.body instanceof FormData const res = await fetch(path, { ...options, - headers: { 'Content-Type': 'application/json', ...options.headers }, + headers: esFormData + ? options.headers + : { 'Content-Type': 'application/json', ...options.headers }, }) const contentType = res.headers.get('content-type') || '' @@ -29,6 +32,9 @@ async function request(path, options = {}) { export const api = { get: (path) => request(path), + // Sin Content-Type a mano: en un multipart el boundary lo pone el navegador, + // y fijarlo nosotros deja el body ilegible del lado del servidor. + postForm: (path, formData) => request(path, { method: 'POST', body: formData, headers: {} }), post: (path, body) => request(path, { method: 'POST', body: JSON.stringify(body) }), put: (path, body) => request(path, { method: 'PUT', body: JSON.stringify(body) }), del: (path) => request(path, { method: 'DELETE' }), diff --git a/orchestrator/src/router.js b/orchestrator/src/router.js index 7e1613e..2cf9d4b 100644 --- a/orchestrator/src/router.js +++ b/orchestrator/src/router.js @@ -4,6 +4,9 @@ import TenantAgentes from './views/TenantAgentes.vue' import AgenteDetail from './views/AgenteDetail.vue' import Uso from './views/Uso.vue' import AiPropia from './views/AiPropia.vue' +import Pendientes from './views/Pendientes.vue' +import Archivos from './views/Archivos.vue' +import Plantillas from './views/Plantillas.vue' import { contexto } from './lib/contexto.js' const router = createRouter({ @@ -13,6 +16,9 @@ const router = createRouter({ { path: '/tenants/:id', name: 'tenant-agentes', component: TenantAgentes, props: true }, { path: '/tenants/:id/uso', name: 'uso', component: Uso, props: true }, { path: '/tenants/:id/ia', name: 'ai-propia', component: AiPropia, props: true }, + { path: '/tenants/:id/pendientes', name: 'pendientes', component: Pendientes, props: true }, + { path: '/tenants/:id/archivos', name: 'archivos', component: Archivos, props: true }, + { path: '/tenants/:id/plantillas', name: 'plantillas', component: Plantillas, props: true }, { path: '/tenants/:tenantId/agentes/:agenteId', name: 'agente-detail', diff --git a/orchestrator/src/views/AgenteDetail.vue b/orchestrator/src/views/AgenteDetail.vue index d16fa30..b155186 100644 --- a/orchestrator/src/views/AgenteDetail.vue +++ b/orchestrator/src/views/AgenteDetail.vue @@ -6,6 +6,7 @@ import { apiUmind, contexto } from '../lib/contexto.js' import UiEmptyState from '../components/ui/UiEmptyState.vue' import UiIcono from '../components/ui/UiIcono.vue' import TabAuditoria from './agente/TabAuditoria.vue' +import TabAcciones from './agente/TabAcciones.vue' import TabConexiones from './agente/TabConexiones.vue' import TabChat from './agente/TabChat.vue' import TabConversaciones from './agente/TabConversaciones.vue' @@ -268,6 +269,7 @@ async function cargarConexiones() { const ZONAS = [ ['conversaciones', 'Conversaciones'], ['conocimiento', 'Lo que sabe'], + ['acciones', 'Lo que hace'], ['canales', 'Dónde atiende'], ] @@ -663,6 +665,8 @@ watch( /> + + diff --git a/orchestrator/src/views/AiPropia.vue b/orchestrator/src/views/AiPropia.vue index 9ec0ba2..691078c 100644 --- a/orchestrator/src/views/AiPropia.vue +++ b/orchestrator/src/views/AiPropia.vue @@ -4,6 +4,7 @@ import { api } from '../lib/api.js' import { apiUmind } from '../lib/contexto.js' import UiEmptyState from '../components/ui/UiEmptyState.vue' import UiIcono from '../components/ui/UiIcono.vue' +import NavEspacio from '../components/NavEspacio.vue' const props = defineProps({ id: { type: String, required: true } }) @@ -121,6 +122,8 @@ async function borrar(c) {