Skip to content

feat: improve overlay debug visibility and triggers#326

Merged
senamakel merged 9 commits intotinyhumansai:mainfrom
senamakel:fix/overlay
Apr 5, 2026
Merged

feat: improve overlay debug visibility and triggers#326
senamakel merged 9 commits intotinyhumansai:mainfrom
senamakel:fix/overlay

Conversation

@senamakel
Copy link
Copy Markdown
Member

@senamakel senamakel commented Apr 5, 2026

Summary

  • replace the overlay-only voice orb with a larger debug-capable overlay that shows live voice, screen intelligence, and autocomplete state
  • expose foreground screen context, cumulative screenshot count, and last window title from core screen-intelligence status for overlay debugging
  • keep the macOS Globe/Fn trigger path and accessory-style overlay behavior while expanding the overlay window to fit the debug panel
  • preserve voice transcription and active-field insertion flow while surfacing live subsystem diagnostics in the same overlay

Problem

  • The overlay was only showing voice-state feedback, which made it hard to verify whether screen intelligence and autocomplete were actually running.
  • Screen intelligence status did not expose enough detail for the overlay to show the true active screen context or a running screenshot count.
  • Autocomplete activity and the current suggestion were not visible from the overlay, so debugging cross-process behavior required separate tools.

Solution

  • Poll openhuman.accessibility_status and openhuman.autocomplete_status from the overlay and render a compact debug card below the voice control.
  • Extend screen-intelligence status to include foreground_context, cumulative capture_count, and last_window_title so the overlay can display accurate active-screen information.
  • Reuse existing core RPC methods instead of creating a parallel debug subsystem, and add overlay-side logging for each refresh cycle.
  • Resize the overlay window to accommodate the new debug content while keeping the utility-style overlay interaction model.

Submission Checklist

  • Unit tests — Vitest (app/) and/or cargo test (core) for logic you add or change
  • E2E / integration — Verified with cargo check --manifest-path Cargo.toml and yarn build in overlay/; no dedicated E2E coverage was added in this PR
  • N/A — If truly not applicable, say why (e.g. change is documentation-only)
  • Doc comments — existing module/file docs preserved; added public status fields without introducing undocumented new public modules
  • Inline comments — existing comments retained; no new non-obvious branch required extra inline commentary beyond logging

Impact

  • Desktop/macOS overlay behavior is the primary runtime impact.
  • The core JSON-RPC screen-intelligence status payload now includes extra debug fields; consumers that ignore unknown fields remain compatible.
  • No intended security change; debug output remains UI-focused and avoids secret payloads.

Related

  • Issue(s): none linked
  • Follow-up PR(s)/TODOs: consider exposing richer autocomplete candidate lists if the overlay should show more than the latest suggestion

Summary by CodeRabbit

Release Notes

  • New Features

    • Added overlay UI for audio capture and voice-to-text transcription with direct insertion into focused fields.
    • Added Globe/Fn key listener support for overlay activation.
    • Added log viewer with module and severity filtering.
    • Added click-through mode for overlay window interactions.
  • Chores

    • Added foundational overlay configuration and build infrastructure.

- Added a new overlay project for OpenHuman, featuring a transparent window with a log viewer.
- Implemented core components including TitleBar, ModuleFilter, LogViewer, and StatusBar for enhanced user interaction.
- Integrated Tauri for desktop application capabilities, allowing for real-time log monitoring and management.
- Configured TypeScript, Tailwind CSS, and Vite for a modern development experience.
- Included necessary files such as package.json, tsconfig.json, and README.md to guide setup and usage.
- Replaced `tokio::spawn` with `tauri::async_runtime::spawn` for improved compatibility with Tauri's async runtime.
- This change enhances the integration of the OpenHuman core server within the Tauri application, ensuring better performance and stability.
- Added a click-through toggle feature to the TitleBar component, allowing mouse events to pass through the overlay.
- Updated the App component to manage the click-through state and handle its toggling.
- Enhanced the MODULE_LABELS in types.ts to include additional known modules for filtering.
- Modified Tauri backend to support the click-through functionality, ensuring proper state management and event handling.
- Added audio recording and transcription capabilities to the overlay, allowing users to capture and transcribe speech.
- Introduced functions for audio processing, including converting audio blobs to WAV format and handling audio streams.
- Updated the App component to manage recording states and display transcription results.
- Enhanced the user interface with a microphone icon indicating recording status.
- Adjusted window dimensions and properties in the Tauri configuration for improved user experience.
- Implemented a new function to insert transcribed text into the currently focused field of the active application, improving user experience.
- Added detailed logging for overlay actions, including recording start/stop events and transcript insertion attempts, to aid in debugging and monitoring.
- Updated the App component to utilize the new insertion functionality and log relevant information during transcription processes.
- Added a new Globe/Fn key listener feature for macOS, enabling the application to respond to Globe key events.
- Implemented functions to start, poll, and stop the Globe listener, enhancing user interaction with the overlay.
- Updated the App component to manage the listener's lifecycle and display relevant status messages.
- Modified Tauri configuration to adjust overlay visibility settings for improved user experience.
- Introduced a new module for Globe listener management, encapsulating related functionality and improving code organization.
…fo.plist

- Introduced a new Info.plist file to configure macOS application settings.
- Implemented accessory activation policy for the overlay on macOS, enhancing user experience by allowing the app to run in the background without a dock icon.
- Updated the application setup to include macOS-specific configurations for improved functionality.
- Introduced new interfaces for managing accessibility and autocomplete statuses, improving the structure of debug information.
- Implemented a polling mechanism to refresh the overlay debug state, capturing accessibility and autocomplete data in real-time.
- Updated the App component to display active application and window titles, along with autocomplete suggestions and phases.
- Adjusted the overlay dimensions in Tauri configuration for better user experience and visibility.
- Enhanced logging for debug snapshot updates, aiding in monitoring and troubleshooting.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 5, 2026

Warning

Rate limit exceeded

@senamakel has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 2 minutes and 58 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 2 minutes and 58 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3fe8f0e3-1f9b-4b22-8479-f4f18f530bcf

📥 Commits

Reviewing files that changed from the base of the PR and between 424cca1 and 0edb445.

📒 Files selected for processing (4)
  • src/openhuman/accessibility/globe.rs
  • src/openhuman/screen_intelligence/ops.rs
  • src/openhuman/screen_intelligence/schemas.rs
  • src/openhuman/screen_intelligence/types.rs
📝 Walkthrough

Walkthrough

This PR introduces a new Tauri-based overlay application for real-time log viewing and text insertion workflows, along with macOS Globe/Fn key listener support. The overlay integrates with OpenHuman core via RPC, featuring a React frontend with log filtering and audio transcription capabilities. Backend enhancements expose hotkey polling and session capture tracking.

Changes

Cohort / File(s) Summary
Overlay Project Configuration
overlay/.gitignore, overlay/.vscode/extensions.json, overlay/README.md, overlay/package.json, overlay/postcss.config.js, overlay/tailwind.config.js, overlay/tsconfig.json, overlay/vite.config.ts
Project setup files including build/dev scripts, dependencies (React 19, Vite, Tauri, Tailwind), and configuration for TypeScript, PostCSS, and Vite dev server on port 1430.
Overlay Frontend Entry & Styles
overlay/index.html, overlay/src/main.tsx, overlay/src/styles.css
HTML entry point with React 18 root mounting, global stylesheet with Tailwind directives, custom scrollbar styling, and font imports.
Overlay Frontend Components
overlay/src/App.tsx, overlay/src/components/LogViewer.tsx, overlay/src/components/ModuleFilter.tsx, overlay/src/components/StatusBar.tsx, overlay/src/components/TitleBar.tsx
React components for log display with filtering, module selection tabs, level-based filtering, status bar, and custom draggable title bar with click-through toggle and window controls.
Overlay Frontend Logic
overlay/src/hooks/useLogs.ts, overlay/src/types.ts
Log buffer hook managing 5000-entry in-memory cache with live event subscription; type definitions for LogEntry, log level colors, and module labels.
Overlay App.tsx Functionality
overlay/src/App.tsx
Full-screen overlay with hotkey listener, microphone recording workflow, WAV audio conversion (16 kHz mono), transcription via Tauri RPC, text insertion into focused field, and debug panel for accessibility/autocomplete state.
Overlay Tauri Backend Setup
overlay/src-tauri/.gitignore, overlay/src-tauri/Cargo.toml, overlay/src-tauri/build.rs, overlay/src-tauri/Info.plist, overlay/src-tauri/tauri.conf.json
Rust build configuration, Tauri v2 app manifest (overlay window: 600×800, transparent, always-on-top, taskbar hidden), macOS plist with LSUIElement, and Cargo dependencies (Tauri, tokio, tracing, logging).
Overlay Tauri Backend Implementation
overlay/src-tauri/src/main.rs, overlay/src-tauri/src/lib.rs, overlay/src-tauri/src/log_bridge.rs, overlay/src-tauri/capabilities/default.json
Main entrypoint, command handlers (get_log_history, set_click_through, core_rpc, insert_text_into_focused_field), log event bridge with ring buffer and tracing subscriber layer, and Tauri window capabilities.
Core Accessibility: Globe Key Listener
src/openhuman/accessibility/globe.rs
macOS-only Globe/Fn key listener via managed helper process; spawns Swift helper, parses stdout events into bounded queue, tracks input-monitoring permission and process state; non-macOS stub returns supported: false.
Screen Intelligence: Type & Ops Updates
src/openhuman/screen_intelligence/types.rs, src/openhuman/screen_intelligence/ops.rs, src/openhuman/screen_intelligence/schemas.rs
Re-exported Globe hotkey types; added RPC endpoints (accessibility_globe_listener_start/poll/stop); registered handlers in controller schema registry.
Screen Intelligence: Session Tracking
src/openhuman/screen_intelligence/engine.rs
Added per-session capture_count: u64 tracking incremented on each frame capture; extended SessionStatus with capture_count and last_window_title: Option<String>; added foreground_context: Option<AppContextInfo> to AccessibilityStatus.
Accessibility Module Export
src/openhuman/accessibility/mod.rs
Added mod globe submodule and public re-exports for globe_listener_start/poll/stop, GlobeHotkeyStatus, and GlobeHotkeyPollResult.

Sequence Diagrams

sequenceDiagram
    participant User
    participant Overlay as Overlay (React)
    participant TauriBackend as Tauri Backend
    participant OpenHumanCore as OpenHuman Core
    participant OSAccess as OS (macOS)

    User->>Overlay: Press Globe/Fn key
    Overlay->>TauriBackend: invoke("globe_listener_poll")
    TauriBackend->>OpenHumanCore: globe_listener_poll()
    OpenHumanCore->>OSAccess: Read helper process queue
    OSAccess-->>OpenHumanCore: Return pending events
    OpenHumanCore-->>TauriBackend: Return poll result with events
    TauriBackend-->>Overlay: Hotkey event received
    Overlay->>Overlay: Show window, start listening
    User->>Overlay: Speak into microphone
    Overlay->>Overlay: Capture audio → convert to 16kHz mono WAV
    Overlay->>TauriBackend: invoke("core_rpc", {transcription request})
    TauriBackend->>OpenHumanCore: JSON-RPC transcription call
    OpenHumanCore-->>TauriBackend: Transcription result
    TauriBackend-->>Overlay: Return transcript
    Overlay->>TauriBackend: invoke("insert_text_into_focused_field", {text})
    TauriBackend->>OpenHumanCore: Insert text via accessibility API
    OpenHumanCore->>OSAccess: Apply text to focused field
    OSAccess-->>User: Text inserted in active app
Loading
sequenceDiagram
    participant TauriApp as Tauri App (Rust)
    participant TracingLayer as Log Bridge Layer
    participant LogBuffer as LogBuffer (Ring)
    participant Renderer as Frontend (React)

    TauriApp->>TauriApp: Module code generates tracing events
    TauriApp->>TracingLayer: on_event() triggered
    TracingLayer->>LogBuffer: push(LogEntry)
    LogBuffer->>LogBuffer: Append & maintain capacity (5000)
    TracingLayer->>TauriApp: Emit core:log event to frontend
    TauriApp-->>Renderer: Send LogEntry payload
    Renderer->>Renderer: Append to state, auto-scroll if near bottom
    Renderer->>Renderer: Apply module/level filters and render
    User->>Renderer: Click "Clear" button
    Renderer->>TauriApp: invoke("get_log_history") on startup
    TauriApp->>TauriApp: Call snapshot()
    TauriApp-->>Renderer: Return buffered entries
    Renderer->>Renderer: Populate log viewer with history
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • #275: Modifies src/openhuman/screen_intelligence/engine.rs (same file affected in capture_count and status tracking additions).
  • #184: Introduces/modifies accessibility APIs and types; overlaps with new Globe hotkey module and accessibility re-exports.

Suggested reviewers

  • graycyrus

Poem

🐰 Hops with glee at the overlay new,
Globe key listeners, transcription too!
Logs flowing swift through the Tauri-bound lane,
Audio to text—no more manual strain!
With rings of memories and hotkeys so fine,
OpenHuman glows brighter in design!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 58.46% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: improve overlay debug visibility and triggers' accurately describes the main objective of adding debug-capable overlay with live state display and enhanced triggers.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Nitpick comments (6)
overlay/vite.config.ts (1)

7-7: Unnecessary async wrapper.

The defineConfig callback doesn't use await, so async is superfluous. This is a minor nit but keeping it simple improves readability.

Suggested simplification
-export default defineConfig(async () => ({
+export default defineConfig({
   plugins: [react()],
   clearScreen: false,
   server: {
     port: 1430,
     strictPort: true,
     host: host || false,
     hmr: host
       ? {
           protocol: "ws",
           host,
           port: 1431,
         }
       : undefined,
     watch: {
       ignored: ["**/src-tauri/**"],
     },
   },
-}));
+});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@overlay/vite.config.ts` at line 7, The defineConfig callback is declared
async but never uses await; remove the unnecessary async modifier on the
callback returned to defineConfig (the function starting with
"defineConfig(async () => ({") so the export becomes a plain synchronous
function. Update the declaration that currently references defineConfig and
ensure no other code relies on the function returning a Promise.
overlay/src/components/TitleBar.tsx (1)

44-47: Consider making click-through state text explicit on the toggle.

Both states render "CT" (Line 46), so textual state isn’t obvious without color/tooltips. CT ON / CT OFF would be clearer.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@overlay/src/components/TitleBar.tsx` around lines 44 - 47, The toggle button
in TitleBar.tsx currently renders identical text for both states; update the
button's inner text to reflect the clickThrough boolean explicitly (e.g., render
"CT ON" when clickThrough is true and "CT OFF" when false). Locate the button
that uses the clickThrough variable and change its children so the displayed
label includes the state (use the clickThrough ternary already used for title,
e.g., clickThrough ? "CT ON" : "CT OFF") to make the state obvious without
relying on color or tooltips.
overlay/src-tauri/src/log_bridge.rs (1)

45-51: Vec::remove(0) is O(n); use VecDeque for O(1) eviction.

With a capacity of 5000 and frequent log writes, removing from the front of a Vec causes repeated memory shifts. VecDeque::pop_front() is O(1).

♻️ Proposed fix using VecDeque
+use std::collections::VecDeque;
+
 pub struct LogBuffer {
-    entries: Mutex<Vec<LogEntry>>,
+    entries: Mutex<VecDeque<LogEntry>>,
     capacity: usize,
 }

 impl LogBuffer {
     pub fn new(capacity: usize) -> Self {
         Self {
-            entries: Mutex::new(Vec::with_capacity(capacity)),
+            entries: Mutex::new(VecDeque::with_capacity(capacity)),
             capacity,
         }
     }

     pub fn push(&self, entry: LogEntry) {
         let mut entries = self.entries.lock();
         if entries.len() >= self.capacity {
-            entries.remove(0);
+            entries.pop_front();
         }
         entries.push(entry);
+        // Note: VecDeque uses push_back, but push also works
     }

     pub fn snapshot(&self) -> Vec<LogEntry> {
-        self.entries.lock().clone()
+        self.entries.lock().iter().cloned().collect()
     }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@overlay/src-tauri/src/log_bridge.rs` around lines 45 - 51, The push method
currently evicts the oldest log with entries.remove(0) which is O(n); change the
underlying collection used by entries from Vec<LogEntry> to VecDeque<LogEntry>
and replace the front-removal logic with pop_front() to make eviction O(1).
Update the type wherever entries is declared/initialized (including the
Mutex-wrapped field and any constructors) to use VecDeque, and in push (the
method shown) use entries.pop_front() when entries.len() >= self.capacity before
entries.push_back(entry). Ensure imports include std::collections::VecDeque and
adjust any other code that relied on Vec APIs to use VecDeque equivalents.
overlay/src/App.tsx (1)

200-201: Move getCurrentWindow() call inside useEffect or useMemo.

Calling getCurrentWindow() directly in the component body executes on every render. While likely cheap, this should be memoized or moved into effects that use it.

♻️ Suggested refactor
 export function App() {
-  const appWindow = getCurrentWindow();
+  const appWindow = useMemo(() => getCurrentWindow(), []);
   const mediaRecorderRef = useRef<MediaRecorder | null>(null);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@overlay/src/App.tsx` around lines 200 - 201, The App component calls
getCurrentWindow() directly in the component body (const appWindow =
getCurrentWindow()), causing it to run on every render; move the call into a
stable hook so it only runs when needed—either wrap it in useMemo (e.g., const
appWindow = useMemo(() => getCurrentWindow(), [])) if you need a synchronous
stable reference, or call it inside useEffect and store it in state (useState +
useEffect) if it’s only used in effects or after mount; update any usages of
appWindow in the component to read from the memoized ref/state accordingly.
src/openhuman/accessibility/globe.rs (1)

241-291: This follows the established compilation pattern in helper.rs, but consider long-term reliability improvements for the accessibility module.

The dynamic Swift compilation approach (writing source to temp directory, compiling on first use) is consistent with the existing helper.rs implementation. However, the concerns you raise apply system-wide:

  1. Temp directory reliability: OS may clean /tmp between boots or sessions
  2. User experience: Missing Xcode command-line tools produces cryptic errors
  3. Latency: Compilation on first hotkey activation adds startup delay

These are valid architectural considerations for the entire accessibility module, not issues specific to this change. If reliability improvements are pursued, apply them consistently across both helper.rs and globe.rs.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/openhuman/accessibility/globe.rs` around lines 241 - 291, The current
ensure_globe_helper_binary() writes Swift source to std::env::temp_dir() and
compiles it on first use which can be unreliable (OS tmp cleanup), produces
cryptic errors when swift/xcrun is missing, and adds runtime latency; update
ensure_globe_helper_binary() to (1) use a stable per-user cache (e.g.,
dirs::cache_dir or an application-specific cache path instead of
std::env::temp_dir()) when creating cache_dir and storing globe_listener.swift
and globe_listener_bin, (2) improve error handling around
Command::new("xcrun")/Command::new("swiftc") to detect common failures and
surface actionable messages (e.g., detect ENOENT and return an error suggesting
installing Xcode Command Line Tools or run `xcode-select --install`), and (3)
add a TODO/note in globe_swift_source()/ensure_globe_helper_binary() to consider
bundling a prebuilt binary fallback to avoid compile-time latency; keep existing
compile retry logic and preserve LOG_PREFIX debug logs.
overlay/src-tauri/src/lib.rs (1)

118-128: Consider adding explicit shutdown handling to the spawned JSON-RPC server.

The tauri::async_runtime::spawn task blocks on axum::serve(), which has no graceful shutdown mechanism. When the Tauri app exits, this task is dropped without signaling the server to close connections cleanly. To avoid potential connection interruption and ensure clean resource teardown, consider implementing a cancellation token or shutdown channel that the server can listen to.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@overlay/src-tauri/src/lib.rs` around lines 118 - 128, The spawned task runs
openhuman_core::core::jsonrpc::run_server and is dropped on app exit without
graceful shutdown; create a cancellation/shutdown channel (e.g.,
tokio::sync::watch or oneshot) and arrange for the Tauri shutdown event (or
AppHandle drop) to send the signal, then pass the receiver/future into
run_server (or update run_server signature) so the axum server can listen for
the shutdown token (via tokio::select or Server::with_graceful_shutdown) and
close connections cleanly; update the tauri::async_runtime::spawn block to
create and forward the shutdown handle and wire the app exit handler to trigger
it.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@overlay/README.md`:
- Line 3: Update the product name casing in the README sentence "This template
should help get you started developing with Tauri in vanilla HTML, CSS and
Typescript." — change "Typescript" to the correct "TypeScript" so the
user-facing documentation uses proper casing.

In `@overlay/src-tauri/tauri.conf.json`:
- Around line 13-36: The security.csp entry is set to null which disables CSP
entirely; replace that null with an explicit, production-ready CSP string (do
not leave security.csp: null) and ensure the configuration is tested with
withGlobalTauri enabled; update the tauri config's "security" -> "csp" value to
a restrictive policy appropriate for your trusted sources (e.g., default-src
'self' ...), verify it works in both dev and production builds, and document the
chosen directives for future reviewers.

In `@overlay/src/components/StatusBar.tsx`:
- Around line 8-9: The LEVELS constant in StatusBar.tsx currently omits "FATAL"
and the label generation logic appends an accidental "+" to each option; update
the LEVELS array (const LEVELS) to include "FATAL" and remove the trailing "+"
from wherever option labels are created (the code that maps LEVELS to
filter/options in the StatusBar component) so labels render correctly and users
can filter by FATAL.

In `@overlay/src/hooks/useLogs.ts`:
- Around line 63-66: The clear() callback currently only resets entriesRef and
setEntries, leaving modules and modulesRef stale; update the clear function (in
useLogs.ts) to also reset module state by clearing modulesRef.current and
calling setModules([]) (or the equivalent setter for modules) inside the same
useCallback so the module filter UI is refreshed; ensure you reference and clear
both modulesRef and the modules state used elsewhere in the hook.

In `@overlay/src/styles.css`:
- Line 17: The font-family declaration currently uses unnecessary quotes around
"Inter"; update the CSS rule containing font-family: "Inter", system-ui,
sans-serif to remove the quotes so it becomes font-family: Inter, system-ui,
sans-serif to satisfy the font-family-name-quotes lint rule.
- Line 1: Stylelint flags the `@import` url(...) notation; update the `@import` line
to use the string notation required by the import-notation rule by replacing
`@import`
url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=JetBrains+Mono:wght@300;400;500&display=swap');
with the string form `@import`
"https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=JetBrains+Mono:wght@300;400;500&display=swap";
so the import uses quoted string notation instead of url(...).

In `@src/openhuman/screen_intelligence/types.rs`:
- Around line 5-6: CI is failing because the re-export block in types.rs isn't
formatted; run the Rust formatter (cargo fmt or rustfmt) on
src/openhuman/screen_intelligence/types.rs and commit the changes so the pub use
lines (the re-exports for PermissionKind, PermissionState, PermissionStatus,
GlobeHotkeyPollResult, GlobeHotkeyStatus) match the project's rustfmt style
(combining/sorting items as configured). Ensure the edited lines referencing
those symbols and the pub use paths are updated exactly by the formatter and no
manual style edits remain.

---

Nitpick comments:
In `@overlay/src-tauri/src/lib.rs`:
- Around line 118-128: The spawned task runs
openhuman_core::core::jsonrpc::run_server and is dropped on app exit without
graceful shutdown; create a cancellation/shutdown channel (e.g.,
tokio::sync::watch or oneshot) and arrange for the Tauri shutdown event (or
AppHandle drop) to send the signal, then pass the receiver/future into
run_server (or update run_server signature) so the axum server can listen for
the shutdown token (via tokio::select or Server::with_graceful_shutdown) and
close connections cleanly; update the tauri::async_runtime::spawn block to
create and forward the shutdown handle and wire the app exit handler to trigger
it.

In `@overlay/src-tauri/src/log_bridge.rs`:
- Around line 45-51: The push method currently evicts the oldest log with
entries.remove(0) which is O(n); change the underlying collection used by
entries from Vec<LogEntry> to VecDeque<LogEntry> and replace the front-removal
logic with pop_front() to make eviction O(1). Update the type wherever entries
is declared/initialized (including the Mutex-wrapped field and any constructors)
to use VecDeque, and in push (the method shown) use entries.pop_front() when
entries.len() >= self.capacity before entries.push_back(entry). Ensure imports
include std::collections::VecDeque and adjust any other code that relied on Vec
APIs to use VecDeque equivalents.

In `@overlay/src/App.tsx`:
- Around line 200-201: The App component calls getCurrentWindow() directly in
the component body (const appWindow = getCurrentWindow()), causing it to run on
every render; move the call into a stable hook so it only runs when
needed—either wrap it in useMemo (e.g., const appWindow = useMemo(() =>
getCurrentWindow(), [])) if you need a synchronous stable reference, or call it
inside useEffect and store it in state (useState + useEffect) if it’s only used
in effects or after mount; update any usages of appWindow in the component to
read from the memoized ref/state accordingly.

In `@overlay/src/components/TitleBar.tsx`:
- Around line 44-47: The toggle button in TitleBar.tsx currently renders
identical text for both states; update the button's inner text to reflect the
clickThrough boolean explicitly (e.g., render "CT ON" when clickThrough is true
and "CT OFF" when false). Locate the button that uses the clickThrough variable
and change its children so the displayed label includes the state (use the
clickThrough ternary already used for title, e.g., clickThrough ? "CT ON" : "CT
OFF") to make the state obvious without relying on color or tooltips.

In `@overlay/vite.config.ts`:
- Line 7: The defineConfig callback is declared async but never uses await;
remove the unnecessary async modifier on the callback returned to defineConfig
(the function starting with "defineConfig(async () => ({") so the export becomes
a plain synchronous function. Update the declaration that currently references
defineConfig and ensure no other code relies on the function returning a
Promise.

In `@src/openhuman/accessibility/globe.rs`:
- Around line 241-291: The current ensure_globe_helper_binary() writes Swift
source to std::env::temp_dir() and compiles it on first use which can be
unreliable (OS tmp cleanup), produces cryptic errors when swift/xcrun is
missing, and adds runtime latency; update ensure_globe_helper_binary() to (1)
use a stable per-user cache (e.g., dirs::cache_dir or an application-specific
cache path instead of std::env::temp_dir()) when creating cache_dir and storing
globe_listener.swift and globe_listener_bin, (2) improve error handling around
Command::new("xcrun")/Command::new("swiftc") to detect common failures and
surface actionable messages (e.g., detect ENOENT and return an error suggesting
installing Xcode Command Line Tools or run `xcode-select --install`), and (3)
add a TODO/note in globe_swift_source()/ensure_globe_helper_binary() to consider
bundling a prebuilt binary fallback to avoid compile-time latency; keep existing
compile retry logic and preserve LOG_PREFIX debug logs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7faee74f-86a7-413b-bdab-3997f5149a2e

📥 Commits

Reviewing files that changed from the base of the PR and between fa1c618 and 424cca1.

⛔ Files ignored due to path filters (17)
  • overlay/src-tauri/Cargo.lock is excluded by !**/*.lock
  • overlay/src-tauri/icons/128x128.png is excluded by !**/*.png
  • overlay/src-tauri/icons/128x128@2x.png is excluded by !**/*.png
  • overlay/src-tauri/icons/32x32.png is excluded by !**/*.png
  • overlay/src-tauri/icons/Square107x107Logo.png is excluded by !**/*.png
  • overlay/src-tauri/icons/Square142x142Logo.png is excluded by !**/*.png
  • overlay/src-tauri/icons/Square150x150Logo.png is excluded by !**/*.png
  • overlay/src-tauri/icons/Square284x284Logo.png is excluded by !**/*.png
  • overlay/src-tauri/icons/Square30x30Logo.png is excluded by !**/*.png
  • overlay/src-tauri/icons/Square310x310Logo.png is excluded by !**/*.png
  • overlay/src-tauri/icons/Square44x44Logo.png is excluded by !**/*.png
  • overlay/src-tauri/icons/Square71x71Logo.png is excluded by !**/*.png
  • overlay/src-tauri/icons/Square89x89Logo.png is excluded by !**/*.png
  • overlay/src-tauri/icons/StoreLogo.png is excluded by !**/*.png
  • overlay/src-tauri/icons/icon.ico is excluded by !**/*.ico
  • overlay/src-tauri/icons/icon.png is excluded by !**/*.png
  • overlay/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (34)
  • overlay/.gitignore
  • overlay/.vscode/extensions.json
  • overlay/README.md
  • overlay/index.html
  • overlay/package.json
  • overlay/postcss.config.js
  • overlay/src-tauri/.gitignore
  • overlay/src-tauri/Cargo.toml
  • overlay/src-tauri/Info.plist
  • overlay/src-tauri/build.rs
  • overlay/src-tauri/capabilities/default.json
  • overlay/src-tauri/icons/icon.icns
  • overlay/src-tauri/src/lib.rs
  • overlay/src-tauri/src/log_bridge.rs
  • overlay/src-tauri/src/main.rs
  • overlay/src-tauri/tauri.conf.json
  • overlay/src/App.tsx
  • overlay/src/components/LogViewer.tsx
  • overlay/src/components/ModuleFilter.tsx
  • overlay/src/components/StatusBar.tsx
  • overlay/src/components/TitleBar.tsx
  • overlay/src/hooks/useLogs.ts
  • overlay/src/main.tsx
  • overlay/src/styles.css
  • overlay/src/types.ts
  • overlay/tailwind.config.js
  • overlay/tsconfig.json
  • overlay/vite.config.ts
  • src/openhuman/accessibility/globe.rs
  • src/openhuman/accessibility/mod.rs
  • src/openhuman/screen_intelligence/engine.rs
  • src/openhuman/screen_intelligence/ops.rs
  • src/openhuman/screen_intelligence/schemas.rs
  • src/openhuman/screen_intelligence/types.rs

Comment thread overlay/README.md
@@ -0,0 +1,7 @@
# Tauri + Vanilla TS

This template should help get you started developing with Tauri in vanilla HTML, CSS and Typescript.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix product name casing in docs (TypeScript).

Small typo in user-facing documentation.

✏️ Proposed fix
-This template should help get you started developing with Tauri in vanilla HTML, CSS and Typescript.
+This template should help get you started developing with Tauri in vanilla HTML, CSS and TypeScript.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
This template should help get you started developing with Tauri in vanilla HTML, CSS and Typescript.
This template should help get you started developing with Tauri in vanilla HTML, CSS and TypeScript.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@overlay/README.md` at line 3, Update the product name casing in the README
sentence "This template should help get you started developing with Tauri in
vanilla HTML, CSS and Typescript." — change "Typescript" to the correct
"TypeScript" so the user-facing documentation uses proper casing.

Comment on lines +13 to +36
"withGlobalTauri": true,
"windows": [
{
"label": "overlay",
"title": "",
"width": 376,
"height": 432,
"minWidth": 376,
"minHeight": 432,
"transparent": true,
"decorations": false,
"alwaysOnTop": true,
"skipTaskbar": true,
"resizable": false,
"visible": false,
"center": false,
"x": 16,
"y": 16
}
],
"macOSPrivateApi": true,
"security": {
"csp": null
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In Tauri v2, what are the recommended production CSP settings, and what are the security implications of setting security.csp to null?

💡 Result:

In Tauri v2, the recommended production CSP settings are tailored to the application's needs but should be as restrictive as possible. The official documentation provides an example from the API example: "csp": { "default-src": "'self' customprotocol: asset:", "connect-src": "ipc: http://ipc.localhost", "font-src": ["https://fonts.gstatic.com"], "img-src": "'self' asset: http://asset.localhost blob: data:", "style-src": "'unsafe-inline' 'self' https://fonts.googleapis.com" } Tauri automatically appends nonces and hashes for local scripts and styles at compile time. Developers must adjust directives like script-src, style-src based on trusted hosts and assets. Setting security.csp to null disables CSP entirely. This removes protection against common web vulnerabilities like XSS, allowing any content to load without restrictions. It is not recommended for production as it leaves the WebView unsecured, though it may be used in development or specific cases. Official sources confirm: "csp: null indeed disables the csp" and "The CSP protection is only enabled if set on the Tauri configuration file."

Citations:


Remove security.csp: null before production.

Setting CSP to null disables Content Security Policy entirely, removing critical XSS protections. Combined with withGlobalTauri: true, this creates a significant security gap. CSP must be explicitly configured even for development builds intended to simulate production.

Recommended CSP configuration
   "security": {
-    "csp": null
+    "csp": {
+      "default-src": ["'self'"],
+      "style-src": ["'self'", "'unsafe-inline'", "https://fonts.googleapis.com"],
+      "font-src": ["'self'", "https://fonts.gstatic.com"],
+      "img-src": ["'self'", "data:"]
+    }
   }

Adjust directives based on your trusted content sources. See Tauri CSP documentation for comprehensive guidance.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"withGlobalTauri": true,
"windows": [
{
"label": "overlay",
"title": "",
"width": 376,
"height": 432,
"minWidth": 376,
"minHeight": 432,
"transparent": true,
"decorations": false,
"alwaysOnTop": true,
"skipTaskbar": true,
"resizable": false,
"visible": false,
"center": false,
"x": 16,
"y": 16
}
],
"macOSPrivateApi": true,
"security": {
"csp": null
}
"withGlobalTauri": true,
"windows": [
{
"label": "overlay",
"title": "",
"width": 376,
"height": 432,
"minWidth": 376,
"minHeight": 432,
"transparent": true,
"decorations": false,
"alwaysOnTop": true,
"skipTaskbar": true,
"resizable": false,
"visible": false,
"center": false,
"x": 16,
"y": 16
}
],
"macOSPrivateApi": true,
"security": {
"csp": {
"default-src": ["'self'"],
"style-src": ["'self'", "'unsafe-inline'", "https://fonts.googleapis.com"],
"font-src": ["'self'", "https://fonts.gstatic.com"],
"img-src": ["'self'", "data:"]
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@overlay/src-tauri/tauri.conf.json` around lines 13 - 36, The security.csp
entry is set to null which disables CSP entirely; replace that null with an
explicit, production-ready CSP string (do not leave security.csp: null) and
ensure the configuration is tested with withGlobalTauri enabled; update the
tauri config's "security" -> "csp" value to a restrictive policy appropriate for
your trusted sources (e.g., default-src 'self' ...), verify it works in both dev
and production builds, and document the chosen directives for future reviewers.

Comment on lines +8 to +9
const LEVELS = ["TRACE", "DEBUG", "INFO", "WARN", "ERROR"];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix level filter options and option label typo.

Line 8 omits FATAL, so users cannot filter to fatal-only entries, and Line 33 appends an accidental + to every label.

Suggested patch
-const LEVELS = ["TRACE", "DEBUG", "INFO", "WARN", "ERROR"];
+const LEVELS = ["TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"];
@@
-            <option key={l} value={l} className="bg-gray-900 text-white">
-              {l}+
+            <option key={l} value={l} className="bg-gray-900 text-white">
+              {l}
             </option>

Also applies to: 31-35

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@overlay/src/components/StatusBar.tsx` around lines 8 - 9, The LEVELS constant
in StatusBar.tsx currently omits "FATAL" and the label generation logic appends
an accidental "+" to each option; update the LEVELS array (const LEVELS) to
include "FATAL" and remove the trailing "+" from wherever option labels are
created (the code that maps LEVELS to filter/options in the StatusBar component)
so labels render correctly and users can filter by FATAL.

Comment on lines +63 to +66
const clear = useCallback(() => {
entriesRef.current = [];
setEntries([]);
}, []);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

clear() leaves module filter state stale.

After clearing entries, modules and modulesRef still retain old modules, so the filter UI can show stale options.

Suggested fix
   const clear = useCallback(() => {
     entriesRef.current = [];
+    modulesRef.current = new Set();
     setEntries([]);
+    setModules(new Set());
   }, []);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const clear = useCallback(() => {
entriesRef.current = [];
setEntries([]);
}, []);
const clear = useCallback(() => {
entriesRef.current = [];
modulesRef.current = new Set();
setEntries([]);
setModules(new Set());
}, []);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@overlay/src/hooks/useLogs.ts` around lines 63 - 66, The clear() callback
currently only resets entriesRef and setEntries, leaving modules and modulesRef
stale; update the clear function (in useLogs.ts) to also reset module state by
clearing modulesRef.current and calling setModules([]) (or the equivalent setter
for modules) inside the same useCallback so the module filter UI is refreshed;
ensure you reference and clear both modulesRef and the modules state used
elsewhere in the hook.

Comment thread overlay/src/styles.css
@@ -0,0 +1,33 @@
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=JetBrains+Mono:wght@300;400;500&display=swap');
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix import notation to satisfy Stylelint.

The current url(...) form is flagged by your configured import-notation rule.

Suggested change
-@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=JetBrains+Mono:wght@300;400;500&display=swap');
+@import 'https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=JetBrains+Mono:wght@300;400;500&display=swap';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=JetBrains+Mono:wght@300;400;500&display=swap');
`@import` 'https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=JetBrains+Mono:wght@300;400;500&display=swap';
🧰 Tools
🪛 Stylelint (17.6.0)

[error] 1-1: Expected "url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=JetBrains+Mono:wght@300;400;500&display=swap')" to be "'https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=JetBrains+Mono:wght@300;400;500&display=swap'" (import-notation)

(import-notation)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@overlay/src/styles.css` at line 1, Stylelint flags the `@import` url(...)
notation; update the `@import` line to use the string notation required by the
import-notation rule by replacing `@import`
url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=JetBrains+Mono:wght@300;400;500&display=swap');
with the string form `@import`
"https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=JetBrains+Mono:wght@300;400;500&display=swap";
so the import uses quoted string notation instead of url(...).

Comment thread overlay/src/styles.css
}

body {
font-family: "Inter", system-ui, sans-serif;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Remove unnecessary quotes around Inter for lint compliance.

This line is currently flagged by font-family-name-quotes.

Suggested change
-  font-family: "Inter", system-ui, sans-serif;
+  font-family: Inter, system-ui, sans-serif;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
font-family: "Inter", system-ui, sans-serif;
font-family: Inter, system-ui, sans-serif;
🧰 Tools
🪛 Stylelint (17.6.0)

[error] 17-17: Unexpected quotes around "Inter" (font-family-name-quotes)

(font-family-name-quotes)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@overlay/src/styles.css` at line 17, The font-family declaration currently
uses unnecessary quotes around "Inter"; update the CSS rule containing
font-family: "Inter", system-ui, sans-serif to remove the quotes so it becomes
font-family: Inter, system-ui, sans-serif to satisfy the font-family-name-quotes
lint rule.

Comment on lines +5 to +6
pub use crate::openhuman::accessibility::{PermissionKind, PermissionState, PermissionStatus};
pub use crate::openhuman::accessibility::{GlobeHotkeyPollResult, GlobeHotkeyStatus};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

CI is failing on this re-export formatting block.

Please apply formatter output here before merge (the Type Check job reports this section in the formatting diff).

🧰 Tools
🪛 GitHub Actions: Type Check

[error] 2-6: Prettier --check failed. Formatting diff indicates re-export lines order/formatting should be adjusted (PermissionKind/PermissionState/PermissionStatus).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/openhuman/screen_intelligence/types.rs` around lines 5 - 6, CI is failing
because the re-export block in types.rs isn't formatted; run the Rust formatter
(cargo fmt or rustfmt) on src/openhuman/screen_intelligence/types.rs and commit
the changes so the pub use lines (the re-exports for PermissionKind,
PermissionState, PermissionStatus, GlobeHotkeyPollResult, GlobeHotkeyStatus)
match the project's rustfmt style (combining/sorting items as configured).
Ensure the edited lines referencing those symbols and the pub use paths are
updated exactly by the formatter and no manual style edits remain.

…d screen intelligence modules

- Reformatted code in `globe.rs`, `ops.rs`, `schemas.rs`, and `types.rs` for better clarity and consistency.
- Enhanced logging statements and function definitions to follow a more uniform style.
- Updated imports in `types.rs` to maintain organization and improve accessibility module integration.
@senamakel senamakel merged commit ffb4c89 into tinyhumansai:main Apr 5, 2026
7 of 9 checks passed
@senamakel senamakel deleted the fix/overlay branch April 5, 2026 03:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant