Skip to content

feat(skills): channels grid + integrations card polish; tolerant Composio trigger decode#1112

Merged
senamakel merged 4 commits into
tinyhumansai:mainfrom
senamakel:feat/may-2
May 3, 2026
Merged

feat(skills): channels grid + integrations card polish; tolerant Composio trigger decode#1112
senamakel merged 4 commits into
tinyhumansai:mainfrom
senamakel:feat/may-2

Conversation

@senamakel
Copy link
Copy Markdown
Member

@senamakel senamakel commented May 3, 2026

Summary

  • Reworked the Connections (Skills) tab: Channels card moved above Integrations, both rendered as icon-grid tiles with the same status-color vocabulary.
  • Search bar + category chips now live inside the Integrations card (Channels chip removed; channels are no longer filtered).
  • Added an iMessage channel icon (green chat bubble) and renamed the WhatsApp Composio toolkit display name to "WhatsApp Business".
  • Removed the redundant "composio" badge chip from the Composio connect/manage modal header.
  • Made ComposioActiveTrigger deserialization tolerant of upstream API shape drift (e.g. toolkit arriving as an object instead of a string), fixing the runtime Couldn't load triggers: ... invalid type: map, expected a string error in the modal.

Problem

  • The Connections tab visual hierarchy mixed list-style Channels with grid-style Integrations and exposed UI controls (search, chips) that filtered the wrong things.
  • The Composio connect modal carried an obvious "composio" chip on top of an already Composio-branded surface.
  • composio_list_triggers started failing at runtime because Composio now returns objects (e.g. toolkit: { slug: ... }) where our struct expected plain strings, blocking the trigger toggles inside the connect modal.

Solution

  • New ChannelTile mirrors ComposioConnectorTile styling (12×12 icon, name, status label, sage outline when connected) so Channels and Integrations look like one cohesive surface.
  • Channels group is derived from the unfiltered item list so the search/chip controls only affect Integrations and discovered skills; the Channels chip is excluded from the available categories.
  • Integrations card always renders so its embedded search/chip controls remain accessible; an inline "No integrations match your search" message replaces the previous full-page empty state.
  • de_string_or_object / de_opt_string_or_object helpers in src/openhuman/composio/types.rs accept either a string or an object (extracting slug/id/name/key), applied to ComposioActiveTrigger's id, slug, toolkit, connection_id, and state fields.

Submission Checklist

  • Tests added or updated — N/A: existing 286 Composio unit tests cover the deserialization paths and continue to pass; UI changes are visual-only with no behavioral test gaps introduced.
  • Diff coverage ≥ 80% — diff is mostly visual JSX rearrangement plus tolerant deserializer helpers; existing Composio tests exercise the happy path.
  • Coverage matrix updated — N/A: behaviour-only change.
  • No new external network dependencies introduced.
  • Manual smoke checklist updated — N/A: not a release-cut surface change.
  • Linked issue closed — N/A: no tracked issue.

Impact

  • Desktop UI only for the Skills/Connections rework; no new IPC or RPC surface.
  • Composio trigger decode fix prevents a hard-failure on the manage modal whenever upstream returns nested toolkit objects; safe for both old and new payload shapes.

Summary by CodeRabbit

  • New Features

    • Added iMessage channel support.
  • Improvements

    • Refined Composio connect modal copy and header.
    • Updated WhatsApp label to "WhatsApp Business".
    • Reorganized Skills page with a dedicated Channels section, refreshed card layouts and clearer status labels.
    • Tightened usage, budget and promo credit thresholds.
    • Improved robustness of Composio/integration handling.
  • Tests

    • Added channel grid tests and updated integration UI assertions.

@senamakel senamakel requested a review from a team May 3, 2026 02:41
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 3, 2026

📝 Walkthrough

Walkthrough

This PR updates Composio/connect modal copy and toolkit display names, refactors the Skills page to separate Channels and add iMessage support with accompanying tests, tightens USD thresholds to treat <= $0.01 as zero for budget/usage logic and promo banner visibility, and adds resilient Serde deserializers and tests for Composio active trigger fields.

Changes

Composio Integration UI & Skills Page refactor

Layer / File(s) Summary
UI Copy & Modal
app/src/components/composio/ComposioConnectModal.tsx, app/src/components/composio/toolkitMeta.tsx
Removed small header badge spans; shortened the initial "Connect …" paragraph; changed ScopeToggles title to "Permissions"; defaultDescription() fallback shortened; whatsapp display name changed to "WhatsApp Business".
Channel Icons
app/src/components/skills/skillIcons.tsx
Imported IoChatbubble and added a new imessage entry to CHANNEL_ICONS with label and styling classes.
Skills Page Layout & Status
app/src/pages/Skills.tsx
Removed dot-based channelStatusDot/composioStatusDot; rely on statusLabel/statusColor; added ChannelTile component and separate channelsGroup; excluded Channels from category-filtered groups; added renderGroup helper; integrations card now contains search/filter and shows Composio connector grid or an empty-state message.
Tests / Assertions
app/src/pages/__tests__/Skills.channels-grid.test.tsx, app/src/pages/__tests__/Skills.third-party-notion-debug-tools.test.tsx, app/src/pages/__tests__/Skills.discovered-skills.test.tsx
Added channel-grid tests (Telegram and iMessage tiles, setup modal assertions); parameterized channel connection-state class assertions; updated Notion test copy expectation; added/expanded discovered-skills tests for scope labels, uninstall action, and detail drawer behavior.

Budget & Usage threshold adjustments

Layer / File(s) Summary
Usage logic
app/src/hooks/useUsageState.ts
Threshold comparisons changed from > 0/<= 0 to > 0.01/<= 0.01 for usagePct10h, usagePct7d, isBudgetExhausted, and shouldShowBudgetCompletedMessage.
Promo banner
app/src/pages/Home.tsx
showPromoBanner now requires promoCredits > 0.01 instead of > 0, tightening visibility for very small balances.

Composio trigger deserialization robustness (Rust)

Layer / File(s) Summary
Deserializer helpers
src/openhuman/composio/types.rs
Added private Serde deserializers de_string_or_object and de_opt_string_or_object to accept either a string or an object containing first-match keys (slug/id/name/key); optional variant maps null/missing/unrecognized shapes to None.
Model wiring
src/openhuman/composio/types.rs
Applied de_string_or_object to ComposioActiveTrigger fields id, slug, toolkit, and connection_id; applied de_opt_string_or_object to state (keeps Option<String>).
Tests
src/openhuman/composio/types.rs (tests)
Added unit tests validating acceptance of string and object forms for required fields, state extraction/fallback behavior, and that object forms missing supported keys fail deserialization.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

I nibble code and copy neat,
Channels split and icons meet.
Tiny budgets round away,
Serde hears both string and clay.
A rabbit hops — the UI's sweet 🐰

🚥 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 summarizes the main changes across the pull request: channels grid UI refactor, integrations card polish, and improved Composio trigger deserialization robustness.
Docstring Coverage ✅ Passed Docstring coverage is 82.35% 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.


Review rate limit: 4/5 reviews remaining, refill in 12 minutes.

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)
app/src/hooks/useUsageState.ts (1)

79-104: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Align isRateLimited with the new near-zero threshold semantics.

usagePct10h/budget flags now treat <= 0.01 as zero, but isRateLimited still uses fiveHourCapUsd > 0 (Line 103). For tiny caps, this can still mark users as rate-limited while other state says effectively zero budget.

Suggested fix
   const isRateLimited =
     teamUsage !== null &&
     !teamUsage.bypassCycleLimit &&
-    teamUsage.fiveHourCapUsd > 0 &&
+    teamUsage.fiveHourCapUsd > 0.01 &&
     teamUsage.cycleLimit5hr >= teamUsage.fiveHourCapUsd;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/hooks/useUsageState.ts` around lines 79 - 104, Update isRateLimited
to use the same near-zero threshold as the other budget checks: change the
fiveHourCapUsd condition in isRateLimited (currently checking fiveHourCapUsd >
0) to use > 0.01, keeping the rest of the logic (!teamUsage.bypassCycleLimit and
cycleLimit5hr >= fiveHourCapUsd) unchanged so tiny caps are treated as
zero-consistent with usagePct10h and budget flags.
🧹 Nitpick comments (1)
src/openhuman/composio/types.rs (1)

245-264: ⚡ Quick win

Please add regression tests for the new tolerant trigger decoding path.

This path now handles multiple upstream shapes; adding focused tests for string/object variants (especially mixed-key state objects) will protect against silent regressions.

Example tests to add
+    #[test]
+    fn active_trigger_deserializes_string_and_object_fields() {
+        let raw = json!({
+            "id": {"id": "trg_1"},
+            "slug": {"slug": "GMAIL_NEW_GMAIL_MESSAGE"},
+            "toolkit": {"slug": "gmail", "name": "Gmail"},
+            "connectionId": {"id": "conn_1"},
+            "state": {"state": "ACTIVE", "id": "meta_ignored"}
+        });
+        let t: ComposioActiveTrigger = serde_json::from_value(raw).unwrap();
+        assert_eq!(t.id, "trg_1");
+        assert_eq!(t.slug, "GMAIL_NEW_GMAIL_MESSAGE");
+        assert_eq!(t.toolkit, "gmail");
+        assert_eq!(t.connection_id, "conn_1");
+        assert_eq!(t.state.as_deref(), Some("ACTIVE"));
+    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/openhuman/composio/types.rs` around lines 245 - 264, Add focused
regression tests that exercise the tolerant trigger decoding path in types.rs by
covering both string and object variants for fields using de_string_or_object
and de_opt_string_or_object (notably the struct fields trigger_config and
state), including mixed-key/state-as-object cases and combinations (e.g., state
as string, state as object, trigger_config present/absent). Write tests that
deserialize representative JSON payloads into the target struct and assert the
resulting id/slug/toolkit/connection_id/trigger_config/state values match
expectations; include negative cases where malformed shapes should fail if
appropriate. Place tests near existing serde tests for composio types and
reference the deserializers de_string_or_object and de_opt_string_or_object so
future changes to those functions will be covered. Ensure tests are
deterministic and cover both Option::None and Some(...) branches for state.
🤖 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/openhuman/composio/types.rs`:
- Around line 52-53: The loop that picks a string from JSON fields uses a
priority order ["slug","id","name","key","value","state"] which can pick
metadata keys before the actual "state" or "value"; update the selection logic
in the deserialization code that contains the for key in ["slug", "id", "name",
"key", "value", "state"] construct so it prefers "state" and "value" (or
explicitly matches the exact intended field) before metadata keys (or switch to
exact-key matching rather than first-found priority), and apply the same fix at
the other occurrence around lines 259-264 to ensure correct deserialization of
state strings.

---

Outside diff comments:
In `@app/src/hooks/useUsageState.ts`:
- Around line 79-104: Update isRateLimited to use the same near-zero threshold
as the other budget checks: change the fiveHourCapUsd condition in isRateLimited
(currently checking fiveHourCapUsd > 0) to use > 0.01, keeping the rest of the
logic (!teamUsage.bypassCycleLimit and cycleLimit5hr >= fiveHourCapUsd)
unchanged so tiny caps are treated as zero-consistent with usagePct10h and
budget flags.

---

Nitpick comments:
In `@src/openhuman/composio/types.rs`:
- Around line 245-264: Add focused regression tests that exercise the tolerant
trigger decoding path in types.rs by covering both string and object variants
for fields using de_string_or_object and de_opt_string_or_object (notably the
struct fields trigger_config and state), including mixed-key/state-as-object
cases and combinations (e.g., state as string, state as object, trigger_config
present/absent). Write tests that deserialize representative JSON payloads into
the target struct and assert the resulting
id/slug/toolkit/connection_id/trigger_config/state values match expectations;
include negative cases where malformed shapes should fail if appropriate. Place
tests near existing serde tests for composio types and reference the
deserializers de_string_or_object and de_opt_string_or_object so future changes
to those functions will be covered. Ensure tests are deterministic and cover
both Option::None and Some(...) branches for 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: 6618d92a-9ca4-4bea-99e2-903fe6de3cd8

📥 Commits

Reviewing files that changed from the base of the PR and between 195c9c5 and dd918e7.

⛔ Files ignored due to path filters (2)
  • Cargo.lock is excluded by !**/*.lock
  • app/src-tauri/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (7)
  • app/src/components/composio/ComposioConnectModal.tsx
  • app/src/components/composio/toolkitMeta.tsx
  • app/src/components/skills/skillIcons.tsx
  • app/src/hooks/useUsageState.ts
  • app/src/pages/Home.tsx
  • app/src/pages/Skills.tsx
  • src/openhuman/composio/types.rs

Comment thread src/openhuman/composio/types.rs Outdated
…grid coverage, prefer state/value keys in tolerant decoder

- Update Skills Notion test for the trimmed modal copy ("Connect your Notion account.").
- Add Skills.channels-grid test covering ChannelTile rendering, setup-modal open, and absence of the Channels chip.
- Address CodeRabbit feedback: `de_opt_string_or_object` now prefers `state`/`value` keys before slug/id metadata.
- Add Rust unit tests for ComposioActiveTrigger string + object payloads.
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)
app/src/pages/__tests__/Skills.channels-grid.test.tsx (1)

60-63: ⚡ Quick win

Avoid scoping these tests with .rounded-2xl.

Both lookups depend on a styling class, so a visual-only refactor will break the suite even if the UI still works. Please switch to a semantic hook on the card and query that instead.

As per coding guidelines, app/src/**/*.test.{ts,tsx}: Prefer testing behavior over implementation details.

Also applies to: 80-83

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

In `@app/src/pages/__tests__/Skills.channels-grid.test.tsx` around lines 60 - 63,
The tests currently scope the card using a styling class via
channelsHeading.closest('.rounded-2xl') and then call within(channelsCard as
HTMLElement); replace this brittle selector with a semantic hook on the card
(e.g., an accessible role/aria-label or existing data-testid like
"channels-card") and query that element (e.g.,
getByRole/getByLabelText/getByTestId) instead, then pass the found element into
within(...) using the same within$ variable; make the same replacement for the
other occurrence that mirrors lines 80-83 so no tests rely on the '.rounded-2xl'
styling class.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@app/src/pages/__tests__/Skills.channels-grid.test.tsx`:
- Around line 60-63: The tests currently scope the card using a styling class
via channelsHeading.closest('.rounded-2xl') and then call within(channelsCard as
HTMLElement); replace this brittle selector with a semantic hook on the card
(e.g., an accessible role/aria-label or existing data-testid like
"channels-card") and query that element (e.g.,
getByRole/getByLabelText/getByTestId) instead, then pass the found element into
within(...) using the same within$ variable; make the same replacement for the
other occurrence that mirrors lines 80-83 so no tests rely on the '.rounded-2xl'
styling class.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b7fa655d-a47d-4b4f-bad4-c3e48baa5806

📥 Commits

Reviewing files that changed from the base of the PR and between dd918e7 and e407ff6.

📒 Files selected for processing (3)
  • app/src/pages/__tests__/Skills.channels-grid.test.tsx
  • app/src/pages/__tests__/Skills.third-party-notion-debug-tools.test.tsx
  • src/openhuman/composio/types.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/openhuman/composio/types.rs

coderabbitai[bot]
coderabbitai Bot previously approved these changes May 3, 2026
… ignore unreachable BUILT_IN_SKILLS branches

- Drop dead `ConnectionBadge`/`isMessagingId` import (the channel branch in renderGroup is gone now that channels render via ChannelTile).
- Mark the unreachable per-id BUILT_IN_SKILLS branches in renderGroup with v8 ignore so diff-cover doesn't count code that can't fire while the list is empty.
- Extend the channels-grid test with parameterized cases for connected / connecting / error states so the ChannelTile className branches are covered.
- New Skills.discovered-skills test renders user / project / legacy scope rows, asserts the scope-color mapping, that Uninstall only surfaces on user-scope, and that View opens the detail drawer.
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

🧹 Nitpick comments (1)
app/src/pages/Skills.tsx (1)

570-729: 💤 Low value

Missing explicit return for channel kind in renderGroup map.

The items.map callback handles 'builtin' and 'discovered' kinds but has no explicit case for 'channel'. While channels are filtered out via otherGroups (line 550), if one ever slips through due to a future refactor, the callback would implicitly return undefined, rendering nothing silently.

Consider adding an explicit defensive case:

🛡️ Defensive fix
           );
         }
+        // Channels are rendered in a dedicated card above; skip if one leaks through.
+        if (item.kind === 'channel') {
+          return null;
+        }
+        return null; // Exhaustive fallback
       })}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/pages/Skills.tsx` around lines 570 - 729, The map callback over items
(items.map) currently handles 'builtin' and 'discovered' but lacks an explicit
branch for item.kind === 'channel', which can lead to an implicit undefined
return; add a defensive case for channel inside the same map (or a final else)
that explicitly returns either a UnifiedSkillCard representing the channel
(using item.id, item.icon, item.name, item.description and
navigate(item.route!)) or returns null while logging a warning (e.g.,
console.warn('[skills] unexpected channel item', { id: item.id })) so the intent
is explicit and no implicit undefined is rendered; update the code paths that
set secondaryActions/onCtaClick accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/src/pages/__tests__/Skills.channels-grid.test.tsx`:
- Around line 35-41: The current mocks point to the wrong module and are dead —
remove the vi.mock calls that target the unused module paths and instead add a
mock for the actual API used by Skills.tsx: mock the skillsApi module so that
skillsApi.listSkills is stubbed (resolve to an empty list or fixture) and also
mock skillsApi.installSkill if the test expects it; ensure the test imports use
the mock by creating a vi.mock for the real skillsApi module and providing
listSkills and installSkill fakes so the component effect
(skillsApi.listSkills()) is driven by the test rather than the real API.

---

Nitpick comments:
In `@app/src/pages/Skills.tsx`:
- Around line 570-729: The map callback over items (items.map) currently handles
'builtin' and 'discovered' but lacks an explicit branch for item.kind ===
'channel', which can lead to an implicit undefined return; add a defensive case
for channel inside the same map (or a final else) that explicitly returns either
a UnifiedSkillCard representing the channel (using item.id, item.icon,
item.name, item.description and navigate(item.route!)) or returns null while
logging a warning (e.g., console.warn('[skills] unexpected channel item', { id:
item.id })) so the intent is explicit and no implicit undefined is rendered;
update the code paths that set secondaryActions/onCtaClick accordingly.
🪄 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: da4ce6f8-ce70-4473-ae77-65d48a5ef933

📥 Commits

Reviewing files that changed from the base of the PR and between e407ff6 and a953de1.

📒 Files selected for processing (3)
  • app/src/pages/Skills.tsx
  • app/src/pages/__tests__/Skills.channels-grid.test.tsx
  • app/src/pages/__tests__/Skills.discovered-skills.test.tsx

Comment thread app/src/pages/__tests__/Skills.channels-grid.test.tsx Outdated
CodeRabbit flagged the `lib/skills/*` mocks as dead — Skills.tsx imports
from `services/api/skillsApi`, so swap to the matching factory (mirrors
Skills.discovered-skills.test.tsx) to keep listSkills off the network.
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

🧹 Nitpick comments (1)
app/src/pages/__tests__/Skills.channels-grid.test.tsx (1)

122-128: ⚡ Quick win

Prefer behavior assertions over container class-name matching here.

expect(telegramTile.className).toMatch(...) is brittle to style refactors and ties the test to Tailwind internals. Assert observable status/CTA semantics instead (accessible name/text), which is what users actually experience.

Suggested refactor
-      expect(telegramTile.className).toMatch(classPattern);
+      expect(telegramTile).toHaveAccessibleName(
+        new RegExp(`Telegram.*${labelPattern.source}`, 'i')
+      );
+      if (status === 'connected') {
+        expect(telegramTile).toHaveAccessibleName(/Manage/i);
+      } else {
+        expect(telegramTile).toHaveAccessibleName(/Setup/i);
+      }

As per coding guidelines: "Prefer testing behavior over implementation details; use existing helpers from app/src/test/ before adding new harness code".

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

In `@app/src/pages/__tests__/Skills.channels-grid.test.tsx` around lines 122 -
128, The test is asserting on the DOM className (telegramTile.className) which
is brittle; replace that with behavior-focused assertions: locate the Telegram
tile via the existing telegramTile variable (found with
within(...).getByRole('button', ...)) and assert its accessible semantics
instead — e.g., that the button's accessible name/text matches labelPattern
(using toHaveAccessibleName or checking .textContent), that any status is
exposed via aria attributes (aria-pressed/aria-checked/aria-disabled) or that
the expected CTA/button state is present, and/or assert that clicking the button
triggers the expected handler; remove the classPattern assertion and prefer
existing test helpers from app/src/test/ for accessibility assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/src/pages/__tests__/Skills.channels-grid.test.tsx`:
- Around line 122-126: The test calls within(channelsCard as HTMLElement) after
const channelsCard = screen.getByRole(...).closest('.rounded-2xl') but closest
can return null; add an explicit non-null guard before using within to produce a
clear failure. Locate the channelsCard variable in the test and add a check
(e.g., expect(channelsCard).not.toBeNull() or if (!channelsCard) throw new
Error(...)) immediately after the closest(...) call, then safely cast
channelsCard to HTMLElement before calling within(...) to find telegramTile via
getByRole.

---

Nitpick comments:
In `@app/src/pages/__tests__/Skills.channels-grid.test.tsx`:
- Around line 122-128: The test is asserting on the DOM className
(telegramTile.className) which is brittle; replace that with behavior-focused
assertions: locate the Telegram tile via the existing telegramTile variable
(found with within(...).getByRole('button', ...)) and assert its accessible
semantics instead — e.g., that the button's accessible name/text matches
labelPattern (using toHaveAccessibleName or checking .textContent), that any
status is exposed via aria attributes (aria-pressed/aria-checked/aria-disabled)
or that the expected CTA/button state is present, and/or assert that clicking
the button triggers the expected handler; remove the classPattern assertion and
prefer existing test helpers from app/src/test/ for accessibility assertions.
🪄 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: 52c3267d-4386-41ac-809f-f5967d79cdaa

📥 Commits

Reviewing files that changed from the base of the PR and between a953de1 and 20d4d6b.

📒 Files selected for processing (1)
  • app/src/pages/__tests__/Skills.channels-grid.test.tsx

Comment thread app/src/pages/__tests__/Skills.channels-grid.test.tsx
@senamakel senamakel merged commit 07b02d5 into tinyhumansai:main May 3, 2026
19 checks passed
jwalin-shah added a commit to jwalin-shah/openhuman that referenced this pull request May 5, 2026
* feat(remotion): Ghosty character library with transparent MOV variants (tinyhumansai#1059)

Co-authored-by: WOZCODE <contact@withwoz.com>

* feat(composio/gmail): sync into memory tree (Slack-parity) (tinyhumansai#1056)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(scheduler-gate): throttle background AI on battery / busy CPU (tinyhumansai#1062)

* fix(core,cef): run core in-process and stop orphaning CEF helpers on Cmd+Q (tinyhumansai#1061)

* ci: add dedicated staging release workflow (tinyhumansai#1066)

* fix(sentry): Rust source context + per-release deploy marker (tinyhumansai#405) (tinyhumansai#1067)

* fix(welcome): re-enable OAuth buttons with focus/timeout recovery (tinyhumansai#1049) (tinyhumansai#1069)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(dependencies): update pnpm-lock.yaml and Cargo.lock for package… (tinyhumansai#1082)

* fix(onboarding): personalize welcome agent greeting with user identity (tinyhumansai#1078)

* fix(chat): make agent message bubbles fit content width (tinyhumansai#1083)

* Feat/dmg checks (tinyhumansai#1084)

* fix(linux): Add X11 platform flags to .deb package launcher (tinyhumansai#1087)

Co-authored-by: unn-Known1 <unn-known1@users.noreply.github.com>

* fix(sentry): auto-send React events; collapse core→tauri for desktop (tinyhumansai#1086)

Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>

* fix(cef): run blank reload guard on the CEF UI thread (tinyhumansai#1092)

* fix(app): reload webview instead of restart_app in dev mode (tinyhumansai#1068) (tinyhumansai#1071)

* fix(linux): deliver X11 ozone flags via custom .desktop template (tinyhumansai#1091)

* fix(webview-accounts): retry data-dir purge so CEF handle race doesn't leak cookies (tinyhumansai#1076) (tinyhumansai#1081)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>

* fix(webview/slack): media perms + deep-link isolation (tinyhumansai#1074) (tinyhumansai#1080)

Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>

* ci(release): split staging vs production workflows; promote staging tags (tinyhumansai#1094)

* Update release-staging.yml (tinyhumansai#1097)

* chore(staging): v0.53.5

* chore(staging): v0.53.6

* ci(staging): cut staging from main; add act local-debug helper (tinyhumansai#1099)

* chore(staging): v0.53.7

* fix(ci): correct sentry-cli download URL and trap scope (tinyhumansai#1100)

* chore(staging): v0.53.8

* feat(chat): forward thread_id to backend for KV cache locality (tinyhumansai#1095)

* fix(ci): bump pinned sentry-cli to 3.4.1 (2.34.2 was never published) (tinyhumansai#1102)

* chore(staging): v0.53.9

* fix(ci): drop bash trap in upload_sentry_symbols.sh; inline cleanup (tinyhumansai#1103)

* chore(staging): v0.53.10

* refactor(session): flatten session_raw/, switch md to YYYY_MM_DD (tinyhumansai#1098)

* Add full Composio managed-auth toolkit catalog (tinyhumansai#1093)

* ci: add diff-aware 80% coverage gate (Vitest + cargo-llvm-cov) (tinyhumansai#1104)

* feat(scripts): pnpm work + pnpm debug for agent-driven workflows (tinyhumansai#1105)

* ci: pull pnpm into CI image, drop redundant setup steps (tinyhumansai#1107)

* docs: add Cursor Cloud specific instructions to AGENTS.md (tinyhumansai#1106)

Co-authored-by: Cursor Agent <cursoragent@cursor.com>

* chore(staging): v0.53.11

* docs: surface 80% coverage gate and scripts/debug runners (tinyhumansai#1108)

* feat(app): show Composio integrations as sorted icon grid on Skills (tinyhumansai#1109)

Co-authored-by: Cursor Agent <cursoragent@cursor.com>

* feat(composio): client-side trigger enable/disable toggles (tinyhumansai#1110)

* feat(skills): channels grid + integrations card polish; tolerant Composio trigger decode (tinyhumansai#1112)

* chore(staging): v0.53.12

* feat(home): early-bird banner + assistant→agent terminology (tinyhumansai#1113)

* feat(updater): in-app auto-update with auto-download + restart prompt (tinyhumansai#677) (tinyhumansai#1114)

* chore(claude): add ship-and-babysit slash command (tinyhumansai#1115)

* feat(home): EarlyBirdyBanner + agent terminology + LinkedIn enrichment model pin (tinyhumansai#1118)

* fix(chat): single onboarding thread in sidebar after wizard (tinyhumansai#1116)

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Steven Enamakel <senamakel@users.noreply.github.com>

* fix: filter out global namespace from citation chips (tinyhumansai#1124)

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Co-authored-by: senamakel-droid <281415773+senamakel-droid@users.noreply.github.com>

* feat(nav): enable Memory tab in BottomTabBar (tinyhumansai#1125)

* feat(memory): singleton ingestion + status RPC + UI pill (tinyhumansai#1126)

* feat(human): mascot tab with viseme-driven lipsync (staging only) (tinyhumansai#1127)

* Fix CEF zombie processes on full app close and restart (tinyhumansai#1128)

Co-authored-by: senamakel-droid <281415773+senamakel-droid@users.noreply.github.com>
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>

* Update issue templates for GitHub issue types (tinyhumansai#1146)

* feat(human): expand mascot expressions and tighten reply-speech state machine (tinyhumansai#1147)

* feat(memory): ingestion pipeline + tree-architecture docs + ops/schemas split (tinyhumansai#1142)

* feat(threads): surface live subagent work in parent thread (tinyhumansai#1122) (tinyhumansai#1159)

* fix(human): keep mascot mouth animating when TTS ships no viseme data (tinyhumansai#1160)

* feat(composio): consume backend markdownFormatted for LLM output (tinyhumansai#1165)

* fix(subagent): lazy-register toolkit actions filtered out of fuzzy top-K (tinyhumansai#1162)

* feat(memory): user-facing long-term memory window preset (tinyhumansai#1137) (tinyhumansai#1161)

* fix(tauri-shell): proactively kill stale openhuman RPC on startup (tinyhumansai#1166)

* chore(staging): v0.53.13

* fix(composio): per-action tool consumes backend markdownFormatted (tinyhumansai#1167)

* fix(threads): persist selectedThreadId across reloads (tinyhumansai#1168)

* feat(memory_tree): switch embed model to bge-m3 (1024-dim, 8K context) (tinyhumansai#1174)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(agent): drop redundant [Memory context] recall injection (tinyhumansai#1173)

* chore(memory_tree): drop body-read timeouts on Ollama HTTP calls (tinyhumansai#1171)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(transcript): emit thread_id + fix orchestrator missing cost (tinyhumansai#1169)

* fix(composio/gmail): phase out html2md, prefer text/plain MIME part (tinyhumansai#1170)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(tools): markdown output for internal tool results (tinyhumansai#1172)

* feat(security): enforce prompt-injection guard before model and tool execution (tinyhumansai#1175)

* fix(cef): popup paint dies after first frame — skip blank-page guard for popups (tinyhumansai#1079) (tinyhumansai#1182)

Co-authored-by: Steven Enamakel <31011319+senamakel@users.noreply.github.com>

* chore(sentry): rename OPENHUMAN_SENTRY_DSN → OPENHUMAN_CORE_SENTRY_DSN (tinyhumansai#1186)

* feat(remotion): add yellow mascot character with all animation variants (tinyhumansai#1193)

Co-authored-by: Neel Mistry <neelmistry@Neels-MacBook-Pro.local>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor(composio): hide raw connection ID, derive friendly label (tinyhumansai#1153) (tinyhumansai#1185)

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>

* fix(windows): align install.ps1 MSI with per-machine scope (tinyhumansai#913) (tinyhumansai#1187)

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(tauri): deterministic CEF teardown on full app close (tinyhumansai#1120) (tinyhumansai#1189)

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(composio): cap Gmail HTML body before strip (crash mitigation) (tinyhumansai#1191)

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(auth): stop stale chat threads after signup (tinyhumansai#1192)

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(sentry): staging-only "Trigger Sentry Test" button (tinyhumansai#1072) (tinyhumansai#1183)

* chore(staging): v0.53.14

* chore(staging): v0.53.15

* feat(composio): format trigger slugs into human-readable labels (tinyhumansai#1129) (tinyhumansai#1179)

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>

* fix(ui): hide unsupported permission UI on non-macOS for Screen Intelligence (tinyhumansai#1194)

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore(tauri-shell): retire embedded Gmail webview-account flow (tinyhumansai#1181)

* feat(onboarding): replace welcome-agent bot with react-joyride walkthrough (tinyhumansai#1180)

* chore(release): v0.53.16

* fix(threads): preserve selectedThreadId on cold-boot identity hydration (tinyhumansai#1196)

* feat(core): version/shutdown/update RPCs + mid-thread integration refresh (tinyhumansai#1195)

* fix(mascot): swap to yellow mascot via @remotion/player (tinyhumansai#1200)

* feat(memory_tree): cloud-default LLM, queue priority, entity filter, Memory tab UI (tinyhumansai#1198)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Persist turn state + restore conversation history on cold-boot (tinyhumansai#1202)

* feat(mascot): floating desktop mascot via native NSPanel + WKWebView (macOS) (tinyhumansai#1203)

* fix(memory/tree): emit summary children as Obsidian wikilinks (tinyhumansai#1210)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(tools): coding-harness baseline primitives (tinyhumansai#1205) (tinyhumansai#1208)

* docs: add Codex PR checklist for remote agents

---------

Co-authored-by: Steven Enamakel <31011319+senamakel@users.noreply.github.com>
Co-authored-by: WOZCODE <contact@withwoz.com>
Co-authored-by: sanil-23 <sanil@vezures.xyz>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Cyrus Gray <144336577+graycyrus@users.noreply.github.com>
Co-authored-by: CodeGhost21 <164498022+CodeGhost21@users.noreply.github.com>
Co-authored-by: oxoxDev <164490987+oxoxDev@users.noreply.github.com>
Co-authored-by: Mega Mind <146339422+M3gA-Mind@users.noreply.github.com>
Co-authored-by: Gaurang Patel <ptelgm.yt@gmail.com>
Co-authored-by: unn-Known1 <unn-known1@users.noreply.github.com>
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Steven Enamakel <senamakel@users.noreply.github.com>
Co-authored-by: Steven Enamakel's Droid <enamakel.agent@tinyhumans.ai>
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Co-authored-by: senamakel-droid <281415773+senamakel-droid@users.noreply.github.com>
Co-authored-by: YellowSnnowmann <167776381+YellowSnnowmann@users.noreply.github.com>
Co-authored-by: Neil <neil@maha.xyz>
Co-authored-by: Neel Mistry <neelmistry@Neels-MacBook-Pro.local>
Co-authored-by: obchain <167975049+obchain@users.noreply.github.com>
Co-authored-by: Jwalin Shah <jshah1331@gmail.com>
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.

1 participant