Skip to content

fix: add missing created field to text completion response#1894

Open
qcu266 wants to merge 1 commit intomaximhq:mainfrom
qcu266:fix/text-completion-response-missing-created-parms
Open

fix: add missing created field to text completion response#1894
qcu266 wants to merge 1 commit intomaximhq:mainfrom
qcu266:fix/text-completion-response-missing-created-parms

Conversation

@qcu266
Copy link

@qcu266 qcu266 commented Mar 3, 2026

Summary

add missing created field to text completion response

ref: https://developers.openai.com/api/reference/resources/completions/methods/create

In some strictly validated client libraries, an error indicating the missing 'created' field will be reported. e.g. zed Self-Hosted OpenAI-compatible servers

Changes

  • add missing created field to text completion response

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

# Core/Transports
go version
go test ./...

Screenshots/Recordings

N/A

Breaking changes

  • Yes
  • No

Related issues

N/A

Security considerations

N/A

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 3, 2026

📝 Walkthrough

Summary by CodeRabbit

Release Notes

  • New Features
    • Text completion responses now include a creation timestamp field that indicates when each completion was generated. This timestamp is consistently available across all supported AI providers, providing enhanced visibility into response timing and enabling better tracking of completion generation times.

Walkthrough

Added a Created timestamp (int64, JSON "created") to Bifrost text completion responses and propagated runtime assignment of that timestamp across schemas, providers, utils, and streaming types for both streamed and non‑streamed responses.

Changes

Cohort / File(s) Summary
Schema / Response Type
core/schemas/textcompletions.go, core/schemas/chatcompletions.go
Added Created int64 to Bifrost text completion response literals; conversion sites now set Created (with int64 conversions where required).
Utils / Response Builder
core/providers/utils/utils.go
Updated CreateBifrostTextCompletionChunkResponse signature to accept created int64 and set Created on returned BifrostTextCompletionResponse; added header access-control-expose-headers to filter list.
Providers — Anthropic / Bedrock / OpenAI / Replicate
core/providers/anthropic/text.go, core/providers/bedrock/text.go, core/providers/openai/openai.go, core/providers/replicate/replicate.go, core/providers/replicate/text.go
Providers capture or compute a creation timestamp (e.g., time.Now().Unix() or parsed provider timestamp) and populate Created on per‑chunk and final Bifrost responses; OpenAI streaming forwards captured created into chunk responses.
Streaming Framework
framework/streaming/types.go
Streaming text completion response now includes Created (from StartTimestamp.Unix()) alongside existing Usage.
Manifest / Imports
go.mod, files with added imports (e.g., time)
Added time imports where needed to compute Unix timestamps.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Client as Client
    participant Provider as Provider
    participant Utils as CreateChunk (utils)
    participant Streamer as Streamer

    Client->>Provider: request text completion
    Provider-->>Provider: generate completion\n(capture/parse created timestamp)
    Provider->>Utils: CreateBifrostTextCompletionChunkResponse(..., created)
    Utils->>Streamer: emit chunk (includes Created)
    Streamer->>Client: stream chunk(s) and final (each includes Created)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped through code at night,

I stamped each reply with a tiny light,
Now every chunk that leaps and sings,
Carries the whisper of when it sprang its wings,
A timestamped hop — delightful things.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding the missing 'created' field to text completion responses, which is the primary objective of the entire changeset.
Description check ✅ Passed The description covers the template's main sections with summary, changes, type of change, affected areas, and testing instructions; however, critical checklist items about tests, documentation, builds, and CI verification are left unchecked.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
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

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

Inline comments:
In `@core/schemas/textcompletions.go`:
- Line 70: Several code paths construct BifrostTextCompletionResponse without
setting the non-omitempty Created field, causing serialized responses to show
created: 0; update every construction site (e.g., the constructors/creations in
framework/streaming/types.go around line ~251, core/providers/replicate/text.go,
core/providers/bedrock/text.go, core/providers/anthropic/text.go,
core/providers/utils/utils.go where responses are built, and any manual
conversions from chat completions in core/schemas/chatcompletions.go) to assign
Created = int(time.Now().Unix()) (or equivalent integer Unix timestamp) when
creating a BifrostTextCompletionResponse or when converting into one; ensure any
path that currently relies on HandleProviderResponse() still preserves or sets
Created if the upstream provider omits it.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3764bdb and ff810d9.

📒 Files selected for processing (1)
  • core/schemas/textcompletions.go

type BifrostTextCompletionResponse struct {
ID string `json:"id"`
Choices []BifrostResponseChoice `json:"choices"`
Created int `json:"created"`
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find all construction sites for BifrostTextCompletionResponse
echo "=== BifrostTextCompletionResponse construction sites ==="
rg -nP --type=go 'BifrostTextCompletionResponse\s*\{' -A5

echo ""
echo "=== BifrostTextCompletionResponse assignments (& or *) ==="
rg -nP --type=go '&BifrostTextCompletionResponse|:=.*BifrostTextCompletionResponse' -A8

echo ""
echo "=== Created field assignments ==="
rg -nP --type=go -B2 -A2 'Created\s*:'

echo ""
echo "=== Check for BifrostTextCompletionResponse usages ==="
rg -nP --type=go 'BifrostTextCompletionResponse' --type-list

Repository: maximhq/bifrost

Length of output: 36563


🏁 Script executed:

#!/bin/bash
# Check if openai and azure HandleProviderResponse/json unmarshaling sets Created
echo "=== OpenAI text completion handling ==="
rg -nP --type=go -A10 'HandleOpenAITextCompletion\(' core/providers/openai/openai.go | head -50

echo ""
echo "=== Check if Created is set after construction in OpenAI ==="
rg -nP --type=go -B5 -A15 'response := &schemas.BifrostTextCompletionResponse{}' core/providers/openai/openai.go

echo ""
echo "=== Check if Created is set after construction in Azure ==="
rg -nP --type=go -B5 -A15 'response := &schemas.BifrostTextCompletionResponse{}' core/providers/azure/azure.go

echo ""
echo "=== Check framework/streaming/types.go for Created assignment to text responses ==="
rg -nP --type=go -B3 -A10 'textResp := &schemas.BifrostTextCompletionResponse' framework/streaming/types.go

Repository: maximhq/bifrost

Length of output: 3079


🏁 Script executed:

#!/bin/bash
# Check HandleProviderResponse function to see if it unmarshals JSON
echo "=== HandleProviderResponse implementation ==="
rg -nP --type=go -A20 'func HandleProviderResponse' core/providers/utils/

echo ""
echo "=== Check if text completion responses are deserialized from provider JSON ==="
rg -nP --type=go -B5 -A10 'json.Unmarshal.*Body' core/providers/openai/ | head -60

echo ""
echo "=== Check framework streaming for any Created field assignment in text path ==="
rg -nP --type=go -A30 'textResp := &schemas.BifrostTextCompletionResponse' framework/streaming/types.go | head -50

Repository: maximhq/bifrost

Length of output: 3065


🏁 Script executed:

#!/bin/bash
# Get the full HandleProviderResponse function to see if it unmarshals JSON
echo "=== Full HandleProviderResponse function ==="
rg -nP --type=go -A60 'func HandleProviderResponse\[T any\]' core/providers/utils/utils.go | head -80

echo ""
echo "=== Check if sonic or json.Unmarshal is used for response ==="
rg -nP --type=go -A5 'sonic.Unmarshal.*response\|json.Unmarshal.*response' core/providers/utils/utils.go

Repository: maximhq/bifrost

Length of output: 2569


Set Created timestamp on all BifrostTextCompletionResponse construction paths.

Line 70 adds a non-omitempty Created field. Code paths that manually construct BifrostTextCompletionResponse (e.g., framework/streaming/types.go:251, core/providers/replicate/text.go:95, core/providers/bedrock/text.go:118, core/providers/anthropic/text.go:89, core/providers/utils/utils.go:1569, core/schemas/chatcompletions.go conversions) do not assign Created, resulting in created: 0 in serialized responses. Paths using HandleProviderResponse() depend on upstream provider JSON including a created field. Ensure all construction sites assign an actual timestamp, typically using int(time.Now().Unix()).

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

In `@core/schemas/textcompletions.go` at line 70, Several code paths construct
BifrostTextCompletionResponse without setting the non-omitempty Created field,
causing serialized responses to show created: 0; update every construction site
(e.g., the constructors/creations in framework/streaming/types.go around line
~251, core/providers/replicate/text.go, core/providers/bedrock/text.go,
core/providers/anthropic/text.go, core/providers/utils/utils.go where responses
are built, and any manual conversions from chat completions in
core/schemas/chatcompletions.go) to assign Created = int(time.Now().Unix()) (or
equivalent integer Unix timestamp) when creating a BifrostTextCompletionResponse
or when converting into one; ensure any path that currently relies on
HandleProviderResponse() still preserves or sets Created if the upstream
provider omits it.

@akshaydeo
Copy link
Contributor

@qcu266 thanks for the PR - as CodeRabbit suggests - we will need to populate the field across the codebase

Copy link
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 `@core/providers/openai/openai.go`:
- Around line 624-626: The code only assigns created = response.Created inside
the branch that checks response.Usage != nil, so compatible backends that omit
usage chunks leave created unset; update the streaming/response-handling logic
(the loop that processes streaming chunks and later builds the terminal chunk)
to always set created = response.Created whenever response.Created is non-zero
regardless of response.Usage, ensuring the terminal chunk creation (where
created is used) reflects the last non-zero Created value from any chunk.

In `@core/providers/replicate/text.go`:
- Around line 136-144: The code sets bifrostResponse.Created from
response.CompletedAt which is wrong; use response.CreatedAt instead. Edit the
anonymous func that assigns bifrostResponse.Created (the block referencing
response.CompletedAt) to parse and return response.CreatedAt (time.Parse
time.RFC3339 on *response.CreatedAt), falling back to time.Now().Unix() on nil
or parse error, keeping the same return semantics as other provider files
(responses.go, videos.go, images.go, chat.go).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 20c5785f-b873-4db2-bffd-a9cd1a73c3e1

📥 Commits

Reviewing files that changed from the base of the PR and between ff810d9 and 43698a5.

📒 Files selected for processing (9)
  • core/providers/anthropic/text.go
  • core/providers/bedrock/text.go
  • core/providers/openai/openai.go
  • core/providers/replicate/replicate.go
  • core/providers/replicate/text.go
  • core/providers/utils/utils.go
  • core/schemas/chatcompletions.go
  • core/schemas/textcompletions.go
  • framework/streaming/types.go

@qcu266 qcu266 force-pushed the fix/text-completion-response-missing-created-parms branch from b1fd65d to 1bfd5d0 Compare March 4, 2026 10:05
Copy link
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

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

Inline comments:
In `@core/providers/openai/openai.go`:
- Around line 624-631: There is a duplicated response.Usage = nil assignment and
an extra closing brace that breaks syntax in the aggregation block handling
response chunks; inside the code that sets response.Usage = nil and tracks
created (look for the variables response and created and the surrounding if
response.Created > 0 block), remove the duplicate response.Usage = nil line and
delete the stray '}' so the if/else blocks and function braces balance
correctly, ensuring the final aggregated chunk retains the single intended
assignment and created is set only once.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ded4dacd-80f5-41e1-a150-857265368ae0

📥 Commits

Reviewing files that changed from the base of the PR and between 43698a5 and 41971b7.

📒 Files selected for processing (1)
  • core/providers/openai/openai.go

Comment on lines 624 to 631
response.Usage = nil
}

// Track created timestamp from any chunk so final aggregated chunk is always populated.
if response.Created > 0 {
created = response.Created
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read the file to inspect lines around 624-631
echo "=== Code context (lines 610-645) ==="
sed -n '610,645p' core/providers/openai/openai.go | cat -n

echo ""
echo "=== Running gofmt to check for syntax errors ==="
gofmt -d core/providers/openai/openai.go 2>&1 | head -100 || echo "No gofmt changes needed"

echo ""
echo "=== Checking if file is valid Go ==="
go fmt ./core/providers/openai/... 2>&1 | head -50 || true

Repository: maximhq/bifrost

Length of output: 2560


Remove the extra closing brace and duplicate assignment in the usage/created block

The code contains a duplicate response.Usage = nil assignment (lines 624–625) and an extra } at line 631 that breaks Go syntax and prevents compilation. The gofmt output confirms multiple parse errors cascading from this malformed block.

Proposed fix
			if response.Usage.PromptTokensDetails != nil {
				usage.PromptTokensDetails = response.Usage.PromptTokensDetails
			}
			response.Usage = nil
-			response.Usage = nil
		}

		// Track created timestamp from any chunk so final aggregated chunk is always populated.
		if response.Created > 0 {
			created = response.Created
		}
-		}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
response.Usage = nil
}
// Track created timestamp from any chunk so final aggregated chunk is always populated.
if response.Created > 0 {
created = response.Created
}
}
if response.Usage.PromptTokensDetails != nil {
usage.PromptTokensDetails = response.Usage.PromptTokensDetails
}
response.Usage = nil
}
// Track created timestamp from any chunk so final aggregated chunk is always populated.
if response.Created > 0 {
created = response.Created
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@core/providers/openai/openai.go` around lines 624 - 631, There is a
duplicated response.Usage = nil assignment and an extra closing brace that
breaks syntax in the aggregation block handling response chunks; inside the code
that sets response.Usage = nil and tracks created (look for the variables
response and created and the surrounding if response.Created > 0 block), remove
the duplicate response.Usage = nil line and delete the stray '}' so the if/else
blocks and function braces balance correctly, ensuring the final aggregated
chunk retains the single intended assignment and created is set only once.

@qcu266 qcu266 marked this pull request as draft March 4, 2026 10:07
@qcu266 qcu266 force-pushed the fix/text-completion-response-missing-created-parms branch from 1bfd5d0 to 1240952 Compare March 4, 2026 11:26
@qcu266 qcu266 marked this pull request as ready for review March 4, 2026 11:27
Copy link
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)
core/schemas/chatcompletions.go (1)

32-35: Unify Created type to int64 for schema consistency.

BifrostChatResponse.Created is int while other response schemas (BifrostTextCompletionResponse, BifrostModel, BifrostImage) use int64 for the same field, forcing four explicit type casts in the conversion methods. Change Created to int64 to eliminate this friction and align with the rest of the schema definitions.

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

In `@core/schemas/chatcompletions.go` around lines 32 - 35, Change the Created
field on BifrostChatResponse from int to int64 to match other schemas (replace
"Created int" with "Created int64" in the BifrostChatResponse struct) and update
any conversion/mapper functions that handle BifrostChatResponse (remove the
explicit int-to-int64 casts where Created is used); ensure functions that
consume Created (conversion helpers or methods that previously cast the value)
now accept int64 and compile without the four explicit casts.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@core/schemas/chatcompletions.go`:
- Around line 32-35: Change the Created field on BifrostChatResponse from int to
int64 to match other schemas (replace "Created int" with "Created int64" in the
BifrostChatResponse struct) and update any conversion/mapper functions that
handle BifrostChatResponse (remove the explicit int-to-int64 casts where Created
is used); ensure functions that consume Created (conversion helpers or methods
that previously cast the value) now accept int64 and compile without the four
explicit casts.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6118c31e-da41-4b38-a8a7-eaff1aebaf4c

📥 Commits

Reviewing files that changed from the base of the PR and between 1bfd5d0 and 1240952.

📒 Files selected for processing (9)
  • core/providers/anthropic/text.go
  • core/providers/bedrock/text.go
  • core/providers/openai/openai.go
  • core/providers/replicate/replicate.go
  • core/providers/replicate/text.go
  • core/providers/utils/utils.go
  • core/schemas/chatcompletions.go
  • core/schemas/textcompletions.go
  • framework/streaming/types.go
🚧 Files skipped from review as they are similar to previous changes (6)
  • core/providers/replicate/text.go
  • core/providers/replicate/replicate.go
  • core/providers/anthropic/text.go
  • core/schemas/textcompletions.go
  • framework/streaming/types.go
  • core/providers/bedrock/text.go

@qcu266
Copy link
Author

qcu266 commented Mar 4, 2026

@qcu266 thanks for the PR - as CodeRabbit suggests - we will need to populate the field across the codebase

@akshaydeo , I have carefully reviewed it and made corresponding modifications in other places, but I'm not sure if there are still any omissions.

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.

2 participants