-
Notifications
You must be signed in to change notification settings - Fork 46k
feat(frontend/copilot): add per-turn work-done summary stats #12257
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
Merged
0ubbe
merged 17 commits into
dev
from
lluisagusti/secrt-2026-add-live-job-duration-timer-and-work-done-summary-stats-to
Mar 5, 2026
Merged
Changes from 13 commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
15c40e8
feat(frontend/copilot): add live job duration timer and work-done sum…
0ubbe 38b2c6f
fix(frontend/copilot): address review suggestions for job stats bar
0ubbe 1ea7c27
chore: review suggestions
0ubbe f375110
feat(platform): add per-turn stats and clickable tool invocation moda…
0ubbe 20b74ec
fix(frontend): only show per-turn stats on the final assistant messag…
0ubbe 21d23bb
refactor(frontend): remove clickable modals from stats counters, disp…
0ubbe af228eb
fix(frontend): show copy/TTS actions only on final assistant message …
0ubbe c0d1850
refactor(frontend): remove global JobStatsBar above chat input
0ubbe 1878941
fix(frontend): strip custom SSE fields before AI SDK parses them
0ubbe 5082240
fix(platform): use client-side timing instead of custom SSE fields
0ubbe 9dbd35e
refactor(frontend): remove turn duration/timing code from copilot
0ubbe 648ea0a
Merge remote-tracking branch 'origin/dev' into lluisagusti/secrt-2026…
0ubbe bc0481d
refactor(frontend/copilot): clean up comments and tidy code per conve…
0ubbe 4f90d23
Merge remote-tracking branch 'origin/dev' and address review feedback
0ubbe e9b0fcd
Merge branch 'dev' into lluisagusti/secrt-2026-add-live-job-duration-…
0ubbe dcd8c0d
Merge branch 'dev' into lluisagusti/secrt-2026-add-live-job-duration-…
0ubbe 79fd9e6
Merge branch 'dev' into lluisagusti/secrt-2026-add-live-job-duration-…
0ubbe File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
29 changes: 29 additions & 0 deletions
29
autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/TurnStatsBar.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| import type { UIDataTypes, UIMessage, UITools } from "ai"; | ||
| import { getWorkDoneCounters } from "./useWorkDoneCounters"; | ||
|
|
||
| interface Props { | ||
| turnMessages: UIMessage<unknown, UIDataTypes, UITools>[]; | ||
| } | ||
|
|
||
| export function TurnStatsBar({ turnMessages }: Props) { | ||
| const { counters } = getWorkDoneCounters(turnMessages); | ||
|
|
||
| if (counters.length === 0) return null; | ||
|
|
||
| return ( | ||
| <div className="mt-2 flex items-center gap-1.5"> | ||
| {counters.map(function renderCounter(counter, index) { | ||
| return ( | ||
| <span key={counter.category} className="flex items-center gap-1"> | ||
| {index > 0 && ( | ||
| <span className="text-xs text-neutral-300">·</span> | ||
| )} | ||
| <span className="text-[11px] tabular-nums text-neutral-500"> | ||
| {counter.count} {counter.label} | ||
| </span> | ||
| </span> | ||
| ); | ||
| })} | ||
| </div> | ||
| ); | ||
| } |
74 changes: 74 additions & 0 deletions
74
...latform/frontend/src/app/(platform)/copilot/components/JobStatsBar/useWorkDoneCounters.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| import type { UIDataTypes, UIMessage, UITools } from "ai"; | ||
|
|
||
| const TOOL_TO_CATEGORY: Record<string, string> = { | ||
| find_agent: "search", | ||
| find_library_agent: "search", | ||
| run_agent: "agent run", | ||
| run_block: "block run", | ||
| create_agent: "agent created", | ||
| edit_agent: "agent edited", | ||
| schedule_agent: "agent scheduled", | ||
| }; | ||
|
|
||
| const MAX_COUNTERS = 3; | ||
|
|
||
| function pluralize(label: string, count: number): string { | ||
| if (count === 1) return label; | ||
|
|
||
| // "agent created" -> "agents created", "agent edited" -> "agents edited" | ||
| const nounVerbMatch = label.match( | ||
| /^(\w+)\s+(created|edited|scheduled|run)$/i, | ||
| ); | ||
| if (nounVerbMatch) { | ||
| return pluralizeWord(nounVerbMatch[1]) + " " + nounVerbMatch[2]; | ||
| } | ||
|
|
||
| return pluralizeWord(label); | ||
| } | ||
|
|
||
| function pluralizeWord(word: string): string { | ||
| if (word.endsWith("ch") || word.endsWith("sh") || word.endsWith("x")) | ||
| return word + "es"; | ||
| return word + "s"; | ||
| } | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
|
|
||
| export interface WorkDoneCounter { | ||
| label: string; | ||
| count: number; | ||
| category: string; | ||
| } | ||
|
|
||
| export function getWorkDoneCounters( | ||
| messages: UIMessage<unknown, UIDataTypes, UITools>[], | ||
| ) { | ||
| const categoryCounts = new Map<string, number>(); | ||
|
|
||
| for (const message of messages) { | ||
| if (message.role !== "assistant") continue; | ||
|
|
||
| for (const part of message.parts) { | ||
| if (!part.type.startsWith("tool-")) continue; | ||
|
0ubbe marked this conversation as resolved.
Outdated
|
||
|
|
||
| const toolName = part.type.replace("tool-", ""); | ||
| const category = TOOL_TO_CATEGORY[toolName]; | ||
| if (!category) continue; | ||
|
|
||
| categoryCounts.set(category, (categoryCounts.get(category) ?? 0) + 1); | ||
| } | ||
| } | ||
|
|
||
| const counters: WorkDoneCounter[] = Array.from(categoryCounts.entries()) | ||
| .map(function toCounter([category, count]) { | ||
| return { | ||
| label: pluralize(category, count), | ||
| count, | ||
| category, | ||
| }; | ||
| }) | ||
| .sort(function byCountDesc(a, b) { | ||
| return b.count - a.count; | ||
| }) | ||
| .slice(0, MAX_COUNTERS); | ||
|
|
||
| return { counters }; | ||
| } | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.