@@ -20,13 +20,16 @@ import {
2020 scrollFadeClass ,
2121 useScrollEdges ,
2222} from '@sim/emcn'
23+ import { Calendar , Clock } from '@sim/emcn/icons'
2324import { useQueryClient } from '@tanstack/react-query'
2425import { defaultRangeExtractor , type Range , useVirtualizer } from '@tanstack/react-virtual'
26+ import { useParams } from 'next/navigation'
2527import {
2628 AssistantActionReviewMessage ,
2729 useHasAssistantActionReview ,
2830} from '@/components/assistant-actions'
2931import { SMOOTH_CHASE_RATE } from '@/lib/core/utils/smooth-bottom-chase'
32+ import { parseAutomatedTurn } from '@/lib/mothership/chat/automated-turn'
3033import type { TurnOrigin } from '@/lib/mothership/generated/protocol'
3134import { inter } from '@/app/_styles/fonts/inter/inter'
3235import { FindBar } from '@/app/workspace/[workspaceId]/components/find-bar'
@@ -49,6 +52,7 @@ import {
4952 parseLastQuestionTag ,
5053} from '@/app/workspace/[workspaceId]/home/components/message-content/components/special-tags'
5154import type { SearchIntegrationConnectionProps } from '@/app/workspace/[workspaceId]/home/components/message-content/components/special-tags/search-integration-connection'
55+ import { watchLabel } from '@/app/workspace/[workspaceId]/home/components/message-content/components/watch-activity/watch-activity'
5256import {
5357 prepareCopyableMarkdown ,
5458 toCopyableMarkdown ,
@@ -204,37 +208,54 @@ interface UserMessageRowProps {
204208 attachmentWidthClassName : string
205209}
206210
211+ function describeAutomatedTurn (
212+ origin : TurnOrigin ,
213+ content : string ,
214+ workspaceId ?: string
215+ ) : { label : string ; text : string ; note ?: string } {
216+ const turn = parseAutomatedTurn ( origin , content )
217+ if ( turn ?. origin === 'task' ) {
218+ return {
219+ label : 'Background task' ,
220+ text : watchLabel ( turn . task , workspaceId ) ,
221+ note : turn . task . note || undefined ,
222+ }
223+ }
224+ if ( turn ?. origin === 'job' ) return { label : `Scheduled job · ${ turn . run } ` , text : turn . title }
225+ return origin === 'task'
226+ ? { label : 'Background task' , text : 'Task finished' }
227+ : { label : 'Scheduled job' , text : 'Run started' }
228+ }
229+
207230/**
208- * A turn automation opened, never a user bubble — the user did not type it : a muted system chip
209- * with one line . A background- task notification (mothership 21-background-tasks.md §6.4) shows
210- * its outcome line; a scheduled job's run shows the brief's first line (the job and its run) .
231+ * A turn automation opened (mothership 21-background-tasks.md §6.4) : a message in the user's
232+ * lane, labeled with what sent it . A background task shows the same line as its watch row; a
233+ * scheduled job shows its title and run.
211234 */
212235interface AutomatedTurnRowProps {
213236 origin : TurnOrigin
214237 content : string
215238 rowClassName : string
239+ bubbleClassName : string
216240}
217241
218242const AutomatedTurnRow = memo ( function AutomatedTurnRow ( {
219243 origin,
220244 content,
221245 rowClassName,
246+ bubbleClassName,
222247} : AutomatedTurnRowProps ) {
223- const lines = content . split ( '\n' ) . filter ( ( line ) => line . length > 0 )
224- const summary =
225- origin === 'task'
226- ? ( lines . find ( ( line ) => line . startsWith ( 'Task ' ) ) ?? lines [ lines . length - 1 ] ?? '' ) . replace (
227- / ^ T a s k [ 0 - 9 a - f - ] + / ,
228- ''
229- )
230- : ( lines [ 0 ] ?? '' ) . replace ( / ^ J o b : / , '' )
248+ const params = useParams < { workspaceId ?: string } > ( )
249+ const { label, text, note } = describeAutomatedTurn ( origin , content , params ?. workspaceId )
250+ const Icon = origin === 'task' ? Clock : Calendar
231251 return (
232- < div className = { cn ( 'flex w-full justify-center' , rowClassName ) } >
233- < div className = 'max-w-[85%] rounded-full border border-[var(--border)] bg-[var(--bg)] px-3 py-1 text-[12px] text-[var(--text-secondary)]' >
234- < span className = 'mr-1.5 font-medium text-[var(--text-primary)]' >
235- { origin === 'task' ? 'Background task' : 'Scheduled job' }
236- </ span >
237- { summary }
252+ < div className = { rowClassName } >
253+ < div className = 'flex items-center gap-1.5 text-[12px] text-[var(--text-tertiary)]' >
254+ < Icon className = 'size-[12px]' />
255+ { label }
256+ </ div >
257+ < div className = { bubbleClassName } title = { note } >
258+ < UserMessageContent content = { text } />
238259 </ div >
239260 </ div >
240261 )
@@ -995,7 +1016,8 @@ export function MothershipChat({
9951016 < AutomatedTurnRow
9961017 origin = { msg . origin }
9971018 content = { msg . content }
998- rowClassName = { styles . rowGap }
1019+ rowClassName = { cn ( styles . userRow , styles . rowGap ) }
1020+ bubbleClassName = { styles . userBubble }
9991021 />
10001022 ) : (
10011023 < UserMessageRow
0 commit comments