refactor(agent): consolidate agent type definitions and add multi-agent-type support
This commit is contained in:
@@ -61,7 +61,7 @@ function GroupedTextItem({ item }: { item: GroupedTextMessage }) {
|
||||
|
||||
return (
|
||||
<View style={[stylesheet.card, isThought && stylesheet.thoughtCard]}>
|
||||
<Text style={stylesheet.timestamp}>
|
||||
<Text style={[stylesheet.timestamp, isThought && stylesheet.thoughtTimestamp]}>
|
||||
{formatTimestamp(item.startTimestamp)}
|
||||
</Text>
|
||||
{isThought && (
|
||||
@@ -260,17 +260,21 @@ const stylesheet = StyleSheet.create((theme) => ({
|
||||
backgroundColor: theme.colors.muted,
|
||||
borderLeftWidth: 3,
|
||||
borderLeftColor: theme.colors.palette.purple[500],
|
||||
paddingVertical: theme.spacing[2],
|
||||
},
|
||||
timestamp: {
|
||||
color: theme.colors.mutedForeground,
|
||||
fontSize: theme.fontSize.xs,
|
||||
marginBottom: theme.spacing[1],
|
||||
},
|
||||
thoughtTimestamp: {
|
||||
marginBottom: theme.spacing[0],
|
||||
},
|
||||
thoughtLabel: {
|
||||
color: theme.colors.palette.purple[500],
|
||||
fontSize: theme.fontSize.xs,
|
||||
fontWeight: theme.fontWeight.semibold,
|
||||
marginBottom: theme.spacing[1],
|
||||
marginBottom: theme.spacing[0],
|
||||
},
|
||||
text: {
|
||||
color: theme.colors.foreground,
|
||||
|
||||
@@ -19,18 +19,16 @@ import {
|
||||
UserMessage,
|
||||
ActivityLog,
|
||||
ToolCall,
|
||||
AgentThoughtMessage,
|
||||
} from "./message";
|
||||
import { ToolCallBottomSheet } from "./tool-call-bottom-sheet";
|
||||
import type { StreamItem } from "@/types/stream";
|
||||
import type {
|
||||
SelectedToolCall,
|
||||
PendingPermission,
|
||||
AgentInfo,
|
||||
} from "@/types/shared";
|
||||
import type { SelectedToolCall, PendingPermission } from "@/types/shared";
|
||||
import type { Agent } from "@/contexts/session-context";
|
||||
|
||||
export interface AgentStreamViewProps {
|
||||
agentId: string;
|
||||
agent: AgentInfo;
|
||||
agent: Agent;
|
||||
streamItems: StreamItem[];
|
||||
pendingPermissions: Map<string, PendingPermission>;
|
||||
onPermissionResponse: (requestId: string, optionId: string) => void;
|
||||
@@ -53,6 +51,7 @@ export function AgentStreamView({
|
||||
const hasAutoScrolledOnce = useRef(false);
|
||||
const isProgrammaticScrollRef = useRef(false);
|
||||
const isNearBottomRef = useRef(true);
|
||||
const isUserScrollingRef = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
hasScrolledInitially.current = false;
|
||||
@@ -77,12 +76,41 @@ export function AgentStreamView({
|
||||
const { contentOffset } = event.nativeEvent;
|
||||
const threshold = Math.max(insets.bottom, 32);
|
||||
const nearBottom = contentOffset.y <= threshold;
|
||||
|
||||
if (isProgrammaticScrollRef.current) {
|
||||
if (nearBottom && !isNearBottomRef.current) {
|
||||
isNearBottomRef.current = true;
|
||||
setIsNearBottom(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!nearBottom && !isUserScrollingRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isNearBottomRef.current === nearBottom) {
|
||||
return;
|
||||
}
|
||||
|
||||
isNearBottomRef.current = nearBottom;
|
||||
setIsNearBottom(nearBottom);
|
||||
},
|
||||
[insets.bottom]
|
||||
);
|
||||
|
||||
const handleScrollBeginDrag = useCallback(() => {
|
||||
isUserScrollingRef.current = true;
|
||||
}, []);
|
||||
|
||||
const handleMomentumScrollBegin = useCallback(() => {
|
||||
isUserScrollingRef.current = true;
|
||||
}, []);
|
||||
|
||||
const handleScrollEnd = useCallback(() => {
|
||||
isUserScrollingRef.current = false;
|
||||
}, []);
|
||||
|
||||
const scrollToBottomInternal = useCallback(
|
||||
({ animated }: { animated: boolean }) => {
|
||||
const list = flatListRef.current;
|
||||
@@ -156,10 +184,8 @@ export function AgentStreamView({
|
||||
|
||||
case "thought":
|
||||
return (
|
||||
<ActivityLog
|
||||
type="info"
|
||||
<AgentThoughtMessage
|
||||
message={item.text}
|
||||
timestamp={item.timestamp.getTime()}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -235,6 +261,10 @@ export function AgentStreamView({
|
||||
}}
|
||||
style={stylesheet.list}
|
||||
onScroll={handleScroll}
|
||||
onScrollBeginDrag={handleScrollBeginDrag}
|
||||
onScrollEndDrag={handleScrollEnd}
|
||||
onMomentumScrollBegin={handleMomentumScrollBegin}
|
||||
onMomentumScrollEnd={handleScrollEnd}
|
||||
scrollEventThrottle={16}
|
||||
ListEmptyComponent={
|
||||
<View style={stylesheet.invertedWrapper}>
|
||||
|
||||
@@ -27,24 +27,30 @@ import { useRecentPaths } from "@/hooks/use-recent-paths";
|
||||
import { useSession } from "@/contexts/session-context";
|
||||
import { useRouter } from "expo-router";
|
||||
import { generateMessageId } from "@/types/stream";
|
||||
import {
|
||||
listAgentTypeDefinitions,
|
||||
type AgentType,
|
||||
type AgentTypeDefinition,
|
||||
} from "@server/server/acp/agent-types";
|
||||
|
||||
interface CreateAgentModalProps {
|
||||
isVisible: boolean;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
const MODES = [
|
||||
{
|
||||
value: "plan",
|
||||
label: "Plan",
|
||||
description: "Plan and design before implementing",
|
||||
},
|
||||
{
|
||||
value: "bypassPermissions",
|
||||
label: "Bypass Permissions",
|
||||
description: "Skip permission prompts for faster execution",
|
||||
},
|
||||
] as const;
|
||||
const agentTypeDefinitions = listAgentTypeDefinitions();
|
||||
|
||||
const agentTypeDefinitionMap: Record<AgentType, AgentTypeDefinition> =
|
||||
{} as Record<AgentType, AgentTypeDefinition>;
|
||||
for (const definition of agentTypeDefinitions) {
|
||||
agentTypeDefinitionMap[definition.id] = definition;
|
||||
}
|
||||
|
||||
const fallbackDefinition = agentTypeDefinitionMap.claude ?? agentTypeDefinitions[0];
|
||||
const DEFAULT_AGENT_TYPE: AgentType = fallbackDefinition
|
||||
? fallbackDefinition.id
|
||||
: "claude";
|
||||
const DEFAULT_MODE_FOR_DEFAULT_AGENT = fallbackDefinition?.defaultModeId;
|
||||
|
||||
export function CreateAgentModal({
|
||||
isVisible,
|
||||
@@ -58,11 +64,41 @@ export function CreateAgentModal({
|
||||
const router = useRouter();
|
||||
|
||||
const [workingDir, setWorkingDir] = useState("");
|
||||
const [selectedMode, setSelectedMode] = useState("plan");
|
||||
const [selectedAgentType, setSelectedAgentType] = useState<AgentType>(
|
||||
DEFAULT_AGENT_TYPE
|
||||
);
|
||||
const [selectedMode, setSelectedMode] = useState(
|
||||
DEFAULT_MODE_FOR_DEFAULT_AGENT ?? ""
|
||||
);
|
||||
const [worktreeName, setWorktreeName] = useState("");
|
||||
const [errorMessage, setErrorMessage] = useState("");
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [pendingRequestId, setPendingRequestId] = useState<string | null>(null);
|
||||
const agentDefinition = agentTypeDefinitionMap[selectedAgentType];
|
||||
const modeOptions = agentDefinition?.availableModes ?? [];
|
||||
|
||||
useEffect(() => {
|
||||
if (!agentDefinition) {
|
||||
return;
|
||||
}
|
||||
|
||||
const availableModeIds = agentDefinition.availableModes.map(
|
||||
(mode) => mode.id
|
||||
);
|
||||
|
||||
if (availableModeIds.length === 0) {
|
||||
if (selectedMode !== "") {
|
||||
setSelectedMode("");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!availableModeIds.includes(selectedMode)) {
|
||||
const fallbackModeId =
|
||||
agentDefinition.defaultModeId ?? availableModeIds[0];
|
||||
setSelectedMode(fallbackModeId);
|
||||
}
|
||||
}, [agentDefinition, selectedMode]);
|
||||
|
||||
// Use ref instead of state to survive state resets in onDismiss
|
||||
const pendingNavigationAgentIdRef = useRef<string | null>(null);
|
||||
@@ -164,11 +200,15 @@ export function CreateAgentModal({
|
||||
setPendingRequestId(requestId);
|
||||
setErrorMessage("");
|
||||
|
||||
const modeId =
|
||||
modeOptions.length > 0 && selectedMode !== "" ? selectedMode : undefined;
|
||||
|
||||
// Create the agent
|
||||
try {
|
||||
createAgent({
|
||||
cwd: path,
|
||||
initialMode: selectedMode,
|
||||
agentType: selectedAgentType,
|
||||
initialMode: modeId,
|
||||
worktreeName: worktree || undefined,
|
||||
requestId,
|
||||
});
|
||||
@@ -178,7 +218,17 @@ export function CreateAgentModal({
|
||||
setIsLoading(false);
|
||||
setPendingRequestId(null);
|
||||
}
|
||||
}, [workingDir, worktreeName, selectedMode, isLoading, validateWorktreeName, addRecentPath, createAgent]);
|
||||
}, [
|
||||
workingDir,
|
||||
worktreeName,
|
||||
selectedMode,
|
||||
selectedAgentType,
|
||||
modeOptions,
|
||||
isLoading,
|
||||
validateWorktreeName,
|
||||
addRecentPath,
|
||||
createAgent,
|
||||
]);
|
||||
|
||||
const renderFooter = useCallback(
|
||||
(props: BottomSheetFooterProps) => (
|
||||
@@ -254,7 +304,8 @@ export function CreateAgentModal({
|
||||
// Reset all state
|
||||
setWorkingDir("");
|
||||
setWorktreeName("");
|
||||
setSelectedMode("plan");
|
||||
setSelectedAgentType(DEFAULT_AGENT_TYPE);
|
||||
setSelectedMode(DEFAULT_MODE_FOR_DEFAULT_AGENT ?? "");
|
||||
setErrorMessage("");
|
||||
setIsLoading(false);
|
||||
setPendingRequestId(null);
|
||||
@@ -338,6 +389,58 @@ export function CreateAgentModal({
|
||||
)}
|
||||
</View>
|
||||
|
||||
{/* Agent Type Selector */}
|
||||
<View style={styles.formSection}>
|
||||
<Text style={styles.label}>Agent Type</Text>
|
||||
<View style={styles.agentTypeContainer}>
|
||||
{agentTypeDefinitions.map((definition) => {
|
||||
const isSelected = selectedAgentType === definition.id;
|
||||
return (
|
||||
<Pressable
|
||||
key={definition.id}
|
||||
onPress={() => setSelectedAgentType(definition.id)}
|
||||
disabled={isLoading}
|
||||
style={[
|
||||
styles.agentTypeOption,
|
||||
isSelected && styles.agentTypeOptionSelected,
|
||||
isLoading && styles.agentTypeOptionDisabled,
|
||||
]}
|
||||
>
|
||||
<View style={styles.agentTypeOptionContent}>
|
||||
<View
|
||||
style={[
|
||||
styles.radioOuter,
|
||||
isSelected
|
||||
? styles.radioOuterSelected
|
||||
: styles.radioOuterUnselected,
|
||||
]}
|
||||
>
|
||||
{isSelected && <View style={styles.radioInner} />}
|
||||
</View>
|
||||
<View style={styles.agentTypeTextContainer}>
|
||||
<Text style={styles.agentTypeLabel}>
|
||||
{definition.label}
|
||||
</Text>
|
||||
{definition.description ? (
|
||||
<Text style={styles.agentTypeDescription}>
|
||||
{definition.description}
|
||||
</Text>
|
||||
) : null}
|
||||
<Text style={styles.agentTypeMeta}>
|
||||
{definition.availableModes.length > 0
|
||||
? `Modes: ${definition.availableModes
|
||||
.map((mode) => mode.name)
|
||||
.join(", ")}`
|
||||
: "Modes: none"}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</Pressable>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* Worktree Name Input (Optional) */}
|
||||
<View style={styles.formSection}>
|
||||
<Text style={styles.label}>Worktree Name (Optional)</Text>
|
||||
@@ -364,41 +467,50 @@ export function CreateAgentModal({
|
||||
{/* Mode Selector */}
|
||||
<View style={styles.formSection}>
|
||||
<Text style={styles.label}>Mode</Text>
|
||||
<View style={styles.modeContainer}>
|
||||
{MODES.map((mode) => (
|
||||
<Pressable
|
||||
key={mode.value}
|
||||
onPress={() => setSelectedMode(mode.value)}
|
||||
disabled={isLoading}
|
||||
style={[
|
||||
styles.modeOption,
|
||||
selectedMode === mode.value && styles.modeOptionSelected,
|
||||
isLoading && styles.modeOptionDisabled,
|
||||
]}
|
||||
>
|
||||
<View style={styles.modeOptionContent}>
|
||||
<View
|
||||
{modeOptions.length === 0 ? (
|
||||
<Text style={styles.helperText}>
|
||||
This agent type does not expose selectable modes.
|
||||
</Text>
|
||||
) : (
|
||||
<View style={styles.modeContainer}>
|
||||
{modeOptions.map((mode) => {
|
||||
const isSelected = selectedMode === mode.id;
|
||||
return (
|
||||
<Pressable
|
||||
key={mode.id}
|
||||
onPress={() => setSelectedMode(mode.id)}
|
||||
disabled={isLoading}
|
||||
style={[
|
||||
styles.radioOuter,
|
||||
selectedMode === mode.value
|
||||
? styles.radioOuterSelected
|
||||
: styles.radioOuterUnselected,
|
||||
styles.modeOption,
|
||||
isSelected && styles.modeOptionSelected,
|
||||
isLoading && styles.modeOptionDisabled,
|
||||
]}
|
||||
>
|
||||
{selectedMode === mode.value && (
|
||||
<View style={styles.radioInner} />
|
||||
)}
|
||||
</View>
|
||||
<View style={styles.modeTextContainer}>
|
||||
<Text style={styles.modeLabel}>{mode.label}</Text>
|
||||
<Text style={styles.modeDescription}>
|
||||
{mode.description}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</Pressable>
|
||||
))}
|
||||
</View>
|
||||
<View style={styles.modeOptionContent}>
|
||||
<View
|
||||
style={[
|
||||
styles.radioOuter,
|
||||
isSelected
|
||||
? styles.radioOuterSelected
|
||||
: styles.radioOuterUnselected,
|
||||
]}
|
||||
>
|
||||
{isSelected && <View style={styles.radioInner} />}
|
||||
</View>
|
||||
<View style={styles.modeTextContainer}>
|
||||
<Text style={styles.modeLabel}>{mode.name}</Text>
|
||||
{mode.description ? (
|
||||
<Text style={styles.modeDescription}>
|
||||
{mode.description}
|
||||
</Text>
|
||||
) : null}
|
||||
</View>
|
||||
</View>
|
||||
</Pressable>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</BottomSheetScrollView>
|
||||
</BottomSheetModal>
|
||||
@@ -516,6 +628,45 @@ const styles = StyleSheet.create((theme) => ({
|
||||
color: theme.colors.mutedForeground,
|
||||
fontSize: theme.fontSize.sm,
|
||||
},
|
||||
agentTypeContainer: {
|
||||
gap: theme.spacing[3],
|
||||
},
|
||||
agentTypeOption: {
|
||||
backgroundColor: theme.colors.background,
|
||||
borderRadius: theme.borderRadius.lg,
|
||||
borderWidth: theme.borderWidth[1],
|
||||
borderColor: theme.colors.border,
|
||||
padding: theme.spacing[4],
|
||||
},
|
||||
agentTypeOptionSelected: {
|
||||
borderColor: theme.colors.palette.blue[500],
|
||||
backgroundColor: theme.colors.muted,
|
||||
},
|
||||
agentTypeOptionDisabled: {
|
||||
opacity: theme.opacity[50],
|
||||
},
|
||||
agentTypeOptionContent: {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
},
|
||||
agentTypeTextContainer: {
|
||||
flex: 1,
|
||||
},
|
||||
agentTypeLabel: {
|
||||
color: theme.colors.foreground,
|
||||
fontSize: theme.fontSize.base,
|
||||
fontWeight: theme.fontWeight.semibold,
|
||||
marginBottom: theme.spacing[1],
|
||||
},
|
||||
agentTypeDescription: {
|
||||
color: theme.colors.mutedForeground,
|
||||
fontSize: theme.fontSize.sm,
|
||||
marginBottom: theme.spacing[1],
|
||||
},
|
||||
agentTypeMeta: {
|
||||
color: theme.colors.mutedForeground,
|
||||
fontSize: theme.fontSize.sm,
|
||||
},
|
||||
footer: {
|
||||
borderTopWidth: theme.borderWidth[1],
|
||||
borderTopColor: theme.colors.border,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { View, Text, Pressable, Animated } from "react-native";
|
||||
import { useState, useEffect, useRef, memo } from "react";
|
||||
import { useState, useEffect, useRef, memo, useMemo } from "react";
|
||||
import Markdown from "react-native-markdown-display";
|
||||
import {
|
||||
Circle,
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
Pencil,
|
||||
Eye,
|
||||
SquareTerminal,
|
||||
Brain,
|
||||
} from "lucide-react-native";
|
||||
import { StyleSheet } from "react-native-unistyles";
|
||||
import { baseColors, theme } from "@/styles/theme";
|
||||
@@ -48,7 +49,10 @@ const userMessageStylesheet = StyleSheet.create((theme) => ({
|
||||
},
|
||||
}));
|
||||
|
||||
export const UserMessage = memo(function UserMessage({ message, timestamp }: UserMessageProps) {
|
||||
export const UserMessage = memo(function UserMessage({
|
||||
message,
|
||||
timestamp,
|
||||
}: UserMessageProps) {
|
||||
return (
|
||||
<View style={userMessageStylesheet.container}>
|
||||
<View style={userMessageStylesheet.bubble}>
|
||||
@@ -64,7 +68,7 @@ interface AssistantMessageProps {
|
||||
isStreaming?: boolean;
|
||||
}
|
||||
|
||||
const assistantMessageStylesheet = StyleSheet.create((theme) => ({
|
||||
export const assistantMessageStylesheet = StyleSheet.create((theme) => ({
|
||||
container: {
|
||||
marginBottom: theme.spacing[3],
|
||||
paddingHorizontal: theme.spacing[4],
|
||||
@@ -133,6 +137,20 @@ const assistantMessageStylesheet = StyleSheet.create((theme) => ({
|
||||
},
|
||||
}));
|
||||
|
||||
const markdownStyles = {
|
||||
body: assistantMessageStylesheet.markdownBody,
|
||||
paragraph: assistantMessageStylesheet.markdownParagraph,
|
||||
strong: assistantMessageStylesheet.markdownStrong,
|
||||
em: assistantMessageStylesheet.markdownEm,
|
||||
code_inline: assistantMessageStylesheet.markdownCodeInline,
|
||||
code_block: assistantMessageStylesheet.markdownCodeBlock,
|
||||
fence: assistantMessageStylesheet.markdownFence,
|
||||
link: assistantMessageStylesheet.markdownLink,
|
||||
bullet_list: assistantMessageStylesheet.markdownList,
|
||||
ordered_list: assistantMessageStylesheet.markdownList,
|
||||
list_item: assistantMessageStylesheet.markdownListItem,
|
||||
};
|
||||
|
||||
export const AssistantMessage = memo(function AssistantMessage({
|
||||
message,
|
||||
timestamp,
|
||||
@@ -162,20 +180,6 @@ export const AssistantMessage = memo(function AssistantMessage({
|
||||
}
|
||||
}, [isStreaming, fadeAnim]);
|
||||
|
||||
const markdownStyles = {
|
||||
body: assistantMessageStylesheet.markdownBody,
|
||||
paragraph: assistantMessageStylesheet.markdownParagraph,
|
||||
strong: assistantMessageStylesheet.markdownStrong,
|
||||
em: assistantMessageStylesheet.markdownEm,
|
||||
code_inline: assistantMessageStylesheet.markdownCodeInline,
|
||||
code_block: assistantMessageStylesheet.markdownCodeBlock,
|
||||
fence: assistantMessageStylesheet.markdownFence,
|
||||
link: assistantMessageStylesheet.markdownLink,
|
||||
bullet_list: assistantMessageStylesheet.markdownList,
|
||||
ordered_list: assistantMessageStylesheet.markdownList,
|
||||
list_item: assistantMessageStylesheet.markdownListItem,
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={assistantMessageStylesheet.container}>
|
||||
<Markdown style={markdownStyles}>{message}</Markdown>
|
||||
@@ -376,6 +380,79 @@ export const ActivityLog = memo(function ActivityLog({
|
||||
);
|
||||
});
|
||||
|
||||
interface AgentThoughtMessageProps {
|
||||
message: string;
|
||||
}
|
||||
|
||||
const agentThoughtStylesheet = StyleSheet.create((theme) => ({
|
||||
container: {
|
||||
marginHorizontal: theme.spacing[2],
|
||||
marginBottom: theme.spacing[2],
|
||||
},
|
||||
card: {
|
||||
backgroundColor: theme.colors.card,
|
||||
borderRadius: theme.borderRadius.lg,
|
||||
borderWidth: theme.borderWidth[1],
|
||||
borderColor: theme.colors.border,
|
||||
paddingVertical: theme.spacing[2],
|
||||
paddingHorizontal: theme.spacing[3],
|
||||
flexDirection: "row",
|
||||
alignItems: "flex-start",
|
||||
gap: theme.spacing[3],
|
||||
},
|
||||
iconContainer: {
|
||||
width: 28,
|
||||
height: 28,
|
||||
borderRadius: 14,
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
flexShrink: 0,
|
||||
paddingTop: theme.spacing[1],
|
||||
},
|
||||
icon: {
|
||||
color: theme.colors.mutedForeground,
|
||||
opacity: 0.8,
|
||||
},
|
||||
textContainer: {
|
||||
flex: 1,
|
||||
paddingVertical: theme.spacing[1],
|
||||
},
|
||||
label: {
|
||||
color: theme.colors.mutedForeground,
|
||||
fontSize: theme.fontSize.xs,
|
||||
fontWeight: theme.fontWeight.semibold,
|
||||
textTransform: "uppercase",
|
||||
marginBottom: theme.spacing[1],
|
||||
},
|
||||
text: {
|
||||
color: theme.colors.mutedForeground,
|
||||
fontSize: theme.fontSize.base,
|
||||
lineHeight: 20,
|
||||
},
|
||||
}));
|
||||
|
||||
export function AgentThoughtMessage({ message }: AgentThoughtMessageProps) {
|
||||
const messageText = useMemo(() => {
|
||||
return message
|
||||
.trim()
|
||||
.replace(/^\*\*|\*\*$/g, "")
|
||||
.trim();
|
||||
}, [message]);
|
||||
|
||||
return (
|
||||
<View style={agentThoughtStylesheet.container}>
|
||||
<View style={agentThoughtStylesheet.card}>
|
||||
<View style={agentThoughtStylesheet.iconContainer}>
|
||||
<Brain size={18} style={agentThoughtStylesheet.icon} />
|
||||
</View>
|
||||
<View style={agentThoughtStylesheet.textContainer}>
|
||||
<Text style={agentThoughtStylesheet.text}>{messageText}</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
interface ToolCallProps {
|
||||
toolName: string;
|
||||
kind?: string; // Optional kind for ACP tool calls
|
||||
|
||||
Reference in New Issue
Block a user