Files
agent-ui/frontend/src/services/tools/handlers/themeHandlers.ts
josedario87 4450d1e034 feat: Add /tools page with centralized tool registry management
- Add ToolsPage for managing MCP tools activation and persistence
- Centralize all tool handlers in services/tools/handlers/
- toolRegistry.ts is now the single source of truth for tool state
- Add tools store for pinned tools (persisted in localStorage)
- Tools can be pinned to stay active across page navigation
- Remove old individual tool files, replaced by centralized handlers
2026-02-13 13:46:55 -06:00

212 lines
7.0 KiB
TypeScript

import type { ToolConfig } from './index'
import { useThemeStore } from '../../../stores/theme'
export function createThemeHandlers(): ToolConfig[] {
return [
{
name: 'get_design_tokens',
description: 'Obtiene los design tokens del tema activo',
category: 'theme',
schema: {
type: 'object',
properties: {
category: {
type: 'string',
enum: ['all', 'colors', 'text', 'accent', 'semantic', 'spacing', 'typography', 'effects'],
description: 'Categoria de tokens'
}
}
},
handler: async (args: { category?: string }) => {
const themeStore = useThemeStore()
const theme = themeStore.activeTheme
if (!theme) {
return 'No hay tema activo'
}
const category = args.category || 'all'
const variables = theme.variables
if (category !== 'all' && variables[category as keyof typeof variables]) {
const categoryVars = variables[category as keyof typeof variables]
const tokenList = Object.entries(categoryVars)
.map(([name, value]) => `--${name}: ${value}`)
.join('\n')
return `Design Tokens - ${category.toUpperCase()}:\n\n${tokenList}`
}
const allTokens = Object.entries(variables)
.map(([cat, vars]) => {
const tokenList = Object.entries(vars as Record<string, string>)
.map(([name, value]) => ` --${name}: ${value}`)
.join('\n')
return `[${cat.toUpperCase()}]\n${tokenList}`
})
.join('\n\n')
return `Design Tokens del tema "${theme.name}":\n\n${allTokens}`
}
},
{
name: 'get_active_theme',
description: 'Obtiene info del tema activo',
category: 'theme',
schema: { type: 'object', properties: {} },
handler: () => {
const themeStore = useThemeStore()
const theme = themeStore.activeTheme
if (!theme) return 'No hay tema activo'
return `Tema activo: "${theme.name}"\n` +
`ID: ${theme.id}\n` +
`Sistema: ${theme.is_system ? 'Si' : 'No'}\n` +
`Default: ${theme.is_default ? 'Si' : 'No'}`
}
},
{
name: 'set_theme_variable',
description: 'Modifica una variable CSS del tema',
category: 'theme',
schema: {
type: 'object',
properties: {
name: { type: 'string', description: 'Nombre de la variable sin --' },
value: { type: 'string', description: 'Nuevo valor' }
},
required: ['name', 'value']
},
handler: (args: { name: string; value: string }) => {
const themeStore = useThemeStore()
const root = document.documentElement
const varName = args.name.startsWith('--') ? args.name : `--${args.name}`
const keyName = args.name.startsWith('--') ? args.name.slice(2) : args.name
const currentValue = getComputedStyle(root).getPropertyValue(varName).trim()
root.style.setProperty(varName, args.value)
if (themeStore.activeTheme) {
const variables = themeStore.activeTheme.variables
for (const category of Object.keys(variables) as (keyof typeof variables)[]) {
if (keyName in variables[category]) {
themeStore.updateVariable(category, keyName, args.value)
break
}
}
}
return `Variable ${varName} cambiada:\n Anterior: ${currentValue || '(no definida)'}\n Nuevo: ${args.value}`
}
},
{
name: 'save_theme',
description: 'Guarda el tema actual',
category: 'theme',
schema: {
type: 'object',
properties: {
name: { type: 'string', description: 'Nombre del tema' },
description: { type: 'string', description: 'Descripcion' },
setAsDefault: { type: 'boolean', description: 'Establecer como default' }
},
required: ['name']
},
handler: async (args: { name: string; description?: string; setAsDefault?: boolean }) => {
const themeStore = useThemeStore()
const variablesToSave = themeStore.previewTheme || themeStore.activeTheme?.variables
if (!variablesToSave) {
return 'Error: No hay variables para guardar'
}
const result = await themeStore.saveTheme({
name: args.name,
description: args.description || `Tema creado el ${new Date().toLocaleString()}`,
variables: variablesToSave,
metadata: { author: 'Claude', version: '1.0', base: themeStore.activeTheme?.id || null }
})
if (args.setAsDefault && result.id) {
await themeStore.setDefaultTheme(result.id)
return `Tema "${args.name}" guardado y establecido como default. ID: ${result.id}`
}
return `Tema "${args.name}" guardado. ID: ${result.id}`
}
},
{
name: 'list_themes',
description: 'Lista todos los temas disponibles',
category: 'theme',
schema: { type: 'object', properties: {} },
handler: async () => {
const themeStore = useThemeStore()
await themeStore.fetchThemes()
const themes = themeStore.themes
if (themes.length === 0) return 'No hay temas disponibles'
const systemThemes = themes.filter(t => t.is_system)
const userThemes = themes.filter(t => !t.is_system)
let result = `Temas disponibles (${themes.length}):\n\n`
if (systemThemes.length > 0) {
result += `[SISTEMA]\n`
result += systemThemes.map(t => ` - ${t.name}${t.is_default ? ' [DEFAULT]' : ''}`).join('\n')
result += '\n\n'
}
if (userThemes.length > 0) {
result += `[PERSONALIZADOS]\n`
result += userThemes.map(t => ` - ${t.name}${t.is_default ? ' [DEFAULT]' : ''}`).join('\n')
}
return result
}
},
{
name: 'switch_theme',
description: 'Cambia al tema especificado',
category: 'theme',
schema: {
type: 'object',
properties: {
theme: { type: 'string', description: 'Nombre o ID del tema' }
},
required: ['theme']
},
handler: async (args: { theme: string }) => {
const themeStore = useThemeStore()
await themeStore.fetchThemes()
const theme = themeStore.themes.find(t =>
t.id === args.theme || t.name.toLowerCase() === args.theme.toLowerCase()
)
if (!theme) {
return `Tema "${args.theme}" no encontrado`
}
themeStore.selectTheme(theme)
return `Tema cambiado a "${theme.name}"`
}
},
{
name: 'reset_theme',
description: 'Descarta cambios no guardados',
category: 'theme',
schema: { type: 'object', properties: {} },
handler: () => {
const themeStore = useThemeStore()
if (!themeStore.previewTheme) {
return 'No hay cambios pendientes'
}
themeStore.resetPreview()
return 'Cambios descartados'
}
}
]
}