Skip to content

Commit d61cb55

Browse files
authored
gemini named content cache support (#3194)
## Summary Adds a full named cached content lifecycle (create, list, retrieve, update, delete) for Gemini (Google AI Studio) and Vertex AI, exposes it through the HTTP transport layer, and extends the `Provider` interface so all existing providers satisfy it with explicit "unsupported" stubs. Also fixes Bedrock Converse and Vertex-Anthropic to auto-fetch and inline remote URL images and documents (both APIs only accept inline base64 bytes), and adds a JSON unmarshal normalizer that transparently converts Anthropic-style `{type:"document", source:{...}}` content blocks into bifrost's canonical `{type:"file", file:{...}}` shape. ## Changes - **`core/schemas/cachedcontents.go`** — New file defining `CachedContentObject` and the five request/response pairs (`BifrostCachedContentCreate/List/Retrieve/Update/Delete Request/Response`). TTL and `expireTime` are documented as mutually exclusive. - **`core/schemas/bifrost.go`** — Added five new `RequestType` constants, wired the new request/response structs into `BifrostRequest` / `BifrostResponse`, and extended `GetRequestFields` to cover all five operations. - **`core/schemas/provider.go`** — Added `CachedContentCreate`, `CachedContentList`, `CachedContentRetrieve`, `CachedContentUpdate`, and `CachedContentDelete` to the `Provider` interface. - **`core/bifrost.go`** — Added five public `CachedContent*Request` methods on `Bifrost` with nil/empty-field guards, and wired the new request types into `handleProviderRequest`. - **`core/providers/gemini/cachedcontents.go`** — Full implementation against Google AI Studio's `/v1beta/cachedContents` endpoints. List/retrieve/update/delete iterate over keys and return on first success. `normalizeCachedContentName` ensures the `cachedContents/` prefix is always present. - **`core/providers/vertex/cachedcontents.go`** — Full implementation against Vertex AI's `/v1/projects/{p}/locations/{l}/cachedContents` endpoints. `expandVertexCachedContentName` and `expandVertexModelPath` rewrite short IDs to full resource paths. OAuth bearer tokens are applied per-request via the existing `getAuthTokenSource` helper. - **`core/providers/{anthropic,azure,bedrock,cerebras,cohere,elevenlabs,fireworks,groq,huggingface,mistral,nebius,ollama,openai,openrouter,parasail,perplexity,replicate,runway,sgl,vllm,xai}/cachedcontents.go`** — Unsupported-operation stubs for every other provider so the interface is satisfied. - **`core/providers/utils/fetch.go`** — New `FetchAndEncodeURL` utility: downloads a remote resource with a 20 s timeout and 25 MiB cap, returns the response `Content-Type` and base64-encoded body. Used by Bedrock and Vertex-Anthropic converters. - **`core/providers/bedrock/utils.go`** — `convertImageToBedrockSource` now fetches remote `http(s)://` image URLs and inlines them instead of rejecting them. `convertContentBlock` gains the same fetch-and-inline path for URL-sourced document blocks, with `Content-Type`-driven format detection. - **`core/providers/vertex/vertex.go`** — `inlineDocumentURLs` pre-processes chat requests for Anthropic-on-Vertex, replacing URL document sources with fetched base64 bytes before the Anthropic converter runs. Called in both `ChatCompletion` and `ChatCompletionStream`. - **`core/schemas/chatcompletions.go`** — `ChatContentBlock.UnmarshalJSON` now transparently rewrites Anthropic-style `{type:"document", source:{...}}` blocks to `{type:"file", file:{...}}` using `gjson`/`sjson`, covering `base64`, `text`, `url`, and `file` source variants. Sibling fields (`citations`, `cache_control`, `cachePoint`, `title`) are preserved. - **`transports/bifrost-http/integrations/router.go`** — Added `CachedContentRequest` wrapper struct, five converter/response-converter function types, corresponding `RouteConfig` fields, route-type detection, and `handleCachedContentRequest` dispatch method. - **`transports/bifrost-http/integrations/genai.go`** — `CreateGenAICachedContentRouteConfigs` registers `POST/GET/PATCH/DELETE /v1beta/cachedContents[/{cached_id}]` routes under the `/genai` prefix with pre-callbacks for path and query parameter extraction. - **`transports/bifrost-http/integrations/openai.go`** — Added `/responses` path detection and `OpenAIResponsesRequest` type dispatch so the Responses API route is handled correctly alongside chat completions; added `ResponsesResponseConverter` and `ResponsesStreamResponseConverter` to the route config. - **Docs / harness** — `test-harness-coverage.mdx` rewritten as per-provider tables with `✅*` for preview-gated rows and a `[PREVIEW]` tag explanation. `HARNESS_COVERAGE_BACKLOG.md` marks cached content CRUD as complete. `provider-harness.json` promotes "Gemini: list cached contents" from `[PREVIEW]` to a standard test and fixes the Anthropic skills/container body shape. ## Type of change - [ ] Bug fix - [x] Feature - [ ] Refactor - [ ] Documentation - [ ] Chore/CI ## Affected areas - [x] Core (Go) - [x] Transports (HTTP) - [x] Providers/Integrations - [ ] Plugins - [ ] UI (React) - [x] Docs ## How to test ```sh # Build and unit tests go build ./... go test ./... # End-to-end harness (requires GENAI_API_KEY and VERTEX credentials) make run-provider-harness-test # Include preview-gated tests (cached content reference, MCP, preview deployments) make run-provider-harness-test INCLUDE_PREVIEW=1 ``` To exercise the cached content lifecycle directly: ```sh # Create a cached content (Gemini) curl -X POST http://localhost:8080/genai/v1beta/cachedContents \ -H "x-goog-api-key: $GENAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{"model":"models/gemini-2.5-flash","contents":[...],"ttl":"3600s"}' # List curl http://localhost:8080/genai/v1beta/cachedContents \ -H "x-goog-api-key: $GENAI_API_KEY" # Retrieve / Update / Delete follow the same /v1beta/cachedContents/{id} path ``` ## Breaking changes - [x] Yes - [ ] No The `Provider` interface gains five new methods. Any external implementation of `Provider` must add stubs for `CachedContentCreate`, `CachedContentList`, `CachedContentRetrieve`, `CachedContentUpdate`, and `CachedContentDelete`. The provided unsupported-operation pattern can be copied directly from any of the stub files. ## Security considerations `FetchAndEncodeURL` issues outbound HTTP requests to URLs supplied by callers. It is bounded by a 20 s timeout and a 25 MiB body cap to limit SSRF blast radius, but operators running bifrost in environments with strict egress controls should be aware that Bedrock and Vertex-Anthropic document/image URL inputs will now trigger outbound fetches from the bifrost process. ## Checklist - [ ] I read `docs/contributing/README.md` and followed the guidelines - [x] I added/updated tests where appropriate - [x] I updated documentation where needed - [x] I verified builds succeed (Go and UI) - [ ] I verified the CI pipeline passes locally if applicable
1 parent 68bf0c7 commit d61cb55

42 files changed

Lines changed: 3598 additions & 351 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

core/bifrost.go

Lines changed: 154 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2313,6 +2313,123 @@ func (bifrost *Bifrost) FileContentRequest(ctx *schemas.BifrostContext, req *sch
23132313
return response.FileContentResponse, nil
23142314
}
23152315

2316+
// CachedContentCreateRequest creates a new cached content (Gemini / Vertex AI named cache lifecycle).
2317+
func (bifrost *Bifrost) CachedContentCreateRequest(ctx *schemas.BifrostContext, req *schemas.BifrostCachedContentCreateRequest) (*schemas.BifrostCachedContentCreateResponse, *schemas.BifrostError) {
2318+
if req == nil {
2319+
return nil, &schemas.BifrostError{IsBifrostError: false, Error: &schemas.ErrorField{Message: "cached content create request is nil"}}
2320+
}
2321+
if req.Provider == "" {
2322+
return nil, &schemas.BifrostError{IsBifrostError: false, Error: &schemas.ErrorField{Message: "provider is required for cached content create request"}}
2323+
}
2324+
if req.Model == "" {
2325+
return nil, &schemas.BifrostError{IsBifrostError: false, Error: &schemas.ErrorField{Message: "model is required for cached content create request"}}
2326+
}
2327+
if ctx == nil {
2328+
ctx = bifrost.ctx
2329+
}
2330+
bifrostReq := bifrost.getBifrostRequest()
2331+
bifrostReq.RequestType = schemas.CachedContentCreateRequest
2332+
bifrostReq.CachedContentCreateRequest = req
2333+
response, err := bifrost.handleRequest(ctx, bifrostReq)
2334+
if err != nil {
2335+
return nil, err
2336+
}
2337+
return response.CachedContentCreateResponse, nil
2338+
}
2339+
2340+
// CachedContentListRequest lists cached contents.
2341+
func (bifrost *Bifrost) CachedContentListRequest(ctx *schemas.BifrostContext, req *schemas.BifrostCachedContentListRequest) (*schemas.BifrostCachedContentListResponse, *schemas.BifrostError) {
2342+
if req == nil {
2343+
return nil, &schemas.BifrostError{IsBifrostError: false, Error: &schemas.ErrorField{Message: "cached content list request is nil"}}
2344+
}
2345+
if req.Provider == "" {
2346+
return nil, &schemas.BifrostError{IsBifrostError: false, Error: &schemas.ErrorField{Message: "provider is required for cached content list request"}}
2347+
}
2348+
if ctx == nil {
2349+
ctx = bifrost.ctx
2350+
}
2351+
bifrostReq := bifrost.getBifrostRequest()
2352+
bifrostReq.RequestType = schemas.CachedContentListRequest
2353+
bifrostReq.CachedContentListRequest = req
2354+
response, err := bifrost.handleRequest(ctx, bifrostReq)
2355+
if err != nil {
2356+
return nil, err
2357+
}
2358+
return response.CachedContentListResponse, nil
2359+
}
2360+
2361+
// CachedContentRetrieveRequest retrieves a single cached content by name.
2362+
func (bifrost *Bifrost) CachedContentRetrieveRequest(ctx *schemas.BifrostContext, req *schemas.BifrostCachedContentRetrieveRequest) (*schemas.BifrostCachedContentRetrieveResponse, *schemas.BifrostError) {
2363+
if req == nil {
2364+
return nil, &schemas.BifrostError{IsBifrostError: false, Error: &schemas.ErrorField{Message: "cached content retrieve request is nil"}}
2365+
}
2366+
if req.Provider == "" {
2367+
return nil, &schemas.BifrostError{IsBifrostError: false, Error: &schemas.ErrorField{Message: "provider is required for cached content retrieve request"}}
2368+
}
2369+
if req.Name == "" {
2370+
return nil, &schemas.BifrostError{IsBifrostError: false, Error: &schemas.ErrorField{Message: "name is required for cached content retrieve request"}}
2371+
}
2372+
if ctx == nil {
2373+
ctx = bifrost.ctx
2374+
}
2375+
bifrostReq := bifrost.getBifrostRequest()
2376+
bifrostReq.RequestType = schemas.CachedContentRetrieveRequest
2377+
bifrostReq.CachedContentRetrieveRequest = req
2378+
response, err := bifrost.handleRequest(ctx, bifrostReq)
2379+
if err != nil {
2380+
return nil, err
2381+
}
2382+
return response.CachedContentRetrieveResponse, nil
2383+
}
2384+
2385+
// CachedContentUpdateRequest updates expiration on a cached content.
2386+
func (bifrost *Bifrost) CachedContentUpdateRequest(ctx *schemas.BifrostContext, req *schemas.BifrostCachedContentUpdateRequest) (*schemas.BifrostCachedContentUpdateResponse, *schemas.BifrostError) {
2387+
if req == nil {
2388+
return nil, &schemas.BifrostError{IsBifrostError: false, Error: &schemas.ErrorField{Message: "cached content update request is nil"}}
2389+
}
2390+
if req.Provider == "" {
2391+
return nil, &schemas.BifrostError{IsBifrostError: false, Error: &schemas.ErrorField{Message: "provider is required for cached content update request"}}
2392+
}
2393+
if req.Name == "" {
2394+
return nil, &schemas.BifrostError{IsBifrostError: false, Error: &schemas.ErrorField{Message: "name is required for cached content update request"}}
2395+
}
2396+
if ctx == nil {
2397+
ctx = bifrost.ctx
2398+
}
2399+
bifrostReq := bifrost.getBifrostRequest()
2400+
bifrostReq.RequestType = schemas.CachedContentUpdateRequest
2401+
bifrostReq.CachedContentUpdateRequest = req
2402+
response, err := bifrost.handleRequest(ctx, bifrostReq)
2403+
if err != nil {
2404+
return nil, err
2405+
}
2406+
return response.CachedContentUpdateResponse, nil
2407+
}
2408+
2409+
// CachedContentDeleteRequest deletes a cached content by name.
2410+
func (bifrost *Bifrost) CachedContentDeleteRequest(ctx *schemas.BifrostContext, req *schemas.BifrostCachedContentDeleteRequest) (*schemas.BifrostCachedContentDeleteResponse, *schemas.BifrostError) {
2411+
if req == nil {
2412+
return nil, &schemas.BifrostError{IsBifrostError: false, Error: &schemas.ErrorField{Message: "cached content delete request is nil"}}
2413+
}
2414+
if req.Provider == "" {
2415+
return nil, &schemas.BifrostError{IsBifrostError: false, Error: &schemas.ErrorField{Message: "provider is required for cached content delete request"}}
2416+
}
2417+
if req.Name == "" {
2418+
return nil, &schemas.BifrostError{IsBifrostError: false, Error: &schemas.ErrorField{Message: "name is required for cached content delete request"}}
2419+
}
2420+
if ctx == nil {
2421+
ctx = bifrost.ctx
2422+
}
2423+
bifrostReq := bifrost.getBifrostRequest()
2424+
bifrostReq.RequestType = schemas.CachedContentDeleteRequest
2425+
bifrostReq.CachedContentDeleteRequest = req
2426+
response, err := bifrost.handleRequest(ctx, bifrostReq)
2427+
if err != nil {
2428+
return nil, err
2429+
}
2430+
return response.CachedContentDeleteResponse, nil
2431+
}
2432+
23162433
func (bifrost *Bifrost) Passthrough(
23172434
ctx *schemas.BifrostContext,
23182435
provider schemas.ModelProvider,
@@ -5608,8 +5725,9 @@ func (bifrost *Bifrost) requestWorker(provider schemas.Provider, config *schemas
56085725
isMultiKeyBatchOp := isBatchRequestType(req.RequestType) && req.RequestType != schemas.BatchCreateRequest
56095726
isMultiKeyFileOp := isFileRequestType(req.RequestType) && req.RequestType != schemas.FileUploadRequest
56105727
isMultiKeyContainerOp := isContainerRequestType(req.RequestType) && req.RequestType != schemas.ContainerCreateRequest && req.RequestType != schemas.ContainerFileCreateRequest
5728+
isMultiKeyCachedContentOp := isCachedContentRequestType(req.RequestType) && req.RequestType != schemas.CachedContentCreateRequest
56115729

5612-
if isMultiKeyBatchOp || isMultiKeyFileOp || isMultiKeyContainerOp {
5730+
if isMultiKeyBatchOp || isMultiKeyFileOp || isMultiKeyContainerOp || isMultiKeyCachedContentOp {
56135731
var modelPtr *string
56145732
if model != "" {
56155733
modelPtr = &model
@@ -6033,6 +6151,36 @@ func (bifrost *Bifrost) handleProviderRequest(provider schemas.Provider, config
60336151
return nil, bifrostError
60346152
}
60356153
response.FileContentResponse = fileContentResponse
6154+
case schemas.CachedContentCreateRequest:
6155+
cachedContentCreateResponse, bifrostError := provider.CachedContentCreate(req.Context, key, req.BifrostRequest.CachedContentCreateRequest)
6156+
if bifrostError != nil {
6157+
return nil, bifrostError
6158+
}
6159+
response.CachedContentCreateResponse = cachedContentCreateResponse
6160+
case schemas.CachedContentListRequest:
6161+
cachedContentListResponse, bifrostError := provider.CachedContentList(req.Context, keys, req.BifrostRequest.CachedContentListRequest)
6162+
if bifrostError != nil {
6163+
return nil, bifrostError
6164+
}
6165+
response.CachedContentListResponse = cachedContentListResponse
6166+
case schemas.CachedContentRetrieveRequest:
6167+
cachedContentRetrieveResponse, bifrostError := provider.CachedContentRetrieve(req.Context, keys, req.BifrostRequest.CachedContentRetrieveRequest)
6168+
if bifrostError != nil {
6169+
return nil, bifrostError
6170+
}
6171+
response.CachedContentRetrieveResponse = cachedContentRetrieveResponse
6172+
case schemas.CachedContentUpdateRequest:
6173+
cachedContentUpdateResponse, bifrostError := provider.CachedContentUpdate(req.Context, keys, req.BifrostRequest.CachedContentUpdateRequest)
6174+
if bifrostError != nil {
6175+
return nil, bifrostError
6176+
}
6177+
response.CachedContentUpdateResponse = cachedContentUpdateResponse
6178+
case schemas.CachedContentDeleteRequest:
6179+
cachedContentDeleteResponse, bifrostError := provider.CachedContentDelete(req.Context, keys, req.BifrostRequest.CachedContentDeleteRequest)
6180+
if bifrostError != nil {
6181+
return nil, bifrostError
6182+
}
6183+
response.CachedContentDeleteResponse = cachedContentDeleteResponse
60366184
case schemas.BatchCreateRequest:
60376185
batchCreateResponse, bifrostError := provider.BatchCreate(req.Context, key, req.BifrostRequest.BatchCreateRequest)
60386186
if bifrostError != nil {
@@ -6920,6 +7068,11 @@ func resetBifrostRequest(req *schemas.BifrostRequest) {
69207068
req.FileRetrieveRequest = nil
69217069
req.FileDeleteRequest = nil
69227070
req.FileContentRequest = nil
7071+
req.CachedContentCreateRequest = nil
7072+
req.CachedContentListRequest = nil
7073+
req.CachedContentRetrieveRequest = nil
7074+
req.CachedContentUpdateRequest = nil
7075+
req.CachedContentDeleteRequest = nil
69237076
req.BatchCreateRequest = nil
69247077
req.BatchListRequest = nil
69257078
req.BatchRetrieveRequest = nil
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package anthropic
2+
3+
import (
4+
providerUtils "github.com/maximhq/bifrost/core/providers/utils"
5+
"github.com/maximhq/bifrost/core/schemas"
6+
)
7+
8+
// CachedContentCreate is unsupported on AnthropicProvider. Only Gemini and Vertex AI
9+
// implement the cached-content lifecycle (Google AI Studio + Vertex AI named
10+
// caches). Other providers either lack named cache management entirely or
11+
// handle caching implicitly via per-message cache_control markers.
12+
func (provider *AnthropicProvider) CachedContentCreate(ctx *schemas.BifrostContext, key schemas.Key, request *schemas.BifrostCachedContentCreateRequest) (*schemas.BifrostCachedContentCreateResponse, *schemas.BifrostError) {
13+
return nil, providerUtils.NewUnsupportedOperationError(schemas.CachedContentCreateRequest, provider.GetProviderKey())
14+
}
15+
16+
// CachedContentList is unsupported on AnthropicProvider (see CachedContentCreate).
17+
func (provider *AnthropicProvider) CachedContentList(ctx *schemas.BifrostContext, keys []schemas.Key, request *schemas.BifrostCachedContentListRequest) (*schemas.BifrostCachedContentListResponse, *schemas.BifrostError) {
18+
return nil, providerUtils.NewUnsupportedOperationError(schemas.CachedContentListRequest, provider.GetProviderKey())
19+
}
20+
21+
// CachedContentRetrieve is unsupported on AnthropicProvider (see CachedContentCreate).
22+
func (provider *AnthropicProvider) CachedContentRetrieve(ctx *schemas.BifrostContext, keys []schemas.Key, request *schemas.BifrostCachedContentRetrieveRequest) (*schemas.BifrostCachedContentRetrieveResponse, *schemas.BifrostError) {
23+
return nil, providerUtils.NewUnsupportedOperationError(schemas.CachedContentRetrieveRequest, provider.GetProviderKey())
24+
}
25+
26+
// CachedContentUpdate is unsupported on AnthropicProvider (see CachedContentCreate).
27+
func (provider *AnthropicProvider) CachedContentUpdate(ctx *schemas.BifrostContext, keys []schemas.Key, request *schemas.BifrostCachedContentUpdateRequest) (*schemas.BifrostCachedContentUpdateResponse, *schemas.BifrostError) {
28+
return nil, providerUtils.NewUnsupportedOperationError(schemas.CachedContentUpdateRequest, provider.GetProviderKey())
29+
}
30+
31+
// CachedContentDelete is unsupported on AnthropicProvider (see CachedContentCreate).
32+
func (provider *AnthropicProvider) CachedContentDelete(ctx *schemas.BifrostContext, keys []schemas.Key, request *schemas.BifrostCachedContentDeleteRequest) (*schemas.BifrostCachedContentDeleteResponse, *schemas.BifrostError) {
33+
return nil, providerUtils.NewUnsupportedOperationError(schemas.CachedContentDeleteRequest, provider.GetProviderKey())
34+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package azure
2+
3+
import (
4+
providerUtils "github.com/maximhq/bifrost/core/providers/utils"
5+
"github.com/maximhq/bifrost/core/schemas"
6+
)
7+
8+
// CachedContentCreate is unsupported on AzureProvider. Only Gemini and Vertex AI
9+
// implement the cached-content lifecycle (Google AI Studio + Vertex AI named
10+
// caches). Other providers either lack named cache management entirely or
11+
// handle caching implicitly via per-message cache_control markers.
12+
func (provider *AzureProvider) CachedContentCreate(ctx *schemas.BifrostContext, key schemas.Key, request *schemas.BifrostCachedContentCreateRequest) (*schemas.BifrostCachedContentCreateResponse, *schemas.BifrostError) {
13+
return nil, providerUtils.NewUnsupportedOperationError(schemas.CachedContentCreateRequest, provider.GetProviderKey())
14+
}
15+
16+
// CachedContentList is unsupported on AzureProvider (see CachedContentCreate).
17+
func (provider *AzureProvider) CachedContentList(ctx *schemas.BifrostContext, keys []schemas.Key, request *schemas.BifrostCachedContentListRequest) (*schemas.BifrostCachedContentListResponse, *schemas.BifrostError) {
18+
return nil, providerUtils.NewUnsupportedOperationError(schemas.CachedContentListRequest, provider.GetProviderKey())
19+
}
20+
21+
// CachedContentRetrieve is unsupported on AzureProvider (see CachedContentCreate).
22+
func (provider *AzureProvider) CachedContentRetrieve(ctx *schemas.BifrostContext, keys []schemas.Key, request *schemas.BifrostCachedContentRetrieveRequest) (*schemas.BifrostCachedContentRetrieveResponse, *schemas.BifrostError) {
23+
return nil, providerUtils.NewUnsupportedOperationError(schemas.CachedContentRetrieveRequest, provider.GetProviderKey())
24+
}
25+
26+
// CachedContentUpdate is unsupported on AzureProvider (see CachedContentCreate).
27+
func (provider *AzureProvider) CachedContentUpdate(ctx *schemas.BifrostContext, keys []schemas.Key, request *schemas.BifrostCachedContentUpdateRequest) (*schemas.BifrostCachedContentUpdateResponse, *schemas.BifrostError) {
28+
return nil, providerUtils.NewUnsupportedOperationError(schemas.CachedContentUpdateRequest, provider.GetProviderKey())
29+
}
30+
31+
// CachedContentDelete is unsupported on AzureProvider (see CachedContentCreate).
32+
func (provider *AzureProvider) CachedContentDelete(ctx *schemas.BifrostContext, keys []schemas.Key, request *schemas.BifrostCachedContentDeleteRequest) (*schemas.BifrostCachedContentDeleteResponse, *schemas.BifrostError) {
33+
return nil, providerUtils.NewUnsupportedOperationError(schemas.CachedContentDeleteRequest, provider.GetProviderKey())
34+
}

core/providers/bedrock/bedrock_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2605,7 +2605,7 @@ func TestToolResultJSONParsingResponsesAPI(t *testing.T) {
26052605
},
26062606
}
26072607

2608-
messages, _, err := bedrock.ConvertBifrostMessagesToBedrockMessages(input)
2608+
messages, _, err := bedrock.ConvertBifrostMessagesToBedrockMessages(context.Background(), input)
26092609
require.NoError(t, err)
26102610
require.Len(t, messages, 1)
26112611

@@ -4510,7 +4510,7 @@ func TestToolResultImageContentResponsesAPI(t *testing.T) {
45104510
},
45114511
}
45124512

4513-
messages, _, err := bedrock.ConvertBifrostMessagesToBedrockMessages(input)
4513+
messages, _, err := bedrock.ConvertBifrostMessagesToBedrockMessages(context.Background(), input)
45144514
require.NoError(t, err)
45154515
require.Len(t, messages, 1)
45164516

@@ -4554,7 +4554,7 @@ func TestToolResultImageContentResponsesAPI(t *testing.T) {
45544554
},
45554555
}
45564556

4557-
messages, _, err := bedrock.ConvertBifrostMessagesToBedrockMessages(input)
4557+
messages, _, err := bedrock.ConvertBifrostMessagesToBedrockMessages(context.Background(), input)
45584558
require.NoError(t, err)
45594559
require.Len(t, messages, 1)
45604560

@@ -4587,7 +4587,7 @@ func TestToolResultImageContentResponsesAPI(t *testing.T) {
45874587
},
45884588
}
45894589

4590-
messages, _, err := bedrock.ConvertBifrostMessagesToBedrockMessages(input)
4590+
messages, _, err := bedrock.ConvertBifrostMessagesToBedrockMessages(context.Background(), input)
45914591
require.NoError(t, err)
45924592
require.Len(t, messages, 1)
45934593

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package bedrock
2+
3+
import (
4+
providerUtils "github.com/maximhq/bifrost/core/providers/utils"
5+
"github.com/maximhq/bifrost/core/schemas"
6+
)
7+
8+
// CachedContentCreate is unsupported on BedrockProvider. Only Gemini and Vertex AI
9+
// implement the cached-content lifecycle (Google AI Studio + Vertex AI named
10+
// caches). Other providers either lack named cache management entirely or
11+
// handle caching implicitly via per-message cache_control markers.
12+
func (provider *BedrockProvider) CachedContentCreate(ctx *schemas.BifrostContext, key schemas.Key, request *schemas.BifrostCachedContentCreateRequest) (*schemas.BifrostCachedContentCreateResponse, *schemas.BifrostError) {
13+
return nil, providerUtils.NewUnsupportedOperationError(schemas.CachedContentCreateRequest, provider.GetProviderKey())
14+
}
15+
16+
// CachedContentList is unsupported on BedrockProvider (see CachedContentCreate).
17+
func (provider *BedrockProvider) CachedContentList(ctx *schemas.BifrostContext, keys []schemas.Key, request *schemas.BifrostCachedContentListRequest) (*schemas.BifrostCachedContentListResponse, *schemas.BifrostError) {
18+
return nil, providerUtils.NewUnsupportedOperationError(schemas.CachedContentListRequest, provider.GetProviderKey())
19+
}
20+
21+
// CachedContentRetrieve is unsupported on BedrockProvider (see CachedContentCreate).
22+
func (provider *BedrockProvider) CachedContentRetrieve(ctx *schemas.BifrostContext, keys []schemas.Key, request *schemas.BifrostCachedContentRetrieveRequest) (*schemas.BifrostCachedContentRetrieveResponse, *schemas.BifrostError) {
23+
return nil, providerUtils.NewUnsupportedOperationError(schemas.CachedContentRetrieveRequest, provider.GetProviderKey())
24+
}
25+
26+
// CachedContentUpdate is unsupported on BedrockProvider (see CachedContentCreate).
27+
func (provider *BedrockProvider) CachedContentUpdate(ctx *schemas.BifrostContext, keys []schemas.Key, request *schemas.BifrostCachedContentUpdateRequest) (*schemas.BifrostCachedContentUpdateResponse, *schemas.BifrostError) {
28+
return nil, providerUtils.NewUnsupportedOperationError(schemas.CachedContentUpdateRequest, provider.GetProviderKey())
29+
}
30+
31+
// CachedContentDelete is unsupported on BedrockProvider (see CachedContentCreate).
32+
func (provider *BedrockProvider) CachedContentDelete(ctx *schemas.BifrostContext, keys []schemas.Key, request *schemas.BifrostCachedContentDeleteRequest) (*schemas.BifrostCachedContentDeleteResponse, *schemas.BifrostError) {
33+
return nil, providerUtils.NewUnsupportedOperationError(schemas.CachedContentDeleteRequest, provider.GetProviderKey())
34+
}

core/providers/bedrock/chat.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func ToBedrockChatCompletionRequest(ctx *schemas.BifrostContext, bifrostReq *sch
2424
}
2525

2626
// Convert messages and system messages
27-
messages, systemMessages, err := convertMessages(bifrostReq.Input)
27+
messages, systemMessages, err := convertMessages(ctx, bifrostReq.Input)
2828
if err != nil {
2929
return nil, fmt.Errorf("failed to convert messages: %w", err)
3030
}

0 commit comments

Comments
 (0)