feat: Agent "superpower" content types - #96
Conversation
Introduce the five dynamic agent content cards that show how Convos works for the user, surfacing the right thing at the right time: - Thinking → live reasoning steps while the agent works - Sources → citations/references backing an answer - Action → a tool call/action, with approve/decline when needed - Memory → what the agent remembers (stored with the user) - Suggestions → tappable follow-up prompts Implemented as a self-contained agent-content module (types, assertions, a shared expandable AgentCard, per-type render components, a dispatcher mirroring conversation-message.tsx, and mock fixtures). Kept decoupled from the XMTP-bound message union so it has no wire-format codec yet and doesn't touch the protocol conversion layer. Added an "Agent content examples" dev screen (reachable from App Settings) that renders every card with mock data for review. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rov93B6jifGmgS6EGyw94c
WalkthroughIntroduces a complete "agent superpower" card UI system for conversation messages. Adds TypeScript type definitions and type guards for five agent content types (thinking, sources, action, memory, suggestions), a shared ChangesAgent Content Cards UI System
Sequence Diagram(s)sequenceDiagram
participant User
participant AgentContentExamplesScreen
participant AgentContent
participant TypeGuards as isAgent*Content
participant CardComponent as AgentContentThinking/Action/Memory/Sources/Suggestions
User->>AgentContentExamplesScreen: navigates to AgentContentExamples route
AgentContentExamplesScreen->>AgentContent: renders each fixture from allAgentContentFixtures
AgentContent->>TypeGuards: checks agentContent.type via isAgentThinkingContent, isAgentSourcesContent, etc.
TypeGuards-->>AgentContent: narrows to matching IAgent*Content
AgentContent->>CardComponent: renders matched card with content prop
CardComponent-->>User: displays themed AgentCard with content-specific layout
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 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. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
ApprovabilityVerdict: Needs human review This PR introduces a substantial new feature with five new agent content type components, new types, navigation changes, and user interaction flows (approve/decline actions). New features of this scope warrant human review regardless of the author's admin status. You can customize Macroscope's approvability policy. Learn more. |
ThemedStyle<ViewStyle> isn't assignable to an Image's style prop, which would fail the tsc check. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rov93B6jifGmgS6EGyw94c
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (4)
features/conversation/conversation-chat/conversation-message/agent-content/agent-card.tsx (3)
1-2: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAlias third-party imports to match repository convention.
Imports from external libraries should use
asaliases for source clarity per repo standard.As per coding guidelines: “When importing types or functions from external libraries, rename them to clearly indicate their source. Use the 'as' keyword to rename imports from third-party libraries.”
Proposed change
-import { memo, ReactNode, useState } from "react" -import { ViewStyle } from "react-native" +import { memo as reactMemo, ReactNode as ReactReactNode, useState as reactUseState } from "react" +import { ViewStyle as RNViewStyle } from "react-native" ... -export const AgentCard = memo(function AgentCard(props: IAgentCardProps) { +export const AgentCard = reactMemo(function AgentCard(props: IAgentCardProps) { ... - const [expanded, setExpanded] = useState(defaultExpanded) + const [expanded, setExpanded] = reactUseState(defaultExpanded) ... -const $card: ThemedStyle<ViewStyle> = ({ colors, spacing, borderRadius, borderWidth }) => ({ +const $card: ThemedStyle<RNViewStyle> = ({ colors, spacing, borderRadius, borderWidth }) => ({🤖 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 `@features/conversation/conversation-chat/conversation-message/agent-content/agent-card.tsx` around lines 1 - 2, The imports from external libraries (react and react-native) need to be aliased to match repository conventions for clarity. In the import statements at the top of the file, add aliases using the `as` keyword for all imported items: memo, ReactNode, useState from the "react" import, and ViewStyle from the "react-native" import. This makes the source of each imported item explicit and improves code readability when these items are used throughout the component.Source: Coding guidelines
81-87: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winReplace render ternary with an early-return style branch.
Line 81 uses a render ternary for header wrapping; switch to a precomputed branch/early-return pattern to align with the TSX rendering guideline.
As per coding guidelines: “Prefer early returns over ternaries in React component render logic.”
Proposed change
+ const headerContent = collapsible ? ( + <Pressable withHaptics onPress={() => setExpanded((prev) => !prev)}> + {Header} + </Pressable> + ) : ( + Header + ) + return ( <VStack style={themed($card)}> - {collapsible ? ( - <Pressable withHaptics onPress={() => setExpanded((prev) => !prev)}> - {Header} - </Pressable> - ) : ( - Header - )} + {headerContent} {(!collapsible || expanded) && !!children && ( <VStack style={themed($body)}>{children}</VStack> )} </VStack> )🤖 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 `@features/conversation/conversation-chat/conversation-message/agent-content/agent-card.tsx` around lines 81 - 87, The Header rendering logic uses a ternary operator to conditionally wrap the Header in a Pressable component based on the collapsible prop. Refactor this to use an early-return pattern instead: check if collapsible is false and return the Header directly without the Pressable wrapper, then render the Pressable-wrapped Header with the setExpanded callback for the truthy case. This aligns with the guideline to prefer early returns over ternaries in React component render logic.Source: Coding guidelines
19-22: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winTrim obvious inline/JSDoc comments in this TSX component.
These comments mostly duplicate what prop names and function bodies already express; keeping only non-obvious rationale will improve signal.
As per coding guidelines: “Don't add comments for obvious code… Avoid verbose JSDoc-style documentation when TypeScript types already provide this information.”
Also applies to: 27-34, 114-115
🤖 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 `@features/conversation/conversation-chat/conversation-message/agent-content/agent-card.tsx` around lines 19 - 22, Remove or significantly simplify the JSDoc comments for the props and other code in the agent-card.tsx component that simply restate what the code already expresses. Specifically, trim the verbose comments for the `trailing` and `collapsible` props (in the diff area at lines 19-22), as well as similar obvious comments found at lines 27-34 and 114-115. Keep only comments that explain non-obvious rationale or important implementation details that cannot be inferred from the prop names and TypeScript types themselves. This will improve code readability by reducing redundant documentation.Source: Coding guidelines
features/conversation/conversation-chat/conversation-message/agent-content/agent-content.types.ts (1)
3-20: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winReduce verbose commentary in this TypeScript types module.
These block comments restate what the type names and fields already communicate; trimming them will keep the file cleaner and aligned with the repo TS style.
As per coding guidelines: “Don't add comments for obvious code… Avoid verbose JSDoc-style documentation when TypeScript types already provide this information.”
Also applies to: 28-30, 48-50, 65-67, 86-88, 101-103, 115-117
🤖 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 `@features/conversation/conversation-chat/conversation-message/agent-content/agent-content.types.ts` around lines 3 - 20, Remove or significantly reduce the verbose JSDoc comment block at the start of the agent-content.types.ts file that explains the five buckets of agent superpowers, as the type names and field structure already communicate this information clearly. Apply the same principle to trim verbose comments at the other specified line ranges (28-30, 48-50, 65-67, 86-88, 101-103, 115-117) throughout the file. Keep only essential, non-obvious comments that add value beyond what the TypeScript type definitions themselves convey, following the repository's style guideline of avoiding verbose JSDoc-style documentation when types are already self-explanatory.Source: Coding guidelines
🤖 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
`@features/conversation/conversation-chat/conversation-message/agent-content/agent-content-examples.screen.tsx`:
- Around line 14-17: Remove the verbose JSDoc comment block (the multi-line
comment starting with /** and ending with */) at the top of the
agent-content-examples.screen.tsx file. The component name already clearly
conveys its purpose as a demo screen for agent content examples, making the
detailed explanation redundant and unnecessary to maintain according to the
project's coding guidelines.
In
`@features/conversation/conversation-chat/conversation-message/agent-content/agent-content-sources.tsx`:
- Around line 58-66: The handlePress callback function currently passes
source.url directly to the WebviewPreview navigation without validating the URL
scheme, which could allow unsafe URI schemes to be executed. In the handlePress
function, add validation logic before the navigate call to ensure that
source.url only uses safe schemes (http or https). Check if the URL starts with
http:// or https:// and only proceed with navigation if this condition is true,
otherwise skip the navigation to prevent potentially dangerous scheme handlers
from being triggered.
In
`@features/conversation/conversation-chat/conversation-message/agent-content/agent-content-thinking.tsx`:
- Around line 72-76: The Text component in agent-content-thinking.tsx has an
invalid weight prop value of "regular" which is not supported by the component's
type definition; it only accepts values from typography.primary, which includes
"normal" instead. Replace the string literal "regular" with "normal" in the
weight prop of the Text component that checks step.status to fix the
type-checking error.
---
Nitpick comments:
In
`@features/conversation/conversation-chat/conversation-message/agent-content/agent-card.tsx`:
- Around line 1-2: The imports from external libraries (react and react-native)
need to be aliased to match repository conventions for clarity. In the import
statements at the top of the file, add aliases using the `as` keyword for all
imported items: memo, ReactNode, useState from the "react" import, and ViewStyle
from the "react-native" import. This makes the source of each imported item
explicit and improves code readability when these items are used throughout the
component.
- Around line 81-87: The Header rendering logic uses a ternary operator to
conditionally wrap the Header in a Pressable component based on the collapsible
prop. Refactor this to use an early-return pattern instead: check if collapsible
is false and return the Header directly without the Pressable wrapper, then
render the Pressable-wrapped Header with the setExpanded callback for the truthy
case. This aligns with the guideline to prefer early returns over ternaries in
React component render logic.
- Around line 19-22: Remove or significantly simplify the JSDoc comments for the
props and other code in the agent-card.tsx component that simply restate what
the code already expresses. Specifically, trim the verbose comments for the
`trailing` and `collapsible` props (in the diff area at lines 19-22), as well as
similar obvious comments found at lines 27-34 and 114-115. Keep only comments
that explain non-obvious rationale or important implementation details that
cannot be inferred from the prop names and TypeScript types themselves. This
will improve code readability by reducing redundant documentation.
In
`@features/conversation/conversation-chat/conversation-message/agent-content/agent-content.types.ts`:
- Around line 3-20: Remove or significantly reduce the verbose JSDoc comment
block at the start of the agent-content.types.ts file that explains the five
buckets of agent superpowers, as the type names and field structure already
communicate this information clearly. Apply the same principle to trim verbose
comments at the other specified line ranges (28-30, 48-50, 65-67, 86-88,
101-103, 115-117) throughout the file. Keep only essential, non-obvious comments
that add value beyond what the TypeScript type definitions themselves convey,
following the repository's style guideline of avoiding verbose JSDoc-style
documentation when types are already self-explanatory.
🪄 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: e40fc646-05c1-43f8-b1f3-af23addbeffe
📒 Files selected for processing (14)
features/app-settings/app-settings.screen.tsxfeatures/conversation/conversation-chat/conversation-message/agent-content/agent-card.tsxfeatures/conversation/conversation-chat/conversation-message/agent-content/agent-content-action.tsxfeatures/conversation/conversation-chat/conversation-message/agent-content/agent-content-examples.screen.tsxfeatures/conversation/conversation-chat/conversation-message/agent-content/agent-content-memory.tsxfeatures/conversation/conversation-chat/conversation-message/agent-content/agent-content-sources.tsxfeatures/conversation/conversation-chat/conversation-message/agent-content/agent-content-suggestions.tsxfeatures/conversation/conversation-chat/conversation-message/agent-content/agent-content-thinking.tsxfeatures/conversation/conversation-chat/conversation-message/agent-content/agent-content.assertions.tsfeatures/conversation/conversation-chat/conversation-message/agent-content/agent-content.fixtures.tsfeatures/conversation/conversation-chat/conversation-message/agent-content/agent-content.tsxfeatures/conversation/conversation-chat/conversation-message/agent-content/agent-content.types.tsnavigation/app-navigator.tsxnavigation/navigation.types.tsx
| /** | ||
| * Dev/demo screen that renders every agent content card with mock data so the | ||
| * five "superpower" buckets can be reviewed without protocol plumbing. | ||
| */ |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Remove verbose JSDoc on the screen component.
This comment is descriptive but redundant with the component name and implementation; it adds maintenance overhead when behavior evolves.
✂️ Suggested change
-/**
- * Dev/demo screen that renders every agent content card with mock data so the
- * five "superpower" buckets can be reviewed without protocol plumbing.
- */
export const AgentContentExamplesScreen = memo(function AgentContentExamplesScreen() {As per coding guidelines, "**/*.{ts,tsx}: Don't add comments for obvious code ... Avoid verbose JSDoc-style documentation when TypeScript types already provide this information."
📝 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.
| /** | |
| * Dev/demo screen that renders every agent content card with mock data so the | |
| * five "superpower" buckets can be reviewed without protocol plumbing. | |
| */ | |
| export const AgentContentExamplesScreen = memo(function AgentContentExamplesScreen() { |
🤖 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
`@features/conversation/conversation-chat/conversation-message/agent-content/agent-content-examples.screen.tsx`
around lines 14 - 17, Remove the verbose JSDoc comment block (the multi-line
comment starting with /** and ending with */) at the top of the
agent-content-examples.screen.tsx file. The component name already clearly
conveys its purpose as a demo screen for agent content examples, making the
detailed explanation redundant and unnecessary to maintain according to the
project's coding guidelines.
Source: Coding guidelines
- Use "normal" instead of the invalid "regular" Text weight in the thinking step list (fixes a tsc error in this PR's code). - Only open http(s) source URLs in the WebView, so unexpected URI schemes can't be forwarded to an external handler. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Rov93B6jifGmgS6EGyw94c
What
Builds the five dynamic agent content cards from the Slack thread — the "5 components every agent needs," rendered as rich content types that show how Convos works for the user and surface the right thing at the right time.
agentThinkingagentSourcesagentActionagentMemoryagentSuggestionsHow
Self-contained module under
features/conversation/conversation-chat/conversation-message/agent-content/:agent-content.types.ts— discriminated union + per-type schemasagent-content.assertions.ts— type guardsagent-card.tsx— shared expandable card primitive (icon badge, title/subtitle, collapsible body)agent-content-{thinking,sources,action,memory,suggestions}.tsx— the five render componentsagent-content.tsx— dispatcher mirroring the pattern inconversation-message.tsxagent-content.fixtures.ts— mock dataScope of this PR
IConversationMessageunion, so there's no wire-format codec yet and the protocol conversion layer is untouched. Encode/decode + send/receive can come in a follow-up.Testing
Matches existing design-system conventions (themed styles, presets, tokens).
node_modulescouldn't be installed in this environment (package registry blocked), so a fulltscrun wasn't possible here — every component API was verified against source instead. Worth a localyarn typecheckbefore merge.🤖 Generated with Claude Code
Generated by Claude Code
Note
Add agent 'superpower' content type components for thinking, actions, sources, memory, and suggestions
IAgentContentdiscriminated union inagent-content.types.tscovering five content categories: thinking, actions, sources, memory, and suggestions.AgentContentthat routes each union variant to a dedicated card component (AgentContentThinking,AgentContentAction,AgentContentSources,AgentContentMemory,AgentContentSuggestions).AgentCardbase component that supports theming, icon accents, optional trailing content, and collapsible bodies.AgentContentExamplesScreenaccessible from App Settings that renders all content types using fixture data for preview.AgentContentExamplesroute inapp-navigator.tsxand adds the row to settings inapp-settings.screen.tsx.Macroscope summarized 885efe6.
Summary by CodeRabbit