feat(composio): granular trigger triage settings — per-toolkit + global toggle#1334
Conversation
…al toggle Adds user-configurable control over the LLM triage pipeline that runs on every incoming Composio trigger, without breaking any existing behavior. Core: - ComposioConfig gains two serde(default) fields: triage_disabled (global kill) and triage_disabled_toolkits (per-toolkit slug list). Existing config.toml files without these fields default to current behavior. - ComposioTriggerSettingsPatch + apply/load_and_apply/get helpers added to config::ops following the established settings-patch pattern. - Two new RPC controllers: openhuman.update_composio_trigger_settings and openhuman.get_composio_trigger_settings wired into the controller registry. - bus.rs: after the existing OPENHUMAN_TRIGGER_TRIAGE_DISABLED env-var gate, now also checks config.composio.triage_disabled (global) and config.composio.triage_disabled_toolkits (per-toolkit, case-insensitive). Fail-open on config load error — triage still runs rather than silently dropping events. App: - Two typed RPC wrappers in tauriCommands/config.ts. - ComposioTriagePanel: global toggle + per-toolkit slug input. - Routed at /settings/composio-triggers, reachable from Developer Options. Replaces/complements OPENHUMAN_TRIGGER_TRIAGE_DISABLED env var with a persisted, product-discoverable setting. Env var remains as emergency override.
|
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds Composio trigger triage controls: config schema fields, backend RPCs and handlers, frontend Tauri wrappers and a settings panel with routing/menu entry, and subscriber gating that conditionally skips LLM triage; includes unit tests. ChangesComposio Trigger Triage Configuration
Sequence Diagram(s)sequenceDiagram
participant UI as ComposioTriagePanel
participant RPC as Tauri RPC
participant Core as Backend RPC Handler
participant Config as Config Ops
participant Storage as Config Storage
participant Subscriber as ComposioTriggerSubscriber
Note over UI,Subscriber: Initial Load
UI->>RPC: openhumanGetComposioTriggerSettings()
RPC->>Core: call openhuman.get_composio_trigger_settings
Core->>Config: get_composio_trigger_settings()
Config->>Storage: load config
Storage-->>Config: config
Config-->>Core: triage_disabled, triage_disabled_toolkits
Core-->>RPC: result
RPC-->>UI: settings
UI->>UI: render toggles and input
Note over UI,Subscriber: User Saves Settings
UI->>RPC: openhumanUpdateComposioTriggerSettings(patch)
RPC->>Core: call openhuman.update_composio_trigger_settings
Core->>Config: load_and_apply_composio_trigger_settings(patch)
Config->>Storage: load config
Storage-->>Config: config
Config->>Config: apply patch
Config->>Storage: persist
Storage-->>Config: ok
Config-->>Core: outcome
Core-->>RPC: result
RPC-->>UI: success/error
Note over UI,Subscriber: Trigger Submission
Subscriber->>Storage: load config (on trigger event)
Storage-->>Subscriber: config with triage flags
Subscriber->>Subscriber: check triage_disabled
Subscriber->>Subscriber: check toolkit in triage_disabled_toolkits
Subscriber->>Subscriber: conditionally skip LLM triage
Subscriber->>Storage: record trigger to history
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Warning Review ran into problems🔥 ProblemsGit: Failed to clone repository. Please run the Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 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.
Inline comments:
In `@app/src/components/settings/panels/ComposioTriagePanel.tsx`:
- Around line 115-131: The per-toolkit input is only visually blocked via CSS
but not actually disabled for keyboard/screen-reader users; update the input
with a proper disabled attribute bound to triageDisabled (e.g., <input
id="disabled-toolkits" ... disabled={triageDisabled} />) so it is removed from
the tab order and exposed as disabled to assistive tech; you can keep the
existing visual class (pointer-events-none) if desired but ensure
disabled={triageDisabled} is present and that the onChange handler
(setDisabledToolkits) relies on the browser preventing input events when
disabled.
- Line 46: The setTimeout call that sets saveStatus back to 'idle' in
ComposioTriagePanel.tsx can fire after the component unmounts; change it to
store the timer ID in a ref (e.g., saveTimeoutRef) when calling setTimeout in
your save handler, clear any existing timeout before creating a new one, and add
a useEffect cleanup that calls clearTimeout(saveTimeoutRef.current) to prevent
the stale setSaveStatus('idle') update on unmount.
- Around line 19-32: The code is using an unsafe cast by treating the entire
CommandResponse as ComposioTriggerSettings; update the
openhumanGetComposioTriggerSettings() handler to only use res.result (the
ComposioTriggerSettings), remove the fallback cast, and explicitly handle the
missing/undefined result (e.g., log or throw an error and avoid reading
settings.triage_disabled from the response object); keep using setTriageDisabled
and setDisabledToolkits only with validated settings.triage_disabled and
settings.triage_disabled_toolkits values and preserve the existing
.catch/.finally behavior to setLoading(false).
In `@src/openhuman/composio/bus_tests.rs`:
- Around line 59-68: The test function composio_config_triage_disabled_default
in the ComposioConfig tests is failing the repository formatting check; run
rustfmt to fix styling and revalidate. Locally run `cargo fmt --all` to reformat
the changed Rust files (including the test), then run `cargo check` (or `cargo
test`) to ensure no build/test regressions before committing; after formatting,
update the branch so the CI `cargo fmt --all -- --check` passes.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: ca4387ed-f1d7-4ddf-95a9-cd8fe1be7e1e
📒 Files selected for processing (10)
app/src/components/settings/hooks/useSettingsNavigation.tsapp/src/components/settings/panels/ComposioTriagePanel.tsxapp/src/components/settings/panels/DeveloperOptionsPanel.tsxapp/src/pages/Settings.tsxapp/src/utils/tauriCommands/config.tssrc/openhuman/composio/bus.rssrc/openhuman/composio/bus_tests.rssrc/openhuman/config/ops.rssrc/openhuman/config/schema/tools.rssrc/openhuman/config/schemas.rs
- Remove unsafe CommandResponse fallback cast; use res.result directly with an explicit early-return when falsy - Track saveStatus timer in a ref and clear it in effect cleanup to avoid stale state updates on unmount - Add disabled attribute to per-toolkit input when global toggle is on (pointer-events-none alone is not sufficient for keyboard/a11y)
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
app/src/components/settings/panels/ComposioTriagePanel.tsx (1)
20-31: ⚡ Quick winUse namespaced debug logs instead of ad-hoc
console.warnin this panel.Please add structured, namespaced debug logs around load/save entry, success/failure branches, and external RPC calls (not only warnings on failure).
As per coding guidelines “Add substantial, development-oriented logs at entry/exit points, branch decisions, external calls, retries/timeouts, state transitions, and error handling paths; use namespaced
debuglogs in production app code.”Also applies to: 53-55
🤖 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 `@app/src/components/settings/panels/ComposioTriagePanel.tsx` around lines 20 - 31, Replace ad-hoc console.warn usage in the ComposioTriagePanel effect with namespaced debug logging and add entry/exit and branch logs: at the start of the useEffect for ComposioTriagePanel log entry (e.g., "ComposioTriagePanel: loading settings"), before/after calling openhumanGetComposioTriggerSettings log the external RPC call and its result, log success branch when you call setTriageDisabled and setDisabledToolkits (including the values applied), log the failure branch using the same namespaced debug (not console.warn) with the error, and log the final state change when setLoading(false) is invoked; follow the same pattern around the save logic referenced at lines 53-55.
🤖 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.
Inline comments:
In `@app/src/components/settings/panels/ComposioTriagePanel.tsx`:
- Around line 95-117: The toggle button in ComposioTriagePanel lacks accessible
state; update the button element (the one using setTriageDisabled and
triageDisabled) to expose its on/off state to assistive tech by adding
role="switch" (or ensure a suitable role) plus aria-checked set to the boolean
triageDisabled, and include a clear aria-label or aria-labelledby that describes
the control; keep the existing onClick behavior with setTriageDisabled so visual
and programmatic states remain synced.
- Around line 51-53: The save-status timer can overlap when Save is clicked
repeatedly; in ComposioTriagePanel ensure you clear any previous timer before
creating a new one by calling clearTimeout(saveStatusTimer.current) (or
clearInterval) just prior to assigning saveStatusTimer.current =
setTimeout(...), so older timers cannot reset the status prematurely; keep using
setSaveStatus('saved') then set the new timeout to setSaveStatus('idle') after
3000ms and ensure saveStatusTimer is properly typed/initialized for the
environment.
---
Nitpick comments:
In `@app/src/components/settings/panels/ComposioTriagePanel.tsx`:
- Around line 20-31: Replace ad-hoc console.warn usage in the
ComposioTriagePanel effect with namespaced debug logging and add entry/exit and
branch logs: at the start of the useEffect for ComposioTriagePanel log entry
(e.g., "ComposioTriagePanel: loading settings"), before/after calling
openhumanGetComposioTriggerSettings log the external RPC call and its result,
log success branch when you call setTriageDisabled and setDisabledToolkits
(including the values applied), log the failure branch using the same namespaced
debug (not console.warn) with the error, and log the final state change when
setLoading(false) is invoked; follow the same pattern around the save logic
referenced at lines 53-55.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 3401a79d-e584-4ddd-8ade-60243cb2ae33
📒 Files selected for processing (1)
app/src/components/settings/panels/ComposioTriagePanel.tsx
- Clear previous saveStatus timer before setting a new one to prevent stale timer firing when Save is clicked in quick succession - Add role=switch + aria-checked + aria-label to global toggle button so screen readers announce its on/off state correctly
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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.
Inline comments:
In `@app/src/components/settings/panels/ComposioTriagePanel.tsx`:
- Around line 20-31: The effect that calls openhumanGetComposioTriggerSettings
can update state after the component unmounts; wrap the async flow with an
"isMounted" boolean (or AbortController) inside the useEffect for the initial
settings load and check it before calling setTriageDisabled,
setDisabledToolkits, or setLoading (also guard inside catch/finally), and flip
isMounted to false in the effect cleanup; target the async call in the useEffect
that invokes openhumanGetComposioTriggerSettings and the state setters
setTriageDisabled, setDisabledToolkits, and setLoading to make the update
unmount-safe.
- Around line 90-94: The current descriptive text in the ComposioTriagePanel UI
(component ComposioTriagePanel.tsx) fails to tell users that the environment
kill-switch OPENHUMAN_TRIGGER_TRIAGE_DISABLED takes precedence over saved UI
toggles; update the paragraph shown to include a short sentence clarifying that
if OPENHUMAN_TRIGGER_TRIAGE_DISABLED is set, triage will be disabled regardless
of UI settings (mention the env var by name), so users aren’t misled when they
save toggles that appear to have no effect.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 3a929507-86b0-4d25-8490-e1c60f74b9e2
📒 Files selected for processing (1)
app/src/components/settings/panels/ComposioTriagePanel.tsx
- Add isMounted boolean to the initial settings-load effect so state setters are never called after the component unmounts (CR feedback). - Guard catch and finally branches with the same isMounted check. - Add a sentence to the panel description noting that OPENHUMAN_TRIGGER_TRIAGE_DISABLED env var overrides UI settings (CR feedback).
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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.
Inline comments:
In `@app/src/components/settings/panels/ComposioTriagePanel.tsx`:
- Around line 57-65: In ComposioTriagePanel's save routine ensure the catch
block clears the pending success timer (saveStatusTimer.current) before calling
setSaveStatus('error')—mirror the success-path logic: if saveStatusTimer.current
!== null then clearTimeout(saveStatusTimer.current) and null it, then
setSaveStatus('error') so a previously scheduled timeout won't later overwrite
the error state.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 0f62f7d0-bb3e-4d85-af2b-c214e60c69a5
📒 Files selected for processing (1)
app/src/components/settings/panels/ComposioTriagePanel.tsx
…mands Cover the new ComposioTriagePanel component (loading/loaded states, toggle flip, save success/error, fetch error recovery, env-var note) and the two new tauriCommands/config.ts functions (openhumanUpdateComposioTriggerSettings, openhumanGetComposioTriggerSettings) to satisfy the ≥ 80% diff-cover gate.
Summary
triage_disabled(global) andtriage_disabled_toolkits(per-slug list) toComposioConfigwithserde(default)— existing configs keep current behavior unchanged.openhuman.update_composio_trigger_settings/openhuman.get_composio_trigger_settingsfollowing the established settings-patch pattern.ComposioTriggerSubscribernow checks the config-level gates after the existingOPENHUMAN_TRIGGER_TRIAGE_DISABLEDenv var; fail-open on config load error so events are never silently dropped.Problem
run_triage/apply_decision. High-volume sources (email, Slack) can generate many events, burning battery and model quota even when users only want read/send tooling.OPENHUMAN_TRIGGER_TRIAGE_DISABLEDenv var — global, not per-toolkit, not persisted in settings.Solution
ComposioConfig(existing TOML without them gets current behavior via#[serde(default)]).trigger_history) is unconditionally before all gates — disabling triage never drops event history.Submission Checklist
docs/TESTING-STRATEGY.md— 3 new Rust unit tests:composio_config_triage_disabled_default,composio_config_triage_disabled_toolkit_match,trigger_subscriber_skips_triage_when_env_disabled.Impact
triage_disableddefaults tofalse,triage_disabled_toolkitsdefaults to[].Related
OPENHUMAN_TRIGGER_TRIAGE_DISABLEDdocs note to settings panel copy.AI Authored PR Metadata (required for Codex/Linear PRs)
Linear Issue
Commit & Branch
Validation Run
pnpm --filter openhuman-app format:checkpnpm typecheckcomposio_config_triage_disabled_default,composio_config_triage_disabled_toolkit_match,trigger_subscriber_skips_triage_when_env_disabledcargo check --manifest-path Cargo.toml— cleanValidation Blocked
Behavior Changes
ComposioTriggerSubscriber::handlenow checksconfig.composio.triage_disabledandconfig.composio.triage_disabled_toolkitsbefore schedulingrun_triage. When either gate fires, the event is recorded to history but no LLM turn is spawned.Parity Contract
OPENHUMAN_TRIGGER_TRIAGE_DISABLEDenv var still works as before; config gates only checked after it.load_config_with_timeouterror — triage runs, no events dropped.Duplicate / Superseded PR Handling
Summary by CodeRabbit
New Features
Tests