diff --git a/frontend-modern/src/App.tsx b/frontend-modern/src/App.tsx index 9b01f6fc9..d34d822cf 100644 --- a/frontend-modern/src/App.tsx +++ b/frontend-modern/src/App.tsx @@ -46,6 +46,7 @@ import SettingsIcon from 'lucide-solid/icons/settings'; import NetworkIcon from 'lucide-solid/icons/network'; import Maximize2Icon from 'lucide-solid/icons/maximize-2'; import Minimize2Icon from 'lucide-solid/icons/minimize-2'; +import { PulsePatrolLogo } from '@/components/Brand/PulsePatrolLogo'; import { TokenRevealDialog } from './components/TokenRevealDialog'; import { useAlertsActivation } from './stores/alertsActivation'; import { UpdateProgressModal } from './components/UpdateProgressModal'; @@ -53,6 +54,7 @@ import type { UpdateStatus } from './api/updates'; import { AIChat } from './components/AI/Chat'; import { AIStatusIndicator } from './components/AI/AIStatusIndicator'; import { aiChatStore } from './stores/aiChat'; +import { getPatrolStatus } from './api/patrol'; import { useResourcesAsLegacy } from './hooks/useResources'; import { updateSystemSettingsFromResponse, markSystemSettingsLoadedWithDefaults } from './stores/systemSettings'; import { initKioskMode, isKioskMode, setKioskMode, subscribeToKioskMode } from './utils/url'; @@ -83,6 +85,9 @@ const HostsOverview = lazy(() => default: module.HostsOverview, })), ); +const AIIntelligencePage = lazy(() => + import('./pages/AIIntelligence').then((module) => ({ default: module.AIIntelligence })), +); // Enhanced store type with proper typing @@ -962,6 +967,7 @@ function App() { } /> + ); @@ -1037,6 +1043,17 @@ function AppLayout(props: { const navigate = useNavigate(); const location = useLocation(); + // Track patrol license status for Pro badge + const [patrolLicenseRequired, setPatrolLicenseRequired] = createSignal(false); + onMount(async () => { + try { + const status = await getPatrolStatus(); + setPatrolLicenseRequired(status.license_required ?? false); + } catch { + // Ignore errors - default to not showing badge + } + }); + const readSeenPlatforms = (): Record => { if (typeof window === 'undefined') return {}; try { @@ -1101,6 +1118,7 @@ function AppLayout(props: { if (path.startsWith('/hosts')) return 'hosts'; if (path.startsWith('/servers')) return 'hosts'; // Legacy redirect if (path.startsWith('/alerts')) return 'alerts'; + if (path.startsWith('/ai')) return 'ai'; if (path.startsWith('/settings')) return 'settings'; return 'proxmox'; }; @@ -1223,11 +1241,11 @@ function AppLayout(props: { scopes.includes('*') || scopes.includes('settings:read'); const tabs: Array<{ - id: 'alerts' | 'settings'; + id: 'alerts' | 'ai' | 'settings'; label: string; route: string; tooltip: string; - badge: 'update' | null; + badge: 'update' | 'pro' | null; count: number | undefined; breakdown: { warning: number; critical: number } | undefined; icon: JSX.Element; @@ -1242,6 +1260,16 @@ function AppLayout(props: { breakdown, icon: , }, + { + id: 'ai', + label: 'Patrol', + route: '/ai', + tooltip: 'Pulse Patrol monitoring and analysis', + badge: patrolLicenseRequired() ? 'pro' : null, + count: undefined, + breakdown: undefined, + icon: , + }, ]; // Only show settings tab if user has access @@ -1484,6 +1512,11 @@ function AppLayout(props: { + + + Pro + + ); }} diff --git a/frontend-modern/src/api/agentProfiles.ts b/frontend-modern/src/api/agentProfiles.ts index cc666c6d1..4ee1f02fc 100644 --- a/frontend-modern/src/api/agentProfiles.ts +++ b/frontend-modern/src/api/agentProfiles.ts @@ -231,7 +231,7 @@ export class AgentProfilesAPI { if (!response.ok) { const text = await response.text(); if (response.status === 503) { - throw new Error('AI service is not available. Please check AI settings.'); + throw new Error('Pulse Assistant service is not available. Please check Pulse Assistant settings.'); } throw new Error(text || `Failed to get suggestion: ${response.status}`); } diff --git a/frontend-modern/src/components/Backups/UnifiedBackups.tsx b/frontend-modern/src/components/Backups/UnifiedBackups.tsx index 935ffb7d8..6eeaf93bc 100644 --- a/frontend-modern/src/components/Backups/UnifiedBackups.tsx +++ b/frontend-modern/src/components/Backups/UnifiedBackups.tsx @@ -1163,7 +1163,7 @@ const UnifiedBackups: Component = () => { } title="No backup sources configured" - description="Add a Proxmox VE or PBS node in the Settings tab to start monitoring backups." + description="Install the Pulse agent for extra capabilities (temperature monitoring and Pulse Patrol automation), or add a node via API token in Settings → Proxmox." actions={ diff --git a/frontend-modern/src/components/Settings/DiagnosticsPanel.tsx b/frontend-modern/src/components/Settings/DiagnosticsPanel.tsx index f94799645..69c3afa05 100644 --- a/frontend-modern/src/components/Settings/DiagnosticsPanel.tsx +++ b/frontend-modern/src/components/Settings/DiagnosticsPanel.tsx @@ -684,7 +684,7 @@ export const DiagnosticsPanel: Component = () => {

Pulse Assistant

-

Pulse AI Service

+

Pulse Assistant Service

= (props) => {
  • Creates monitoring user and API token automatically
  • Registers the node with Pulse
  • Enables temperature monitoring (no SSH required)
  • -
  • Enables AI features for managing VMs/containers
  • +
  • Enables Pulse Patrol automation for managing VMs/containers
  • Run this command on your Proxmox VE node: @@ -797,7 +797,7 @@ export const NodeModal: Component = (props) => {

    - Limited functionality: API-only mode does not include temperature monitoring or AI features. + Limited functionality: API-only mode does not include temperature monitoring or Pulse Patrol automation. For full functionality, use the Agent Install tab instead.

    @@ -1307,7 +1307,7 @@ export const NodeModal: Component = (props) => {
    • One-command setup (creates API user and token automatically)
    • Built-in temperature monitoring (no SSH required)
    • -
    • Pulse features (execute commands via Pulse AI)
    • +
    • Pulse features (execute commands via Pulse Assistant)
    • Automatic reconnection on network issues

    diff --git a/frontend-modern/src/components/Settings/ProLicensePanel.tsx b/frontend-modern/src/components/Settings/ProLicensePanel.tsx index 970b4557d..a764c2fe1 100644 --- a/frontend-modern/src/components/Settings/ProLicensePanel.tsx +++ b/frontend-modern/src/components/Settings/ProLicensePanel.tsx @@ -19,8 +19,8 @@ const TIER_LABELS: Record = { const FEATURE_LABELS: Record = { ai_patrol: 'Pulse Patrol', ai_alerts: 'Pulse Alert Analysis', - ai_autofix: 'AI Auto-Fix', - kubernetes_ai: 'Kubernetes AI', + ai_autofix: 'Patrol Auto-Fix', + kubernetes_ai: 'Kubernetes Insights', update_alerts: 'Update Alerts', multi_user: 'Multi-user / RBAC', white_label: 'White-label Branding', @@ -153,7 +153,7 @@ export const ProLicensePanel: Component = () => {

    = (props) => {

    - Recommended: Install the Pulse agent on your Proxmox nodes for automatic setup, temperature monitoring, and AI features. + Recommended: Install the Pulse agent on your Proxmox nodes for extra capabilities like temperature monitoring and Pulse Patrol automation (it also auto-creates the API token and links the node). +

    +

    + Prefer not to run an agent on PVE? Use the manual API token setup below.

    diff --git a/frontend-modern/src/components/Settings/SuggestProfileModal.tsx b/frontend-modern/src/components/Settings/SuggestProfileModal.tsx index 4b9676223..b895df095 100644 --- a/frontend-modern/src/components/Settings/SuggestProfileModal.tsx +++ b/frontend-modern/src/components/Settings/SuggestProfileModal.tsx @@ -247,10 +247,10 @@ export const SuggestProfileModal: Component = (props)

    - AI Profile Suggestion + Pulse Assistant Profile Suggestion

    - Describe what you need, and AI will draft a profile + Describe what you need, and Pulse Assistant will draft a profile

    diff --git a/frontend-modern/src/components/Settings/UnifiedAgents.tsx b/frontend-modern/src/components/Settings/UnifiedAgents.tsx index df018de33..57b533614 100644 --- a/frontend-modern/src/components/Settings/UnifiedAgents.tsx +++ b/frontend-modern/src/components/Settings/UnifiedAgents.tsx @@ -1,6 +1,8 @@ import { Component, createSignal, Show, For, onMount, createEffect, createMemo } from 'solid-js'; +import { useNavigate } from '@solidjs/router'; import { useWebSocket } from '@/App'; import { Card } from '@/components/shared/Card'; +import { ProxmoxIcon } from '@/components/icons/ProxmoxIcon'; import { formatRelativeTime, formatAbsoluteTime } from '@/utils/format'; import { MonitoringAPI } from '@/api/monitoring'; import { AgentProfilesAPI, type AgentProfile, type AgentProfileAssignment } from '@/api/agentProfiles'; @@ -144,6 +146,7 @@ const buildCommandsByPlatform = (url: string): Record< export const UnifiedAgents: Component = () => { const { state } = useWebSocket(); + const navigate = useNavigate(); let hasLoggedSecurityStatusError = false; @@ -476,7 +479,7 @@ export const UnifiedAgents: Component = () => { profile.description?.toLowerCase().includes('pulse ai') || name.toLowerCase().startsWith('ai scope'); return isAIManaged - ? { label: 'AI-managed', detail: name, category: 'ai-managed' as const } + ? { label: 'Patrol-managed', detail: name, category: 'ai-managed' as const } : { label: name, detail: 'Assigned profile', category: 'profile' as const }; }; @@ -756,7 +759,7 @@ export const UnifiedAgents: Component = () => { try { await MonitoringAPI.updateHostAgentConfig(hostId, { commandsEnabled: enabled }); - notificationStore.success(`AI command execution ${enabled ? 'enabled' : 'disabled'}. Syncing with agent...`); + notificationStore.success(`Pulse command execution ${enabled ? 'enabled' : 'disabled'}. Syncing with agent...`); } catch (err) { // On error, clear the pending state so toggle reverts setPendingCommandConfig(prev => { @@ -816,6 +819,24 @@ export const UnifiedAgents: Component = () => {

    +
    +
    + +
    +

    + Proxmox nodes can be added here with the unified agent for extra capabilities like temperature monitoring and Pulse Patrol automation (auto-creates the API token and links the node). +

    + +
    +
    +
    +
    @@ -962,11 +983,11 @@ export const UnifiedAgents: Component = () => { onChange={(e) => setEnableCommands(e.currentTarget.checked)} class="rounded border-gray-300 text-blue-600 focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-700" /> - Enable Pulse command execution (for AI auto-fix) + Enable Pulse command execution (for Patrol auto-fix)
    - Pulse commands enabled — The agent will accept diagnostic and fix commands from Pulse AI features. + Pulse commands enabled — The agent will accept diagnostic and fix commands from Pulse Patrol features.
    @@ -1249,7 +1270,7 @@ export const UnifiedAgents: Component = () => { - +
    @@ -1446,8 +1467,8 @@ export const UnifiedAgents: Component = () => { title={isPending ? 'Syncing with agent...' : effectiveEnabled - ? 'AI command execution enabled' - : 'AI command execution disabled' + ? 'Pulse command execution enabled' + : 'Pulse command execution disabled' } > = (props) => { const features = [ { id: 'ai', - name: 'Pulse AI', + name: 'Pulse Assistant', icon: '🤖', - desc: 'Intelligent monitoring assistant with auto-fix capabilities', + desc: 'Guided troubleshooting with Patrol automation and auto-fix capabilities', enabled: aiEnabled, setEnabled: setAiEnabled, badge: 'New in 5.0', @@ -97,12 +97,12 @@ export const FeaturesStep: Component = (props) => { ))} - {/* AI info box */} + {/* Assistant info box */}
    -

    Pulse AI Features

    +

    Pulse Assistant & Patrol Features

    • Chat assistant for infrastructure questions
    • Patrol mode for proactive monitoring
    @@ -110,7 +110,7 @@ export const FeaturesStep: Component = (props) => { • Predictive failure detection

    - Requires API key configuration in Settings → AI after setup + Requires API key configuration in Settings → Pulse Assistant after setup

    diff --git a/frontend-modern/src/components/Storage/Storage.tsx b/frontend-modern/src/components/Storage/Storage.tsx index af7501041..a78a9fbe2 100644 --- a/frontend-modern/src/components/Storage/Storage.tsx +++ b/frontend-modern/src/components/Storage/Storage.tsx @@ -754,7 +754,7 @@ const Storage: Component = () => { } title="No storage configured" - description="Add a Proxmox VE or PBS node in the Settings tab to start monitoring storage." + description="Install the Pulse agent for extra capabilities (temperature monitoring and Pulse Patrol automation), or add a node via API token in Settings → Proxmox." actions={