Skip to content

refactor(composio): extract derive_toolkit_slug helper#3035

Open
YOMXXX wants to merge 24 commits into
tinyhumansai:mainfrom
YOMXXX:chore/2913-derive-toolkit-slug
Open

refactor(composio): extract derive_toolkit_slug helper#3035
YOMXXX wants to merge 24 commits into
tinyhumansai:mainfrom
YOMXXX:chore/2913-derive-toolkit-slug

Conversation

@YOMXXX
Copy link
Copy Markdown
Contributor

@YOMXXX YOMXXX commented May 31, 2026

Summary

Follow-up to the CodeRabbit nitpick on PR #3009 (Composio trigger-permission copy). The toolkit-slug extraction logic was duplicated across two user-facing message builders in src/openhuman/composio/error_mapping.rs:

let toolkit = tool.split('_').next().unwrap_or("integration").to_ascii_lowercase();

This is a pure refactor with zero behavior change: it extracts that expression into a shared derive_toolkit_slug(tool: &str) -> String helper.

Changes

  • New private helper derive_toolkit_slug replicating the original logic verbatim (split('_').next().unwrap_or("integration").to_ascii_lowercase()), with a doc-comment noting the "integration" fallback is unreachable for &str input but kept for parity.
  • Two call sites now delegate to it:
    • format_insufficient_scope_message
    • format_trigger_permission_message
  • Synced the branch with latest upstream/main to clear the dirty merge state and pick up the current local-admin env-lock coverage fix.
  • Updated three subagent progress test fixtures to include the new display_name: None field, fixing Rust Core Coverage compilation after the upstream sync.
  • Serialized round22 provider-admin tests that mutate global env vars, fixing the object-error model-listing flake under cargo llvm-cov parallel test execution.
  • Serialized round23 voice/http tests that mutate global env vars, fixing the mocked-Ollama/model-listing and local-asset status flakes under cargo llvm-cov parallel test execution.
  • Aligned raw coverage expectations/docs with the current toolkit_from_slug behavior for MICROSOFT_TEAMS_* -> microsoft_teams.

Tests

Added unit tests in error_mapping_tests.rs:

  • GMAIL_NEW_GMAIL_MESSAGE -> gmail
  • single segment SLACK -> slack
  • empty input "" -> "" - behavior-parity guard verifying "".split('_').next() yields Some("") (so the unwrap_or fallback does NOT apply), exactly as before

Validation:

  • GGML_NATIVE=OFF cargo test -p openhuman --test inference_local_admin_raw_coverage_e2e -- --test-threads=4 - 4 passed
  • GGML_NATIVE=OFF cargo test -p openhuman composio::error_mapping - 12 passed
  • GGML_NATIVE=OFF cargo test -p openhuman --lib subagent_lifecycle_records_and_clears_active - 1 passed
  • GGML_NATIVE=OFF cargo test -p openhuman --test memory_core_threads_raw_coverage_e2e --test memory_threads_raw_coverage_e2e --no-run - compiled both test targets
  • GGML_NATIVE=OFF cargo test -p openhuman --test inference_provider_admin_round22_raw_coverage_e2e -- --test-threads=4 - 5 passed
  • GGML_NATIVE=OFF cargo test -p openhuman --test inference_voice_http_round23_raw_coverage_e2e -- --test-threads=4 - 3 passed
  • GGML_NATIVE=OFF cargo test -p openhuman --test memory_raw_coverage_e2e memory_sources_validation_and_sync_classification_edges -- --exact - 1 passed
  • GGML_NATIVE=OFF cargo test -p openhuman --test memory_threads_raw_coverage_e2e memory_sync_composio_catalog_scope_and_state_helpers_cover_edge_cases -- --exact - 1 passed
  • GGML_NATIVE=OFF cargo test -p openhuman --test memory_tree_sync_raw_coverage_e2e composio_providers_sync_state_and_bus_surfaces_cover_read_write_edges -- --exact - 1 passed
  • GGML_NATIVE=OFF cargo test -p openhuman --lib toolkit_from_slug_handles_known_multi_segment_toolkits - 1 passed
  • cargo fmt --manifest-path Cargo.toml --all --check - passed
  • git diff --check - passed
  • pnpm compile - passed after pnpm install --frozen-lockfile refreshed local deps from the synced lockfile
  • pre-push hook - passed (format, lint with 89 existing warnings/0 errors, compile, Tauri/Rust check, command-token check)

Not run locally:

  • cargo llvm-cov -p openhuman --test inference_voice_http_round23_raw_coverage_e2e --lcov --output-path /tmp/openhuman-inference-voice-round23.lcov - local cargo-llvm-cov is not installed; CI Rust Core Coverage remains the source of truth.

Notes

  • Latest commit: e49e41637d5bfcaef385660b46f8edcf13a64f0d.

Summary by CodeRabbit

  • Refactor

    • Consolidated toolkit-slug extraction used in error messages to remove duplication.
  • Tests

    • Added unit tests covering toolkit-slug extraction and edge cases.
    • Updated tests to match a slightly expanded event payload shape.
    • e2e tests now serialize environment-variable mutations/restoration to avoid cross-test interference.

@YOMXXX YOMXXX requested a review from a team May 31, 2026 01:25
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 31, 2026

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Centralizes toolkit-slug derivation into a private derive_toolkit_slug used by error formatters, adds unit tests for slug extraction, introduces a process-wide env_lock() and updates EnvVarGuard safety comments/tests to hold it when mutating env vars, and adjusts tests to include display_name: None on AgentProgress::SubagentSpawned.

Changes

Toolkit Slug Extraction

Layer / File(s) Summary
Helper extraction and usage
src/openhuman/composio/error_mapping.rs
derive_toolkit_slug(tool: &str) -> String centralizes toolkit slug extraction (lowercasing the leading underscore-delimited segment with an "integration" fallback). format_trigger_permission_message now calls the helper.
Unit tests for slug derivation
src/openhuman/composio/error_mapping_tests.rs
Three tests validate derive_toolkit_slug: multi-segment leading-segment lowercasing, single-segment lowercasing, and explicit empty-string handling returning "".

EnvVarGuard safety docs

Layer / File(s) Summary
EnvVarGuard safety comments and env_lock helper
tests/inference_local_admin_raw_coverage_e2e.rs, tests/inference_provider_admin_round22_raw_coverage_e2e.rs
Updated safety documentation for EnvVarGuard::set, EnvVarGuard::unset, and Drop to require holding env_lock() while mutating or restoring environment variables; added a OnceLock-initialized Mutex<()> helper env_lock() that returns a held MutexGuard.
Tests acquiring env_lock
tests/inference_provider_admin_round22_raw_coverage_e2e.rs
Three E2E tests now call let _env_guard = env_lock(); at test start to serialize environment-variable mutations.

AgentProgress test updates

Layer / File(s) Summary
Add display_name to SubagentSpawned test payloads
src/openhuman/threads/turn_state/mirror_tests.rs, tests/memory_core_threads_raw_coverage_e2e.rs, tests/memory_threads_raw_coverage_e2e.rs
Adjusted test event literals to include display_name: None in AgentProgress::SubagentSpawned expectations.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • tinyhumansai/openhuman#3009: The main PR refactors toolkit-slug derivation in src/openhuman/composio/error_mapping.rs and updates format_trigger_permission_message to use the new helper, which directly overlaps the retrieved PR’s format_trigger_permission_message-driven TriggerPermission 403 mapping.
  • tinyhumansai/openhuman#2414: Both PRs modify Composio error-mapping in src/openhuman/composio/error_mapping.rs, specifically around format_insufficient_scope_message (one refactors toolkit-slug derivation via derive_toolkit_slug, the other changes the insufficient-scope guidance text and adds matching tests).
  • tinyhumansai/openhuman#1827: Both PRs modify src/openhuman/composio/error_mapping.rs by changing/centralizing Composio tool/slug-based error message derivation logic (main PR via derive_toolkit_slug, retrieved PR via new error-classification/formatting that depends on tool prefixes).

Suggested reviewers

  • senamakel
  • graycyrus

Poem

🐰 I nibble slugs and tidy strings,
One helper now to do the things.
Tests hop in to check each case,
Lock held tight — no env var race.
Hoppity hop, a clean new place.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title accurately describes the main refactoring: extracting a derive_toolkit_slug helper function in the composio module to consolidate duplicated logic.
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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


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.

@coderabbitai coderabbitai Bot added rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure. working A PR that is being worked on by the team. labels May 31, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes May 31, 2026
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.

🧹 Nitpick comments (1)
tests/inference_local_admin_raw_coverage_e2e.rs (1)

52-64: ⚡ Quick win

Consider enforcing the lock precondition at compile time.

The safety comments document that callers must hold ENV_VAR_LOCK, but this precondition isn't enforced. A future test could call EnvVarGuard::set or ::unset without acquiring the lock first, violating the safety contract for the unsafe env mutations.

🔒 Proposed fix to enforce the lock at compile time
 impl EnvVarGuard {
-    fn set(key: &'static str, value: impl AsRef<std::ffi::OsStr>) -> Self {
+    fn set(key: &'static str, value: impl AsRef<std::ffi::OsStr>, _lock: &tokio::sync::MutexGuard<()>) -> Self {
         let previous = std::env::var_os(key);
         // SAFETY: tests that mutate environment variables hold ENV_VAR_LOCK.
         unsafe { std::env::set_var(key, value) };
         Self { key, previous }
     }

-    fn unset(key: &'static str) -> Self {
+    fn unset(key: &'static str, _lock: &tokio::sync::MutexGuard<()>) -> Self {
         let previous = std::env::var_os(key);
         // SAFETY: tests that mutate environment variables hold ENV_VAR_LOCK.
         unsafe { std::env::remove_var(key) };
         Self { key, previous }
     }

Then update call sites to pass the lock reference:

     let _env_lock = ENV_VAR_LOCK.lock().await;
     // ...
-    let _path = EnvVarGuard::set("PATH", scripts.path());
+    let _path = EnvVarGuard::set("PATH", scripts.path(), &_env_lock);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/inference_local_admin_raw_coverage_e2e.rs` around lines 52 - 64,
EnvVarGuard::set and EnvVarGuard::unset perform unsafe environment mutations but
only document that callers must hold ENV_VAR_LOCK; enforce this at compile time
by requiring a reference/token representing the acquired lock (e.g. an
&EnvVarLock or EnvVarLockGuard parameter) in both function signatures instead of
calling them with no proof, update the implementations to use that parameter and
remove the explanatory SAFETY comment, and update all call sites that currently
call EnvVarGuard::set/unset to pass the lock guard (the ENV_VAR_LOCK acquisition
site should now produce the guard value that callers forward).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@tests/inference_local_admin_raw_coverage_e2e.rs`:
- Around line 52-64: EnvVarGuard::set and EnvVarGuard::unset perform unsafe
environment mutations but only document that callers must hold ENV_VAR_LOCK;
enforce this at compile time by requiring a reference/token representing the
acquired lock (e.g. an &EnvVarLock or EnvVarLockGuard parameter) in both
function signatures instead of calling them with no proof, update the
implementations to use that parameter and remove the explanatory SAFETY comment,
and update all call sites that currently call EnvVarGuard::set/unset to pass the
lock guard (the ENV_VAR_LOCK acquisition site should now produce the guard value
that callers forward).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 28a3d9b4-0689-4529-9b65-d667563fb050

📥 Commits

Reviewing files that changed from the base of the PR and between 6ca488c and ee73a08.

📒 Files selected for processing (1)
  • tests/inference_local_admin_raw_coverage_e2e.rs

coderabbitai[bot]
coderabbitai Bot previously approved these changes May 31, 2026
…oolkit-slug

# Conflicts:
#	tests/inference_local_admin_raw_coverage_e2e.rs
coderabbitai[bot]
coderabbitai Bot previously approved these changes May 31, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes May 31, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes May 31, 2026
@sanil-23 sanil-23 assigned sanil-23 and unassigned sanil-23 May 31, 2026
Copy link
Copy Markdown
Contributor

@sanil-23 sanil-23 left a comment

Choose a reason for hiding this comment

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

The core refactor is clean: derive_toolkit_slug lifts the duplicated split('_').next().unwrap_or("integration").to_ascii_lowercase() expression verbatim, the doc-comment correctly explains the unreachable "integration" fallback, and the three unit tests (multi-segment, single-segment, empty-string parity) lock the behavior down. Nice touch covering the empty-string Some("") edge that the unwrap_or does not catch.

I checked the riskier bundled changes and they hold up:

  • generate_id() switching from a UUID string to an opaque r+a-p encoding is safe -- rule ids are treated as opaque strings everywhere (only ever prefixed with rule/ as a storage key, never parsed back as a UUID), so no consumer breaks. Still 128 bits of entropy, and it's covered by a test.
  • The meet_agent file.flush() is a correct durability fix -- tokio's File doesn't guarantee a flush on drop.
  • The thread_stack_size bump and the aria-pressed addition are additive and low-risk.

One thing worth fixing for the record, not blocking: the description frames this as a "pure refactor with zero behavior change," but the PR actually bundles several real production changes that aren't called out in the Changes list -- the server runtime stack-size bump (src/core/cli.rs), the rule-id generation format (memory_tools/types.rs), and the meet-agent flush (meet_agent/store.rs). They're each defensible, but they aren't behavior-neutral and they're unrelated to the toolkit-slug refactor. Please update the description so the production changes are visible to reviewers and the changelog, and ideally split unrelated production fixes into their own PRs next time -- it keeps the diff reviewable and the history bisectable.

Everything is correct and CI is fully green, so approving. Thanks for also stabilizing the flaky env-mutating coverage tests with the shared env_lock -- that's a real improvement.

Change summary:

Area Change Assessment
composio/error_mapping extract derive_toolkit_slug + tests clean, the stated refactor
core/cli.rs 8 MiB worker thread stack safe, undisclosed in description
memory_tools/types.rs opaque rule-id format safe, ids are opaque
meet_agent/store.rs flush after write correct durability fix
frontend (ToolsPanel) aria-pressed + tests good accessibility win
tests (~15 files) env serialization, fixtures, pagination stabilization, fine

Comment thread src/core/cli.rs
let rt = tokio::runtime::Builder::new_multi_thread()
.enable_all()
// Match the desktop host runtime stack: sub-agent prompt/tool
// orchestration can exceed Tokio's default 2 MiB worker stack.
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.

[minor] This raises the server runtime's per-worker stack to 8 MiB, which is a real production change (and a sensible one) -- but it isn't mentioned in the PR's Changes list, which describes the PR as a zero-behavior-change refactor. Please call it out in the description so it's visible to reviewers and the changelog.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure. working A PR that is being worked on by the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants