Skip to content

feat: migrate logging system to Winston with BigInt and rotation fixes#189

Closed
Saul-Gomez-J wants to merge 35 commits intolevante-hub:mainfrom
Saul-Gomez-J:feat/winston-logger-migration
Closed

feat: migrate logging system to Winston with BigInt and rotation fixes#189
Saul-Gomez-J wants to merge 35 commits intolevante-hub:mainfrom
Saul-Gomez-J:feat/winston-logger-migration

Conversation

@Saul-Gomez-J
Copy link
Contributor

🎯 Resumen

Migración completa del sistema de logging custom a Winston con correcciones críticas de BigInt serialization y rotación excesiva de archivos.


🚀 Cambios Principales

Migración a Winston (Commits anteriores)

  • Reemplazó 420 líneas de transports custom por configuración Winston
  • Logs JSON estructurados en producción
  • Diferenciación desarrollo vs producción
  • Compresión gzip automática en producción
  • Sistema de rotación con límites (maxFiles, maxAge, maxSize)
  • Zero overhead preservado para categorías deshabilitadas

🐛 Fix: BigInt Serialization Error (Este PR)

Problema:

[ChatStore] Failed to create session: 
Error: Do not know how to serialize a BigInt

Causa: SQLite devuelve lastInsertRowid como BigInt. Winston usa JSON.stringify que no puede serializar BigInt nativamente.

Solución:

  • Convertir BigInt a String antes de loggear
  • Eliminar logging de fullResult que contenía BigInt

Archivos modificados:

  • src/main/services/databaseService.ts - Conversión de lastInsertRowid
  • src/renderer/stores/chatStore.ts - Eliminación de fullResult

🐛 Fix: Rotación Excesiva de Logs (Este PR)

Problema:

levante-2026-01-28-205641.log
levante-2026-01-28-205647.log  ← 6 segundos después!
levante-2026-01-28-205650.log  ← 3 segundos después!

Causa: datePattern: 'YYYY-MM-DD-HHmmss' incluye segundos, causando rotación cada segundo.

Solución: Cambiar a datePattern: 'YYYY-MM-DD' → 1 archivo por día

Archivos modificados:

  • src/main/services/logging/config.ts - Actualización de datePattern

📊 Impacto

Aspecto Antes Después
BigInt serialization ❌ Crashea ✅ Convierte a String
Rotación de archivos 🔴 Cada segundo ✅ Diaria
Archivos generados/día Cientos 1
Formato de logs Custom Winston estándar
Producción Debug verbose JSON estructurado

🧪 Testing Realizado

Verificaciones

  • ✅ No hay errores de BigInt serialization
  • ✅ Logs rotan correctamente (1 archivo/día)
  • ✅ Todas las categorías funcionando (AI-SDK, DATABASE, CORE, MCP, MODELS, PREFERENCES)
  • ✅ Formato legible en desarrollo (timestamp + categoría + nivel + JSON indentado)
  • ✅ Sin colores ANSI en archivos (texto plano)
  • ✅ Winston audit system trackeando correctamente
  • ✅ Limpieza automática configurada (maxFiles: 3, maxAge: 7 días en dev)
  • ✅ TypeScript compilation passes

📝 Ejemplo de Log

[2026-01-28 21:13:34] [DATABASE] [INFO] Message persisted
{
  "messageId": "j3iFHexTKGo4643r",
  "sessionId": "1769631193527-w69b0cu",
  "role": "assistant",
  "hasToolCalls": false
}

📁 Archivos Modificados

Este PR (3 archivos)

  • src/main/services/databaseService.ts - BigInt fix
  • src/main/services/logging/config.ts - Rotation fix
  • src/renderer/stores/chatStore.ts - Error logging cleanup

PR Original Winston Migration

  • src/main/services/logging/winstonConfig.ts (nuevo)
  • src/main/services/logging/logger.ts (refactor)
  • src/main/services/logging/config.ts (actualizado)
  • Otros archivos (ver PR feat: migrate logging system to Winston #186 original)

🔗 Enlaces Relacionados


✅ Checklist de Revisión

  • ✅ TypeScript compila sin errores
  • ✅ No hay errores de BigInt serialization
  • ✅ Rotación de logs funciona correctamente (diaria)
  • ✅ Todas las categorías de logs funcionan
  • ✅ Formato de logs es legible
  • ✅ Sistema de limpieza automática configurado
  • ✅ Zero overhead preservado
  • ✅ No breaking changes

📝 Notas Adicionales

Historia del Bug BigInt:

  • Introducido en commit 98c443c (migración a logging centralizado)
  • Expuesto en commit 060e19e (AI SDK v5 migration)
  • NO relacionado con Winston (bug pre-existente)

Decisión de diseño - Rotación diaria:

  • Desarrollo: YYYY-MM-DD (1 archivo/día)
  • Producción: YYYY-MM-DD (1 archivo/día)
  • Tamaño máximo ya controlado por maxSize (10MB dev, 50MB prod)

🤖 Generated with Claude Code

aalejandrossj and others added 30 commits January 5, 2026 15:52
  Problema:
  - No se seleccionaba ningún modelo por defecto al crear chats nuevos
  - El sistema permitía enviar peticiones sin modelo seleccionado
  - Con muchos modelos configurados, el usuario debía seleccionar manualmente cada vez

  Solución:
  - Guardar el último modelo seleccionado en ui-preferences.json (lastUsedModel)
  - Cargar automáticamente lastUsedModel al crear un nuevo chat
  - Prevenir envío de mensajes sin modelo seleccionado:
    * Botón de envío deshabilitado cuando no hay modelo
    * Validación en handleSubmit antes de crear sesión
    * Verificación de existencia del modelo en modelos disponibles

  Beneficios:
  - Mejor experiencia de usuario con modelo pre-seleccionado
  - Previene errores al enviar sin modelo
  - Reduce fricción en el flujo de trabajo

  Archivos modificados:
  - src/renderer/hooks/useModelSelection.ts
  - src/renderer/pages/ChatPage.tsx
  - src/renderer/components/chat/ChatPromptInput.tsx
## New Features

### Message Editing
- Users can now edit their own messages in the chat
- Edit button appears on hover below the message (outside the message container)
- Inline editing with auto-resizing textarea (min 60px, max 300px height)
- Cancel and Send buttons for edit actions
- Editing a message triggers a new AI response with the updated content

### Copy to Clipboard
- New copy button alongside the edit button
- Allows users to quickly copy message content to clipboard

## UI/UX Improvements
- Action buttons (copy, edit) appear on hover below user messages
- Clean, minimal design matching the application style
- Textarea auto-grows based on content length
- Minimum width of 500px for better editing experience

## Technical Changes

### Frontend (Renderer)
- `ChatMessageItem.tsx`: Added editing state, copy/edit buttons, inline textarea
- `ChatPage.tsx`: Implemented `handleEditMessage` function
- `chatStore.ts`: Added `editMessage` action with conversation branching logic
- `prompt-input.tsx`: Minor adjustments for consistency

### Backend (Main Process)
- `chatService.ts`: Added `editMessage` method with conversation history management
- `databaseHandlers.ts`: New IPC handler for `levante/chat/edit-message`

### Preload & Types
- `database.ts`: Added `editMessage` API method
- `preload.ts`: Exposed `editMessage` in the bridge
- `database.ts` (types): Added `EditMessageParams` interface

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Show green check icon for 2 seconds after copying
- Change tooltip to "Copied!" when copied
- Smooth transition between icons

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
feat(chat): add message editing and copy functionality for user messages
Replace CSS field-sizing-content with JavaScript auto-resize since
the CSS property is not supported in Electron's Chromium version.

Changes:
- Add useRef, useEffect, useCallback hooks for resize logic
- Implement adjustHeight function that calculates height within bounds
- Merge internal/external refs for proper ref forwarding
- Update maxHeight default from 300px to 164px (~6 lines)
- Add overflow-y-auto for internal scrolling at max height
- Remove unsupported field-sizing-content CSS property

The textarea now grows automatically as user types, stops at 164px
showing internal scroll, and shrinks when text is deleted.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…o-resize

fix(chat): implement JavaScript-based auto-resize for textarea
Add the ability to enable/disable individual MCP tools from the chat UI,
giving users fine-grained control over which tools are available to the AI.

## Features

- **Tool Selection UI**: New dropdown in chat toolbar showing all MCP servers
  and their tools with checkboxes to enable/disable each one
- **Server Toggle**: Enable/disable entire MCP servers with real connection
  management (not just config changes)
- **Performance Warning**: Alert when >40 tools enabled, error when >80
- **Persistence**: Tool preferences saved to ui-preferences.json
- **Real-time Updates**: Listen for MCP tools/list_changed notifications

## Architecture

### Data Model (Negative List Pattern)
- Only disabled tools are stored in `disabledTools[serverId][]`
- New tools are enabled by default
- Compact storage, follows Claude Desktop pattern

### IPC Handlers (src/main/ipc/mcpHandlers/tools.ts)
- `get-tools-cache`: Get cached tools without reconnecting
- `get-disabled-tools`: Get disabled tools map
- `toggle-tool`: Toggle individual tool
- `toggle-all-tools`: Toggle all tools for a server
- `clear-server-tools`: Cleanup on server removal

### AI Integration (src/main/services/ai/mcpToolsAdapter.ts)
- `getMCPTools()` now accepts `disabledTools` parameter
- Filters out disabled tools before passing to AI model
- Logs show disabled tool count for debugging

### Store (src/renderer/stores/mcpStore.ts)
- New state: `toolsCache`, `disabledTools`, `loadingTools`
- Actions: `toggleTool`, `toggleAllTools`, `isToolEnabled`, etc.
- `enableServer`/`disableServer` now properly connect/disconnect

## UI Components

- **ToolsMenu**: Redesigned with two dropdowns (settings + tools)
- **ToolsWarning**: Performance warning component
- **ToolSelector**: Reusable tool selection component
- **useMCPEvents**: Hook for MCP event handling

## Translations

Added complete translations (EN/ES) for:
- chat.json: tools_menu.* keys
- settings.json: mcp_tools.* keys

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Convert denied tools to output-available state in sanitizeMessagesForModel
  to generate valid tool_result for Anthropic (fixes 500 error)
- Replace lastAssistantMessageIsCompleteWithApprovalResponses with custom
  sendAutomaticallyWhen that only triggers for approvals, not denials
  (fixes infinite loop)
- Update tool-approval-flow-explained.md with complete denial flow documentation

The deny flow now:
1. User clicks Deny → sendAutomaticallyWhen returns false → no new call
2. If user continues conversation → denial converted to tool_result
3. Anthropic receives valid message structure

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove console.log statements added during debugging:
- ElectronChatTransport.ts: FLOW-5, FLOW-6, FLOW-7, FLOW-8 logs
- ChatMessageItem.tsx: FLOW-13, FLOW-14 logs

The structured logger.aiSdk.debug calls are preserved as they are
part of the logging system and can be toggled via DEBUG_AI_SDK env var.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…nable-disable

feat(mcp): add individual tool enable/disable functionality
- Remove yellow card container and header from ToolApprovalInline
- Add translations for tool approval (EN/ES)
- Use useTranslation hook for all user-facing strings

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove outdated documentation files and keep single comprehensive guide:
- Remove tool-approval-deep-dive.md
- Remove tool-approval-error-diagnostic.md
- Remove tool-approval-implementation-plan.md
- Remove tool-approval-status.md
- Remove tool-execution-flow.md

All information is now consolidated in tool-approval-flow-explained.md

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add useToolAutoApproval hook for per-session server auto-approval
- Add "Approve for session" button to tool approval UI
- Auto-approve tools from pre-approved servers automatically
- Update tool-approval-flow-explained.md with accurate line references
- Add i18n support for new approval button (en/es)
- Clear auto-approvals when changing chat sessions

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change from dynamic import() to static import for mcp-use
- Remove module-level variables (MCPClient, MCPLogger)
- Simplify initialize() to only configure Logger

This fixes IPC handler registration errors that occurred when mcp-use
was bundled with Vite (commit 74691fd). The dynamic import pattern was
designed for external modules but fails with bundled code.

Benefits:
- Maintains optimized bundle size (~128MB vs ~489MB)
- Fixes missing handlers: levante/mcp/get-tools-cache, get-disabled-tools
- Only winston remains external (required for Logger.configure())

Bundle analysis:
- mcp-use: bundled by Vite
- winston: external (runtime dependency)
- Total DMG: 128MB (-74% from original)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Update mcp-use dependency to latest version (1.13.4)
- Adapt Logger.configure() to new API (removed 'console' option)
- Use level: 'error' and format: 'minimal' for quiet logging

Breaking changes in mcp-use Logger API:
- Removed: { console: boolean }
- Added: { level?: LogLevel, format?: 'minimal' | 'detailed' | 'emoji' }

Version compatibility:
- mcp-use 1.13.4 uses @modelcontextprotocol/sdk 1.25.1 (matches our direct dependency)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Resolved all open security vulnerabilities:
- Update @modelcontextprotocol/sdk 1.25.1 → 1.25.2 (ReDoS fix)
- Force react-router ≥7.12.0 (XSS and CSRF fixes)
- Force tar ≥7.5.3 (dev-only, path traversal fix)
- Remove unnecessary jsondiffpatch override
- Fix broken @modelcontextprotocol/sdk override (^1.24.3 → 1.25.2 exact)

Fixes alerts: levante-hub#22, levante-hub#24, levante-hub#25, levante-hub#26, levante-hub#27, levante-hub#28, levante-hub#29, levante-hub#30, levante-hub#31

Changes:
- Update @modelcontextprotocol/sdk to ^1.25.2
- Add react-router: >=7.12.0 override
- Add tar: >=7.5.3 override
- Fix @modelcontextprotocol/sdk override to exact version 1.25.2
- Remove jsondiffpatch override (package not installed)

Verified: typecheck passes, all vulnerable packages at secure versions

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…ol-execution2

feat(approval): Tool Approval System with Session-based Auto-approval
 fix: seleccionar último modelo usado por defecto en chats nuevos
…c-import

fix: resolve security vulnerabilities and optimize mcp-use integration
- Add .mcp.json and .claude/ to .gitignore
- Remove files from git tracking while preserving local copies
- Ensures user-specific Claude Code settings remain local

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…menu

Improves UX by organizing MCP servers into 'Enabled' and 'Disabled' tabs, with enabled servers shown by default. Users can switch to the disabled tab to re-enable servers as needed.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Resolves levante-hub#158

The title generation for new chats was blocking the entire flow,
causing a 3-5 second delay before redirecting to the chat page.

Changes:
- Title generation now runs in background (fire-and-forget)
- Redirect happens immediately after message persistence
- Title updates asynchronously when ready
- Added error handling for background title generation

Impact:
- Chat creation feels instant
- Better perceived performance
- Title appears 1-2 seconds later without blocking UX

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- ai: 6.0.3 → 6.0.39
- @ai-sdk/anthropic: 3.0.1 → 3.0.15
- @ai-sdk/gateway: 3.0.2 → 3.0.16
- @ai-sdk/google: 3.0.1 → 3.0.10
- @ai-sdk/openai: 3.0.1 → 3.0.12
- @ai-sdk/openai-compatible: 2.0.1 → 2.0.13
- @ai-sdk/react: 3.0.3 → 3.0.41

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…roval-tool-execution2"

This reverts commit 9b031a0, reversing
changes made to 3576f65.
The ToolsMenu was displaying "No MCP servers configured" even when servers
were connected and functioning. This happened because the MCP store state
(activeServers, connectionStatus) was only loaded when visiting the Store page.

Changes:
- Load MCP state on app startup in useMCPEvents hook
- Add periodic refresh of connection status (30s interval)
- Remove duplicate connection refresh interval in store-layout

This ensures the ToolsMenu shows accurate server status from app start.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Some MCP servers only implement structuredContent (MCP spec 2025-06-18)
without providing the legacy content field. This caused responses to
appear empty in the UI. Now both MCP service implementations prioritize
structuredContent as the primary data source and fall back to content
for backward compatibility.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
olivermontes and others added 5 commits January 17, 2026 13:19
Adds optional displayName field to MCP integrations to show user-friendly
names in the UI while maintaining technical names for API compatibility.

- Add displayName field to LevanteAPIServer and MCPRegistryEntry types
- Map displayName from API responses in MCPProviderService
- Update UI components to display displayName with fallback to name
- Use technical name for server config to avoid special characters in APIs
- Include displayName in search queries for better discoverability
- Update AI tools to search and display using displayName

This allows integrations like "Buscador_de_vuelos_navidenos" to be shown
as "Buscador de vuelos navideños" while keeping API-safe names in configs.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…sion

feat: add displayName support for user-friendly MCP integration names
## Summary
Migrated Levante's custom logging system (420 lines) to Winston logger while maintaining 100% backward compatibility and zero overhead for disabled categories.

## Key Changes

### New Files
- `src/main/services/logging/winstonConfig.ts` - Winston transport configuration
- `src/main/services/logging/timezoneFormat.ts` - Timezone support (extracted from transports.ts)
- `docs/testing/winston-migration-testing.md` - Comprehensive testing guide
- `scripts/test-winston-logging.ts` - Automated testing script

### Modified Files
- `src/main/services/logging/logger.ts` - Replaced custom transports with Winston logger
- `src/main/services/logging/config.ts` - Added production/development defaults
- `src/main/services/logging/index.ts` - Updated exports
- `package.json` - Added winston-daily-rotate-file dependency

### Removed Files
- `src/main/services/logging/transports.ts` - Replaced by Winston transports (420 lines removed)

## Features

### Production vs Development
**Development** (NODE_ENV=development):
- Console output with colors
- Debug level logging
- Verbose categories enabled (ai-sdk, mcp, database, oauth)
- Single file: levante-YYYY-MM-DD-HHmmss.log
- Rotation: 10MB, 3 files, 7 days

**Production** (NODE_ENV=production):
- No console output (file only)
- Warn level logging
- Verbose categories disabled
- Two files: all logs + error-only log
- Rotation: 50MB, 10 files, 30 days
- Gzip compression enabled

### Preserved Features
✅ Zero overhead for disabled categories
✅ 9 categories (ai-sdk, mcp, database, ipc, preferences, models, core, analytics, oauth)
✅ Environment variable configuration
✅ Timezone support
✅ IPC bridge (renderer → main)
✅ Same public API (no breaking changes)

### New Capabilities
✨ Structured JSON logs (production)
✨ Separate error log file (production)
✨ Battle-tested Winston transports
✨ Automatic gzip compression
✨ Winston audit files for rotation tracking
✨ Foundation for future log viewer UI

## Code Impact
- Lines added: ~350
- Lines removed: ~420
- Net reduction: ~70 lines
- Breaking changes: 0

## Documentation
- Updated `docs/LOGGING.md` with "Arquitectura Winston" section
- Updated `CLAUDE.md` logging section
- Added comprehensive testing guide

## Testing
- ✅ Typecheck passes
- ✅ Zero overhead verified
- ✅ Backward compatible API
- Manual testing required per testing guide

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
## Bloqueantes Corregidos

1. **Console colorization**: Moved `colorize()` before `printf()` to enable ANSI colors in development console logs
2. **Type safety**: Removed unnecessary `any` cast for `initializeFromEnvironment()`
3. **Error handling**: Added try-catch with rollback in `configure()` and `refresh()` to prevent broken logger state

## Mejora Opcional

- **Development file format**: Use human-readable format (without ANSI colors) for log files in development mode

## Files Changed

- `src/main/services/logging/winstonConfig.ts` - Fix colorize order + dev file format
- `src/main/services/logging/logger.ts` - Fix type cast + error handling

## Testing

- ✅ Console logs now show colors in development
- ✅ Logger remains functional if reconfiguration fails
- ✅ Typecheck passes

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
## Fixes

### 1. BigInt Serialization Error
**Problem**: SQLite returns `lastInsertRowid` as BigInt, which cannot be
serialized to JSON by Winston, causing "Do not know how to serialize a BigInt" errors.

**Root Cause**: Bug introduced in commit 98c443c when migrating from console.log
(handles BigInt natively) to structured logging (uses JSON.stringify).

**Solution**:
- Convert BigInt to String in databaseService.ts before logging
- Remove `fullResult` logging in chatStore.ts that contained BigInt

**Files Changed**:
- `src/main/services/databaseService.ts` - Convert lastInsertRowid to String
- `src/renderer/stores/chatStore.ts` - Remove fullResult from error logs

### 2. Excessive Log Rotation
**Problem**: Logs were rotating every second, creating hundreds of tiny files
(levante-2026-01-28-205641.log, levante-2026-01-28-205647.log, etc.)

**Root Cause**: datePattern 'YYYY-MM-DD-HHmmss' includes seconds, causing
winston-daily-rotate-file to rotate whenever the second changes.

**Solution**:
- Changed datePattern from 'YYYY-MM-DD-HHmmss' to 'YYYY-MM-DD'
- Now creates 1 file per day instead of per second

**Files Changed**:
- `src/main/services/logging/config.ts` - Update datePattern to daily rotation

## Testing

- ✅ No BigInt serialization errors
- ✅ Logs rotate daily (1 file per day)
- ✅ All log categories working (AI-SDK, DATABASE, CORE, MCP)
- ✅ JSON formatting correct with indentation
- ✅ No ANSI colors in log files
- ✅ Winston audit system tracking files correctly

## Impact

- Eliminates BigInt serialization crashes
- Reduces file system clutter (1 file/day vs hundreds)
- Maintains all Winston logging benefits

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@Saul-Gomez-J
Copy link
Contributor Author

Closing to recreate against develop branch

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants