Skip to content

adds CalculateCost and GetModelConfig for ctx in plugins - #5682

Merged
akshaydeo merged 1 commit into
devfrom
07-30-adds_calculatecost_and_getmodelinfo_for_ctx_in_plugins
Jul 30, 2026
Merged

adds CalculateCost and GetModelConfig for ctx in plugins#5682
akshaydeo merged 1 commit into
devfrom
07-30-adds_calculatecost_and_getmodelinfo_for_ctx_in_plugins

Conversation

@TejasGhatte

@TejasGhatte TejasGhatte commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

Summary

Plugins running inside Bifrost hooks had no way to look up model pricing or capability metadata without taking a direct dependency on the framework package, which core cannot import. This PR wires a ModelInfoProvider interface into the request context so every plugin hook — pre-request, pre-LLM, post-LLM, streaming, realtime, and MCP tool execution — can call ctx.GetModelInfo(provider, model) and ctx.CalculateCost(resp) without any extra construction-time wiring.

Changes

  • core/schemas/modelcatalog.go — introduces the ModelInfoProvider interface (declared in core, implemented in framework) mirroring how Tracer is wired: interface here, concrete type there, handle stamped onto the context per request.
  • core/schemas/bifrost.go — adds BifrostContextKeyModelCatalog context key and ModelCatalog ModelInfoProvider field to BifrostConfig.
  • core/schemas/context.go — adds GetModelInfo and CalculateCost accessor methods on BifrostContext. Both are inert (return nil / 0) when no catalog is configured, keeping plugins portable between the HTTP gateway and bare Go SDK embeddings.
  • core/bifrost.go — stores the catalog from BifrostConfig at Init, adds setModelCatalogOnContext which stamps (or clears) the handle on every entry point: handleRequest, handleStreamRequest, RunPreRequestHooks, RunStreamPreHooks, RunRealtimeTurnPreHooks, ExecuteChatMCPTool, and ExecuteResponsesMCPTool. The clear-on-nil path ensures long-lived realtime contexts don't serve a catalog that was subsequently removed.
  • framework/modelcatalog/modelinfo.go — adds GetModelInfo and CalculateRequestCost on *ModelCatalog, and extracts ApplyModelInfo as an exported function. All reference-typed fields (pointer scalars, slices, maps, Architecture) are deep-cloned on the way out so third-party plugin code cannot accidentally mutate catalog state or race the pricing sync.
  • transports/bifrost-http/handlers/inference.go — replaces the inline enrichment block in enrichListModelsResponse with a call to modelcatalog.ApplyModelInfo, so the list-models endpoint and ctx.GetModelInfo always use identical mapping logic.
  • transports/bifrost-http/handlers/middlewares.go — stamps the catalog onto the context in TransportInterceptorMiddleware so HTTPTransportPreHook sees it before the inference path runs.
  • transports/bifrost-http/server/server.go — passes ModelCatalog through to BifrostConfig at bootstrap.
  • Docsplugins.mdx documents the plugin-to-Bifrost communication model; writing-go-plugin.mdx adds full reference entries for both accessors; writing-wasm-plugin.mdx notes that these accessors are not reachable from WASM.

Notable design decisions:

  • The interface is declared in core/schemas and implemented in framework/modelcatalog to preserve the existing dependency direction (framework → core, never core → framework).
  • CalculateRequestCost is named differently from ModelCatalog.CalculateCost to avoid a signature collision on the concrete type while still letting the plugin-facing wrapper apply the full governance pricing chain.
  • The clear-on-nil behaviour in setModelCatalogOnContext is intentional: reused WebSocket contexts re-enter the stamping path on every message, so skipping the clear would leave a stale handle after SetModelCatalog(nil).

Type of change

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

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • Providers/Integrations
  • Plugins
  • UI (React)
  • Docs

How to test

go test ./core/... ./core/schemas/... ./framework/modelcatalog/... ./transports/bifrost-http/...

Two new integration tests in core/modelcataloghooks_test.go drive a real ChatCompletionRequest through a probe plugin and assert:

  • TestModelCatalogReachesPluginHooksOnRealRequest — all three hook phases (PreRequestHook, PreLLMHook, PostLLMHook) receive the catalog handle and return the expected model info and cost.
  • TestModelCatalogAbsentLeavesHooksInert — with no catalog wired, all accessors return zero values and no panic occurs.

Unit tests in core/schemas/modelcatalog_test.go cover delegation, empty-argument guards, plugin-scope visibility, and derived-context inheritance.

Unit tests in framework/modelcatalog/modelinfo_test.go cover pricing population, deprecation reporting, unknown model handling, provider-value preservation, and deep-clone correctness for all mutable fields.

Breaking changes

  • Yes
  • No

Security considerations

The ModelInfoProvider handle is stamped onto the request context and read back via a typed assertion. No credentials or secrets pass through this path. The deep-clone in ApplyModelInfo prevents a plugin from mutating shared catalog state, which would otherwise be a data-race vector on the pricing sync goroutine.

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

@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.

@TejasGhatte
TejasGhatte marked this pull request as ready for review July 30, 2026 10:25

Copy link
Copy Markdown
Collaborator Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 558c785d-9fd9-425e-8c6f-b49ed5e49501

📥 Commits

Reviewing files that changed from the base of the PR and between 1fc6277 and 13caf74.

📒 Files selected for processing (14)
  • core/bifrost.go
  • core/modelcataloghooks_test.go
  • core/schemas/bifrost.go
  • core/schemas/context.go
  • core/schemas/modelcatalog.go
  • core/schemas/modelcatalog_test.go
  • docs/architecture/core/plugins.mdx
  • docs/plugins/writing-go-plugin.mdx
  • docs/plugins/writing-wasm-plugin.mdx
  • framework/modelcatalog/modelinfo.go
  • framework/modelcatalog/modelinfo_test.go
  • transports/bifrost-http/handlers/inference.go
  • transports/bifrost-http/handlers/middlewares.go
  • transports/bifrost-http/server/server.go
🚧 Files skipped from review as they are similar to previous changes (4)
  • docs/architecture/core/plugins.mdx
  • docs/plugins/writing-wasm-plugin.mdx
  • core/schemas/modelcatalog_test.go
  • docs/plugins/writing-go-plugin.mdx

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Added a model catalog that provides model capabilities, pricing, deprecation status, and calculates request costs.
    • Exposed plugin helpers to fetch model info and compute costs from request context.
    • Ensured catalog availability across standard, streaming, realtime, and MCP tool execution paths, with consistent behavior when no catalog is configured.
  • Documentation
    • Documented plugin access patterns for model info and cost calculation, including WASM limitations.
  • Tests
    • Added coverage for catalog-to-plugin hook propagation, correct cost calculation, metadata merging, and inert behavior when the catalog is absent.

Walkthrough

Adds a model catalog provider contract, context accessors for model metadata and cost, catalog-backed model enrichment, and propagation through Bifrost, transport, MCP, and plugin hook execution paths. Tests and documentation cover configured and absent catalog behavior.

Changes

Model catalog integration

Layer / File(s) Summary
Catalog contracts and context accessors
core/schemas/*, docs/architecture/core/plugins.mdx, docs/plugins/*
Defines ModelInfoProvider, configuration and context-key contracts, GetModelInfo, CalculateCost, and plugin documentation for Go and WASM contexts.
Catalog lookup and pricing operations
framework/modelcatalog/modelinfo.go, framework/modelcatalog/modelinfo_test.go, transports/bifrost-http/handlers/inference.go
Adds catalog metadata lookup, cloning and merge behavior, request cost calculation, nil safety, centralized model enrichment, and corresponding tests.
Request-context catalog propagation
core/bifrost.go, transports/bifrost-http/handlers/middlewares.go, transports/bifrost-http/server/server.go
Propagates the configured catalog through standard, streaming, realtime, MCP, transport, and initialization paths.
Hook integration validation
core/modelcataloghooks_test.go
Verifies catalog access and cost calculation across plugin hook phases, plus inert behavior when no catalog is configured.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

  • maximhq/bifrost#5599: Adds similar model-catalog context propagation and plugin accessors.
  • maximhq/bifrost#5640: Modifies the overlapping model-catalog context dependency using model-directory terminology.
  • maximhq/bifrost#5561: Adds model-catalog synchronization and configuration plumbing used by the HTTP server.

Suggested reviewers: akshaydeo, danpiths, pratham-mishra04

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Title check ⚠️ Warning It matches the main feature, but says GetModelConfig instead of the added GetModelInfo API. Rename it to mention GetModelInfo and keep CalculateCost, e.g. "adds GetModelInfo and CalculateCost for plugin ctx".
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The PR description is mostly complete and covers summary, changes, testing, breaking changes, security, and checklist items.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ 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 07-30-adds_calculatecost_and_getmodelinfo_for_ctx_in_plugins

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (1)
core/modelcataloghooks_test.go (1)

164-166: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

infoCalls is recorded but never asserted.

Asserting infoCalls == 3 alongside costCalls would pin down that all three hook phases actually reached the catalog, rather than inferring it from the recorded pointers.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/modelcataloghooks_test.go` around lines 164 - 166, Add an assertion
beside the existing costCalls check in the relevant test to verify
catalog.infoCalls equals 3, reporting the actual count and expected value
consistently. Use the existing infoCalls field on catalog without changing the
surrounding hook behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@core/modelcataloghooks_test.go`:
- Around line 183-189: Strengthen the no-catalog test around the relevant hook
execution checks: require the pre-request and pre-LLM hooks to have run before
asserting their captured info is nil, mirroring the positive test’s guard.
Update the assertions associated with preRequestInfo and preLLMInfo while
preserving the existing postRan and postInfo checks.

In `@docs/plugins/writing-go-plugin.mdx`:
- Around line 455-459: Update the catalog key-points guidance to clarify that
optionality applies to pointer, map, and slice metadata fields, which must be
nil-checked individually. Identify ID and IsDeprecated as non-optional value
fields, and keep the documented nullability aligned with the schemas.Model
definition.

In `@framework/modelcatalog/modelinfo_test.go`:
- Around line 163-165: Extend the test around the first and second model lookups
to assert the expected state of second.SupportedParameters after mutating
first.SupportedParameters[0]. Use the existing second lookup variables and
verify the aliasing behavior intended by the related modelinfo.go change.

In `@framework/modelcatalog/modelinfo.go`:
- Around line 39-41: Ensure ApplyModelInfo clones the slice returned by
GetSupportedParameters before assigning SupportedParameters, preserving caller
ownership; update framework/modelcatalog/modelinfo.go lines 39-41. Extend the
regression test in framework/modelcatalog/modelinfo_test.go lines 163-165 to
assert the second GetModelInfo result does not retain the mutated value, such as
verifying second.SupportedParameters[0] is not "mutated".

---

Nitpick comments:
In `@core/modelcataloghooks_test.go`:
- Around line 164-166: Add an assertion beside the existing costCalls check in
the relevant test to verify catalog.infoCalls equals 3, reporting the actual
count and expected value consistently. Use the existing infoCalls field on
catalog without changing the surrounding hook 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: cb453fab-4ebd-4ccd-bc42-0710e4fc7f0c

📥 Commits

Reviewing files that changed from the base of the PR and between ef0507b and 1fc6277.

📒 Files selected for processing (14)
  • core/bifrost.go
  • core/modelcataloghooks_test.go
  • core/schemas/bifrost.go
  • core/schemas/context.go
  • core/schemas/modelcatalog.go
  • core/schemas/modelcatalog_test.go
  • docs/architecture/core/plugins.mdx
  • docs/plugins/writing-go-plugin.mdx
  • docs/plugins/writing-wasm-plugin.mdx
  • framework/modelcatalog/modelinfo.go
  • framework/modelcatalog/modelinfo_test.go
  • transports/bifrost-http/handlers/inference.go
  • transports/bifrost-http/handlers/middlewares.go
  • transports/bifrost-http/server/server.go

Comment thread core/modelcataloghooks_test.go Outdated
Comment thread docs/plugins/writing-go-plugin.mdx
Comment thread framework/modelcatalog/modelinfo_test.go Outdated
Comment thread framework/modelcatalog/modelinfo.go
@TejasGhatte
TejasGhatte force-pushed the 07-30-adds_calculatecost_and_getmodelinfo_for_ctx_in_plugins branch from 1fc6277 to 13caf74 Compare July 30, 2026 10:47

akshaydeo commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Merge activity

  • Jul 30, 11:12 AM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Jul 30, 11:13 AM UTC: @akshaydeo merged this pull request with Graphite.

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