feat: Sensing-only UI mode with Gaussian splat visualization and Rust migration ADR

- Add Python WebSocket sensing server (ws_server.py) with ESP32 UDP CSI
  and Windows RSSI auto-detect collectors on port 8765
- Add Three.js Gaussian splat renderer with custom GLSL shaders for
  real-time WiFi signal field visualization (blue→green→red gradient)
- Add SensingTab component with RSSI sparkline, feature meters, and
  motion classification badge
- Add sensing.service.js WebSocket client with reconnect and simulation fallback
- Implement sensing-only mode: suppress all DensePose API calls when
  FastAPI backend (port 8000) is not running, clean console output
- ADR-019: Document sensing-only UI architecture and data flow
- ADR-020: Migrate AI/model inference to Rust with RuVector ONNX Runtime,
  replacing ~2.7GB Python stack with ~50MB static binary
- Add ruvnet/ruvector as upstream remote for RuVector crate ecosystem

Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
ruv
2026-02-28 14:37:29 -05:00
parent 6e4cb0ad5b
commit b7e0f07e6e
20 changed files with 2551 additions and 24 deletions

View File

@@ -67,9 +67,14 @@ export class ApiService {
// Generic request method
async request(url, options = {}) {
try {
// In sensing-only mode, skip all DensePose API calls
if (backendDetector.sensingOnlyMode) {
throw new Error('DensePose API unavailable (sensing-only mode)');
}
// Process request through interceptors
const processed = await this.processRequest(url, options);
// Determine the correct base URL (real backend vs mock)
let finalUrl = processed.url;
if (processed.url.startsWith(API_CONFIG.BASE_URL)) {
@@ -99,7 +104,10 @@ export class ApiService {
return data;
} catch (error) {
console.error('API Request Error:', error);
// Only log if not a connection refusal (expected when DensePose API is down)
if (error.message && !error.message.includes('Failed to fetch')) {
console.error('API Request Error:', error);
}
throw error;
}
}