- Add cluster-aware guest ID generation (clusterName-VMID instead of instanceName-VMID)
to prevent duplicate VMs/containers when multiple cluster nodes are monitored
- Add cluster deduplication at registration time - when a node is added that belongs
to an already-configured cluster, merge as endpoint instead of creating duplicate
- Add startup consolidation to automatically merge duplicate cluster instances
- Change host agent token binding from agent GUID to hostname, allowing:
- Multiple host agents to share a token (each bound by hostname)
- Agent reinstalls on same host without token conflicts
- Remove 12-character password minimum requirement
- Remove emoji from auto-registration success message
- Fix grouped view node lookup to support both cluster-aware node IDs
(clusterName-nodeName) and legacy guest grouping keys (instance-nodeName)
Fixes duplicate guests appearing when agents are installed on multiple
cluster nodes. Also improves multi-agent UX by allowing shared tokens.
- NodeGroupHeader shows '+ Host Agent' badge when node has linked agent
- NodeSummaryTable shows '+Agent' badge in the node row
- Filter out linked hosts from Managed Agents list (prevents duplication)
This provides visual feedback when a PVE node has enhanced monitoring
via an installed host agent.
- Added linkedHostAgentId to Node interface
- Added linkedNodeId/linkedVmId/linkedContainerId to Host interface
- Filter out linked hosts from 'Managed Agents' list (they show merged with nodes)
Next: Update Dashboard to display linked entity badges
When a host agent registers, it now searches for a PVE node with a
matching hostname and links them together. Similarly, when PVE nodes
are discovered, they check for existing host agents with matching hostnames.
This prevents the confusion of seeing duplicate entries when users install
agents on PVE cluster nodes that were already discovered via the cluster API.
- Added LinkedHostAgentID field to Node struct
- Added LinkedNodeID/LinkedVMID/LinkedContainerID fields to Host struct
- Added findLinkedProxmoxEntity() to match by hostname (with domain stripping)
- Updated UpdateNodesForInstance() to preserve and auto-set links
Users no longer need to manually click 'New Token' - a fresh token is
automatically generated after each copy. The command shown is always
ready for the next host.
- Setup wizard now clearly states 'Use a different token for each host'
- New Token button is always visible and more prominent (blue styling)
- WebSocket store now clears stale agents (>60s since lastSeen) immediately
when receiving empty host arrays, instead of waiting for 3 consecutive updates
The anti-flapping logic previously required 3 consecutive empty updates
before clearing stale agents from the UI. Now if all existing hosts/dockerHosts
have lastSeen > 60 seconds ago, empty updates are applied immediately.
This fixes the issue where removed agents stayed visible for too long.
The previous fix added legacy cleanup for systemd/macOS but missed the
Unraid-specific section. Now removes pulse-host-agent and pulse-docker-agent
entries from /boot/config/go and cleans up /boot/config/pulse directory.
Changed misleading 'Each copy uses a unique token' to 'Use the same
command on multiple servers'. Also toned down the 'Different Token'
button since it's rarely needed.
The --uninstall flag now removes:
- Unified pulse-agent (service, binary, logs)
- Legacy pulse-host-agent (service, binary, logs)
- Legacy pulse-docker-agent (service, binary, logs)
- Agent state directory (/var/lib/pulse-agent)
- All related log files
Works on Linux (systemd), macOS (launchd), and other supported platforms.
Removed Connect and Features steps that were adding friction without much value.
The wizard now focuses on:
1. Welcome - introduction and bootstrap token entry
2. Security - credential setup
3. Complete - shows install command and connected agents
Agent polling now happens in CompleteStep instead of relying on WebSockets
which aren't available during the pre-login setup phase.
When no auth is configured (fresh install), CheckAuth allows all requests.
This creates a race condition where existing agents from a previous setup
can report data before the wizard completes security configuration.
This fix clears all host agents and docker hosts when /api/security/quick-setup
is called, ensuring the wizard shows a clean state after security is configured.
Added:
- State.ClearAllHosts() - removes all host agents
- State.ClearAllDockerHosts() - removes all docker hosts
- Monitor.ClearUnauthenticatedAgents() - clears both and resets token bindings
- Call to ClearUnauthenticatedAgents() in handleQuickSecuritySetupFixed()
The button was showing when aiChatStore.enabled was undefined.
Changed condition from 'enabled !== false' to 'enabled === true'
to only show when AI is explicitly enabled.
- Disabling OIDC now saves immediately (safe operation)
- Enabling requires Save button press (prevents lockout without config)
- Shows helpful hint when enabling: configure first, then save
- Fixed type mismatches in ProxmoxAgentNodesPanel (prop signatures)
- Fixed temperatureTransports type (array vs single object)
- Added ARIA attributes to SetupWizard for screen reader support
- All tsc --noEmit checks pass
- Fixed unused variables in wizard components
- Fixed invalid aiEnabled field in FeaturesStep (AI uses separate API)
- Added AI endpoints section to API.md
- New SetupWizard component with 5-step flow:
1. Welcome: Bootstrap token unlock, platform showcase
2. Security: Admin account + API token creation
3. Connect: Multi-platform infrastructure (Proxmox, Docker, K8s)
4. Features: AI and auto-updates toggles
5. Complete: Credentials display with copy/download
- Replaced FirstRunSetup with SetupWizard in Login.tsx
- Added Install Update button to UpdatesSettingsPanel
- Enhanced UpdatesSettingsPanel with update plan integration
- Added UpdateConfirmationModal to Settings for inline updates
Positions Pulse as a unified infrastructure monitoring platform,
not just a Proxmox-specific tool.
- Add GET /api/metrics-store/history endpoint for querying SQLite-backed metrics
- Support flexible time ranges: 1h, 6h, 12h, 24h, 7d, 30d, 90d
- Return aggregated data with min/max values for longer time ranges
- Add TypeScript types and ChartsAPI.getMetricsHistory() client method
This enables frontend charts to visualize long-term trends using the
tiered retention system (raw → minute → hourly → daily averages).
- Add MetricsRetentionRawHours, MetricsRetentionMinuteHours, MetricsRetentionHourlyDays, MetricsRetentionDailyDays to SystemSettings
- Wire settings from system.json through Config to metrics store initialization
- Set sensible defaults: Raw=2h, Minute=24h, Hourly=7d, Daily=90d
- Log active retention values on startup for transparency
Users can now customize how long metrics are stored at each aggregation tier.
General Settings:
- Add animated sun/moon icon to dark mode toggle with gradient backgrounds
- Dynamic label showing current theme state (Light mode/Dark mode)
- Smooth CSS transitions for icon rotation and scaling
Updates Settings:
- Redesign version display with visual card layout
- Add build type badges (Development, Docker, Source) as colorful pills
- Show 3-column layout with arrow indicator when updates available
- Move Check Now button to footer with refresh icon
- Display auto-check status indicator
Security Overview:
- Add loading skeleton during data fetch
- Enhance proxy auth notice with gradient header and admin badge
- Style logout/guide links as proper buttons
- Add Security Best Practices tips card with recommendations
1. resources/store.go: Implement sorting in Query.Execute()
- Added sortResources function with support for common fields
- Supports: name, type, status, cpu, memory, disk, last_seen
- Both ascending and descending order supported
2. ai/service.go: Implement hasAgentForTarget properly
- Now maps target to specific agent based on hostname/node
- Uses ResourceProvider lookup for container→host mapping
- Supports cluster peer routing for Proxmox clusters
- Properly handles single-agent vs multi-agent scenarios
- Added toggle button to switch between relative and absolute time display
- Time preference is persisted to localStorage
- Toggle shows clock icon with 'Relative' or 'Absolute' label
- Implements the TODO from UnifiedBackups.tsx
- Prefix unused catch error variables with underscore in AIChat.tsx and Alerts.tsx
- Reduced lint warnings from 8 to 0
- Clean lint output with no warnings or errors
- Removed unused getPulsePort/getPulseWebSocketUrl imports
- Optimized polling to only run on proxmox tab (DiagnosticsPanel handles its own fetching)
- Remaining lint warnings are for legacy code that may need future refactoring
- Added dynamic security score calculation (0-100%)
- Added gradient header that changes color based on score:
- Green (>=80%): Strong security
- Amber (50-79%): Moderate security
- Red (<50%): Weak security
- Improved visual hierarchy with color-coded status cards
- Added 'Critical' labels for important missing features
- Changed icons to lucide-solid for consistency
- Created standalone DiagnosticsPanel component with modern visual design
- Gradient header with system health indicator
- Card-based layout for System Runtime, PVE Nodes, PBS, Discovery
- Status badges and improved visual hierarchy
- Export functionality (full and GitHub-sanitized)
- Reduced Settings.tsx from 8,035 to 5,956 lines (26% reduction)
- Removed ~2,079 lines of inline diagnostics code
- Improved maintainability by encapsulating diagnostics logic
- Improved AI Settings UX:
- Cost Controls: Gradient design, RECOMMENDED badge, $ prefix
- Shows daily/weekly budget equivalents when value is entered
- Auto-Fix: Streamlined acknowledgment with clear button instead of checkbox
- Better visual hierarchy throughout