feat(chat): allow prompting subagent sessions

This commit is contained in:
Bohdan Triapitsyn
2026-07-13 01:06:44 +03:00
parent 04307e163b
commit 7e12a0dcef
16 changed files with 92 additions and 9 deletions
@@ -436,9 +436,10 @@ const writeRevealedToolIds = (messageId: string, value: Set<string>): void => {
revealedToolIdsByMessage.set(messageId, new Set(value));
};
const UserMessageBody = React.memo(({ messageId, parts, isMobile, alwaysShowActions = isMobile, hasTouchInput, hasTextContent, onCopyMessage, copiedMessage, onShowPopup, agentMention, onRevert, onFork, userActionsMode = 'inline', stickyUserHeaderEnabled = true }: {
const UserMessageBody = React.memo(({ messageId, parts, messageCreatedAt, isMobile, alwaysShowActions = isMobile, hasTouchInput, hasTextContent, onCopyMessage, copiedMessage, onShowPopup, agentMention, onRevert, onFork, userActionsMode = 'inline', stickyUserHeaderEnabled = true }: {
messageId: string;
parts: Part[];
messageCreatedAt?: number | null;
isMobile: boolean;
alwaysShowActions?: boolean;
hasTouchInput?: boolean;
@@ -452,8 +453,9 @@ const UserMessageBody = React.memo(({ messageId, parts, isMobile, alwaysShowActi
userActionsMode?: 'inline' | 'external-content' | 'external-actions';
stickyUserHeaderEnabled?: boolean;
}) => {
const { t } = useI18n();
const { locale, t } = useI18n();
const chatSurfaceMode = useChatSurfaceMode();
const timeFormatPreference = useUIStore((state) => state.timeFormatPreference);
const [copyHintVisible, setCopyHintVisible] = React.useState(false);
const copyHintTimeoutRef = React.useRef<number | null>(null);
@@ -528,6 +530,12 @@ const UserMessageBody = React.memo(({ messageId, parts, isMobile, alwaysShowActi
);
const effectiveOnFork = chatSurfaceMode === 'mini-chat' ? undefined : onFork;
const timestamp = React.useMemo(() => {
void locale;
if (typeof messageCreatedAt !== 'number' || messageCreatedAt <= 0) return null;
const formatted = formatTimestampForDisplay(messageCreatedAt, timeFormatPreference);
return formatted.length > 0 ? formatted : null;
}, [locale, messageCreatedAt, timeFormatPreference]);
const actionsBlock = ((canCopyMessage && hasCopyableText) || onRevert || effectiveOnFork) && showUserActions ? (
<div className={cn(
'group/user-actions',
@@ -556,6 +564,20 @@ const UserMessageBody = React.memo(({ messageId, parts, isMobile, alwaysShowActi
: 'pointer-events-none opacity-0 transition-opacity duration-150 group-hover/message:pointer-events-auto group-hover/message:opacity-100 group-hover/user-actions:pointer-events-auto group-hover/user-actions:opacity-100 group-hover/user-shell:pointer-events-auto group-hover/user-shell:opacity-100'
)}
>
{timestamp ? (
<Tooltip>
<TooltipTrigger asChild>
<span
className="mr-1 flex items-center gap-1 text-sm tabular-nums text-muted-foreground/60"
aria-label={`Message time: ${timestamp}`}
>
<Icon name="time" className="h-3.5 w-3.5" />
<span className="message-footer__label">{timestamp}</span>
</span>
</TooltipTrigger>
<TooltipContent>{timestamp}</TooltipContent>
</Tooltip>
) : null}
{onRevert && (
<Tooltip>
<TooltipTrigger asChild>
@@ -2125,6 +2147,7 @@ const MessageBody = React.memo(({ isUser, ...props }: MessageBodyProps) => {
<UserMessageBody
messageId={props.messageId}
parts={props.parts}
messageCreatedAt={props.messageCreatedAt}
isMobile={props.isMobile}
alwaysShowActions={props.alwaysShowActions}
hasTouchInput={props.hasTouchInput}