core/v1.7.15
firecrawl/pdf-inspectorcore/v1.7.15Aug 27, 2026by akshaydeo
AI Summary
A major core update adding support for Gemini tool signatures, Runware 3D generation, and optimizing Bedrock and Vertex integrations.
Key Highlights
- Added support for Gemini server-side tool calls with thought signature round-trip fidelity
- Introduced async 3D generation on Runware with cost tracking
- Enabled sending s3:// references directly to Bedrock Converse to avoid downloading and re-uploading
- Resolved Vertex URL sources per model family to support multi-hundred-MB video inputs
Breaking Changes
- Breaking on the Gemini API surface: requests carrying both function declarations and Google Search without `includeServerSideToolInvocations` now drop Google Search and send function declarations instead.
New Features
- Support for Gemini server-side toolCall/toolResponse with thoughtSignature round-trip fidelity
- Async 3D generation on Runware via /videos and raw /runware_passthrough route
- Surface Runware provider-reported per-task cost across image, video/3D, and passthrough
- Send s3:// image and document references to Bedrock Converse as s3Location
- Resolve Vertex URL sources per model family (forward gs:// to Gemini/Gemma)
- Filter Accept-Encoding on passthrough headers to supported codecs (gzip, deflate, brotli, zstd)
Full Release Notes
## Core Release v1.7.15
- feat: support Gemini's server-side `toolCall`/`toolResponse` parts with `thoughtSignature` round-trip fidelity - server-side search rounds now surface as `web_search_call` items carrying their own call ID and queries, unmapped tool types are preserved on the native round-trip instead of being dropped, and each `thoughtSignature` appears exactly once across the reconstructed parts so Gemini accepts the replayed turn
- feat: async 3D generation on Runware via `/videos` plus a raw `/runware_passthrough` route - `taskType` is now read from extra_params so any Runware async task can be driven through `/videos` (the 16:9 1080p width/height defaults now apply only to `videoInference`), `outputs.files[].url` is surfaced as `VideoOutput` URLs with the content type derived from the file extension, and the passthrough route forwards raw task arrays for capabilities with no first-class Bifrost surface such as upscaling and background removal
- feat: surface Runware's provider-reported per-task `cost` across image, video/3D and passthrough so pricing uses the exact figure verbatim instead of a datasheet estimate - this matters for task types like 3D that have no datasheet rate; when no cost is reported the behavior is unchanged
- feat: send `s3://` image and document references to Bedrock Converse as the `s3Location` source member instead of downloading the bytes and re-uploading them - Converse resolves the object itself, which skips a round trip and the 25 MiB inline cap entirely. Image format is derived from the object extension since nothing is fetched and there is no `Content-Type` to read, and an extension-less object is rejected up front rather than producing an opaque 400
- feat: resolve Vertex URL sources per model family rather than inlining everything - a `gs://` URI is now forwarded to Gemini/Gemma as `fileData.fileUri` (the documented form, resolved under the caller's own project IAM, and the only thing that keeps multi-hundred-MB video inputs viable) and read from Cloud Storage with the request key's own Google credentials for Claude-on-Vertex, which accepts base64 sources only. `http(s)` is still always fetched: forwarding one was measured against the harness and Vertex rejected every endpoint shape with `URL_REJECTED-REJECTED_FC_TOO_MANY_PENDING`
- feat: filter `Accept-Encoding` on passthrough headers to codecs Bifrost can actually decode, and expand `CheckAndDecodeBody` to deflate, brotli, zstd and chained encodings - buffered requests now forward `gzip`, `x-gzip`, `deflate`, `br`, `zstd` and `identity` (unsupported tokens and `*` are stripped, and the header is dropped entirely when nothing survives), while streaming endpoints use a dedicated `SetPassthroughHeadersForStreaming` that restricts the offer to `gzip`/`x-gzip`/`identity`, since brotli and zstd need the full buffer and cannot be decoded incrementally mid-SSE. `CheckAndDecodeBody` applies chained encodings in reverse order per RFC 9110 and returns an explicit error for anything it cannot decode
- fix: allow Vertex AI to send function declarations and a Google Search tool in the same request without `includeServerSideToolInvocations` - Vertex accepts the combination natively, so Google Search was being dropped for no reason, and search localization via `RetrievalConfig.LatLng` is now preserved when both tool types are present
- fix: prefer function declarations over Google Search when tool combination is disabled on Gemini - Google's tool combination is Preview and Gemini 3 only (https://ai.google.dev/gemini-api/docs/generate-content/tool-combination), so on every other model one of the two tool types has to be dropped. Function declarations now win: they carry the caller's own tools, or the ones Bifrost's MCP gateway synthesized from their connected servers, and dropping those leaves the model unable to invoke them at all while it answers as though the capabilities never existed. Dropping Google Search only costs grounding, so the model still answers, just without citations. One is disabled, the other is degraded. Set `include_server_side_tool_invocations` to send both. A lone Google Search tool still converts back correctly, and `retrievalConfig` is only emitted when a search tool actually survived conversion
<Warning>
Breaking on the Gemini API surface: a request carrying both function declarations and Google Search without `include_server_side_tool_invocations` previously kept Google Search and dropped the function declarations. It now does the opposite. Set `include_server_side_tool_invocations` to `true` to send both, which is supported on Gemini 3 models. Vertex is unaffected, since it accepts the combination natively and drops neither.
</Warning>
- fix: always emit a Gemini candidate carrying its finish reason on `generateContent`, even when nothing visible was generated - a thinking model that spends its whole output budget before emitting a token is a successful 200 with an empty answer, but `Candidates` is `omitempty`, so dropping that candidate produced a body with no `candidates` key at all and left a lone `usageMetadata` object that every Gemini-shaped client dereferences blind
- fix: drop payload-free Gemini parts when assembling a candidate - every `Part` field is `omitempty`, so such a part marshals to exactly `{}`; the harness observed one on the wire when a transcription request for an unintelligible tone came back as `parts:[{}]`, where it is noise a client will try to read and it masks the contentless case by making the parts slice look non-empty
- fix: accept a bare model identifier on Bedrock rerank by synthesizing the foundation-model ARN from the resolved region - Rerank is the one Bedrock surface that names its model by ARN rather than by bare ID, so all three rerank drop-ins in the provider harness 400'd on `amazon.rerank-v1:0`. The partition is derived from the region (`aws`, `aws-cn`, `aws-us-gov`) so GovCloud and China build a correct ARN, and an explicit ARN still passes through untouched
- fix: stop stripping `file_url` from OpenAI-shaped chat file blocks on marshal - dropping it produced `{"type":"file","file":{}}` and an upstream complaint about a missing `file_id`, which hid the fact that a source had been discarded. Providers that cannot take a URL now say so by name, and any OpenAI-compatible endpoint that does accept one keeps working without a Bifrost change
- fix: leave URL content sources Bifrost cannot download in place on the OpenAI and native-Anthropic paths instead of failing the request - only `http(s)` is fetched, and whether a `gs://`, `s3://` or scheme-less reference is usable is the provider's call, so the source now travels as `{"type":"url"}` and the platform answers for itself
- fix: redact identity-aware-proxy headers before connector export - `RedactSensitiveHeaders` replaces the value of every header `IsSensitiveHeader` matches with the redaction marker while keeping the key visible in telemetry, and the sensitive set now covers Cloudflare Access (`cf-access-*`, including `cf-access-jwt-assertion`) and AWS ALB OIDC (`x-amzn-oidc-*`) headers plus generic `jwt`/`assertion` substring patterns, so a broad capture pattern like `*` can no longer ship credential-bearing headers to observability backends
- fix: clear Anthropic raw-body passthrough per resolved provider and model, not provider alone - Vertex, Azure and Bedrock Mantle are multi-family: they serve the Anthropic Messages API for Claude models and OpenAI/Gemini surfaces for everything else, so the blanket provider exemption let a routing rule that retargets a Claude Code request to a non-Claude model on one of them pass the raw Anthropic body to an endpoint that does not speak it. The exemption now reuses the same `IsAnthropicModelFamily` predicate those providers' own dispatch uses, evaluated after key-level alias resolution, and raw-capture signals are derived after the clearing step so a converted response is no longer captured and left unstripped on a request that no longer passes anything through
- fix: strip a replayed encrypted reasoning signature when the upstream says the field is unsupported, not only when it fails to verify - Bedrock Converse answers a Claude-minted signature replayed onto a non-Anthropic model (a mid-conversation model switch onto Kimi, GLM or DeepSeek) with "This model doesn't support the reasoningContent.reasoningText.signature field" rather than a verification failure, and that model will never accept the token, so it earns the same fail-soft strip
### Installation
```bash
go get github.com/maximhq/bifrost/core@v1.7.14
```
---
_This release was automatically created from version file: `core/version`_