From 902029c805a0aa0062064694110e41a50912acc7 Mon Sep 17 00:00:00 2001 From: josedario87 Date: Sat, 14 Feb 2026 03:20:51 -0600 Subject: [PATCH] feat: Add HTTPS/Traefik support with centralized endpoints - Create traefik/agent-ui.yml with full routing config for domain z590.nucleoriofrio.com - Add frontend/src/config/endpoints.ts for automatic HTTP/HTTPS detection - Update all hardcoded localhost URLs to use relative paths - WebSocket connections auto-detect wss:// vs ws:// based on page protocol - Configure path-based WebSocket routing (/ws/terminal, /ws/mcp, /ws/status, /ws/whisper) - Add commented IP whitelist middleware for future security --- .claude/settings.local.json | 127 +++++++++ frontend/src/App.vue | 3 +- frontend/src/components/FloatingTerminal.vue | 3 +- frontend/src/components/FloatingVoice.vue | 11 +- .../composables/database/useDatabaseApi.ts | 3 +- .../composables/database/useQueryExecutor.ts | 3 +- frontend/src/config/endpoints.ts | 44 ++++ frontend/src/pages/SourceCodePage.vue | 6 +- frontend/src/pages/TerminalPage.vue | 3 +- frontend/src/services/dynamicComponents.ts | 3 +- frontend/src/services/themeService.ts | 3 +- .../tools/handlers/databaseHandlers.ts | 3 +- .../services/tools/handlers/globalHandlers.ts | 10 +- .../tools/handlers/sourceCodeHandlers.ts | 3 +- frontend/src/services/webmcp.ts | 18 +- frontend/src/stores/projectCanvas.ts | 3 +- frontend/src/stores/theme.ts | 3 +- traefik/agent-ui.yml | 248 ++++++++++++++++++ 18 files changed, 471 insertions(+), 26 deletions(-) create mode 100644 frontend/src/config/endpoints.ts create mode 100644 traefik/agent-ui.yml diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 4eeb78e..cfb8468 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -1,4 +1,131 @@ { + "hooks": { + "UserPromptSubmit": [ + { + "hooks": [ + { + "type": "command", + "command": "powershell -NoProfile -Command \"try { Invoke-RestMethod -Uri 'http://localhost:4101/api/claude-status' -Method POST -Body '{\\\"status\\\":\\\"processing\\\"}' -ContentType 'application/json' -TimeoutSec 2 | Out-Null } catch {}\"", + "timeout": 5000 + } + ] + } + ], + "PreToolUse": [ + { + "matcher": "Read|Glob|Grep", + "hooks": [ + { + "type": "command", + "command": "powershell -NoProfile -Command \"try { Invoke-RestMethod -Uri 'http://localhost:4101/api/claude-status' -Method POST -Body '{\\\"status\\\":\\\"reading\\\",\\\"tool\\\":\\\"$CLAUDE_TOOL_NAME\\\"}' -ContentType 'application/json' -TimeoutSec 2 | Out-Null } catch {}\"", + "timeout": 5000 + } + ] + }, + { + "matcher": "Edit|Write", + "hooks": [ + { + "type": "command", + "command": "powershell -NoProfile -Command \"try { Invoke-RestMethod -Uri 'http://localhost:4101/api/claude-status' -Method POST -Body '{\\\"status\\\":\\\"writing\\\",\\\"tool\\\":\\\"$CLAUDE_TOOL_NAME\\\"}' -ContentType 'application/json' -TimeoutSec 2 | Out-Null } catch {}\"", + "timeout": 5000 + } + ] + }, + { + "matcher": ".*", + "hooks": [ + { + "type": "command", + "command": "powershell -NoProfile -Command \"try { Invoke-RestMethod -Uri 'http://localhost:4101/api/claude-status' -Method POST -Body '{\\\"status\\\":\\\"toolUse\\\",\\\"tool\\\":\\\"$CLAUDE_TOOL_NAME\\\"}' -ContentType 'application/json' -TimeoutSec 2 | Out-Null } catch {}\"", + "timeout": 5000 + } + ] + } + ], + "PostToolUse": [ + { + "matcher": ".*", + "hooks": [ + { + "type": "command", + "command": "powershell -NoProfile -Command \"try { Invoke-RestMethod -Uri 'http://localhost:4101/api/claude-status' -Method POST -Body '{\\\"status\\\":\\\"toolDone\\\",\\\"tool\\\":\\\"$CLAUDE_TOOL_NAME\\\"}' -ContentType 'application/json' -TimeoutSec 2 | Out-Null } catch {}\"", + "timeout": 5000 + } + ] + } + ], + "SessionStart": [ + { + "hooks": [ + { + "type": "command", + "command": "powershell -NoProfile -Command \"try { Invoke-RestMethod -Uri 'http://localhost:4101/api/claude-status' -Method POST -Body '{\\\"status\\\":\\\"sessionStart\\\"}' -ContentType 'application/json' -TimeoutSec 2 | Out-Null } catch {}\"", + "timeout": 5000 + } + ] + } + ], + "SubagentStart": [ + { + "matcher": ".*", + "hooks": [ + { + "type": "command", + "command": "powershell -NoProfile -Command \"try { Invoke-RestMethod -Uri 'http://localhost:4101/api/claude-status' -Method POST -Body '{\\\"status\\\":\\\"subagentStart\\\"}' -ContentType 'application/json' -TimeoutSec 2 | Out-Null } catch {}\"", + "timeout": 5000 + } + ] + } + ], + "SubagentStop": [ + { + "matcher": ".*", + "hooks": [ + { + "type": "command", + "command": "powershell -NoProfile -Command \"try { Invoke-RestMethod -Uri 'http://localhost:4101/api/claude-status' -Method POST -Body '{\\\"status\\\":\\\"subagentStop\\\"}' -ContentType 'application/json' -TimeoutSec 2 | Out-Null } catch {}\"", + "timeout": 5000 + } + ] + } + ], + "PermissionRequest": [ + { + "matcher": ".*", + "hooks": [ + { + "type": "command", + "command": "powershell -NoProfile -Command \"try { Invoke-RestMethod -Uri 'http://localhost:4101/api/claude-status' -Method POST -Body '{\\\"status\\\":\\\"permissionRequest\\\",\\\"tool\\\":\\\"$CLAUDE_TOOL_NAME\\\"}' -ContentType 'application/json' -TimeoutSec 2 | Out-Null } catch {}\"", + "timeout": 5000 + } + ] + } + ], + "Notification": [ + { + "matcher": ".*", + "hooks": [ + { + "type": "command", + "command": "powershell -NoProfile -Command \"try { Invoke-RestMethod -Uri 'http://localhost:4101/api/claude-status' -Method POST -Body '{\\\"status\\\":\\\"notification\\\"}' -ContentType 'application/json' -TimeoutSec 2 | Out-Null } catch {}\"", + "timeout": 5000 + } + ] + } + ], + "Stop": [ + { + "hooks": [ + { + "type": "command", + "command": "powershell -NoProfile -Command \"try { Invoke-RestMethod -Uri 'http://localhost:4101/api/claude-status' -Method POST -Body '{\\\"status\\\":\\\"idle\\\"}' -ContentType 'application/json' -TimeoutSec 2 | Out-Null } catch {}\"", + "timeout": 5000 + } + ] + } + ] + }, "permissions": { "allow": [ "Skill(playwright-cli)", diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 8d7beae..5b561c3 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -11,6 +11,7 @@ import FloatingResponse from './components/FloatingResponse.vue' import FloatingVoice from './components/FloatingVoice.vue' import PwaInstallBanner from './components/PwaInstallBanner.vue' import { initWebMCP, getWebMCP, startTokenPolling, stopTokenPolling, connectWithToken } from './services/webmcp' +import { endpoints } from './config/endpoints' import { initToolRegistry, activatePageTools, initToolsOnRefresh } from './services/toolRegistry' import { setTerminalControls } from './services/tools/handlers/terminalHandlers' import { setResponseControls } from './services/tools/handlers/responseHandlers' @@ -48,7 +49,7 @@ let toolFlashTimeout: number | null = null function connectStatusWs() { if (statusWs?.readyState === WebSocket.OPEN) return - statusWs = new WebSocket(`ws://${window.location.hostname}:4103`) + statusWs = new WebSocket(endpoints.claudeStatus) statusWs.onopen = () => { console.log('[App] Status WebSocket connected') diff --git a/frontend/src/components/FloatingTerminal.vue b/frontend/src/components/FloatingTerminal.vue index 09d91bf..33a59b7 100644 --- a/frontend/src/components/FloatingTerminal.vue +++ b/frontend/src/components/FloatingTerminal.vue @@ -6,6 +6,7 @@ import { WebLinksAddon } from '@xterm/addon-web-links' import '@xterm/xterm/css/xterm.css' import { connectWithToken, stopTokenPolling } from '../services/webmcp' import { useCanvasStore } from '../stores/canvas' +import { endpoints } from '../config/endpoints' const props = defineProps<{ modelValue: boolean @@ -47,7 +48,7 @@ let tokenBuffer = '' let tokenTimeout: number | null = null const waitingForToken = ref(false) -const WS_URL = `ws://${window.location.hostname}:4103` +const WS_URL = endpoints.terminal // Mouse position tracking for Ctrl+E const mousePos = ref({ x: 0, y: 0 }) diff --git a/frontend/src/components/FloatingVoice.vue b/frontend/src/components/FloatingVoice.vue index 837af65..9d9495f 100644 --- a/frontend/src/components/FloatingVoice.vue +++ b/frontend/src/components/FloatingVoice.vue @@ -1,6 +1,7 @@