Skip to content

feat(ui): add message timing metrics#357

Open
pascalandr wants to merge 10 commits into
NeuralNomadsAI:devfrom
Pagecran:feat/message-timing-metrics
Open

feat(ui): add message timing metrics#357
pascalandr wants to merge 10 commits into
NeuralNomadsAI:devfrom
Pagecran:feat/message-timing-metrics

Conversation

@pascalandr
Copy link
Copy Markdown
Contributor

@pascalandr pascalandr commented Apr 23, 2026

Fixes #297

Summary

  • show total assistant response duration next to the existing message timestamp using only explicit OpenCode message timing
  • show reasoning duration on reasoning cards only when OpenCode provides explicit part timing

Why

This revision keeps the UI scoped to explicit server-side timing data that OpenCode already provides, which matches the maintainer feedback on this PR.

Validation

  • node --experimental-strip-types --test "packages/ui/src/lib/message-timing.test.ts"
  • npm run build --workspace @codenomad/ui

@pascalandr
Copy link
Copy Markdown
Contributor Author

@CodeNomadBot

I want you to perform the gatekeeper checks for latest PR state

check for regressions
check for better possible implementations
Be the PR gatekeeper
Be ruthless about code quality

@codenomadbot
Copy link
Copy Markdown
Contributor

codenomadbot Bot commented Apr 23, 2026

Gatekeeper review for the latest PR state:

What I reviewed

  • Request understood as: do a ruthless PR gatekeeper pass on the current branch, focused on regressions and better implementation options for the new message timing metrics.
  • Reviewed the changed code paths in packages/ui/src/lib/message-timing.ts, packages/ui/src/lib/message-timing.test.ts, packages/ui/src/components/message-item.tsx, packages/ui/src/components/message-block.tsx, and packages/ui/src/styles/messaging/message-base.css.

Findings

  • No blocking regressions found in the current implementation.
  • No clearly better implementation jumped out that would justify changing this PR. The timing logic is kept in one helper module as requested, and the UI integration stays narrow.

What I checked closely

  • packages/ui/src/lib/message-timing.ts:17-95
    Centralized timing extraction is small and coherent. The completion fallback rules are conservative, and reasoning duration inference prefers explicit values before inferring from the next timed part or message completion.
  • packages/ui/src/components/message-item.tsx:142-145 and :565-569
    Assistant-only total duration display is scoped correctly and does not affect user messages.
  • packages/ui/src/components/message-block.tsx:760-779, :1398-1405, and :1600-1604
    Reasoning cards receive inferred durations without spreading timing logic into the component tree.

Validation

  • node --experimental-strip-types --test "packages/ui/src/lib/message-timing.test.ts" passed.
  • npm run build --workspace @codenomad/ui could not be completed in this workspace because the environment is missing the vite package, so I could not fully verify build-level regressions from here.

Residual risk

  • The helper tests cover the inference rules well, but component-level rendering is still implicitly covered rather than directly tested. If you want this even tighter, the next incremental improvement would be a UI-level test around assistant header timing and reasoning-card timing display.

Gatekeeper verdict

  • Approved from a code-quality and regression-review standpoint, with the only unresolved item being build verification blocked by missing local dependencies in this environment.

--
Yours,
CodeNomadBot

@shantur
Copy link
Copy Markdown
Collaborator

shantur commented Apr 26, 2026

@pascalandr - Are these times provided by OpenCode or its being calculated in CodeNomad based on request and response?
If it's latter, then these times have no value at all, as its not thinking time or anything, it can be the time for the request reaching, queuing, and processing.

@pascalandr
Copy link
Copy Markdown
Contributor Author

pascalandr commented Apr 26, 2026

@pascalandr - Are these times provided by OpenCode or its being calculated in CodeNomad based on request and response? If it's latter, then these times have no value at all, as its not thinking time or anything, it can be the time for the request reaching, queuing, and processing.

It does use an explicit part duration if one is present, but otherwise it is just derived from the timing metadata we have in the stream.
A better version would be to only show explicit server-side timings, right ?
OpenCode does already provide some server-side timing data for messages and parts, so a basic elapsed duration could be meaningful.

@shantur
Copy link
Copy Markdown
Collaborator

shantur commented Apr 26, 2026

Agreed, we can look at this PR once OC times are used

@shantur shantur added the needs-work PR needs more work label Apr 26, 2026
@pascalandr
Copy link
Copy Markdown
Contributor Author

Updated this PR to only use explicit OpenCode timing data.

What changed:

  • total assistant duration now only uses explicit message timing (duration / time.duration) or time.created -> time.end
  • reasoning duration now only uses explicit part timing (duration / time.duration) or time.start -> time.end
  • removed all client-side inference from updated timestamps, next-part boundaries, and message-completion fallback

Validation:

  • node --experimental-strip-types --test "packages/ui/src/lib/message-timing.test.ts"
  • npm run build --workspace @codenomad/ui

@pascalandr
Copy link
Copy Markdown
Contributor Author

@CodeNomadBot

I want you to perform the gatekeeper checks for latest PR state

check for regressions
check for better possible implementations
Be the PR gatekeeper
Be ruthless about code quality

@codenomadbot
Copy link
Copy Markdown
Contributor

codenomadbot Bot commented Apr 30, 2026

Gatekeeper review for the latest PR state:

What I understood

  • Request: perform a ruthless gatekeeper pass on the revised PR, specifically checking regressions and whether the implementation now correctly avoids unreliable client-side timing inference.
  • Assumption: the intended behavior is exactly what the updated PR body/comment says: show durations only from explicit OpenCode timing data, not from updated, stream ordering, next-part boundaries, or message-completion fallback.

Findings

  • No blocking regressions found.
  • The revised implementation now matches the maintainer feedback: duration display is limited to explicit duration / time.duration, or explicit start/end timing on the same OpenCode message/part.

What I checked

  • packages/ui/src/lib/message-timing.ts:29-38
    Message duration no longer uses local fallback timestamps or time.updated. It uses explicit duration first, then time.created -> time.end only when both are present on the message.
  • packages/ui/src/lib/message-timing.ts:44-60
    Reasoning duration no longer infers from next timed part or message completion. It only uses explicit part duration or explicit part start/created -> end timing.
  • packages/ui/src/lib/message-timing.test.ts:18-43
    Tests now cover the important negative cases: no message duration from updated, and no reasoning duration from message completion.
  • packages/ui/src/components/message-item.tsx:142-144 and :565-569
    Total duration remains assistant-only and empty durations render nothing.
  • packages/ui/src/components/message-block.tsx:760-779 and :1398-1405
    Reasoning-card duration is passed through the helper and displayed only when formatted duration exists.

Better implementation notes

  • Non-blocking: inferReasoningDurationMs is now a compatibility wrapper around getPartDurationMs, so the name is a bit stale. I would not block this PR on renaming it, because keeping the call sites stable makes the fix smaller.
  • Non-blocking: getMessageCompletedAt is exported but currently unused by changed code. It is harmless, but could be removed if there are no expected near-term callers.

Validation

  • node --experimental-strip-types --test "packages/ui/src/lib/message-timing.test.ts" passed.
  • npm run build --workspace @codenomad/ui could not run to completion in this workspace because vite is missing from local dependencies here (ERR_MODULE_NOT_FOUND: Cannot find package 'vite'). This appears to be an environment/dependency-install issue, not a code failure from this PR.

Gatekeeper verdict

  • Approved from code-quality and regression-review standpoint.
  • The prior core concern about client-derived durations has been addressed in the latest PR state.

--
Yours,
CodeNomadBot

pascalandr added 2 commits May 1, 2026 23:04
Resolve the message-block import conflict between the message timing metrics and the session search updates from dev.

This keeps the OpenCode timing helpers wired into reasoning cards while preserving the new session search match typing from dev.

Validated with the message timing unit tests, UI typecheck, and UI build after resolving the merge.
@pascalandr pascalandr removed the needs-work PR needs more work label May 9, 2026
# Conflicts:
#	packages/ui/src/components/message-block.tsx
#	packages/ui/src/components/message-item.tsx
@github-actions
Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/26517588943

Artifacts expire in 7 days.
Artifacts:

  • pr-357-3b2b5cf4fdf3a10b3b3ab886df2578366bdc2e92-tauri-macos
  • pr-357-3b2b5cf4fdf3a10b3b3ab886df2578366bdc2e92-tauri-linux
  • pr-357-3b2b5cf4fdf3a10b3b3ab886df2578366bdc2e92-tauri-windows
  • pr-357-3b2b5cf4fdf3a10b3b3ab886df2578366bdc2e92-electron-macos
  • pr-357-3b2b5cf4fdf3a10b3b3ab886df2578366bdc2e92-tauri-macos-arm64
  • pr-357-3b2b5cf4fdf3a10b3b3ab886df2578366bdc2e92-electron-windows
  • pr-357-3b2b5cf4fdf3a10b3b3ab886df2578366bdc2e92-electron-linux

@pascalandr pascalandr requested a review from shantur May 27, 2026 22:13
@shantur
Copy link
Copy Markdown
Collaborator

shantur commented May 29, 2026

@pascalandr - Do you think we still need this?
Do we miss this feature?

@pascalandr
Copy link
Copy Markdown
Contributor Author

pascalandr commented May 30, 2026

@pascalandr - Do you think we still need this? Do we miss this feature?

@shantur Yes ! It's usefull.
image
maybe I should had "s" for seconds?

Align assistant and reasoning timing display with the explicit OpenChamber/OpenCode semantics by using created/completed timestamps instead of legacy inferred duration fields.

Move visible durations inline after the assistant and thinking labels and add the trailing seconds suffix expected by PR NeuralNomadsAI#357.

Keep the commit scoped to the UI timing files only; unrelated build artifacts and task evidence remain uncommitted.
Clock-formatted message durations already communicate elapsed time without an extra literal suffix. This follow-up removes the trailing s from the shared formatter and updates the targeted timing helper test expectations to match.

Keeping the display as pure clock text avoids ambiguous mixed formatting such as 0:02s and prevents an untranslated unit marker from leaking across locales. Validation included git diff --check, the targeted message timing node test, and the UI typecheck.
@pascalandr
Copy link
Copy Markdown
Contributor Author

@CodeNomadBot
check last 2 changes

@github-actions
Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/26683346160

Artifacts expire in 7 days.
Artifacts: (none found on this run)

1 similar comment
@github-actions
Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/26683346160

Artifacts expire in 7 days.
Artifacts: (none found on this run)

@codenomadbot
Copy link
Copy Markdown
Contributor

codenomadbot Bot commented May 30, 2026

Checked the last 2 changes:

Scope reviewed

  • 171a488a fix(ui): align message timing with OpenChamber
  • e134dab6 fix: 074 remove duration suffix from clock labels

What I understood

  • Request: review only the last two changes for regressions and code-quality issues.
  • Assumption: the intended behavior is to align with the current OpenCode/OpenChamber timing model: assistant message duration from time.created -> time.completed, reasoning/part duration from explicit part time.start -> time.end, and clock labels without a unit suffix.

Findings

  • No blocking issues found in the last two changes.
  • The move from time.end to time.completed for assistant message duration matches the current @opencode-ai/sdk type shape I checked externally: AssistantMessage.time has created and optional completed.
  • Reasoning duration remains correctly constrained to explicit part timing: ReasoningPart.time.start and optional time.end.
  • Removing the duration from the timestamp area and placing it beside the speaker / reasoning label is a reasonable UI improvement and keeps the timestamp visually clean.

Validation

  • node --experimental-strip-types --test "packages/ui/src/lib/message-timing.test.ts" passed.
  • npm run build --workspace @codenomad/ui could not complete in this local workspace because vite is missing from installed dependencies here (ERR_MODULE_NOT_FOUND: Cannot find package 'vite'). This is the same environment limitation as previous bot checks, not a new failure in these two commits.

Non-blocking notes

  • The surrounding message lifecycle code still has references to time.end for completion/streaming status in other files. That is outside these two changes, but if the app is now fully on the completed field, it may deserve a separate follow-up audit.
  • Touched files are already oversized and worth future refactor planning, but I would not block this PR on that: packages/ui/src/components/message-block.tsx is about 1900 lines, packages/ui/src/components/message-item.tsx is about 786 lines, and packages/ui/src/styles/messaging/message-base.css is about 600 lines.

Verdict

  • Last two changes look good from a gatekeeper review standpoint.
  • No requested code changes from me.

--
Yours,
CodeNomadBot

@github-actions
Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/26683371446

Artifacts expire in 7 days.
Artifacts:

  • pr-357-e134dab6355f7e22b72fd60a07d2b5e49defcaba-tauri-linux
  • pr-357-e134dab6355f7e22b72fd60a07d2b5e49defcaba-tauri-macos
  • pr-357-e134dab6355f7e22b72fd60a07d2b5e49defcaba-tauri-windows
  • pr-357-e134dab6355f7e22b72fd60a07d2b5e49defcaba-electron-macos
  • pr-357-e134dab6355f7e22b72fd60a07d2b5e49defcaba-tauri-macos-arm64
  • pr-357-e134dab6355f7e22b72fd60a07d2b5e49defcaba-electron-windows
  • pr-357-e134dab6355f7e22b72fd60a07d2b5e49defcaba-electron-linux

@shantur
Copy link
Copy Markdown
Collaborator

shantur commented May 31, 2026

@pascalandr - Doesn't look correct.
Screenshot 2026-05-31 at 14 19 40

@github-actions
Copy link
Copy Markdown

PR builds are available as GitHub Actions artifacts:

https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/26713603813

Artifacts expire in 7 days.
Artifacts:

  • pr-357-a363fbb34c3113f432b9cdbe8995ddcc57fcf4c7-tauri-macos
  • pr-357-a363fbb34c3113f432b9cdbe8995ddcc57fcf4c7-tauri-linux
  • pr-357-a363fbb34c3113f432b9cdbe8995ddcc57fcf4c7-tauri-windows
  • pr-357-a363fbb34c3113f432b9cdbe8995ddcc57fcf4c7-electron-macos
  • pr-357-a363fbb34c3113f432b9cdbe8995ddcc57fcf4c7-tauri-macos-arm64
  • pr-357-a363fbb34c3113f432b9cdbe8995ddcc57fcf4c7-electron-windows
  • pr-357-a363fbb34c3113f432b9cdbe8995ddcc57fcf4c7-electron-linux

@pascalandr
Copy link
Copy Markdown
Contributor Author

pascalandr commented May 31, 2026

@pascalandr - Doesn't look correct. Screenshot 2026-05-31 at 14 19 40

right but doesn't look correct with or without this PR, I mean this is a layout problem

@shantur
Copy link
Copy Markdown
Collaborator

shantur commented May 31, 2026

@pascalandr - Doesn't look correct. Screenshot 2026-05-31 at 14 19 40

right but doesn't look correct with or without this PR, I mean this is a layout problem

I meant the second time between the Assistant and Agent

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

display thinking time, total response time

2 participants