-
Notifications
You must be signed in to change notification settings - Fork 46k
feat(platform/copilot): message timestamps + accurate thought-for time #12890
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
Merged
Changes from 1 commit
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
f8ec02b
feat(platform/copilot): message timestamps + accurate thought-for time
majdyz 5b5f20e
fix(backend/copilot): reset per-turn reasoning counters + tests
majdyz f4692e6
refactor(platform/copilot): address CodeRabbit nits on timestamps PR
majdyz f9eac1d
fix(frontend/copilot): accept Date object for created_at
majdyz b93db17
test(frontend/copilot): cover TurnStatsBar + combined duration maps
majdyz 41d0fe7
test(platform/copilot): address CodeRabbit review comments on test files
majdyz a05b506
refactor(platform/copilot): collapse 3 parallel stat maps into one Tu…
majdyz ae5b382
feat(frontend/copilot): swap turn-stats label text on hover/click ins…
majdyz a2514e2
refactor(platform/copilot): drop reasoningDurationMs — whole-turn dur…
majdyz 98df6c8
fix(frontend/copilot): anchor live Thinking-Xs counter to last server…
majdyz 9caa8c8
fix(frontend/copilot): show date + time on hover, not just date
majdyz 6e6ddb0
fix(frontend/copilot): anchor live Thinking timer to current turn's u…
majdyz 9323f98
fix(frontend/copilot): simpler anchor + subtle hover fade
majdyz 99a3946
fix(frontend/copilot): hover-only label swap — drop click-to-pin
majdyz 4cec94d
feat(frontend/copilot): show timestamp on user messages on hover (alo…
majdyz 9549b65
fix(frontend/copilot): sub-second turns + late anchorIso sync
majdyz ca7a208
test(frontend/copilot): cover useElapsedTimer anchor paths for codecov
majdyz 7609301
test(platform/copilot): cover more changed lines for codecov patch
majdyz a37699c
fix(frontend/copilot): widen initialProps type for useElapsedTimer te…
majdyz 80e6882
Merge branch 'dev' of github.com:Significant-Gravitas/AutoGPT into fe…
majdyz 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
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
4 changes: 4 additions & 0 deletions
4
autogpt_platform/backend/migrations/20260423120000_add_reasoning_duration_ms/migration.sql
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,4 @@ | ||
| -- Add reasoningDurationMs column to ChatMessage so the copilot UI can show | ||
| -- actual model-reasoning time instead of whole-turn wall clock (which | ||
| -- includes tool execution). | ||
| ALTER TABLE "ChatMessage" ADD COLUMN "reasoningDurationMs" INTEGER; |
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
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
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
102 changes: 75 additions & 27 deletions
102
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 |
|---|---|---|
| @@ -1,52 +1,100 @@ | ||
| import type { UIDataTypes, UIMessage, UITools } from "ai"; | ||
| import { | ||
| Tooltip, | ||
| TooltipContent, | ||
| TooltipProvider, | ||
| TooltipTrigger, | ||
| } from "@/components/atoms/Tooltip/BaseTooltip"; | ||
| import { formatElapsed } from "./formatElapsed"; | ||
| import { getWorkDoneCounters } from "./useWorkDoneCounters"; | ||
|
|
||
| interface Props { | ||
| turnMessages: UIMessage<unknown, UIDataTypes, UITools>[]; | ||
| elapsedSeconds?: number; | ||
| durationMs?: number; | ||
| reasoningDurationMs?: number; | ||
| timestamp?: string; | ||
| } | ||
|
|
||
| function formatLocalTimestamp(iso: string): string { | ||
| const date = new Date(iso); | ||
| if (Number.isNaN(date.getTime())) return iso; | ||
| return date.toLocaleString(undefined, { | ||
| dateStyle: "medium", | ||
| timeStyle: "medium", | ||
| }); | ||
| } | ||
|
|
||
| export function TurnStatsBar({ | ||
| turnMessages, | ||
| elapsedSeconds, | ||
| durationMs, | ||
| reasoningDurationMs, | ||
| timestamp, | ||
| }: Props) { | ||
| const { counters } = getWorkDoneCounters(turnMessages); | ||
|
|
||
| // Prefer live elapsedSeconds, fall back to persisted durationMs | ||
| const displaySeconds = | ||
| elapsedSeconds !== undefined && elapsedSeconds > 0 | ||
| ? elapsedSeconds | ||
| : durationMs !== undefined | ||
| ? Math.round(durationMs / 1000) | ||
| : undefined; | ||
| // Prefer live elapsedSeconds while streaming. Once the turn is finalized | ||
| // use reasoningDurationMs when the backend recorded actual reasoning time | ||
| // — it excludes tool execution, which the user perceives as dead time. | ||
| // Fall back to the whole-turn wall clock for older turns that never had | ||
| // a reasoningDurationMs recorded. | ||
| let displaySeconds: number | undefined; | ||
| if (elapsedSeconds !== undefined && elapsedSeconds > 0) { | ||
| displaySeconds = elapsedSeconds; | ||
| } else if (reasoningDurationMs !== undefined && reasoningDurationMs > 0) { | ||
| displaySeconds = Math.max(1, Math.round(reasoningDurationMs / 1000)); | ||
| } else if (durationMs !== undefined && durationMs > 0) { | ||
| displaySeconds = Math.round(durationMs / 1000); | ||
| } | ||
|
|
||
| const hasTime = displaySeconds !== undefined && displaySeconds > 0; | ||
| const localTime = timestamp ? formatLocalTimestamp(timestamp) : null; | ||
|
|
||
| if (counters.length === 0 && !hasTime && !localTime) return null; | ||
|
|
||
| if (counters.length === 0 && !hasTime) return null; | ||
| const timeLabel = hasTime ? ( | ||
| <span className="cursor-default text-[11px] tabular-nums text-neutral-500"> | ||
| Thought for {formatElapsed(displaySeconds!)} | ||
| </span> | ||
| ) : null; | ||
|
|
||
| return ( | ||
| <div className="mt-2 flex items-center gap-1.5"> | ||
| {hasTime && ( | ||
| <span className="text-[11px] tabular-nums text-neutral-500"> | ||
| Thought for {formatElapsed(displaySeconds)} | ||
| </span> | ||
| )} | ||
| {counters.map(function renderCounter(counter, index) { | ||
| const needsDot = index > 0 || hasTime; | ||
| return ( | ||
| <span key={counter.category} className="flex items-center gap-1"> | ||
| {needsDot && ( | ||
| <span className="text-xs text-neutral-300">·</span> | ||
| )} | ||
| <span className="text-[11px] tabular-nums text-neutral-500"> | ||
| {counter.count} {counter.label} | ||
| <TooltipProvider> | ||
| <div className="mt-2 flex items-center gap-1.5"> | ||
| {timeLabel && | ||
| (localTime ? ( | ||
| <Tooltip> | ||
| <TooltipTrigger asChild>{timeLabel}</TooltipTrigger> | ||
| <TooltipContent side="top">{localTime}</TooltipContent> | ||
| </Tooltip> | ||
| ) : ( | ||
| timeLabel | ||
| ))} | ||
| {!hasTime && localTime && ( | ||
| <Tooltip> | ||
| <TooltipTrigger asChild> | ||
| <span className="cursor-default text-[11px] tabular-nums text-neutral-500"> | ||
| {localTime} | ||
| </span> | ||
| </TooltipTrigger> | ||
| <TooltipContent side="top">{localTime}</TooltipContent> | ||
| </Tooltip> | ||
| )} | ||
|
coderabbitai[bot] marked this conversation as resolved.
Outdated
|
||
| {counters.map(function renderCounter(counter, index) { | ||
| const needsDot = index > 0 || hasTime || !!localTime; | ||
| return ( | ||
| <span key={counter.category} className="flex items-center gap-1"> | ||
| {needsDot && ( | ||
| <span className="text-xs text-neutral-300">·</span> | ||
| )} | ||
| <span className="text-[11px] tabular-nums text-neutral-500"> | ||
| {counter.count} {counter.label} | ||
| </span> | ||
| </span> | ||
| </span> | ||
| ); | ||
| })} | ||
| </div> | ||
| ); | ||
| })} | ||
| </div> | ||
| </TooltipProvider> | ||
| ); | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
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.