Skip to content

feat: add realtime turn logging to logging plugin#2339

Merged
akshaydeo merged 3 commits intov1.5.0from
feature/03-27-feat_add_realtime_turn_logging_to_logging_plugin
Apr 7, 2026
Merged

feat: add realtime turn logging to logging plugin#2339
akshaydeo merged 3 commits intov1.5.0from
feature/03-27-feat_add_realtime_turn_logging_to_logging_plugin

Conversation

@danpiths
Copy link
Copy Markdown
Collaborator

@danpiths danpiths commented Mar 27, 2026

Summary

Extends the logging plugin to handle realtime turn requests. Adds
realtime-specific pre/post hook handling, audio transcript backfill from raw
request events, output message extraction, session log delegation, realtime
metadata merging, and session summary polling. Also adds a realtime skip guard
to the Maxim observability plugin.

Changes

  • Enhanced PreLLMHook to detect RealtimeRequest and set
    object = "realtime.turn", extract params from ResponsesRequest
  • Enhanced PostLLMHook to set ParentRequestID from realtime session context,
    route to applyRealtimeOutputToEntry
  • Added applyRealtimeOutputToEntry for extracting usage, output message, and
    raw request/response from realtime turns
  • Added extractRealtimeInputHistoryFromRawRequest for rebuilding chat message
    history from raw events (audio transcripts, conversation items)
  • Added extractRealtimeOutputMessage for building ChatMessage from
    ResponsesMessage list
  • Added mergeRealtimeMetadata for propagating realtime context keys to log
    metadata
  • Added GetSessionLogs delegation to logstore with pagination defaults
  • Added GetSessionSummary delegation to logstore for lightweight polling
  • Added extractRealtimeInputHistory and helpers for mapping Responses
    roles/content to chat history
  • Tests: audio transcript backfill, placeholder insertion for missing
    transcripts, TotalTokens fallback computation
  • Added realtime skip guard to Maxim plugin PreLLMHook and PostLLMHook
    realtime requests bypass Maxim's trace/generation lifecycle since they use
    Bifrost's own turn-scoped pipeline

Type of change

  • Bug fix
  • Feature
  • Refactor
  • Documentation
  • Chore/CI

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • Providers/Integrations
  • Plugins
  • UI (Next.js)
  • Docs

How to test

cd plugins/logging
go build ./...
go test ./... -run TestApplyRealtime
go test ./... -run TestExtractRealtime

cd ../maxim
go build ./...
go test ./... -run TestPreLLMHookSkipsRealtime
go test ./... -run TestPostLLMHookSkipsRealtime

Screenshots/Recordings

N/A

Breaking changes

  • Yes
  • No

Related issues

N/A

Security considerations

No new security implications — realtime metadata follows existing log redaction
patterns. Maxim plugin skip prevents realtime events from creating unexpected
external traces.

Checklist

  • I read docs/contributing/README.md and followed the guidelines
  • I added/updated tests where appropriate
  • I updated documentation where needed
  • I verified builds succeed (Go and UI)
  • I verified the CI pipeline passes locally if applicable

@danpiths danpiths requested a review from akshaydeo March 27, 2026 17:20
@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 27, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: af8b9654-49dc-44ac-b5ab-a44c4c2c0f9d

📥 Commits

Reviewing files that changed from the base of the PR and between 06d48bd and b3aac17.

📒 Files selected for processing (5)
  • plugins/logging/main.go
  • plugins/logging/operations.go
  • plugins/logging/operations_test.go
  • plugins/logging/utils.go
  • plugins/maxim/main.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • plugins/maxim/main.go
  • plugins/logging/main.go

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Session log retrieval and summaries; realtime-aware enrichment of metadata, input history, transcripts, tool outputs, token usage, and content summaries; realtime session linking and parent resolution improvements.
  • Bug Fixes

    • Realtime requests are excluded from standard streaming/tracing final-chunk paths and routed through dedicated realtime output/backfill flows to preserve transcripts, tool outputs, and error backfills.
  • Tests

    • New unit tests validating realtime parsing, merging, backfilling, and history merging behaviors.

Walkthrough

Pre/Post LLM hooks and logging were extended to recognize realtime requests, merge realtime metadata and session/parent IDs, bypass standard streaming/tracing for realtime, and route realtime results to new processors that backfill transcripts, rebuild input history, extract usage, and expose session retrieval APIs.

Changes

Cohort / File(s) Summary
Logging hooks & entry flow
plugins/logging/main.go, plugins/maxim/main.go
Pre-LLM: mark realtime turns, set object/params, merge realtime metadata, prefer direct realtime parent/session IDs. Post-LLM: exclude realtime from tracer/streaming-final branches, set pending parent from realtime session ctx, merge realtime metadata, and route realtime results to realtime handlers.
Realtime processing & session APIs
plugins/logging/operations.go
Added applyRealtimeOutputToEntry, realtime token-usage extraction, output-message assembly, RawRequest/RawResponse normalization/backfill, input-history extraction/merge/dedup, helpers for flattening/dereferencing realtime events, and GetSessionLogs/GetSessionSummary.
Unit tests for realtime logic
plugins/logging/operations_test.go
New tests covering transcript backfill (including missing-transcript sentinel), tool/function outputs, ToolCallID propagation, content-summary composition, and merging with existing history.
Utilities, interfaces & helpers
plugins/logging/utils.go
Extended logging.LogManager / PluginLogManager with session APIs and validation; enhanced extractInputHistory for realtime ResponsesRequest; added realtime→chat conversion helpers and mergeRealtimeMetadata.
Imports, constants & small guards
plugins/logging/...
Added imports (e.g., strings), realtimeMissingTranscriptText constant, and control-flow guards/early returns to exclude realtime requests from standard tracing/streaming flows.

Sequence Diagram

sequenceDiagram
    participant Client
    participant PreLLM as Pre-LLM Hook
    participant LLM
    participant PostLLM as Post-LLM Hook
    participant RealtimeProc as Realtime Processor
    participant LogStore

    Client->>PreLLM: send request (realtime)
    PreLLM->>PreLLM: mark realtime, set object/params, merge metadata, derive parent/session IDs
    PreLLM-->>LLM: forward request
    LLM-->>PostLLM: return result
    PostLLM->>PostLLM: detect realtime, set pending parent ID, merge metadata
    PostLLM->>RealtimeProc: applyRealtimeOutputToEntry(entry, result)
    RealtimeProc->>RealtimeProc: extract transcripts, normalize raw request/response, rebuild input history, set usage
    RealtimeProc-->>PostLLM: enriched entry
    PostLLM->>LogStore: persist enriched log entry
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Poem

🐰 I hop through realtime logs with glee,
I stitch lost transcripts so they're free,
Parents found and messages aligned,
Tokens counted, histories combined,
A rabbit tidies logs like tea.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.41% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely summarizes the main change: adding realtime turn logging capability to the logging plugin.
Description check ✅ Passed The description is comprehensive and well-structured, covering summary, detailed changes, type, affected areas, testing instructions, breaking changes, and security considerations with proper template compliance.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/03-27-feat_add_realtime_turn_logging_to_logging_plugin

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Mar 27, 2026

Confidence Score: 5/5

Safe to merge — no blocking issues found

All prior P0/P1 concerns from previous review threads are resolved; the one remaining observation is a P2 style note on fallthrough behavior in collectRealtimeRawTextFragments that does not affect correctness for the realtime protocol in practice

No files require special attention; plugins/logging/operations.go has one minor style note

Important Files Changed

Filename Overview
plugins/logging/main.go Extends PreLLMHook/PostLLMHook for realtime turns (object='realtime.turn', applyRealtimeOutputToEntry routing, metadata merge), adds GetSessionLogs/GetSessionSummary delegations with input validation
plugins/logging/operations.go Adds applyRealtimeOutputToEntry, transcript backfill pipeline, extractRealtimeOutputMessage, and mergeRealtimeInputHistory with deduplication; minor fallthrough style note in collectRealtimeRawTextFragments
plugins/logging/operations_test.go Adds 7 well-structured realtime tests: audio transcript backfill, missing-transcript placeholder, and history merging with deduplication
plugins/logging/utils.go Adds extractRealtimeInputHistory, content/role helpers, mergeRealtimeMetadata, and tool output extraction utilities used by both Pre and PostLLMHook paths
plugins/maxim/main.go Adds realtime skip guard at the top of PreLLMHook and PostLLMHook, cleanly preventing spurious Maxim traces for realtime turns

Reviews (15): Last reviewed commit: "feat: add realtime turn logging to loggi..." | Re-trigger Greptile

Comment thread plugins/logging/utils.go Outdated
Comment thread plugins/logging/main.go Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
plugins/logging/operations.go (1)

808-817: Consider populating ChatToolMessage.ToolCallID for tool outputs.

The ChatToolMessage is initialized as an empty struct, but tool outputs typically have a call_id that links them to the original function call. This could help with log correlation.

♻️ Suggested enhancement
 			case event.Item.Type == "function_call_output":
 				if content := extractRealtimeRawItemContent(event.Item); content != "" {
+					var toolCallID *string
+					if event.Item.CallID != "" {
+						toolCallID = schemas.Ptr(event.Item.CallID)
+					}
 					messages = append(messages, schemas.ChatMessage{
 						Role: schemas.ChatMessageRoleTool,
 						Content: &schemas.ChatMessageContent{
 							ContentStr: schemas.Ptr(content),
 						},
-						ChatToolMessage: &schemas.ChatToolMessage{},
+						ChatToolMessage: &schemas.ChatToolMessage{
+							ToolCallID: toolCallID,
+						},
 					})
 				}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/logging/operations.go` around lines 808 - 817, The ChatToolMessage is
being created empty when handling event.Item.Type == "function_call_output";
populate ChatToolMessage.ToolCallID with the call identifier from the event item
(e.g., event.Item.CallID or event.Item.CallId) so the appended
schemas.ChatMessage links to the original function call; update the messages
append block (where extractRealtimeRawItemContent is used and a
schemas.ChatMessage is constructed) to set ChatToolMessage.ToolCallID = &callID
(or appropriate pointer) after extracting the call id from event.Item and handle
missing/empty call ids gracefully.
plugins/logging/utils.go (1)

533-541: Redundant condition in content block extraction.

Lines 537-538 check block.ResponsesOutputMessageContentText != nil && block.Text != nil, but block.Text was already checked and appended on lines 535-536. This case will never be reached.

♻️ Suggested fix
 	for _, block := range content.ContentBlocks {
 		switch {
 		case block.Text != nil && strings.TrimSpace(*block.Text) != "":
 			parts = append(parts, strings.TrimSpace(*block.Text))
-		case block.ResponsesOutputMessageContentText != nil && block.Text != nil && strings.TrimSpace(*block.Text) != "":
-			parts = append(parts, strings.TrimSpace(*block.Text))
 		case block.ResponsesOutputMessageContentRefusal != nil && strings.TrimSpace(block.Refusal) != "":
 			parts = append(parts, strings.TrimSpace(block.Refusal))
 		}
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/logging/utils.go` around lines 533 - 541, The second switch case is
redundant because it checks block.Text again; update the logic in the loop over
content.ContentBlocks to either remove that case or, if you intended to handle
the nested ResponsesOutputMessageContentText payload, change the condition to
check block.ResponsesOutputMessageContentText's own text field (e.g.,
block.ResponsesOutputMessageContentText.Text != nil &&
strings.TrimSpace(*block.ResponsesOutputMessageContentText.Text) != "") and
append the trimmed value; ensure you still keep the first case for block.Text
and the refusal case for block.ResponsesOutputMessageContentRefusal.
plugins/logging/operations_test.go (1)

315-337: Use schemas.Ptr() instead of the address operator for consistency.

Per repository conventions, prefer schemas.Ptr() (or bifrost.Ptr()) over & for creating pointers to values. This applies to assistantText, messageType, and assistantRole.

♻️ Suggested refactor
 func TestApplyRealtimeOutputToEntryBackfillsUserTranscriptFromRawRequest(t *testing.T) {
 	plugin := &LoggerPlugin{}
 	entry := &logstore.Log{}

-	assistantText := "Hello!"
-	messageType := schemas.ResponsesMessageTypeMessage
-	assistantRole := schemas.ResponsesInputMessageRoleAssistant
 	result := &schemas.BifrostResponse{
 		ResponsesResponse: &schemas.BifrostResponsesResponse{
 			Output: []schemas.ResponsesMessage{{
-				Type: &messageType,
-				Role: &assistantRole,
+				Type: schemas.Ptr(schemas.ResponsesMessageTypeMessage),
+				Role: schemas.Ptr(schemas.ResponsesInputMessageRoleAssistant),
 				Content: &schemas.ResponsesMessageContent{
-					ContentStr: &assistantText,
+					ContentStr: schemas.Ptr("Hello!"),
 				},
 			}},

Based on learnings: "In the maximhq/bifrost repository, prefer using bifrost.Ptr() to create pointers instead of the address operator (&) even when & would be valid syntactically."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/logging/operations_test.go` around lines 315 - 337, Replace direct
&-addressing with the repository pointer helper in the test: for the values used
in TestApplyRealtimeOutputToEntryBackfillsUserTranscriptFromRawRequest
(assistantText, messageType, assistantRole) call schemas.Ptr(...) to create
pointers instead of using &assistantText, &messageType, &assistantRole so the
ResponsesMessage fields use schemas.Ptr(...) consistently; update the
instantiation inside the result variable where
ResponsesMessage.Content.ContentStr and ResponsesMessage.Type/Role are assigned
to use schemas.Ptr(...) calls.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@plugins/logging/operations_test.go`:
- Around line 315-337: Replace direct &-addressing with the repository pointer
helper in the test: for the values used in
TestApplyRealtimeOutputToEntryBackfillsUserTranscriptFromRawRequest
(assistantText, messageType, assistantRole) call schemas.Ptr(...) to create
pointers instead of using &assistantText, &messageType, &assistantRole so the
ResponsesMessage fields use schemas.Ptr(...) consistently; update the
instantiation inside the result variable where
ResponsesMessage.Content.ContentStr and ResponsesMessage.Type/Role are assigned
to use schemas.Ptr(...) calls.

In `@plugins/logging/operations.go`:
- Around line 808-817: The ChatToolMessage is being created empty when handling
event.Item.Type == "function_call_output"; populate ChatToolMessage.ToolCallID
with the call identifier from the event item (e.g., event.Item.CallID or
event.Item.CallId) so the appended schemas.ChatMessage links to the original
function call; update the messages append block (where
extractRealtimeRawItemContent is used and a schemas.ChatMessage is constructed)
to set ChatToolMessage.ToolCallID = &callID (or appropriate pointer) after
extracting the call id from event.Item and handle missing/empty call ids
gracefully.

In `@plugins/logging/utils.go`:
- Around line 533-541: The second switch case is redundant because it checks
block.Text again; update the logic in the loop over content.ContentBlocks to
either remove that case or, if you intended to handle the nested
ResponsesOutputMessageContentText payload, change the condition to check
block.ResponsesOutputMessageContentText's own text field (e.g.,
block.ResponsesOutputMessageContentText.Text != nil &&
strings.TrimSpace(*block.ResponsesOutputMessageContentText.Text) != "") and
append the trimmed value; ensure you still keep the first case for block.Text
and the refusal case for block.ResponsesOutputMessageContentRefusal.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0ddb52e6-7bc3-4543-a29d-5ea46f02ab71

📥 Commits

Reviewing files that changed from the base of the PR and between 2f86e4c and 81edf1b.

📒 Files selected for processing (4)
  • plugins/logging/main.go
  • plugins/logging/operations.go
  • plugins/logging/operations_test.go
  • plugins/logging/utils.go

@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_turn_logging_to_logging_plugin branch from 81edf1b to f9bb3b3 Compare March 30, 2026 10:24
@danpiths danpiths force-pushed the feature/03-27-feat_add_session_log_storage_and_realtime_request_normalization branch from 2f86e4c to 16d59fd Compare March 30, 2026 10:24
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
plugins/logging/main.go (1)

754-756: Double merge of realtime metadata is intentional.

The metadata is merged once in PreLLMHook (line 584) and again here in PostLLMHook. This appears intentional to capture realtime context keys (e.g., provider session ID) that may only be available after the provider response. Consider adding a brief comment clarifying this design.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/logging/main.go` around lines 754 - 756, Add a short clarifying
comment near the second merge of realtime metadata to indicate the double-merge
is intentional: explain that metadata is first merged in PreLLMHook and then
merged again in PostLLMHook to capture realtime provider-specific keys (e.g.,
provider session ID) that become available only after the provider response;
annotate the code around entry.MetadataParsed =
mergeRealtimeMetadata(entry.MetadataParsed, ctx) and reference the
PreLLMHook/PostLLMHook merge points so future readers understand the design and
avoid accidental removal.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@plugins/logging/main.go`:
- Around line 754-756: Add a short clarifying comment near the second merge of
realtime metadata to indicate the double-merge is intentional: explain that
metadata is first merged in PreLLMHook and then merged again in PostLLMHook to
capture realtime provider-specific keys (e.g., provider session ID) that become
available only after the provider response; annotate the code around
entry.MetadataParsed = mergeRealtimeMetadata(entry.MetadataParsed, ctx) and
reference the PreLLMHook/PostLLMHook merge points so future readers understand
the design and avoid accidental removal.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2fa40d46-3a0f-4923-aea2-36e470c6310d

📥 Commits

Reviewing files that changed from the base of the PR and between 81edf1b and f9bb3b3.

📒 Files selected for processing (4)
  • plugins/logging/main.go
  • plugins/logging/operations.go
  • plugins/logging/operations_test.go
  • plugins/logging/utils.go
✅ Files skipped from review due to trivial changes (1)
  • plugins/logging/operations_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • plugins/logging/utils.go
  • plugins/logging/operations.go

@danpiths danpiths force-pushed the feature/03-27-feat_add_session_log_storage_and_realtime_request_normalization branch from 16d59fd to edba174 Compare March 30, 2026 12:49
@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_turn_logging_to_logging_plugin branch from f9bb3b3 to 40f5251 Compare March 30, 2026 12:49
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
plugins/logging/utils.go (1)

486-491: Consider using bifrost.Ptr() for pointer creation.

The code uses schemas.Ptr(content) to create string pointers. Based on repository learnings, bifrost.Ptr() is the preferred helper for creating pointers across the codebase.

However, if schemas.Ptr is an alias or equivalent implementation, this is acceptable. Please verify consistency with other files in this package.

Also applies to: 500-506

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/logging/utils.go` around lines 486 - 491, The code creates string
pointers using schemas.Ptr(content) when building schemas.ChatMessageContent
inside the messages append; replace schemas.Ptr(...) with bifrost.Ptr(...) for
consistency across the codebase and update imports to include the bifrost
package, or alternatively confirm that schemas.Ptr is an exact alias of
bifrost.Ptr and document/replace other occurrences (notably the similar blocks
around the schemas.ChatMessageContent construction at lines ~500-506) to keep
pointer helpers consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plugins/logging/operations.go`:
- Around line 727-770: applyRealtimeOutputToEntry extracts
RawRequest/RawResponse regardless of p.disableContentLogging; add the same
content-logging gate used in applyNonStreamingOutputToEntry so raw
request/response are only populated when content logging is allowed (i.e., check
if p.disableContentLogging == nil || !*p.disableContentLogging before handling
extraFields.RawRequest and extraFields.RawResponse and before calling
extractRealtimeInputHistoryFromRawRequest); update references inside
applyRealtimeOutputToEntry to only set entry.RawRequest,
entry.InputHistoryParsed, and entry.RawResponse when the gate permits.

---

Nitpick comments:
In `@plugins/logging/utils.go`:
- Around line 486-491: The code creates string pointers using
schemas.Ptr(content) when building schemas.ChatMessageContent inside the
messages append; replace schemas.Ptr(...) with bifrost.Ptr(...) for consistency
across the codebase and update imports to include the bifrost package, or
alternatively confirm that schemas.Ptr is an exact alias of bifrost.Ptr and
document/replace other occurrences (notably the similar blocks around the
schemas.ChatMessageContent construction at lines ~500-506) to keep pointer
helpers consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e32eb5f3-9082-4a61-a2e2-023feb300314

📥 Commits

Reviewing files that changed from the base of the PR and between f9bb3b3 and 40f5251.

📒 Files selected for processing (4)
  • plugins/logging/main.go
  • plugins/logging/operations.go
  • plugins/logging/operations_test.go
  • plugins/logging/utils.go
✅ Files skipped from review due to trivial changes (1)
  • plugins/logging/operations_test.go

Comment thread plugins/logging/operations.go
@danpiths danpiths force-pushed the feature/03-27-feat_add_session_log_storage_and_realtime_request_normalization branch from edba174 to a3e85c4 Compare March 30, 2026 14:50
@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_turn_logging_to_logging_plugin branch from 40f5251 to 44d1515 Compare March 30, 2026 14:50
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
plugins/logging/utils.go (1)

639-648: Minor: Duplicate context lookup for realtime session ID.

The set function at line 639 already calls bifrost.GetStringFromContext(ctx, schemas.BifrostContextKeyRealtimeSessionID), but line 643 performs the same lookup again. Consider capturing the value once to avoid the redundant call.

♻️ Suggested optimization
 	set("realtime_session_id", schemas.BifrostContextKeyRealtimeSessionID)
 	set("provider_session_id", schemas.BifrostContextKeyRealtimeProviderSessionID)
 	set("realtime_source", schemas.BifrostContextKeyRealtimeSource)
 	set("realtime_event_type", schemas.BifrostContextKeyRealtimeEventType)
-	if bifrost.GetStringFromContext(ctx, schemas.BifrostContextKeyRealtimeSessionID) != "" {
+	if metadata != nil && metadata["realtime_session_id"] != nil {
 		if metadata == nil {
 			metadata = make(map[string]interface{})
 		}
 		metadata["realtime"] = true
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/logging/utils.go` around lines 639 - 648, The code redundantly calls
bifrost.GetStringFromContext(ctx, schemas.BifrostContextKeyRealtimeSessionID)
twice (once inside set and again in the if); capture the realtime session ID
once into a local variable (e.g., realtimeID) before the set calls and reuse
that variable in the conditional that sets metadata["realtime"]=true, updating
references around the set(...) invocations (functions: set,
bifrost.GetStringFromContext, constant:
schemas.BifrostContextKeyRealtimeSessionID, variable: metadata) to avoid the
duplicate lookup while keeping identical behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plugins/logging/utils.go`:
- Around line 500-506: The ChatToolMessage is being created without copying the
originating tool call ID, so update the code that builds the tool message (in
extractRealtimeToolOutputContent where messages = append(messages,
schemas.ChatMessage{...}) and the similar site referenced in operations.go
around the ChatMessage construction) to populate ChatToolMessage.ToolCallID from
the input ResponsesToolMessage.CallID (e.g., set ChatToolMessage:
&schemas.ChatToolMessage{ToolCallID: item.ResponsesToolMessage.CallID}); ensure
you handle a nil ResponsesToolMessage gracefully before accessing CallID to
avoid panics.

---

Nitpick comments:
In `@plugins/logging/utils.go`:
- Around line 639-648: The code redundantly calls
bifrost.GetStringFromContext(ctx, schemas.BifrostContextKeyRealtimeSessionID)
twice (once inside set and again in the if); capture the realtime session ID
once into a local variable (e.g., realtimeID) before the set calls and reuse
that variable in the conditional that sets metadata["realtime"]=true, updating
references around the set(...) invocations (functions: set,
bifrost.GetStringFromContext, constant:
schemas.BifrostContextKeyRealtimeSessionID, variable: metadata) to avoid the
duplicate lookup while keeping identical behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8aef1e5e-175f-448d-bd99-893d82555d3a

📥 Commits

Reviewing files that changed from the base of the PR and between 40f5251 and 44d1515.

📒 Files selected for processing (4)
  • plugins/logging/main.go
  • plugins/logging/operations.go
  • plugins/logging/operations_test.go
  • plugins/logging/utils.go
✅ Files skipped from review due to trivial changes (1)
  • plugins/logging/operations_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • plugins/logging/operations.go
  • plugins/logging/main.go

Comment thread plugins/logging/utils.go
@danpiths danpiths force-pushed the feature/03-27-feat_add_session_log_storage_and_realtime_request_normalization branch from a3e85c4 to 78a4b1f Compare March 30, 2026 17:00
@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_turn_logging_to_logging_plugin branch from 44d1515 to 3062e94 Compare March 30, 2026 17:00
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plugins/logging/utils.go`:
- Around line 531-543: The current helper returns ContentStr when ContentStr is
non-nil even if it trims to empty, which prevents falling back to content
blocks; change the guard in the function that reads ContentStr to require
non-empty trimmed content (e.g., if content.ContentStr != nil &&
strings.TrimSpace(*content.ContentStr) != "" { ... }) so that when ContentStr is
allocated but empty the code continues to assemble parts from ContentBlocks;
make the same change for
ResponsesToolCallOutputStr/ResponsesOutputMessageContentRefusal code paths
(ensure you check trimmed string != "" before returning and only then skip block
fallback).
- Around line 139-146: In GetSessionLogs (PluginLogManager) the sessionID is
trimmed only for validation but the original value is forwarded; trim/normalize
sessionID (e.g., strings.TrimSpace(sessionID)) into a local variable after
validation and pass that normalized value to p.plugin.GetSessionLogs(ctx,
normalizedSessionID, *pagination) so callers like " abc " resolve to the correct
session key while keeping the existing pagination nil check.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 31fe7a48-4588-4802-8b12-a53d4f272c19

📥 Commits

Reviewing files that changed from the base of the PR and between 44d1515 and 3062e94.

📒 Files selected for processing (4)
  • plugins/logging/main.go
  • plugins/logging/operations.go
  • plugins/logging/operations_test.go
  • plugins/logging/utils.go
✅ Files skipped from review due to trivial changes (1)
  • plugins/logging/operations.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • plugins/logging/main.go
  • plugins/logging/operations_test.go

Comment thread plugins/logging/utils.go
Comment thread plugins/logging/utils.go
@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_turn_logging_to_logging_plugin branch from 3062e94 to abc9e04 Compare March 31, 2026 06:16
@danpiths danpiths force-pushed the feature/03-27-feat_add_session_log_storage_and_realtime_request_normalization branch 2 times, most recently from 51db921 to c180d40 Compare March 31, 2026 08:00
@danpiths danpiths force-pushed the feature/03-27-feat_add_session_log_storage_and_realtime_request_normalization branch from c180d40 to aee487f Compare April 3, 2026 08:03
@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_turn_logging_to_logging_plugin branch from 5cc0b46 to 79fd370 Compare April 3, 2026 08:03
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plugins/logging/main.go`:
- Around line 740-744: The code reads BifrostContextKeyRealtimeSessionID from
context (via bifrost.GetStringFromContext) to set pending.ParentRequestID for
realtime requests, but that context key is never set; update the realtime
request entry path to set the context key using the session ID from OpenAI
realtime events (bifrostEvent.Session.ID) before the code that checks it, or
remove the retrieval. Specifically, in the realtime event processing flow where
bifrostEvent is available, set the context value for
BifrostContextKeyRealtimeSessionID on the request context so
bifrost.GetStringFromContext returns bifrostEvent.Session.ID, ensuring
pending.ParentRequestID is populated for realtime requests (or delete the unused
lookup if you prefer to not link sessions).
- Around line 602-610: The code reads
ctx.Value(schemas.BifrostContextKeyParentRequestID) into parentRequestID but no
upstream code ever sets that key—upstream only sets
schemas.BifrostMCPAgentOriginalRequestID for the x-bf-parent-request-id
header—so either populate the missing context key or remove the dead check:
update the header handling code that currently sets
BifrostMCPAgentOriginalRequestID to also set BifrostContextKeyParentRequestID
(mirroring the same value) so parentRequestID is populated, or remove the
BifrostContextKeyParentRequestID lookup in the logging plugin (and use
BifrostMCPAgentOriginalRequestID consistently) and adjust references to
parentRequestID accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 13df2605-ecaf-4f22-beb8-257b6f6b593c

📥 Commits

Reviewing files that changed from the base of the PR and between 5cc0b46 and 79fd370.

📒 Files selected for processing (5)
  • plugins/logging/main.go
  • plugins/logging/operations.go
  • plugins/logging/operations_test.go
  • plugins/logging/utils.go
  • plugins/maxim/main.go
✅ Files skipped from review due to trivial changes (1)
  • plugins/logging/operations_test.go

Comment thread plugins/logging/main.go
Comment thread plugins/logging/main.go
@danpiths danpiths force-pushed the feature/03-27-feat_add_session_log_storage_and_realtime_request_normalization branch from aee487f to 98d9691 Compare April 3, 2026 11:07
@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_turn_logging_to_logging_plugin branch from 79fd370 to 5c9625f Compare April 3, 2026 11:07
@danpiths danpiths force-pushed the feature/03-27-feat_add_session_log_storage_and_realtime_request_normalization branch from 98d9691 to 480d94e Compare April 6, 2026 06:17
@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_turn_logging_to_logging_plugin branch from 5c9625f to 9f6e663 Compare April 6, 2026 06:17
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plugins/logging/operations.go`:
- Around line 760-763: The current guard in the if block that only runs when
len(entry.InputHistoryParsed) == 0 causes transcript-derived items from
extractRealtimeInputHistoryFromRawRequest(entry.RawRequest) to be skipped
whenever any input history already exists; change this to always attempt to
merge the transcript into entry.InputHistoryParsed by introducing a helper
(e.g., mergeRealtimeInputHistory) that takes the existing
entry.InputHistoryParsed and the inputHistory from
extractRealtimeInputHistoryFromRawRequest and appends new items while
deduplicating against existing ResponsesRequest.Input-derived entries; replace
the len(...) == 0 check with a call to that helper when RawRequest is non-empty
so RawRequest-derived placeholders are merged rather than skipped.
- Around line 880-887: The loop over decoded parts in
extractRealtimeTranscript()/the raw content extractor currently treats a
transcript as missing only when the "transcript" key is absent or nil, so empty
strings ("") slip through and cause user audio items to disappear; update the
check inside the loop that examines part["transcript"] (and the surrounding
logic where decoded/part are handled) to treat empty-string transcripts as
missing as well—e.g., coerce part["transcript"] to a string, trim and test for
zero length or explicitly check for ""—so the code returns true (or falls back
to the unavailable placeholder) when transcript == "" in addition to nil/absent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d660609b-190b-4cf6-bbbf-bfd17747c6f5

📥 Commits

Reviewing files that changed from the base of the PR and between 5c9625f and 9f6e663.

📒 Files selected for processing (5)
  • plugins/logging/main.go
  • plugins/logging/operations.go
  • plugins/logging/operations_test.go
  • plugins/logging/utils.go
  • plugins/maxim/main.go
✅ Files skipped from review due to trivial changes (1)
  • plugins/logging/operations_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • plugins/maxim/main.go
  • plugins/logging/main.go

Comment thread plugins/logging/operations.go Outdated
Comment thread plugins/logging/operations.go
@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_turn_logging_to_logging_plugin branch from 9f6e663 to aec9dc0 Compare April 7, 2026 07:45
@danpiths danpiths force-pushed the feature/03-27-feat_add_session_log_storage_and_realtime_request_normalization branch from 480d94e to 4d142a4 Compare April 7, 2026 07:45
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
plugins/logging/main.go (1)

687-701: ⚠️ Potential issue | 🟠 Major

Exclude realtime from the PreLLMHook stream accumulator too.

These guards stop PostLLMHook from ever reading or cleaning tracer state for schemas.RealtimeRequest, but Line 438 still calls CreateStreamAccumulator(...) for any request type that bifrost.IsStreamRequestType treats as streaming. That leaves an unused accumulator behind for each realtime turn.

♻️ Suggested follow-up
-	if bifrost.IsStreamRequestType(req.RequestType) && req.RequestType != schemas.PassthroughStreamRequest {
+	if bifrost.IsStreamRequestType(req.RequestType) &&
+		req.RequestType != schemas.PassthroughStreamRequest &&
+		req.RequestType != schemas.RealtimeRequest {
 		tracer, traceID, err := bifrost.GetTracerFromContext(ctx)
 		if err == nil && tracer != nil && traceID != "" {
 			tracer.CreateStreamAccumulator(traceID, createdTimestamp)
 		}
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/logging/main.go` around lines 687 - 701, PreLLMHook is creating a
stream accumulator for any bifrost.IsStreamRequestType request but doesn't
exclude schemas.RealtimeRequest, leaving unused accumulators; update the
PreLLMHook code path that calls CreateStreamAccumulator(...) to only create an
accumulator when requestType is a stream AND requestType !=
schemas.RealtimeRequest (mirror the guard used in PostLLMHook), i.e., add the
same requestType != schemas.RealtimeRequest check around the
CreateStreamAccumulator call so realtime requests skip accumulator creation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plugins/logging/utils.go`:
- Around line 31-35: The change added two methods GetSessionLogs and
GetSessionSummary to the exported LogManager interface which is a breaking API
for downstream implementers; to fix this, revert adding them directly to
logging.LogManager and instead introduce a new interface (e.g.,
SessionLogManager) that declares GetSessionLogs and GetSessionSummary, or
clearly document this as a breaking change if you intend to keep them on
LogManager; update usages to accept the narrower SessionLogManager where
session-level operations are required (refer to the LogManager interface and the
new SessionLogManager, plus the methods GetSessionLogs and GetSessionSummary) so
existing implementers are not forced to change.

---

Outside diff comments:
In `@plugins/logging/main.go`:
- Around line 687-701: PreLLMHook is creating a stream accumulator for any
bifrost.IsStreamRequestType request but doesn't exclude schemas.RealtimeRequest,
leaving unused accumulators; update the PreLLMHook code path that calls
CreateStreamAccumulator(...) to only create an accumulator when requestType is a
stream AND requestType != schemas.RealtimeRequest (mirror the guard used in
PostLLMHook), i.e., add the same requestType != schemas.RealtimeRequest check
around the CreateStreamAccumulator call so realtime requests skip accumulator
creation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ca5a4f57-b320-4f1b-86e1-d52f89cc0964

📥 Commits

Reviewing files that changed from the base of the PR and between 9f6e663 and aec9dc0.

📒 Files selected for processing (5)
  • plugins/logging/main.go
  • plugins/logging/operations.go
  • plugins/logging/operations_test.go
  • plugins/logging/utils.go
  • plugins/maxim/main.go
✅ Files skipped from review due to trivial changes (2)
  • plugins/maxim/main.go
  • plugins/logging/operations.go

Comment thread plugins/logging/main.go
Comment thread plugins/logging/utils.go
@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_turn_logging_to_logging_plugin branch from aec9dc0 to 702f62b Compare April 7, 2026 09:09
@danpiths danpiths force-pushed the feature/03-27-feat_add_session_log_storage_and_realtime_request_normalization branch from 4d142a4 to 3048cdf Compare April 7, 2026 09:09
@danpiths danpiths force-pushed the feature/03-27-feat_add_session_log_storage_and_realtime_request_normalization branch from 3048cdf to acc3988 Compare April 7, 2026 10:59
@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_turn_logging_to_logging_plugin branch from 702f62b to 06d48bd Compare April 7, 2026 10:59
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@plugins/logging/operations.go`:
- Around line 768-785: applyRealtimeRawRequestBackfill currently marshals
non-string rawRequest values into a single JSON blob which breaks
extractRealtimeInputHistoryFromRawRequest (it expects blank-line-delimited
single-event JSON strings); change applyRealtimeRawRequestBackfill to normalize
structured inputs first: if rawRequest is []byte decode to string; if it's a
slice/array iterate elements and for each element produce an event string (if
element is string use TrimSpace, if element is non-string marshal to JSON) then
join events with "\n\n"; if rawRequest is a map/struct marshal to a single-event
JSON string (not a quoted blob) and only call
extractRealtimeInputHistoryFromRawRequest when the resulting string is non-empty
and in the expected per-event wire format; reference functions
applyRealtimeRawRequestBackfill, extractRealtimeInputHistoryFromRawRequest,
mergeRealtimeInputHistory to locate and update the logic.
- Around line 842-850: The function mergeRealtimeInputHistory short-circuits
when existing is empty which bypasses realtimeInputHistoryContainsEquivalent and
allows duplicates inside a single backfill blob; change the logic in
mergeRealtimeInputHistory so you always run the de-duplication routine:
initialize merged from existing (or empty) and then iterate over backfill items,
calling realtimeInputHistoryContainsEquivalent(merged, item) for each backfill
entry and only append items that are not equivalent; this ensures dedupe runs
even when existing is empty while keeping the existing merge behavior for
non-empty histories.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 17f233e1-398d-4460-ae63-9969d1c17afb

📥 Commits

Reviewing files that changed from the base of the PR and between 702f62b and 06d48bd.

📒 Files selected for processing (5)
  • plugins/logging/main.go
  • plugins/logging/operations.go
  • plugins/logging/operations_test.go
  • plugins/logging/utils.go
  • plugins/maxim/main.go
✅ Files skipped from review due to trivial changes (1)
  • plugins/maxim/main.go

Comment thread plugins/logging/operations.go
Comment thread plugins/logging/operations.go
@danpiths danpiths force-pushed the feature/03-27-feat_add_realtime_turn_logging_to_logging_plugin branch from 06d48bd to b3aac17 Compare April 7, 2026 12:33
@danpiths danpiths force-pushed the feature/03-27-feat_add_session_log_storage_and_realtime_request_normalization branch from acc3988 to 95e9aa6 Compare April 7, 2026 12:33
coderabbitai[bot]
coderabbitai Bot previously approved these changes Apr 7, 2026
Copy link
Copy Markdown
Contributor

akshaydeo commented Apr 7, 2026

Merge activity

  • Apr 7, 2:56 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Apr 7, 2:59 PM UTC: @akshaydeo merged this pull request with Graphite.

@akshaydeo akshaydeo changed the base branch from feature/03-27-feat_add_session_log_storage_and_realtime_request_normalization to graphite-base/2339 April 7, 2026 14:58
@akshaydeo akshaydeo changed the base branch from graphite-base/2339 to v1.5.0 April 7, 2026 14:58
@akshaydeo akshaydeo dismissed coderabbitai[bot]’s stale review April 7, 2026 14:58

The base branch was changed.

@akshaydeo akshaydeo merged commit 949b562 into v1.5.0 Apr 7, 2026
14 of 17 checks passed
@akshaydeo akshaydeo deleted the feature/03-27-feat_add_realtime_turn_logging_to_logging_plugin branch April 7, 2026 14:59
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.

3 participants