Pulse/frontend-modern/vite.config.ts
rcourtman cc3c0187a0 feat: AI features, agent improvements, and host monitoring enhancements
AI Chat Integration:
- Multi-provider support (Anthropic, OpenAI, Ollama)
- Streaming responses with markdown rendering
- Agent command execution for remote troubleshooting
- Context-aware conversations with host/container metadata

Agent Updates:
- Add --enable-proxmox flag for automatic PVE/PBS token setup
- Improve auto-update with semver comparison (prevents downgrades)
- Add updatedFrom tracking to report previous version after update
- Reduce initial update check delay from 30s to 5s
- Add agent version column to Hosts page table

Host Metrics:
- Add DiskIO stats collection (read/write bytes, ops, time)
- Improve disk filtering to exclude Docker overlay mounts
- Add RAID array monitoring via mdadm
- Enhanced temperature sensor parsing

Frontend:
- New Agent Version column on Hosts overview table
- Improved node modal with agent-first installation flow
- Add DiskIO display in host drawer
- Better responsive handling for metric bars
2025-12-05 10:37:02 +00:00

176 lines
5.3 KiB
TypeScript

import { defineConfig } from 'vite';
import solid from 'vite-plugin-solid';
import path from 'path';
import { URL } from 'node:url';
const frontendDevHost = process.env.FRONTEND_DEV_HOST ?? '0.0.0.0';
const frontendDevPort = Number(
process.env.FRONTEND_DEV_PORT ?? process.env.VITE_PORT ?? process.env.PORT ?? 5173,
);
const backendProtocol = process.env.PULSE_DEV_API_PROTOCOL ?? 'http';
const backendHost = process.env.PULSE_DEV_API_HOST ?? '127.0.0.1';
const backendPort = Number(
process.env.PULSE_DEV_API_PORT ??
process.env.FRONTEND_PORT ??
process.env.PORT ??
7655,
);
const backendUrl =
process.env.PULSE_DEV_API_URL ?? `${backendProtocol}://${backendHost}:${backendPort}`;
const backendWsUrl =
process.env.PULSE_DEV_WS_URL ??
(() => {
try {
const parsed = new URL(backendUrl);
parsed.protocol = parsed.protocol === 'https:' ? 'wss:' : 'ws:';
return parsed.toString();
} catch {
return backendUrl
.replace(/^http:\/\//i, 'ws://')
.replace(/^https:\/\//i, 'wss://');
}
})();
export default defineConfig({
plugins: [solid()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
},
conditions: ['import', 'browser', 'default'],
},
server: {
port: frontendDevPort,
host: frontendDevHost, // Listen on all interfaces for remote access
strictPort: true,
proxy: {
'/ws': {
target: backendWsUrl,
ws: true,
changeOrigin: true,
// Browser WebSocket connections are long-lived, disable timeouts
proxyTimeout: 0,
timeout: 0,
configure: (proxy, _options) => {
proxy.options.timeout = 0;
proxy.options.proxyTimeout = 0;
proxy.on('proxyReqWs', (proxyReq, req, socket) => {
socket.setTimeout(0);
socket.setNoDelay(true);
socket.setKeepAlive(true, 30000);
});
proxy.on('open', (proxySocket) => {
proxySocket.setTimeout(0);
proxySocket.setNoDelay(true);
proxySocket.setKeepAlive(true, 30000);
});
},
},
'/api/ai/execute/stream': {
target: backendUrl,
changeOrigin: true,
// SSE requires special handling to prevent proxy timeouts
// Set timeout to 10 minutes (600000ms) for long-running AI requests
timeout: 600000,
proxyTimeout: 600000,
configure: (proxy, _options) => {
// Set proxy-level timeouts
proxy.on('proxyReq', (proxyReq, req, res) => {
// Disable socket timeouts for SSE
req.socket.setTimeout(0);
req.socket.setNoDelay(true);
req.socket.setKeepAlive(true);
// Also set on the proxy request
proxyReq.socket?.setTimeout(0);
});
proxy.on('proxyRes', (proxyRes, req, res) => {
// Disable response socket timeout
res.socket?.setTimeout(0);
res.socket?.setNoDelay(true);
res.socket?.setKeepAlive(true);
// Also disable on proxy response socket
proxyRes.socket?.setTimeout(0);
});
proxy.on('error', (err, req, res) => {
console.error('[SSE Proxy Error]', err.message);
});
},
},
'/api/agent/ws': {
target: backendWsUrl,
ws: true,
changeOrigin: true,
// Agent WebSocket connections are long-lived, disable timeouts
// proxyTimeout: 0 disables the proxy-to-target timeout
// timeout: 0 disables the client-to-proxy timeout
proxyTimeout: 0,
timeout: 0,
configure: (proxy, _options) => {
// Disable http-proxy's internal timeout (default is 2 minutes but seems to be 10s)
proxy.options.timeout = 0;
proxy.options.proxyTimeout = 0;
proxy.on('proxyReqWs', (proxyReq, req, socket) => {
// Disable socket timeouts for WebSocket connections
socket.setTimeout(0);
socket.setNoDelay(true);
socket.setKeepAlive(true, 30000);
});
proxy.on('open', (proxySocket) => {
// Also disable timeout on the proxy socket
proxySocket.setTimeout(0);
proxySocket.setNoDelay(true);
proxySocket.setKeepAlive(true, 30000);
});
proxy.on('error', (err, req, res) => {
console.error('[Agent WS Proxy Error]', err.message);
});
},
},
'/api': {
target: backendUrl,
changeOrigin: true,
},
'/install-docker-agent.sh': {
target: backendUrl,
changeOrigin: true,
},
'/install-container-agent.sh': {
target: backendUrl,
changeOrigin: true,
},
'/install-host-agent.sh': {
target: backendUrl,
changeOrigin: true,
},
'/install-host-agent.ps1': {
target: backendUrl,
changeOrigin: true,
},
'/install.sh': {
target: backendUrl,
changeOrigin: true,
},
'/install.ps1': {
target: backendUrl,
changeOrigin: true,
},
'/download': {
target: backendUrl,
changeOrigin: true,
},
},
},
build: {
target: 'esnext',
},
test: {
environment: 'jsdom',
globals: true,
setupFiles: ['./src/test/setup.ts'],
},
});