Pulse/frontend-modern/vite.config.ts
rcourtman 8c7581d32c feat(profiles): add AI-assisted profile suggestions
Add ability for users to describe what kind of agent profile they need
in natural language, and have AI generate a suggestion with name,
description, config values, and rationale.

- Add ProfileSuggestionHandler with schema-aware prompting
- Add SuggestProfileModal component with example prompts
- Update AgentProfilesPanel with suggest button and description field
- Streamline ValidConfigKeys to only agent-supported settings
- Update profile validation tests for simplified schema
2026-01-15 13:24:18 +00:00

237 lines
7.5 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);
});
},
},
// SSE endpoint for AI chat streaming
'/api/ai/execute/stream': {
target: backendUrl,
changeOrigin: true,
// SSE requires special handling to prevent proxy timeouts
// Set timeout to 0 to completely disable
timeout: 0,
proxyTimeout: 0,
configure: (proxy, _options) => {
// Completely disable http-proxy internal timeouts
proxy.options.timeout = 0;
proxy.options.proxyTimeout = 0;
// 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, 30000);
// 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, 30000);
// Also disable on proxy response socket
proxyRes.socket?.setTimeout(0);
});
proxy.on('error', (err, req, res) => {
console.error('[SSE Proxy Error]', err.message);
});
},
},
// SSE endpoint for AI alert investigation (one-click investigate from alerts page)
'/api/ai/investigate-alert': {
target: backendUrl,
changeOrigin: true,
// SSE requires special handling to prevent proxy timeouts
timeout: 0,
proxyTimeout: 0,
configure: (proxy, _options) => {
proxy.options.timeout = 0;
proxy.options.proxyTimeout = 0;
proxy.on('proxyReq', (proxyReq, req, res) => {
req.socket.setTimeout(0);
req.socket.setNoDelay(true);
req.socket.setKeepAlive(true, 30000);
proxyReq.socket?.setTimeout(0);
});
proxy.on('proxyRes', (proxyRes, req, res) => {
res.socket?.setTimeout(0);
res.socket?.setNoDelay(true);
res.socket?.setKeepAlive(true, 30000);
proxyRes.socket?.setTimeout(0);
});
proxy.on('error', (err, req, res) => {
console.error('[SSE Proxy Error - Investigate Alert]', err.message);
});
},
},
// SSE endpoint for AI patrol streaming
'/api/ai/patrol/stream': {
target: backendUrl,
changeOrigin: true,
timeout: 0,
proxyTimeout: 0,
configure: (proxy, _options) => {
proxy.options.timeout = 0;
proxy.options.proxyTimeout = 0;
proxy.on('proxyReq', (proxyReq, req, res) => {
req.socket.setTimeout(0);
req.socket.setNoDelay(true);
req.socket.setKeepAlive(true, 30000);
proxyReq.socket?.setTimeout(0);
});
proxy.on('proxyRes', (proxyRes, req, res) => {
res.socket?.setTimeout(0);
res.socket?.setNoDelay(true);
res.socket?.setKeepAlive(true, 30000);
proxyRes.socket?.setTimeout(0);
});
proxy.on('error', (err, req, res) => {
console.error('[SSE Proxy Error - Patrol Stream]', 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,
cookieDomainRewrite: '',
},
'/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'],
},
});