Skip to content

refactor(voice): move CLI adapter to controller registry#1005

Merged
senamakel merged 1 commit into
tinyhumansai:mainfrom
jwalin-shah:refactor/consolidate-voice-cli
Apr 29, 2026
Merged

refactor(voice): move CLI adapter to controller registry#1005
senamakel merged 1 commit into
tinyhumansai:mainfrom
jwalin-shah:refactor/consolidate-voice-cli

Conversation

@jwalin-shah
Copy link
Copy Markdown
Contributor

@jwalin-shah jwalin-shah commented Apr 28, 2026

Summary

  • Removes the hardcoded "voice" | "dictate" branch from src/core/cli.rs dispatch
  • Introduces RegisteredCliAdapter + CLI_ADAPTERS static registry in src/core/all.rs
  • Adds cli_handler_for_namespace() lookup so the voice CLI is wired the same way as RPC controllers — via the registry, not ad-hoc branching
  • run_namespace_command now falls through to the registry before printing help, making future CLI adapters zero-touch in cli.rs

Test plan

  • cargo check passes clean (pre-existing private_interfaces warning only, unrelated)
  • cargo fmt --check passes
  • openhuman voice / openhuman dictate subcommands still dispatch correctly
  • Adding a new CLI adapter requires only a registry entry in all.rs, no change to cli.rs

Summary by CodeRabbit

  • Refactor
    • Updated the CLI dispatch system to support namespace-based command handling, improving the flexibility and organization of command routing.

@jwalin-shah jwalin-shah requested a review from a team April 28, 2026 17:54
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 28, 2026

📝 Walkthrough

Walkthrough

Introduces a namespace-based CLI adapter registry in the core module. New public types define handlers and adapters; a lazy global store initializes with a "voice" adapter. The CLI dispatch logic is updated to query this registry for namespace handlers instead of relying on hard-coded subcommands.

Changes

Cohort / File(s) Summary
CLI Adapter Registry
src/core/all.rs
Adds CliHandler type alias, RegisteredCliAdapter struct, and cli_handler_for_namespace() function to enable namespace-based handler lookup. Initializes a lazy global CLI_ADAPTERS store with a "voice" adapter.
CLI Dispatch Logic
src/core/cli.rs
Updates run_namespace_command to query cli_handler_for_namespace() when arguments are empty or request help, delegating to the registered handler if available.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Possibly related PRs

  • #758: Moves domain-specific CLI handlers (voice, text_input, tree_summarizer, screen_intelligence) out of core and updates CLI dispatch to call those domain handlers, using the same namespace-based adapter registry pattern introduced in this PR.

Poem

🐰 A registry now holds the CLI's voice,
Namespaces find their handler with joy!
No hard-coded paths, just a lookup so neat,
Making dispatch adaptive—rabbit-approved treat! 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: consolidating CLI adapter registration from hardcoded branching into a registry-based approach (similar to RPC controllers).
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

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

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/core/cli.rs (1)

350-376: ⚠️ Potential issue | 🟠 Major

Dispatch to CLI adapters before controller-schema lookup.

Right now the adapter is only consulted for empty/help args after grouped.get(namespace), so real invocations like openhuman voice --hotkey ... are parsed as controller functions and never reach run_standalone_subcommand. That also leaves CLI-only aliases like dictate dead unless they happen to have schemas.

Suggested fix
-    let Some(schemas) = grouped.get(namespace) else {
-        return Err(anyhow::anyhow!(
-            "unknown namespace '{namespace}'. Run `openhuman --help` to see available namespaces."
-        ));
-    };
-
     let preparsed = autocomplete_cli_adapter::preparse_namespace(namespace, args);
     let args: &[String] = &preparsed.args;
     if let Some((verbose, scope)) = preparsed.init_logging {
         crate::core::logging::init_for_cli_run(verbose, scope);
     }
 
-    if args.is_empty() || is_help(&args[0]) {
-        // If there's a domain-specific CLI handler for this namespace, use it as the default.
-        if let Some(cli_handler) = all::cli_handler_for_namespace(namespace) {
-            return cli_handler(args);
-        }
-        print_namespace_help(namespace, schemas);
-        return Ok(());
+    if let Some(cli_handler) = all::cli_handler_for_namespace(namespace) {
+        if args.is_empty() || is_help(&args[0]) || args[0].starts_with('-') {
+            return cli_handler(args);
+        }
     }
+
+    let Some(schemas) = grouped.get(namespace) else {
+        return Err(anyhow::anyhow!(
+            "unknown namespace '{namespace}'. Run `openhuman --help` to see available namespaces."
+        ));
+    };

As per coding guidelines, expose domain functionality through the controller registry and avoid one-off transport logic in src/core/cli.rs.

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

In `@src/core/cli.rs` around lines 350 - 376, Move the autocomplete adapter
dispatch (autocomplete_cli_adapter::preparse_namespace and the call to
all::cli_handler_for_namespace) to run before the controller schema lookup
(grouped.get(namespace)) so adapter-handled invocations and CLI-only aliases are
resolved prior to treating args as controller functions; specifically, call
preparse_namespace early, check preparsed.init_logging, then if preparsed.args
is empty or is_help OR if all::cli_handler_for_namespace(namespace) returns
Some, invoke that cli handler and return; only after adapter dispatch fails
should you call grouped.get(namespace) and proceed to schema lookup and
run_standalone_subcommand. Ensure you preserve existing logging initialization
(crate::core::logging::init_for_cli_run) when moving the preparse call.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/core/all.rs`:
- Around line 74-79: The CLI registry currently only registers namespace "voice"
so "openhuman dictate" won't match; update the CLI_ADAPTERS initialization to
also register the "dictate" alias by adding a second RegisteredCliAdapter (or
otherwise include both namespace strings) that uses the same handler
crate::openhuman::voice::cli::run_standalone_subcommand so both "voice" and
"dictate" resolve to the same entrypoint.

---

Outside diff comments:
In `@src/core/cli.rs`:
- Around line 350-376: Move the autocomplete adapter dispatch
(autocomplete_cli_adapter::preparse_namespace and the call to
all::cli_handler_for_namespace) to run before the controller schema lookup
(grouped.get(namespace)) so adapter-handled invocations and CLI-only aliases are
resolved prior to treating args as controller functions; specifically, call
preparse_namespace early, check preparsed.init_logging, then if preparsed.args
is empty or is_help OR if all::cli_handler_for_namespace(namespace) returns
Some, invoke that cli handler and return; only after adapter dispatch fails
should you call grouped.get(namespace) and proceed to schema lookup and
run_standalone_subcommand. Ensure you preserve existing logging initialization
(crate::core::logging::init_for_cli_run) when moving the preparse call.
🪄 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: e635be14-9833-462e-9378-68d1f2ba9846

📥 Commits

Reviewing files that changed from the base of the PR and between 1a25f5b and b5c7730.

📒 Files selected for processing (2)
  • src/core/all.rs
  • src/core/cli.rs

Comment thread src/core/all.rs
Comment on lines +74 to +79
CLI_ADAPTERS.get_or_init(|| {
vec![RegisteredCliAdapter {
namespace: "voice",
handler: crate::openhuman::voice::cli::run_standalone_subcommand,
}]
})
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

Register the dictate alias alongside voice.

run_standalone_subcommand is documented to handle both openhuman voice and openhuman dictate, but the registry only exposes "voice". With exact namespace matching, openhuman dictate will still miss the adapter and fall back to an unknown-namespace error.

Suggested fix
     CLI_ADAPTERS.get_or_init(|| {
-        vec![RegisteredCliAdapter {
-            namespace: "voice",
-            handler: crate::openhuman::voice::cli::run_standalone_subcommand,
-        }]
+        vec![
+            RegisteredCliAdapter {
+                namespace: "voice",
+                handler: crate::openhuman::voice::cli::run_standalone_subcommand,
+            },
+            RegisteredCliAdapter {
+                namespace: "dictate",
+                handler: crate::openhuman::voice::cli::run_standalone_subcommand,
+            },
+        ]
     })

As per coding guidelines, wire domain exports into src/core/all.rs so transport layers stay generic.

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

In `@src/core/all.rs` around lines 74 - 79, The CLI registry currently only
registers namespace "voice" so "openhuman dictate" won't match; update the
CLI_ADAPTERS initialization to also register the "dictate" alias by adding a
second RegisteredCliAdapter (or otherwise include both namespace strings) that
uses the same handler crate::openhuman::voice::cli::run_standalone_subcommand so
both "voice" and "dictate" resolve to the same entrypoint.

@senamakel senamakel merged commit 87f72f8 into tinyhumansai:main Apr 29, 2026
9 checks passed
AusAgentSmith pushed a commit to AusAgentSmith/openhuman that referenced this pull request May 23, 2026
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.

3 participants