Skip to content

Conversation

@andybraren
Copy link
Collaborator

Still need to test this with an updated backend, but this should add per-message timestamps to the eventstream from AGUI, enabling us to show accurate per-message timestamps. Right now all message timestamps in a session change to the time of the most recently received message.

@github-actions

This comment has been minimized.

@jeremyeder
Copy link
Collaborator

@bobbravo2 bobbravo2 added this to the v0.0.20 milestone Jan 30, 2026
- Added logic to set a timestamp for AGUI events in `agui_proxy.go` and `agui.go` if not already present, ensuring accurate message tracking.
- Updated `compaction.go` to preserve the timestamp from events when creating messages.
- Modified frontend components to utilize the timestamp from backend messages, providing a fallback for legacy messages.

This change improves the reliability of message timestamp tracking across the system.
@github-actions
Copy link
Contributor

github-actions bot commented Feb 2, 2026

Claude Code Review

Summary

This PR adds per-message timestamps to the AGUI event stream, fixing an issue where all message timestamps would change to the time of the most recently received message. The changes ensure that timestamps are set at event creation time and preserved throughout the event processing pipeline (backend → compaction → frontend).

Overall Assessment: The implementation is sound and addresses the issue effectively, but there are a few areas that need attention before merging.


Issues by Severity

🔴 Critical Issues

1. Inconsistent timestamp format documentation

  • Location: components/backend/websocket/agui.go:128, agui_proxy.go:286
  • Issue: Using time.RFC3339Nano format but no validation or documentation of expected format
  • Impact: Could cause parsing issues if frontend expects a different format
  • Recommendation: Add a constant for the timestamp format and document it in types/agui.go
// In types/agui.go
const AGUITimestampFormat = time.RFC3339Nano  // "2006-01-02T15:04:05.999999999Z07:00"

2. Race condition with nil check pattern

  • Location: components/backend/websocket/agui.go:127-129, agui.go:179-181, agui_proxy.go:285-287
  • Issue: Pattern if event["timestamp"] == nil || event["timestamp"] == "" is not type-safe
  • Impact: If event["timestamp"] is a non-string type, the empty string comparison could panic or behave unexpectedly
  • Fix: Use type-safe checking:
// SAFER pattern
timestamp, ok := event["timestamp"].(string)
if \!ok || timestamp == "" {
    event["timestamp"] = time.Now().UTC().Format(time.RFC3339Nano)
}

🟡 Major Issues

3. Missing timestamp validation in frontend

  • Location: components/frontend/src/app/projects/[name]/sessions/[sessionName]/page.tsx:762, 857
  • Issue: Fallback to new Date().toISOString() uses a different format than backend (ISO8601 vs RFC3339Nano)
  • Impact: Inconsistent timestamp formats in the UI, potential parsing issues
  • Fix: Use consistent format or validate/normalize timestamps from backend

4. Potential timestamp loss in compaction

  • Location: components/backend/websocket/compaction.go:243-245
  • Issue: Only updates timestamp if c.currentMessage.Timestamp == "", but if the message already has an older timestamp from TEXT_MESSAGE_START, tool call timestamps won't update it
  • Impact: Tool calls might get incorrect timestamps
  • Analysis: This might be intentional (use message start time), but should be documented

5. Makefile changes unrelated to timestamps

  • Location: Makefile:599-601
  • Issue: Service name changes (frontendfrontend-service, backend-apibackend-service) and output suppression removal are unrelated to timestamp feature
  • Impact: Could break existing workflows, makes PR review harder
  • Recommendation: Split these changes into a separate PR or document why they're needed

🔵 Minor Issues

6. Inconsistent comment style

  • Location: components/backend/websocket/agui.go:178, agui_proxy.go:284
  • Issue: Comments say "Add timestamp if not present - critical for message timestamp tracking" but the implementation allows overwriting empty strings too
  • Fix: Update comment to match behavior: "Ensure timestamp is set if missing or empty"

7. Missing error handling for time parsing in frontend

  • Location: components/frontend/src/hooks/use-agui-stream.ts:145, 218, 420, 552, 569, 583
  • Issue: No validation that event.timestamp is a valid RFC3339Nano timestamp
  • Impact: Could lead to "Invalid Date" in the UI
  • Recommendation: Add timestamp validation helper:
function normalizeTimestamp(timestamp: string | undefined): string {
  if (\!timestamp) return new Date().toISOString()
  try {
    // Validate by parsing
    const date = new Date(timestamp)
    return isNaN(date.getTime()) ? new Date().toISOString() : timestamp
  } catch {
    return new Date().toISOString()
  }
}

8. No test coverage for timestamp preservation

  • Impact: Risk of regression in future changes
  • Recommendation: Add tests verifying:
    • Timestamps are preserved through event routing
    • Timestamps are set when missing
    • Compaction preserves timestamps correctly

Positive Highlights

Comprehensive coverage: Timestamps added at all entry points (WebSocket, proxy, compaction)
Backward compatibility: Fallback logic for legacy messages without timestamps
Type safety: Using proper Go struct field (Timestamp string) in types.Message
Consistent placement: All timestamp checks follow similar patterns
Preserves existing behavior: Doesn't break current functionality, only enhances it


Recommendations

Priority 1 (Must fix before merge)

  1. Fix type-unsafe nil checks (Critical Issue Epic: RAT Architecture & Design #2)
  2. Split Makefile changes into separate PR or explain necessity (Major Issue Epic: Jira Integration & Workflow #5)
  3. Add timestamp format constant and documentation (Critical Issue Outcome: Reduce Refinement Time with agent System #1)

Priority 2 (Should fix before merge)

  1. Normalize frontend timestamp formats (Major Issue Epic: Data Source Integration #3)
  2. Document timestamp behavior in compaction (Major Issue Epic: AI Agent Development #4)

Priority 3 (Nice to have)

  1. Add timestamp validation in frontend (Minor Issue Test: Automation Workflow Validation #7)
  2. Add test coverage for timestamp preservation (Minor Issue Test: Updated Workflow Validation #8)

Architecture Compliance

Security: No security issues - timestamps don't contain sensitive data
Error Handling: Follows patterns from .claude/patterns/error-handling.md
Type Safety: Backend uses proper struct fields (though nil checks need improvement)
⚠️ Testing: Missing test coverage for new functionality
Logging: No additional logging needed for this feature


Pre-Merge Checklist

Before merging, verify:

  • Fix type-unsafe nil checks (use type assertion pattern)
  • Either remove Makefile changes or document why they're needed
  • Add AGUITimestampFormat constant in types/agui.go
  • Document timestamp format in Message struct comments
  • Consider normalizing timestamps in frontend
  • Run gofmt -w components/backend/websocket
  • Run go vet ./... in backend
  • Verify frontend builds: npm run build (0 errors, 0 warnings)
  • Test with real session to confirm timestamps are accurate

Testing Notes

Based on PR description, you mentioned "Still need to test this with an updated backend". Before merging:

  1. Create a test session with multiple messages
  2. Verify timestamps in the UI don't all change when new messages arrive
  3. Check tool call timestamps are preserved correctly
  4. Test legacy sessions (without timestamps) still work with fallback logic

Overall: This is a solid fix for the timestamp issue. The main concerns are the type-unsafe nil checks and the unrelated Makefile changes. Once those are addressed, this should be good to merge.

Let me know if you need clarification on any of these points!


🔍 View AI decision process (logs available for 90 days)

📋 View memory system files loaded (click to expand)

What Amber Loaded for Code Review

Amber automatically loaded these repository standards from the memory system:

  1. CLAUDE.md - Master project instructions, development standards
  2. backend-development.md - Go backend, K8s integration patterns
  3. frontend-development.md - NextJS, Shadcn UI, React Query patterns
  4. security-standards.md - Auth, RBAC, token handling
  5. k8s-client-usage.md - User token vs service account patterns
  6. error-handling.md - Consistent error patterns
  7. react-query-usage.md - Data fetching patterns

Impact: This review used your repository's specific code quality standards, security patterns, and best practices from the memory system (PRs #359, #360) - not just generic code review guidelines.

…mponents

- Captured timestamps from AGUI events in the useAGUIStream hook for improved message tracking.

This change improves the accuracy and reliability of message timestamps across the application.
@github-actions
Copy link
Contributor

github-actions bot commented Feb 2, 2026

Claude Code Review

Summary

This PR enhances timestamp handling in the AGUI event stream by ensuring that every event receives a timestamp at the point of creation. The changes address a critical bug where all message timestamps in a session would incorrectly update to the time of the most recently received message.

Overall Assessment: Good implementation with proper timestamp propagation, but requires attention to error handling patterns and testing before merge.


Issues by Severity

Critical Issues

1. Inconsistent Error Handling Pattern (Backend)

File: components/backend/websocket/compaction.go:235

The code uses underscore to ignore type assertion failures which violates error handling standards. Type assertion failures could silently produce empty timestamps, defeating the purpose of this PR.

Files affected:

  • components/backend/websocket/compaction.go:122, 235
  • components/backend/websocket/agui.go (multiple locations)

Major Issues

2. Missing Tests for Timestamp Propagation

No test coverage for the core functionality - timestamp preservation through the event pipeline.

Expected tests:

  • Backend: Unit tests for RouteAGUIEvent verifying timestamp injection
  • Backend: Tests for message compactor timestamp preservation
  • Frontend: Tests for use-agui-stream timestamp handling

Impact: No way to verify timestamps are correctly propagated without manual testing. Regression risk is high.


3. Inconsistent Timestamp Format Documentation

No documentation or comments explaining the timestamp format (time.RFC3339Nano). Add comments at injection points explaining the format choice.


4. Fallback Logic Could Mask Backend Issues (Frontend)

File: components/frontend/src/app/projects/[name]/sessions/[sessionName]/page.tsx:762

Silent fallback to current time makes it impossible to detect when backend fails to provide timestamps. Consider adding console.warn for debugging.


Minor Issues

5. Unrelated Makefile Fix

The Makefile change (fixing port forwarding) is unrelated to timestamp handling. This should be in a separate PR or mentioned in the PR description.


6. TypeScript Could Be More Defensive

File: components/frontend/src/hooks/use-agui-stream.ts:173

Consider adding immediate fallback at the point of capture rather than requiring downstream checks.


Positive Highlights

✅ Excellent timestamp propagation design - Timestamps are added at the source and preserved through the entire pipeline.

✅ Backward compatibility - All frontend code includes fallbacks for legacy messages without timestamps.

✅ Consistent implementation - Timestamp handling is applied uniformly across all event types.

✅ Proper type definitions - TypeScript types correctly updated with optional timestamp fields.

✅ RFC3339Nano format - Using high-precision timestamps ensures correct message ordering.

✅ Strategic timestamp placement - Adding timestamps in RouteAGUIEvent ensures all events get timestamps regardless of source.


Recommendations

Priority 1 (Must Fix Before Merge)

  1. Add error handling for type assertions in backend code - Replace all underscore ignores with proper error checking and logging
  2. Add basic test coverage for timestamp propagation in backend and frontend

Priority 2 (Should Fix Before Merge)

  1. Add logging for timestamp fallbacks in frontend to detect backend issues
  2. Document timestamp format in code comments at injection points
  3. Split Makefile fix into separate commit or mention in PR description

Code Quality Checks

Backend Standards

  • ✅ No panics in production code
  • ⚠️ Error handling needs improvement
  • ✅ Logging includes context
  • ⚠️ Type-safe access pattern not followed
  • ✅ No token/sensitive data in logs

Frontend Standards

  • ✅ Zero any types in changes
  • ✅ Using proper TypeScript types
  • ✅ React Query patterns not affected
  • ✅ Component structure maintained

Security Review

✅ No security issues identified


Performance Considerations

✅ Performance impact is negligible


Final Verdict

Status: ⚠️ Requires Changes Before Merge

This is a solid implementation of timestamp tracking that addresses a real UX issue. However, the error handling violations and lack of test coverage need to be addressed before merging to maintain code quality standards.

Estimated effort: 2-3 hours (add error handling + basic tests)

Merge recommendation: Approve after addressing Priority 1 items.


🔍 View AI decision process (logs available for 90 days)

📋 View memory system files loaded (click to expand)

What Amber Loaded for Code Review

Amber automatically loaded these repository standards from the memory system:

  1. CLAUDE.md - Master project instructions, development standards
  2. backend-development.md - Go backend, K8s integration patterns
  3. frontend-development.md - NextJS, Shadcn UI, React Query patterns
  4. security-standards.md - Auth, RBAC, token handling
  5. k8s-client-usage.md - User token vs service account patterns
  6. error-handling.md - Consistent error patterns
  7. react-query-usage.md - Data fetching patterns

Impact: This review used your repository's specific code quality standards, security patterns, and best practices from the memory system (PRs #359, #360) - not just generic code review guidelines.

@andybraren
Copy link
Collaborator Author

Timestamps for each message are now passing through the eventstream and appearing in the UI correctly, even after refreshing:

2026-02-02 01 29 05

- Introduced constants for AG-UI timestamp formats in `agui.go` to ensure uniformity in timestamp handling.
- Updated various components (`agui_proxy.go`, `agui.go`, `legacy_translator.go`) to utilize the new timestamp constants, improving accuracy and reliability in event timestamping.

This change enhances the overall consistency of timestamp formatting across the application.
@github-actions
Copy link
Contributor

github-actions bot commented Feb 2, 2026

Claude Code Review

Summary

This PR adds proper timestamp handling to AGUI (AG-UI) message streaming to fix the issue where all message timestamps update to the most recent message time. The implementation adds timestamp constants, ensures timestamps are captured from events at the backend, and propagates them through to the frontend display layer.

Overall Assessment: Good implementation with consistent patterns, but has several issues that should be addressed before merge.


Issues by Severity

🚫 Blocker Issues

None - No critical blocking issues that prevent merge.


🔴 Critical Issues

1. Missing Tests for Critical Timestamp Logic

Location: All backend files (agui.go, agui_proxy.go, compaction.go)

The timestamp logic is critical for correctness but has zero test coverage. This is particularly concerning because:

  • Timestamp handling occurs in 3 different backend files with slightly different patterns
  • The fallback logic (event["timestamp"] == nil || event["timestamp"] == "") is repeated 5+ times
  • No validation that timestamps are in RFC3339Nano format
  • No test that timestamps are preserved through the message compaction pipeline

Recommendation: Add unit tests covering:

  • Timestamp preservation through RouteAGUIEvent
  • Timestamp preservation through handleStreamedEvent
  • Timestamp preservation through MessageCompactor
  • Fallback behavior when timestamp is missing
  • Format validation for AGUITimestampFormat

Example test structure:

func TestRouteAGUIEvent_PreservesTimestamp(t *testing.T) {
    expectedTime := "2024-01-15T10:30:45.123456789Z"
    event := map[string]interface{}{
        "type": types.EventTypeTextMessageStart,
        "timestamp": expectedTime,
    }
    // ... test that timestamp is preserved
}

func TestRouteAGUIEvent_AddsTimestampWhenMissing(t *testing.T) {
    event := map[string]interface{}{
        "type": types.EventTypeTextMessageStart,
    }
    // ... test that timestamp is added in RFC3339Nano format
}

2. Code Duplication - Repeated Timestamp Logic

Location:

  • components/backend/websocket/agui.go:127-129
  • components/backend/websocket/agui.go:179-181
  • components/backend/websocket/agui_proxy.go:285-287

The same 3-line timestamp check/set pattern is repeated verbatim in multiple locations:

if event["timestamp"] == nil || event["timestamp"] == "" {
    event["timestamp"] = time.Now().UTC().Format(types.AGUITimestampFormat)
}

Recommendation: Extract to a helper function following DRY principle:

// ensureEventTimestamp adds a timestamp to the event if not present
func ensureEventTimestamp(event map[string]interface{}) {
    if event["timestamp"] == nil || event["timestamp"] == "" {
        event["timestamp"] = time.Now().UTC().Format(types.AGUITimestampFormat)
    }
}

This improves maintainability and ensures consistency across all timestamp handling.


🟡 Major Issues

3. Inconsistent Optional Field Handling

Location: components/backend/websocket/compaction.go:122, 234

The code extracts timestamp with blank identifier:

timestamp, _ := event["timestamp"].(string)

This silently ignores type assertion failures. While this may be intentional for optional fields, it's inconsistent with the project's type-safety standards documented in CLAUDE.md.

Recommendation: Check the boolean return and log unexpected type mismatches:

timestamp, ok := event["timestamp"].(string)
if \!ok && event["timestamp"] \!= nil {
    log.Printf("Warning: timestamp field has unexpected type: %T", event["timestamp"])
}

4. Frontend: Potential Race Condition in Timestamp Assignment

Location: components/frontend/src/app/projects/[name]/sessions/[sessionName]/page.tsx:762-766

The code uses msg.timestamp || new Date().toISOString() as a fallback, but this creates inconsistent timestamp sources:

  • New messages: Server-provided RFC3339Nano timestamp
  • Legacy messages: Client-generated ISO string timestamp

While this is noted in comments as intentional for backward compatibility, it could cause subtle ordering issues if comparing timestamps across new/legacy messages.

Recommendation: Add a comment explaining the risk and consider normalizing all timestamps to UTC in a preprocessing step.


5. Unused AGUIMetadataTimestampFormat Constant

Location: components/backend/types/agui.go:20

The PR adds AGUIMetadataTimestampFormat = time.RFC3339 but never uses it. According to the comment, it's meant for "AGUIRunMetadata.StartedAt, AGUIRunMetadata.FinishedAt" but the code doesn't actually use this constant.

Recommendation: Either:

  1. Use it in the relevant locations (search for StartedAt, FinishedAt and update to use the constant), OR
  2. Remove it and add it in a future PR when actually needed (YAGNI principle)

🔵 Minor Issues

6. Missing Error Handling Documentation

Location: components/backend/websocket/compaction.go:242-245

The code updates currentMessage.Timestamp only if not already set:

if c.currentMessage.Timestamp == "" && timestamp \!= "" {
    c.currentMessage.Timestamp = timestamp
}

However, there's no comment explaining WHY we preserve existing timestamps. This could be important for understanding message lifecycle.

Recommendation: Add a comment:

// Preserve the earliest timestamp (from TEXT_MESSAGE_START) rather than 
// overwriting with tool call timestamps
if c.currentMessage.Timestamp == "" && timestamp \!= "" {
    c.currentMessage.Timestamp = timestamp
}

7. Indentation Inconsistency in Frontend

Location: components/frontend/src/app/projects/[name]/sessions/[sessionName]/components/welcome-experience.tsx:401-405

The indentation was corrected from an incorrect level, but the diff shows the content block now has inconsistent alignment. This appears to be a pre-existing formatting issue that got exposed during the edit.

Recommendation: Run npm run lint -- --fix on the frontend to auto-fix formatting.


8. Type Safety: Timestamp Field is Optional

Location: components/frontend/src/types/agui.ts:329

The currentMessage.timestamp field is marked optional (timestamp?: string), but based on the backend changes, it should ALWAYS be present for new messages after this PR.

Recommendation: Consider making it required in the type definition since the backend guarantees it:

timestamp: string  // Always present after backend fix

Or add a comment if it needs to remain optional for backward compatibility:

timestamp?: string  // Optional for backward compatibility with legacy messages

Positive Highlights

Excellent Documentation: The new timestamp format constants have comprehensive JSDoc-style comments explaining when to use each format and why nanosecond precision matters.

Consistent Format Usage: Good use of named constants (AGUITimestampFormat) rather than inline format strings.

Comprehensive Frontend Updates: All relevant frontend locations were updated to use the new timestamp field (8 locations in use-agui-stream.ts, 8 locations in page.tsx).

Backward Compatibility: Thoughtful fallbacks (msg.timestamp || new Date().toISOString()) ensure old messages still display correctly.

Code Comments: Good inline comments explaining the purpose of timestamp captures (e.g., "Capture timestamp from event").

Minimal Scope: Changes are focused on the specific problem (timestamp handling) without introducing unrelated refactoring.


Recommendations

Priority 1 (Should Fix Before Merge)

  1. Add unit tests for timestamp preservation logic (Critical Issue Outcome: Reduce Refinement Time with agent System #1)
  2. Extract duplicate timestamp logic to helper function (Critical Issue Epic: RAT Architecture & Design #2)
  3. Use or remove AGUIMetadataTimestampFormat constant (Major Issue Epic: Jira Integration & Workflow #5)

Priority 2 (Nice to Have)

  1. Improve type assertion error handling in compaction.go (Major Issue Epic: Data Source Integration #3)
  2. Add clarifying comment to timestamp preservation logic (Minor Issue Epic: Testing & Validation #6)
  3. Run npm run lint -- --fix to fix formatting (Minor Issue Test: Automation Workflow Validation #7)
  4. Document timestamp optionality decision in types (Minor Issue Test: Updated Workflow Validation #8)

Testing Strategy

Since the PR notes "Still need to test this with an updated backend", recommend:

  1. Deploy to dev environment
  2. Create a new session and verify message timestamps are unique
  3. Verify old sessions with legacy messages still display correctly
  4. Check that rapid-fire messages (< 1 second apart) have distinct timestamps

Code Quality Assessment

Category Rating Notes
Correctness ✅ Good Logic appears sound, but lacks test coverage
Security ✅ Good No security implications detected
Performance ✅ Good No performance concerns (timestamp ops are cheap)
Maintainability ⚠️ Fair Code duplication reduces maintainability
Testing ❌ Poor No tests for critical timestamp logic
Documentation ✅ Good Excellent inline documentation

Overall: This PR solves a real user-facing bug with a solid approach. The main concerns are lack of test coverage and code duplication, both of which should be addressed before merge to maintain codebase quality standards.


🔍 View AI decision process (logs available for 90 days)

📋 View memory system files loaded (click to expand)

What Amber Loaded for Code Review

Amber automatically loaded these repository standards from the memory system:

  1. CLAUDE.md - Master project instructions, development standards
  2. backend-development.md - Go backend, K8s integration patterns
  3. frontend-development.md - NextJS, Shadcn UI, React Query patterns
  4. security-standards.md - Auth, RBAC, token handling
  5. k8s-client-usage.md - User token vs service account patterns
  6. error-handling.md - Consistent error patterns
  7. react-query-usage.md - Data fetching patterns

Impact: This review used your repository's specific code quality standards, security patterns, and best practices from the memory system (PRs #359, #360) - not just generic code review guidelines.

@Gkrumbach07 Gkrumbach07 merged commit 6733c5c into ambient-code:main Feb 2, 2026
21 of 22 checks passed
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.

4 participants