-
-
Notifications
You must be signed in to change notification settings - Fork 4.8k
feat(seer-explorer): show work in flight per tool call, and lead rows with the agent's own words #122919
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
feat(seer-explorer): show work in flight per tool call, and lead rows with the agent's own words #122919
Changes from all commits
219a36d
add1eaf
99c0420
51f85f9
5df5772
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,6 +33,7 @@ import { | |
| callRecordFailure, | ||
| callRecordInputQuery, | ||
| callRecordLabel, | ||
| fallbackCallLabel, | ||
| callRecordStatus, | ||
| visibleCallRecords, | ||
| } from 'sentry/views/seerExplorer/callRecords'; | ||
|
|
@@ -240,6 +241,20 @@ function useToolLinks(block: Block) { | |
| // The mirror lives on the block, not per tool call, so it can only be attributed to a call that | ||
| // has not reported yet. With several still in flight there is no way to tell whose calls these | ||
| // are, so it is shown on none of them rather than duplicated across all. | ||
| // Grouped by the call that emitted them: an event names its own, so unlike the mirror below | ||
| // several calls can be in flight and each still reports. | ||
| const progressForCallId = useMemo(() => { | ||
| const grouped = new Map<string, string[]>(); | ||
| for (const event of block.progress ?? []) { | ||
| const message = event?.message?.trim(); | ||
| if (!event?.token || !message) { | ||
| continue; | ||
| } | ||
| grouped.set(event.token, [...(grouped.get(event.token) ?? []), message]); | ||
| } | ||
| return grouped; | ||
| }, [block.progress]); | ||
|
|
||
| const liveCallsForCallId = useMemo(() => { | ||
| const calls = block.live_calls ?? []; | ||
| if (!calls.length) { | ||
|
|
@@ -263,6 +278,7 @@ function useToolLinks(block: Block) { | |
| structuredContentMarkdownByCallId, | ||
| callRecordsByCallId, | ||
| liveCallsForCallId, | ||
| progressForCallId, | ||
| settledCallIds, | ||
| organization, | ||
| projects, | ||
|
|
@@ -285,6 +301,7 @@ export function ToolCallList({block, blocks, getPageReferrer}: ToolCallListProps | |
| structuredContentMarkdownByCallId, | ||
| callRecordsByCallId, | ||
| liveCallsForCallId, | ||
| progressForCallId, | ||
| settledCallIds, | ||
| organization, | ||
| projects, | ||
|
|
@@ -405,6 +422,11 @@ export function ToolCallList({block, blocks, getPageReferrer}: ToolCallListProps | |
| const finishedCalls = toolCall.id | ||
| ? (callRecordsByCallId.get(toolCall.id) ?? []) | ||
| : []; | ||
| // Progress first: attributed by token, so it survives several calls in flight — exactly | ||
| // when the mirror shows nothing. The mirror stays the fallback for an older seer. | ||
| const progressLines = toolCall.id | ||
| ? (progressForCallId.get(toolCall.id) ?? []) | ||
| : []; | ||
| const live = toolCall.id ? (liveCallsForCallId.get(toolCall.id) ?? []) : []; | ||
| // A result exists, so the execute returned and nothing it reported is still running. Read | ||
| // off the result itself rather than off the records it carried: a call that reports none | ||
|
|
@@ -419,7 +441,19 @@ export function ToolCallList({block, blocks, getPageReferrer}: ToolCallListProps | |
| // claiming it wholesale would starve later rows of their bus twins. Those are paired one | ||
| // bus link at a time below instead. | ||
| const claimedLinkKinds = new Set<string>(); | ||
| const callRows = visibleCallRecords(finishedCalls.length ? finishedCalls : live) | ||
| // Progress carries a string, so each line becomes a note-shaped record and rides the same | ||
| // renderer. Negative ids keep them clear of the per-execute counter. | ||
| const inFlightRows: CallRecord[] = progressLines.map((message, index) => ({ | ||
| id: -(index + 1), | ||
| kind: 'note' as const, | ||
| llm_description: message, | ||
| })); | ||
| const rowSource = finishedCalls.length | ||
| ? finishedCalls | ||
| : inFlightRows.length | ||
| ? inFlightRows | ||
| : live; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Progress persists after call settlesMedium Severity
Additional Locations (1)Reviewed by Cursor Bugbot for commit 5df5772. Configure here. |
||
| const callRows = visibleCallRecords(rowSource) | ||
| .map(record => { | ||
| const subject = subjectFromCallRecord(record); | ||
| const link = resolveLink(subject, {organization, projects}); | ||
|
|
@@ -443,10 +477,12 @@ export function ToolCallList({block, blocks, getPageReferrer}: ToolCallListProps | |
| linkLabel: genericLink?.label ?? null, | ||
| }; | ||
| }) | ||
| // A record we have no label for is dropped rather than rendered as a route or an | ||
| // internal identifier — one fewer row beats a raw string on screen. The predicate | ||
| // narrows `label` for the render below, which is why it is not a plain Boolean check. | ||
| .filter((row): row is typeof row & {label: string} => Boolean(row.label)); | ||
| // Reported rather than deleted — a row should never disappear for want of wording — but | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Description hidden on linked rowsMedium Severity A matching link rule still names the row from the generated Reviewed by Cursor Bugbot for commit 5df5772. Configure here. |
||
| // given a generic label, since a raw route reads worse than no row at all. | ||
| .map(row => ({ | ||
| ...row, | ||
| label: row.label ?? fallbackCallLabel(row.record), | ||
| })); | ||
|
|
||
| const residualNavItems = navItems.filter( | ||
| item => !claimedLinkKinds.has(item.kind) | ||
|
|
||


Uh oh!
There was an error while loading. Please reload this page.