Commit graph

493 commits

Author SHA1 Message Date
rcourtman
4cc74021fd feat: add 'Alert' badge to findings triggered by alert-triggered analysis
Shows a purple ' Alert' badge on findings that were discovered through
alert-triggered analysis rather than scheduled patrol runs. This gives
users visibility into how findings were discovered without cluttering
the patrol run history table.
2025-12-21 22:04:32 +00:00
rcourtman
0ce6bda33b fix: AI settings persistence and UI improvements
Bug Fixes:
- Fix boolean fields with 'omitempty' not persisting false values
  - AlertTriggeredAnalysis, PatrolAnalyzeNodes/Guests/Docker/Storage
  - omitempty causes Go to skip false (zero value) when marshaling JSON
  - On reload, NewDefaultAIConfig() sets true, and missing field stays true

- Fix model dropdown losing selection after save (SolidJS reactivity issue)
  - Added explicit 'selected' attribute to option elements
  - Ensures browser maintains selection with optgroups during re-renders

Improvements:
- Change patrol type label from 'Quick' to 'Patrol' in history table
- Add chat_model and patrol_model to AI settings update log
- Add alert_triggered_analysis to AI config load log for debugging
2025-12-21 21:48:09 +00:00
rcourtman
4d7d2e42dc feat(ai): pass raw metric samples to LLM for pattern interpretation
Instead of relying on pre-computed trend heuristics (which can be misleading
for edge cases like step changes vs continuous growth), we now pass downsampled
raw data points to the LLM so it can interpret patterns directly.

Changes:
- Add MetricSamples field to ResourceContext
- Add DownsampleMetrics() to reduce data points for LLM consumption
- Add formatMetricSamples() to format data compactly (e.g., 'Disk: 26→26→31%')
- Add computeGuestMetricSamples() to gather 7-day sampled history
- Populate MetricSamples for VMs and containers during context build
- Add History section to formatted context output

The LLM now sees actual patterns like 'stable for 6 days then jumped' rather
than just '45.8%/day growth rate' - allowing for much more nuanced interpretation.

This approach:
- Leverages LLM's pattern recognition instead of hard-coded heuristics
- Provides 7 days of data (~24 samples) for context on normal behavior
- Uses minimal tokens due to compact formatting with deduplication
- Is more future-proof as LLMs improve

Example output:
  **History (7d sampled, oldest→newest)**: Disk: 26→26→26→26→26→31%

Refs: Frigate disk usage false positive investigation
2025-12-21 21:09:24 +00:00
rcourtman
547fb65e39 fix: remove unused runbook UI code to fix TypeScript errors
- Remove unused correlations state and constants from AIOverviewTable
- Remove unused runbook-related imports, state, and functions from Alerts
- Add type annotation to Set() to fix type error
- Removes dead code left over from runbook UI removal
2025-12-21 19:12:20 +00:00
rcourtman
bc5b0d7584 refactor: remove runbook UI from frontend
Removed:
- Runbook button from finding action buttons
- Runbook Execution panel
- Fix Receipts panel (already removed)

Just showing 'Get Help' and 'I Fixed It' buttons now.
2025-12-21 18:08:47 +00:00
rcourtman
7e66423042 refactor: remove Fix Receipts UI section
Fix Receipts was showing 'No fixes logged' most of the time since:
- Runbooks were removed
- Remediation logging was inconsistent

Just adds visual clutter without value. Removed ~100 lines of UI code.
2025-12-21 18:02:35 +00:00
rcourtman
4780dd2f83 fix(ui): remove AI Intelligence Summary - patrol findings are sufficient
The AI Intelligence Summary was adding noise rather than value:
- Predictions duplicated patrol findings
- Correlations were not actionable
- 'Fixed' items were vague diagnostics
- Status changes were startup noise

The real value is in the patrol findings section which shows:
- Actual issues found (critical/warning/watch/info)
- Actionable recommendations
- Suppression rules

Keeping the patrol findings, removing the redundant summary.
2025-12-21 17:23:25 +00:00
rcourtman
c8a32a7131 fix(ai): raise anomaly threshold to 2x, filter 'Ran diagnostic' noise
More aggressive noise filtering:

1. Anomaly threshold raised from 1.5x to 2x
   - 1.5x is too borderline to be actionable
   - Now requires genuinely significant deviation

2. Filter out 'Ran diagnostic' and 'Executed command' fallback items
   - These are generic summaries that provide no value
   - Only show remediations with specific, meaningful descriptions

Goal: If something shows in AI Intelligence, it should demand attention.
2025-12-21 17:19:32 +00:00
rcourtman
0f22906767 fix(ai): filter out noise from anomalies and status changes
Critical changes to surface only actionable insights:

1. Anomalies now require at least 50% deviation from baseline
   - '1.0x baseline' values filtered out (statistically significant but not actionable)
   - Must be >1.5x above OR <0.5x below baseline to report

2. Status changes filter out startup noise
   - 'unknown → running' is just system starting, not a real state change
   - Backups removed from main list (they have dedicated section)

3. Only show genuinely interesting changes:
   - Config changes, migrations, restarts, deletions
   - Things that require operator attention

This massively reduces noise while keeping high-signal alerts.
2025-12-21 17:15:44 +00:00
rcourtman
5138b01ed8 fix(ui): hide correlations - they're not actionable yet
Correlations currently show 'A and B alert together' which isn't useful:
- Bidirectional correlations (A→B AND B→A) are just coincidence
- 'experiences alert' is too vague to be actionable
- No root cause identification - just shows correlated things correlate

Hidden until we can properly identify:
- Root cause chains (A CAUSES B, not just 'A and B happen together')
- Specific trigger types (what kind of alert?)
- Direction of causality

Other improvements:
- Stopped VMs/containers filtered from anomaly detection
- Lower noise, more signal
2025-12-21 12:46:57 +00:00
rcourtman
367d22e937 fix(ai): filter out noise from AI intelligence display
Critical fixes to show only actionable insights:

1. Skip stopped VMs/containers from anomaly detection
   - '0.0x baseline' for stopped resources is expected, not an anomaly
   - Only check anomalies for status='running'

2. Filter correlations by confidence (>=70%)
   - Low confidence correlations are likely coincidental
   - Only show high-confidence, actionable dependencies

This reduces noise and surfaces genuinely useful intelligence.
2025-12-21 12:41:27 +00:00
rcourtman
98f3d0d48f fix(ui): use Promise.allSettled for resilient API loading
Changed AIOverviewTable to use Promise.allSettled instead of
Promise.all so that one failing endpoint (e.g., anomalies 404)
doesn't break the entire component.

Each API result now has a fallback for failed requests, allowing
the table to gracefully degrade when endpoints are unavailable.
2025-12-21 12:31:09 +00:00
rcourtman
60c0221a37 fix(ui): make anomalies fetch resilient to failures
Separate anomalies API call from Promise.all so that a failure
in the anomalies endpoint doesn't break the entire AI Overview.

This fixes 'Failed to load AI overview data' error when the
anomalies endpoint isn't available (e.g., patrol not started).
2025-12-21 12:27:53 +00:00
rcourtman
b81bd9f913 feat(ui): reduce AI Intelligence table length with 'Show more' buttons
Added collapsible sections to prevent overwhelming list:
- Dependencies limited to top 5 (sorted by confidence)
- Actions limited to top 5
- Changes limited to top 5
- 'Show more' buttons appear at bottom when items are hidden
- Clicking expands to show all items in that category

This addresses user feedback about excessive scrolling when
there are many dependency correlations or remediation actions.
2025-12-21 12:25:43 +00:00
rcourtman
0730f857a4 feat(ui): show anomalies in AI Intelligence Summary table
Adds real-time anomaly detection results to the AI Overview Table:
- Anomalies appear at TOP of list (before predictions) since they're real-time
- Severity-based color coding (critical=red, high=orange, medium=amber, low=blue)
- Shows resource name, metric, and deviation ratio (e.g., 'CPU at 2.5x baseline')
- Subtitle shows current vs baseline values
- Timestamp shows 'Now' since anomalies are current state

This integrates the FREE anomaly detection feature directly alongside
the Pro patrol insights, providing immediate value to all users.
2025-12-21 11:50:54 +00:00
rcourtman
420e4960dc feat(ui): add learning status hook and enhance AI indicator visibility
New useLearningStatus hook:
- Polls /api/ai/intelligence/learning every 60 seconds
- Provides resourceCount(), metricCount(), learningState()
- Convenience accessors: isActive(), isLearning(), isWaiting()

Enhanced AIStatusIndicator:
- Now shows when ANY baselines exist (not just when Patrol enabled)
- Tooltip shows 'X resources baselined' for transparency
- Healthy state  45 resources baselined'shows '
- Works even without Pro license since baselines are FREE

This makes the AI presence visible from the moment Pulse starts
learning, providing immediate value feedback to all users.
2025-12-21 11:45:55 +00:00
rcourtman
783537e1d2 feat(ai): make anomaly detection FREE and add learning status endpoint
Free Features (no license required):
- Anomaly detection - removed license gating, purely statistical analysis
- Learning status endpoint - GET /api/ai/intelligence/learning

Learning Status Response:
- resources_baselined: count of resources with learned baselines
- total_metrics: total metric baselines (cpu + memory + disk)
- metric_breakdown: {cpu: X, memory: Y, disk: Z}
- status: 'waiting' | 'learning' | 'active'
- message: human-readable description

This makes the AI intelligence features visible to all users,
encouraging upgrades for the full LLM-powered patrol experience.
2025-12-21 11:36:54 +00:00
rcourtman
2ba8538de3 feat(ai): enhance intelligence status and add trend prediction
AIStatusIndicator:
- Now shows BOTH patrol findings AND baseline anomalies
- Displays even when only anomaly detection is active (no patrol)
- Badge count includes both findings + anomalies
- Tooltip provides detailed breakdown by severity

Trend Prediction (backend):
- Add TrendPrediction struct for resource exhaustion forecasting
- CalculateTrend() uses linear regression on sample history
- Predicts days until resource is full (or if declining/stable)
- Severity: critical (<7 days), warning (<30 days), info (>30 days)
- Human-readable descriptions like 'full in ~2 weeks (+0.5% per day)'

This creates a more cohesive intelligence experience where anomaly
detection works independently of the pro/patrol features, making
value visible immediately to all users.
2025-12-21 11:29:44 +00:00
rcourtman
db7b385287 feat(ui): wire memory and disk anomaly indicators
Complete the anomaly indicator integration for all three metrics:
- CPU: EnhancedCPUBar (already done)
- Memory: StackedMemoryBar (new)
- Disk: StackedDiskBar (new)

All three metric bars now show a pulsing indicator (e.g., '2.5x↑')
when the current value is significantly above the learned baseline.

Severity colors:
- Critical (>4σ): red
- High (3-4σ): orange
- Medium (2.5-3σ): yellow
- Low (2-2.5σ): blue

This is 100% deterministic - no LLM involved. The indicators appear
automatically based on statistical deviation from learned baselines.
2025-12-21 11:24:42 +00:00
rcourtman
9aad21169d feat(ui): wire CPU anomaly indicator to dashboard
Connect anomaly data to the EnhancedCPUBar component in GuestRow.
When a VM/container's CPU is significantly above its learned baseline,
a pulsing indicator (e.g., '2.5x') appears directly on the CPU bar.

This provides real-time baseline deviation feedback without any LLM
involvement - purely deterministic statistical analysis.

Memory and disk anomaly hooks are prepared but not yet wired to their
respective bar components (TODO for follow-up).
2025-12-21 11:06:23 +00:00
rcourtman
24e072f6b5 feat(ui): add anomaly indicator components and hooks
Add frontend infrastructure for displaying baseline anomalies:
- useAnomalies hook for fetching and caching anomaly data
- AnomalyCell component for displaying multiple anomalies
- AnomalyIndicator/AnomalyBadge components for inline display
- Update EnhancedCPUBar to accept optional anomaly prop

The anomaly endpoint is polled every 30 seconds and cached.
Anomaly badges show severity (color) and deviation ratio (e.g., '2.5x').

This prepares the UI for displaying real-time baseline deviations
without requiring LLM interaction.
2025-12-21 11:04:18 +00:00
rcourtman
c5c9bf4fb9 feat(ai): add real-time anomaly detection endpoint
Add /api/ai/intelligence/anomalies endpoint that compares live metrics
against learned baselines to surface deviations - all deterministic
(no LLM required).

Backend:
- Add AnomalyReport struct with severity classification
- Add CheckResourceAnomalies method to baseline store
- Add HandleGetAnomalies API handler
- Add GetStateProvider getter to AI service

Frontend:
- Add AnomalyReport and AnomaliesResponse types
- Add getAnomalies API function
- Add AnomalySeverity type

This is the first step toward surfacing deterministic intelligence
directly in the UI without requiring LLM interaction.
2025-12-21 10:52:54 +00:00
rcourtman
8019acd6b6 feat(ai): add unified Intelligence orchestrator
- Create Intelligence struct that aggregates all AI subsystems
- Add /api/ai/intelligence endpoint for system-wide and per-resource insights
- Wire Intelligence into PatrolService as a facade (not replacement)
- Add TypeScript types and API client for frontend
- Add unit tests for Intelligence orchestrator
- Fix pre-existing test failures using diagnostic commands instead of actionable ones

The Intelligence orchestrator provides:
- System-wide health scoring (A-F grades)
- Aggregated findings, predictions, correlations
- Per-resource context generation for AI prompts
- Learning progress tracking

This unifies access to AI subsystems without replacing existing code paths.
2025-12-21 10:32:02 +00:00
rcourtman
352a6d4213 Fix ESLint errors breaking CI
- KubernetesClusters.tsx: Escape -> as → in JSX text to fix parsing error
- Settings.tsx: Remove unused HostProxySummary interface (deprecated in v5)
- AIOverviewTable.tsx: Prefix unused summarizeAction with underscore
2025-12-21 00:41:33 +00:00
rcourtman
b7312a22ac cleanup: remove dead code for deprecated pulse-sensor-proxy
The pulse-sensor-proxy feature was deprecated in v5 and disabled by default.
The frontend was still calling /api/temperature-proxy/host-status which
returned 410 Gone, causing console errors.

Removed:
- HostProxyStatusResponse interface
- _hostProxyStatus signal (was never read)
- refreshHostProxyStatus function
- Polling interval that called the deprecated endpoint

The temperature monitoring now uses pulse-agent instead.
2025-12-21 00:39:04 +00:00
rcourtman
82e5b28840 feat: enhance AI baseline context visibility and incident timeline improvements
Backend:
- Enhanced buildEnrichedResourceContext to ALWAYS show learned baselines with
  status indicators (normal/elevated/anomaly) instead of only when anomalous
- This makes Pulse Pro's 'moat' visible - users can see the AI understands
  their infrastructure's normal behavior patterns
- Added baseline import to service.go

Frontend (user changes):
- Added incident event type filtering with toggle buttons
- Added resource incident panel to view all incidents for a resource
- Added timeline expand/collapse functionality in alert history
- Added incident note saving with proper incidentId tracking
- Added startedAt parameter for proper incident timeline loading
2025-12-21 00:14:20 +00:00
rcourtman
f0b983667c fix: normalize guest ID fallbacks to canonical instance:node:vmid format
Multiple frontend components were using - as a fallback
when guest.id was falsy. This format drops the node component, which is
critical for clustered setups where the same VMID can exist on different
nodes.

Changes:
- GuestDrawer.tsx: Updated guestId() and handleAskAI() to use canonical format
- GuestRow.tsx: Updated buildGuestId() to use canonical format
- Dashboard.tsx: Updated handleGuestRowClick() and guest rendering loop,
  also fixed legacy metadata fallback to use consistent keying
- ThresholdsTable.tsx: Updated guestsGroupedByNode() to use canonical format

Backend changes:
- Removed temporary debug logging added during investigation
- Added alert history section to AI buildEnrichedResourceContext() function

The backend generates VM/Container IDs in instance:node:vmid format (e.g.,
delly:delly:101) via makeGuestID(). This format is now consistently used
across all frontend fallbacks to prevent AI context, metadata, overrides,
and metrics from colliding or desyncing in clustered environments.
2025-12-20 22:11:35 +00:00
rcourtman
215cecc555 fix: Allow all threshold types (Storage, Temperature, Host Agent) to be set to 0 to disable alerting
- Fixed normalizeStorageDefaults to allow Trigger=0
- Fixed normalizeNodeDefaults (Temperature) to allow Trigger=0
- Added comprehensive tests for all threshold normalization patterns
- Updated existing test that expected old behavior

Related to #864
2025-12-20 20:42:23 +00:00
rcourtman
19c7cf6970 fix: Allow Host Agent thresholds to be set to 0 to disable alerting. Related to #864 2025-12-20 20:25:20 +00:00
rcourtman
b949255868 Fix login re-auth with stale sessions and hot-dev encryption safety
- Login.tsx: Use apiClient.fetch with skipAuth to avoid auth loops
- router.go: Skip CSRF validation for /api/login endpoint
- hot-dev.sh: Detect encrypted files before generating new key to prevent data loss
2025-12-20 13:45:11 +00:00
rcourtman
7b249763f6 fix: improve DiagnosticsPanel mobile responsiveness
Header and action buttons now stack vertically on narrow screens
instead of overflowing. Button labels are shortened on mobile.

Related to discussion #845 (feedback from @MDE186)
2025-12-20 00:07:34 +00:00
rcourtman
010d0f0e86 fix: ensure hideLocalLogin is set when showing login after logout. Related to #857
When the user logged out, the code would immediately set needsAuth=true
and return WITHOUT first fetching /api/security/status. This meant the
securityStatus signal was null, causing shouldShowLocalLogin() in Login.tsx
to return true (since !undefined === true).

Now we always fetch security status before showing the login form, even
in the just_logged_out path. This ensures hideLocalLogin, oidcEnabled,
and other OIDC settings are properly available to the Login component.
2025-12-20 00:04:19 +00:00
rcourtman
a4b5ce4b25 fix: Add disk tooltip to Proxmox node overview. Related to #862 2025-12-19 23:57:48 +00:00
rcourtman
396ee02ba8 fix: add missing HandleLicenseFeatures method and related changes
- Add HandleLicenseFeatures handler that was missing from license_handlers.go
- Add /api/license/features route to router
- Update AI service and metadata provider
- Update frontend license API and components
- Fix CI build failure caused by tests referencing unimplemented method
2025-12-19 22:59:52 +00:00
rcourtman
97c851c16c fix: show Removed Docker Hosts section in UI for re-enrollment
The 'Removed Docker Hosts' section was not appearing in Settings -> Agents
even when hosts were blocked from re-enrolling. This prevented users from
using the 'Allow re-enroll' button to unblock their Docker agents.

Root cause: The WebSocket store was missing:
1. The 'removedDockerHosts' property in its initial state
2. A handler to process removedDockerHosts data from WebSocket messages

This meant the backend was correctly sending the data, but the frontend
was completely ignoring it.

Changes:
- Add removedDockerHosts to WebSocket store initial state and message handler
- Add removedDockerHosts to App.tsx fallback state for consistency
- Add missing BroadcastState call after AllowDockerHostReenroll succeeds

Also includes previous fixes from this session:
- Add PULSE_AGENT_URL as alias for PULSE_AGENT_CONNECT_URL (config.go)
- Add runtime Docker/Podman auto-detection in pulse-agent (main.go)

Fixes issue reported by darthrater78 in discussion #845
2025-12-19 17:57:04 +00:00
rcourtman
a535b22849 fix(ai): improve patrol timing accuracy and status reporting 2025-12-19 17:04:14 +00:00
rcourtman
3b55639fbe fix(agent): support PULSE_AGENT_CONNECT_URL and improve detection 2025-12-19 17:01:58 +00:00
rcourtman
bede5162d3 feat(license): add initial license implementation structure to fix build 2025-12-19 17:01:57 +00:00
rcourtman
bd1f4682be refactor(ui): standardize URL editing with shared UrlEditPopover component
- Create reusable UrlEditPopover component with fixed positioning
- Add createUrlEditState hook for managing editing state
- Update DockerHostSummaryTable to use new popover
- Update DockerUnifiedTable (containers & services) to use new popover
- Update GuestRow (Proxmox VMs/containers) to use new popover
- Update HostsOverview (Proxmox hosts) to use new popover
- Add Docker host metadata API for custom URLs
- Consistent styling with save, delete, cancel buttons and keyboard shortcuts
2025-12-18 22:22:55 +00:00
rcourtman
337987cb56 v5: gate legacy sensor-proxy and prune dev docs 2025-12-18 21:51:25 +00:00
rcourtman
aff4e9b814 fix(frontend): resolve UI rate limiting on Docker overview (#859)
Previously, each DockerContainerRow component made 2 API calls on mount:
- AIAPI.getSettings() for AI enabled status
- DockerMetadataAPI.getMetadata() for annotations

With 100+ containers, this resulted in 200+ API calls firing simultaneously,
exceeding the 500 requests/minute rate limit and causing 429 errors.

Fix:
- Lift AI settings check to DockerUnifiedTable parent component (1 call)
- Use pre-fetched dockerMetadata prop for annotations (already batch-fetched)
- Pass aiEnabled and initialNotes as props to child rows

This reduces API calls from O(n*2) to O(1) when loading the Docker overview.

Fixes #859
2025-12-18 21:17:56 +00:00
rcourtman
ae70d9e423 feat: add --kube-include-all-deployments flag for Kubernetes agent
Adds IncludeAllDeployments option to show all deployments, not just
problem ones (where replicas don't match desired). This provides parity
with the existing --kube-include-all-pods flag.

- Add IncludeAllDeployments to kubernetesagent.Config
- Add --kube-include-all-deployments flag and PULSE_KUBE_INCLUDE_ALL_DEPLOYMENTS env var
- Update collectDeployments to respect the new flag
- Add test for IncludeAllDeployments functionality
- Update UNIFIED_AGENT.md documentation

Addresses feedback from PR #855
2025-12-18 20:58:30 +00:00
rcourtman
66a8604fa3 fix: restore Hide Local Login functionality for OIDC/SSO (#857)
When 'Hide local login form' was enabled in Settings -> Authentication,
the local login form was still displayed instead of showing only the
SSO login. This regression occurred in Pulse 5.x.

Root cause: When App.tsx passed hasAuth to Login.tsx, the Login component
created a minimal SecurityStatus object with only hasAuthentication set,
missing the hideLocalLogin and other OIDC settings.

Changes:
- App.tsx: Store and pass full securityStatus to Login component
- Login.tsx: Accept securityStatus prop and initialize state from it
- Login.tsx: Initialize authStatus directly from props to respect
  hideLocalLogin on first render
- Added tests for hideLocalLogin behavior

Fixes #857
2025-12-18 18:33:34 +00:00
rcourtman
3b36e4965f fix: resolve all frontend lint errors for unused imports and type issues
- Remove unused type imports: SnapshotAlertConfig, PMGThresholdDefaults, RawOverrideConfig, BackupAlertConfig
- Remove unused imports: Settings, Power, JSX, onMount, createEffect
- Remove unused function _getUnitSuffix
- Fix GuestDefaults type to avoid index signature conflict
- Prefix unused catch variables with underscore
- Fix StickyNote title prop by wrapping in span element
2025-12-18 17:07:05 +00:00
rcourtman
41004ebcea feat(thresholds): add collapsible accordion sections and UX improvements
- Add CollapsibleSection component with animated expand/collapse
- Wrap all 6 resource sections (Nodes, VMs, PBS, Storage, Backups, Snapshots) with accordion UI
- Add section icons and resource counts in headers
- Add expand all / collapse all buttons for quick navigation
- Make help banner dismissible with localStorage persistence
- Add Ctrl/Cmd+F keyboard shortcut to focus search
- Add keyboard shortcut hint badge on search input
- Add icons to tab navigation for quick identification
- Improve mobile tab labels with shorter text on small screens
- Create reusable components: ThresholdBadge, ResourceCard, GlobalDefaultsRow
- Create useCollapsedSections hook with localStorage persistence
- Default less-used sections (Storage, Backups, Snapshots, PBS) to collapsed
2025-12-18 15:47:44 +00:00
rcourtman
558b5a6ccd fix: guest URL icon now appears/disappears immediately after AI sets/removes it
The issue was a SolidJS reactivity problem in the Dashboard component.
When guestMetadata signal was accessed inside a For loop callback and
assigned to a plain variable, SolidJS lost reactive tracking.

Changed from:
  const metadata = guestMetadata()[guestId] || ...
  customUrl={metadata?.customUrl}

To:
  const getMetadata = () => guestMetadata()[guestId] || ...
  customUrl={getMetadata()?.customUrl}

This ensures SolidJS properly tracks the signal dependency when the
getter function is called directly in JSX props.
2025-12-18 14:42:47 +00:00
rcourtman
dccaa3a64c fix(ui): add CPU tooltip to VM/LXC rows in Proxmox Overview. Related to #816
The previous fix (3b4c77de) only addressed PVE/PBS nodes but missed
guest rows. Now VMs and LXC containers also show CPU details tooltip
on hover using EnhancedCPUBar.
2025-12-18 11:28:09 +00:00
rcourtman
65a4534be9 Stabilize core E2E tests
- Preserve alerts activation state when saving thresholds
- Use compliant default E2E password and deterministic bootstrap token seeding
- Harden Playwright selectors, waits, and diagnostics gating
2025-12-17 19:36:48 +00:00
rcourtman
f907440f6b fix(ai): improve AI settings UX with validation and smart fallbacks
Backend:
- Add smart provider fallback when selected model's provider isn't configured
- Automatically switch to a model from a configured provider instead of failing
- Log warning when fallback occurs for visibility

Frontend (AISettings.tsx):
- Add helper functions to check if model's provider is configured
- Group model dropdown: configured providers first, unconfigured marked with ⚠️
- Add inline warning when selecting model from unconfigured provider
- Validate on save that model's provider is configured (or being added)
- Warn before clearing last configured provider (would disable AI)
- Warn before clearing provider that current model uses
- Add patrol interval validation (must be 0 or >= 10 minutes)
- Show red border + inline error for invalid patrol intervals 1-9
- Update patrol interval hint: '(0=off, 10+ to enable)'

These changes prevent confusing '500 Internal Server Error' and
'AI is not enabled or configured' errors when model/provider mismatch.
2025-12-17 18:30:19 +00:00
rcourtman
605d1680da Simplify agent installation UI - remove Force Docker/K8s/Proxmox checkboxes
- Remove confusing Force Docker, Force Kubernetes, Force Proxmox checkboxes
- Auto-detection handles these platforms; checkboxes were redundant
- Keep Skip TLS verification checkbox (commonly needed for self-signed certs)
- Add Troubleshooting section with --enable-* and --disable-* flags for edge cases
- Update tests to reflect simplified UI
2025-12-17 17:14:41 +00:00