Skip to content

Commit 7eccc7c

Browse files
committed
improvement(misc): add more sportmonks tools, improvestreaming ux
1 parent ea83be3 commit 7eccc7c

198 files changed

Lines changed: 29043 additions & 1423 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/docs/content/docs/en/integrations/sportmonks.mdx

Lines changed: 6239 additions & 711 deletions
Large diffs are not rendered by default.

apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/agent-group/agent-group.tsx

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ interface AgentGroupProps {
3232
items: AgentGroupItem[]
3333
isDelegating?: boolean
3434
isStreaming?: boolean
35-
defaultExpanded?: boolean
35+
/** This group is the latest section in its parent sequence (drives collapse). */
36+
isCurrentSection?: boolean
37+
/** The subagent lane is still open (no subagent_end yet) — i.e. actively running. */
38+
isLaneOpen?: boolean
3639
}
3740

3841
export function isAgentGroupResolved(items: AgentGroupItem[]): boolean {
@@ -55,7 +58,8 @@ export function AgentGroup({
5558
items,
5659
isDelegating = false,
5760
isStreaming = false,
58-
defaultExpanded = false,
61+
isCurrentSection = false,
62+
isLaneOpen = false,
5963
}: AgentGroupProps) {
6064
const AgentIcon = getAgentIcon(agentName)
6165
const hasItems = items.length > 0
@@ -66,11 +70,17 @@ export function AgentGroup({
6670
// transport gating is needed to stop an aborted-before-first-tool spinner.
6771
const showDelegatingSpinner = isDelegating && !resolved
6872

69-
// Expand only while the turn is live and the group is still open or working.
70-
// Once the turn ends (isStreaming false) — or a subagent closes mid-turn — the
71-
// group auto-collapses, so finished subagent blocks never stay expanded. A
72-
// manual toggle pins the choice for the rest of the message.
73-
const autoExpanded = isStreaming && (defaultExpanded || !resolved)
73+
// Expand while the turn is live and any of: the lane is open (the subagent is
74+
// actively running), this is the current/latest section, or there is unresolved
75+
// work. A finished group stays open until the NEXT section starts (it is no
76+
// longer the latest), instead of collapsing the instant its own work resolves.
77+
// Keying "still running" off the lane-open signal (not `resolved` alone) avoids
78+
// a collapse/reopen flicker on parallel siblings: a subagent's tools all
79+
// momentarily read "done" in the gap between its last search and its `respond`
80+
// ("Gathering thoughts") tool, transiently flipping `resolved` true; the open
81+
// lane bridges that gap so the row never collapses mid-run. The turn ending
82+
// (isStreaming false) collapses everything; a manual toggle pins the choice.
83+
const autoExpanded = isStreaming && (isCurrentSection || isLaneOpen || !resolved)
7484
const [manualExpanded, setManualExpanded] = useState<boolean | null>(null)
7585
const expanded = manualExpanded ?? autoExpanded
7686

@@ -135,7 +145,8 @@ export function AgentGroup({
135145
items={item.group.items}
136146
isDelegating={item.group.isDelegating}
137147
isStreaming={isStreaming}
138-
defaultExpanded={item.group.isOpen}
148+
isCurrentSection={idx === items.length - 1}
149+
isLaneOpen={item.group.isOpen}
139150
/>
140151
</div>
141152
)

apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,3 @@ export { AgentGroup, CircleStop, isAgentGroupResolved } from './agent-group'
33
export { ChatContent } from './chat-content'
44
export { Options } from './options'
55
export { PendingTagIndicator, parseSpecialTags, SpecialTags } from './special-tags'
6-
export { ThinkingBlock } from './thinking-block'

apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/thinking-block/index.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.

apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/thinking-block/thinking-block.tsx

Lines changed: 0 additions & 108 deletions
This file was deleted.

apps/sim/app/workspace/[workspaceId]/home/components/message-content/message-content.tsx

Lines changed: 9 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,7 @@ import { useChatSurface } from '@/app/workspace/[workspaceId]/home/components/ch
1010
import type { ContentBlock, OptionItem, ToolCallData } from '../../types'
1111
import { SUBAGENT_LABELS } from '../../types'
1212
import type { AgentGroupItem } from './components'
13-
import {
14-
AgentGroup,
15-
ChatContent,
16-
CircleStop,
17-
Options,
18-
PendingTagIndicator,
19-
ThinkingBlock,
20-
} from './components'
13+
import { AgentGroup, ChatContent, CircleStop, Options, PendingTagIndicator } from './components'
2114
import { deriveMessagePhase, isToolDone, type MessagePhase } from './utils'
2215

2316
const FILE_SUBAGENT_ID = 'file'
@@ -29,14 +22,6 @@ interface TextSegment {
2922
content: string
3023
}
3124

32-
interface ThinkingSegment {
33-
type: 'thinking'
34-
id: string
35-
content: string
36-
startedAt?: number
37-
endedAt?: number
38-
}
39-
4025
interface AgentGroupSegment {
4126
type: 'agent_group'
4227
id: string
@@ -56,12 +41,7 @@ interface StoppedSegment {
5641
type: 'stopped'
5742
}
5843

59-
type MessageSegment =
60-
| TextSegment
61-
| ThinkingSegment
62-
| AgentGroupSegment
63-
| OptionsSegment
64-
| StoppedSegment
44+
type MessageSegment = TextSegment | AgentGroupSegment | OptionsSegment | StoppedSegment
6545

6646
const SUBAGENT_KEYS = new Set(Object.keys(SUBAGENT_LABELS))
6747

@@ -279,23 +259,9 @@ function parseBlocksWithSpanTree(blocks: ContentBlock[]): MessageSegment[] {
279259
continue
280260
}
281261

282-
if (block.type === 'thinking') {
283-
if (!block.content?.trim()) continue
284-
const last = segments[segments.length - 1]
285-
if (last?.type === 'thinking' && last.endedAt === undefined) {
286-
last.content += block.content
287-
if (block.endedAt !== undefined) last.endedAt = block.endedAt
288-
} else {
289-
segments.push({
290-
type: 'thinking',
291-
id: `thinking-${i}`,
292-
content: block.content,
293-
startedAt: block.timestamp,
294-
endedAt: block.endedAt,
295-
})
296-
}
297-
continue
298-
}
262+
// Main-agent thinking is intentionally not rendered. The reasoning is still
263+
// reduced and persisted upstream — this is a display-only omission.
264+
if (block.type === 'thinking') continue
299265

300266
if (block.type === 'text') {
301267
if (!block.content) continue
@@ -515,21 +481,10 @@ function parseBlocksLegacy(blocks: ContentBlock[]): MessageSegment[] {
515481
}
516482

517483
if (block.type === 'thinking') {
484+
// Main-agent thinking is not rendered, but it still breaks open subagent
485+
// lanes so later chunks don't merge across it (display-only omission).
518486
if (!block.content?.trim()) continue
519487
flushLanes()
520-
const last = segments[segments.length - 1]
521-
if (last?.type === 'thinking' && last.endedAt === undefined) {
522-
last.content += block.content
523-
if (block.endedAt !== undefined) last.endedAt = block.endedAt
524-
} else {
525-
segments.push({
526-
type: 'thinking',
527-
id: `thinking-${i}`,
528-
content: block.content,
529-
startedAt: block.timestamp,
530-
endedAt: block.endedAt,
531-
})
532-
}
533488
continue
534489
}
535490

@@ -776,29 +731,6 @@ function MessageContentInner({
776731
}
777732
/>
778733
)
779-
case 'thinking': {
780-
const isActive =
781-
isStreaming && i === segments.length - 1 && segment.endedAt === undefined
782-
const elapsedMs =
783-
segment.startedAt !== undefined && segment.endedAt !== undefined
784-
? segment.endedAt - segment.startedAt
785-
: undefined
786-
// Hide completed thinking that took 3s or less — quick thinking
787-
// isn't worth the visual noise. Still show while active (unknown
788-
// duration yet) and still show when timing is missing (old
789-
// persisted blocks) so we don't drop historical content.
790-
if (elapsedMs !== undefined && elapsedMs <= 3000) return null
791-
return (
792-
<div key={segment.id} className={isStreaming ? 'animate-stream-fade-in' : undefined}>
793-
<ThinkingBlock
794-
content={segment.content}
795-
isActive={isActive}
796-
startedAt={segment.startedAt}
797-
isStreaming={isStreaming}
798-
/>
799-
</div>
800-
)
801-
}
802734
case 'agent_group': {
803735
return (
804736
<div key={segment.id} className={isStreaming ? 'animate-stream-fade-in' : undefined}>
@@ -809,7 +741,8 @@ function MessageContentInner({
809741
items={segment.items}
810742
isDelegating={segment.isDelegating}
811743
isStreaming={isStreaming}
812-
defaultExpanded={segment.isOpen}
744+
isCurrentSection={i === segments.length - 1}
745+
isLaneOpen={segment.isOpen}
813746
/>
814747
</div>
815748
)

0 commit comments

Comments
 (0)