Fix markdown list text wrapping on Android
- Add custom list rendering rules in message.tsx for proper flex layout - Remove flexWrap from list content styles (causes Android clipping) - Use flex: 1 and flexShrink: 1 for natural text wrapping - Add minWidth: 0 to content containers for proper shrinking 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.5
parent
09f130408b
commit
37da13a38b
@@ -599,6 +599,111 @@ function PermissionRequestCard({
|
||||
[theme]
|
||||
);
|
||||
|
||||
const markdownRules = useMemo(() => {
|
||||
return {
|
||||
text: (
|
||||
node: any,
|
||||
_children: React.ReactNode[],
|
||||
_parent: any,
|
||||
styles: any,
|
||||
inheritedStyles: any = {}
|
||||
) => (
|
||||
<Text key={node.key} style={[inheritedStyles, styles.text]} selectable>
|
||||
{node.content}
|
||||
</Text>
|
||||
),
|
||||
textgroup: (
|
||||
node: any,
|
||||
children: React.ReactNode[],
|
||||
_parent: any,
|
||||
styles: any,
|
||||
inheritedStyles: any = {}
|
||||
) => (
|
||||
<Text key={node.key} style={[inheritedStyles, styles.textgroup]} selectable>
|
||||
{children}
|
||||
</Text>
|
||||
),
|
||||
code_block: (
|
||||
node: any,
|
||||
_children: React.ReactNode[],
|
||||
_parent: any,
|
||||
styles: any,
|
||||
inheritedStyles: any = {}
|
||||
) => (
|
||||
<Text key={node.key} style={[inheritedStyles, styles.code_block]} selectable>
|
||||
{node.content}
|
||||
</Text>
|
||||
),
|
||||
fence: (
|
||||
node: any,
|
||||
_children: React.ReactNode[],
|
||||
_parent: any,
|
||||
styles: any,
|
||||
inheritedStyles: any = {}
|
||||
) => (
|
||||
<Text key={node.key} style={[inheritedStyles, styles.fence]} selectable>
|
||||
{node.content}
|
||||
</Text>
|
||||
),
|
||||
code_inline: (
|
||||
node: any,
|
||||
_children: React.ReactNode[],
|
||||
_parent: any,
|
||||
styles: any,
|
||||
inheritedStyles: any = {}
|
||||
) => (
|
||||
<Text key={node.key} style={[inheritedStyles, styles.code_inline]} selectable>
|
||||
{node.content}
|
||||
</Text>
|
||||
),
|
||||
bullet_list: (
|
||||
node: any,
|
||||
children: React.ReactNode[],
|
||||
_parent: any,
|
||||
styles: any
|
||||
) => (
|
||||
<View key={node.key} style={styles.bullet_list}>
|
||||
{children}
|
||||
</View>
|
||||
),
|
||||
ordered_list: (
|
||||
node: any,
|
||||
children: React.ReactNode[],
|
||||
_parent: any,
|
||||
styles: any
|
||||
) => (
|
||||
<View key={node.key} style={styles.ordered_list}>
|
||||
{children}
|
||||
</View>
|
||||
),
|
||||
list_item: (
|
||||
node: any,
|
||||
children: React.ReactNode[],
|
||||
parent: any,
|
||||
styles: any
|
||||
) => {
|
||||
const isOrdered = parent?.type === "ordered_list";
|
||||
const index = parent?.children?.indexOf(node) ?? 0;
|
||||
const bullet = isOrdered ? `${index + 1}.` : "•";
|
||||
const iconStyle = isOrdered
|
||||
? styles.ordered_list_icon
|
||||
: styles.bullet_list_icon;
|
||||
const contentStyle = isOrdered
|
||||
? styles.ordered_list_content
|
||||
: styles.bullet_list_content;
|
||||
|
||||
return (
|
||||
<View key={node.key} style={[styles.list_item, { flexShrink: 0 }]}>
|
||||
<Text style={iconStyle}>{bullet}</Text>
|
||||
<Text style={[contentStyle, { flex: 1, flexShrink: 1, minWidth: 0 }]} selectable>
|
||||
{children}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
};
|
||||
}, []);
|
||||
|
||||
const permissionResponse = useDaemonRequest<
|
||||
{ agentId: string; requestId: string; response: AgentPermissionResponse },
|
||||
{ agentId: string; requestId: string },
|
||||
@@ -675,7 +780,7 @@ function PermissionRequestCard({
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Markdown style={markdownStyles}>{planMarkdown}</Markdown>
|
||||
<Markdown style={markdownStyles} rules={markdownRules}>{planMarkdown}</Markdown>
|
||||
</View>
|
||||
</View>
|
||||
) : null}
|
||||
@@ -986,6 +1091,8 @@ const permissionStyles = StyleSheet.create((theme) => ({
|
||||
padding: theme.spacing[3],
|
||||
borderRadius: theme.borderRadius.lg,
|
||||
borderWidth: theme.borderWidth[1],
|
||||
flexShrink: 1,
|
||||
minWidth: 0,
|
||||
},
|
||||
metadataRow: {
|
||||
marginBottom: theme.spacing[2],
|
||||
|
||||
@@ -234,6 +234,8 @@ const expandableBadgeStylesheet = StyleSheet.create((theme) => ({
|
||||
backgroundColor: theme.colors.background,
|
||||
padding: theme.spacing[2],
|
||||
gap: theme.spacing[2],
|
||||
flexShrink: 1,
|
||||
minWidth: 0,
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -417,6 +419,51 @@ export const AssistantMessage = memo(function AssistantMessage({
|
||||
</Text>
|
||||
);
|
||||
},
|
||||
bullet_list: (
|
||||
node: any,
|
||||
children: ReactNode[],
|
||||
_parent: any,
|
||||
styles: any
|
||||
) => (
|
||||
<View key={node.key} style={styles.bullet_list}>
|
||||
{children}
|
||||
</View>
|
||||
),
|
||||
ordered_list: (
|
||||
node: any,
|
||||
children: ReactNode[],
|
||||
_parent: any,
|
||||
styles: any
|
||||
) => (
|
||||
<View key={node.key} style={styles.ordered_list}>
|
||||
{children}
|
||||
</View>
|
||||
),
|
||||
list_item: (
|
||||
node: any,
|
||||
children: ReactNode[],
|
||||
parent: any,
|
||||
styles: any
|
||||
) => {
|
||||
const isOrdered = parent?.type === "ordered_list";
|
||||
const index = parent?.children?.indexOf(node) ?? 0;
|
||||
const bullet = isOrdered ? `${index + 1}.` : "•";
|
||||
const iconStyle = isOrdered
|
||||
? styles.ordered_list_icon
|
||||
: styles.bullet_list_icon;
|
||||
const contentStyle = isOrdered
|
||||
? styles.ordered_list_content
|
||||
: styles.bullet_list_content;
|
||||
|
||||
return (
|
||||
<View key={node.key} style={styles.list_item}>
|
||||
<Text style={iconStyle}>{bullet}</Text>
|
||||
<View style={[contentStyle, { flex: 1, flexShrink: 1, minWidth: 0 }]}>
|
||||
{children}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
};
|
||||
}, [onInlinePathPress]);
|
||||
|
||||
@@ -1007,6 +1054,51 @@ export function AgentThoughtMessage({ message, status = "ready" }: AgentThoughtM
|
||||
{node.content}
|
||||
</Text>
|
||||
),
|
||||
bullet_list: (
|
||||
node: any,
|
||||
children: ReactNode[],
|
||||
_parent: any,
|
||||
styles: any
|
||||
) => (
|
||||
<View key={node.key} style={styles.bullet_list}>
|
||||
{children}
|
||||
</View>
|
||||
),
|
||||
ordered_list: (
|
||||
node: any,
|
||||
children: ReactNode[],
|
||||
_parent: any,
|
||||
styles: any
|
||||
) => (
|
||||
<View key={node.key} style={styles.ordered_list}>
|
||||
{children}
|
||||
</View>
|
||||
),
|
||||
list_item: (
|
||||
node: any,
|
||||
children: ReactNode[],
|
||||
parent: any,
|
||||
styles: any
|
||||
) => {
|
||||
const isOrdered = parent?.type === "ordered_list";
|
||||
const index = parent?.children?.indexOf(node) ?? 0;
|
||||
const bullet = isOrdered ? `${index + 1}.` : "•";
|
||||
const iconStyle = isOrdered
|
||||
? styles.ordered_list_icon
|
||||
: styles.bullet_list_icon;
|
||||
const contentStyle = isOrdered
|
||||
? styles.ordered_list_content
|
||||
: styles.bullet_list_content;
|
||||
|
||||
return (
|
||||
<View key={node.key} style={styles.list_item}>
|
||||
<Text style={iconStyle}>{bullet}</Text>
|
||||
<View style={[contentStyle, { flex: 1, flexShrink: 1, minWidth: 0 }]}>
|
||||
{children}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
};
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -215,13 +215,13 @@ export function createMarkdownStyles(theme: Theme) {
|
||||
|
||||
bullet_list: {
|
||||
marginVertical: theme.spacing[2],
|
||||
paddingLeft: theme.spacing[1],
|
||||
paddingLeft: 0,
|
||||
width: "100%" as const,
|
||||
},
|
||||
|
||||
ordered_list: {
|
||||
marginVertical: theme.spacing[2],
|
||||
paddingLeft: theme.spacing[1],
|
||||
paddingLeft: 0,
|
||||
width: "100%" as const,
|
||||
},
|
||||
|
||||
@@ -229,36 +229,33 @@ export function createMarkdownStyles(theme: Theme) {
|
||||
marginBottom: theme.spacing[1],
|
||||
flexDirection: "row" as const,
|
||||
alignItems: "flex-start" as const,
|
||||
width: "100%" as const,
|
||||
flexShrink: 1,
|
||||
},
|
||||
|
||||
bullet_list_content: {
|
||||
flex: 1,
|
||||
flexShrink: 1,
|
||||
flexWrap: "wrap" as const,
|
||||
},
|
||||
|
||||
ordered_list_content: {
|
||||
flex: 1,
|
||||
flexShrink: 1,
|
||||
flexWrap: "wrap" as const,
|
||||
},
|
||||
|
||||
bullet_list_icon: {
|
||||
color: theme.colors.mutedForeground,
|
||||
marginRight: theme.spacing[2],
|
||||
marginRight: 4,
|
||||
fontSize: theme.fontSize.base,
|
||||
lineHeight: 22,
|
||||
},
|
||||
|
||||
ordered_list_icon: {
|
||||
color: theme.colors.mutedForeground,
|
||||
marginRight: theme.spacing[2],
|
||||
marginRight: 4,
|
||||
fontSize: theme.fontSize.base,
|
||||
fontWeight: theme.fontWeight.semibold,
|
||||
lineHeight: 22,
|
||||
minWidth: 20,
|
||||
minWidth: 12,
|
||||
},
|
||||
|
||||
// =========================================================================
|
||||
|
||||
@@ -5,48 +5,47 @@
|
||||
*/
|
||||
export function getOrchestratorModeInstructions(): string {
|
||||
return `
|
||||
<orchestrator-mode>
|
||||
Activation:
|
||||
- Only activate if the user explicitly says "go into orchestrator mode" (or similar).
|
||||
- Otherwise, do work directly yourself; do not spawn agents.
|
||||
|
||||
## Orchestrator Mode Instructions
|
||||
Core rules:
|
||||
- In orchestrator mode, you accomplish tasks only by managing agents; do not perform the work yourself.
|
||||
- Always prefix agent titles (e.g., "🎭 Feature Implementation", "🎭 Design Discussion").
|
||||
- Set cwd to the repository root and choose the most permissive mode available.
|
||||
- If an agent control call fails, list agents before launching another; it may just be a wait timeout.
|
||||
|
||||
When asked to go into orchestrator mode, you must **only accomplish tasks by managing other agents**. Do NOT perform the work yourself.
|
||||
Context management:
|
||||
- Reuse an existing agent when the next step needs the same context (same files/module/folder or immediate follow-up like investigate → fix in the same area).
|
||||
- Start a new agent when switching to a different area/module, or when an agent has run long and its context feels stale.
|
||||
- Prefer sending follow-up prompts to an existing agent to avoid reloading context.
|
||||
- Use multiple agents when roles diverge (e.g., one for refactor, one for external validation), but default to reuse when context overlaps.
|
||||
|
||||
### Agent Control Best Practices
|
||||
Conversation with agents:
|
||||
- Engage actively: ask pointed questions, probe risks, and request clarifications before accepting proposals.
|
||||
- Encourage agents to validate assumptions, consider edge cases, and describe how they will test/verify.
|
||||
|
||||
- **When agent control tool calls fail**, make sure you list agents before trying to launch another one. It could just be a wait timeout.
|
||||
- **Always prefix agent titles** so we can tell which ones are running under you (e.g., "🎭 Feature Implementation", "🎭 Design Discussion").
|
||||
- **Launch agents in the most permissive mode**: Use full access or bypass permissions mode.
|
||||
- **Set cwd to the repository root** - The agent's working directory should usually be the repo root.
|
||||
Agent selection guidance:
|
||||
- Codex: methodical and slower; great for deep debugging, tracing code paths, refactoring, complex features, and design discussions.
|
||||
- Claude: fast; strong at tool use (e.g., Playwright MCP, web search), agentic control, and managing other agents; may jump to conclusions—ask it to verify.
|
||||
- For debugging with UI/Playwright: Claude can drive Playwright MCP and logging; Codex can audit code and propose fixes.
|
||||
|
||||
### Agent Use Cases
|
||||
Clarifying ambiguous requests:
|
||||
- Research first to understand the current state.
|
||||
- Ask clarifying questions about what the user wants.
|
||||
- Present options with trade-offs.
|
||||
- Get explicit confirmation; never assume.
|
||||
|
||||
You can run agents to:
|
||||
- **Implement a task** - Spawn an agent to write code and implement features
|
||||
- **Have a design discussion** - Discuss architecture and design decisions
|
||||
- **Have a pairing session** - Collaborate on problem-solving
|
||||
- **Test some feature** - Run tests and verify functionality
|
||||
- **Do investigation** - Research and explore the codebase
|
||||
Investigation vs Implementation:
|
||||
- Investigate only unless explicitly asked to implement.
|
||||
- Report findings clearly.
|
||||
- After investigation, ask for direction before implementing.
|
||||
|
||||
### Clarifying Ambiguous Requests
|
||||
|
||||
**CRITICAL:** When user requests are ambiguous or unclear:
|
||||
|
||||
1. **Research first** - Spawn an investigation agent to understand the current state
|
||||
2. **Ask clarifying questions** - After research, ask the user specific questions about what they want
|
||||
3. **Present options** - Offer multiple approaches with trade-offs
|
||||
4. **Get explicit confirmation** - Never assume what the user wants
|
||||
|
||||
### Investigation vs Implementation
|
||||
|
||||
**CRITICAL:** When asked to investigate:
|
||||
|
||||
- **Investigate only** - Do not implement fixes during investigation unless explicitly requested
|
||||
- **Report findings** - Share discovered information clearly
|
||||
- **Ask for direction** - After investigation, ask the user what to do next
|
||||
|
||||
### Tool Usage Discipline
|
||||
|
||||
- **Do not ask users to run commands** — Always run the commands yourself.
|
||||
- **Do not repeat the user’s instructions verbatim** — Summarize them in your own words.
|
||||
- **Be explicit about results** — Tell the user what happened after every command.
|
||||
Tool usage discipline:
|
||||
- Do not ask users to run commands—run them yourself.
|
||||
- Do not repeat the user’s instructions verbatim—summarize them in your own words.
|
||||
- Be explicit about results—tell the user what happened after every command.
|
||||
</orchestrator-mode>
|
||||
`;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user