-
Notifications
You must be signed in to change notification settings - Fork 61
feat: enhance plugin system with short-circuit capability and cleanup method #69
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Caution Review failedThe pull request is closed. Summary by CodeRabbit
Summary by CodeRabbit
WalkthroughThe changes update the Bifrost plugin system by extending the Changes
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (4)
✨ Finishing Touches
🧪 Generate Unit Tests
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
This stack of pull requests is managed by Graphite. Learn more about stacking. |
There was a problem hiding this 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
🔭 Outside diff range comments (1)
core/bifrost.go (1)
525-551
:⚠️ Potential issuePost-hook is executed for plugins whose Pre-hook never ran
When a plugin short-circuits (
resp != nil
) you runPostHook
for all
plugins:for i := len(bifrost.plugins) - 1; i >= 0; i-- { … }Plugins located after the short-circuiting one never had their
PreHook
executed, yet theirPostHook
is invoked, breaking the documented “reverse
order of executed PreHooks” contract and risking panics due to missing
state.Minimal fix – track executed plugins:
-var resp *schemas.BifrostResponse +var ( + resp *schemas.BifrostResponse + executedPlugins []schemas.Plugin +) for _, plugin := range bifrost.plugins { - req, resp, err = plugin.PreHook(&ctx, req) + req, resp, err = plugin.PreHook(&ctx, req) … - if resp != nil { - for i := len(bifrost.plugins) - 1; i >= 0; i-- { - resp, err = bifrost.plugins[i].PostHook(&ctx, resp) + executedPlugins = append(executedPlugins, plugin) + if resp != nil { + for i := len(executedPlugins) - 1; i >= 0; i-- { + resp, err = executedPlugins[i].PostHook(&ctx, resp) … } return resp, nil } }Apply the same fix in
tryChatCompletion
.
♻️ Duplicate comments (1)
core/bifrost.go (1)
528-528
: 🛠️ Refactor suggestionPass
context.Context
, not*context.Context
Continuing the pattern from the interface,
plugin.PreHook(&ctx, req)
leaks the
non-idiomatic pointer usage into every call-site. Switching the interface to
plaincontext.Context
(see previous comment) removes the need for the&
operator here and simplifies code.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (2)
core/bifrost.go
(4 hunks)core/schemas/plugin.go
(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
core/bifrost.go (1)
core/schemas/bifrost.go (3)
BifrostResponse
(191-201)BifrostError
(319-325)ErrorField
(328-335)
core/schemas/plugin.go (1)
core/schemas/bifrost.go (2)
BifrostRequest
(54-64)BifrostResponse
(191-201)
8b88c85
to
58dfdd3
Compare
There was a problem hiding this 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
♻️ Duplicate comments (2)
core/schemas/plugin.go (1)
25-33
: 🛠️ Refactor suggestionAvoid
*context.Context
– passcontext.Context
by value
context.Context
is already reference-like and designed to be passed by value.
Using a pointer is non-idiomatic, invites nil-dereference foot-guns, and complicates cancellation / deadline propagation.-PreHook(ctx *context.Context, req *BifrostRequest) (*BifrostRequest, *BifrostResponse, error) +PreHook(ctx context.Context, req *BifrostRequest) (*BifrostRequest, *BifrostResponse, error) -PostHook(ctx *context.Context, result *BifrostResponse) (*BifrostResponse, error) +PostHook(ctx context.Context, result *BifrostResponse) (*BifrostResponse, error)If a plugin truly needs to mutate the context, let it return a new context (or embed values) rather than taking a pointer.
This change ripples to every implementation & call-site (
core/bifrost.go
, examples in docs, plugins), but keeps the public interface idiomatic and safer.docs/plugins.md (1)
28-34
: 🧹 Nitpick (assertive)Docs drift: update signatures to match idiomatic interface
Once
*context.Context
is removed from thePlugin
interface, the documentation and all code snippets here must be updated accordingly:-PreHook(ctx *context.Context, req *BifrostRequest) (*BifrostRequest, *BifrostResponse, error) +PreHook(ctx context.Context, req *BifrostRequest) (*BifrostRequest, *BifrostResponse, error) … -PostHook(ctx *context.Context, result *BifrostResponse) (*BifrostResponse, error) +PostHook(ctx context.Context, result *BifrostResponse) (*BifrostResponse, error)Keeping docs in lock-step with the exported API prevents consumer confusion.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (4)
core/bifrost.go
(11 hunks)core/schemas/plugin.go
(1 hunks)core/utils.go
(1 hunks)docs/plugins.md
(5 hunks)
🧰 Additional context used
🧠 Learnings (1)
core/bifrost.go (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#65
File: transports/bifrost-http/integrations/utils.go:169-173
Timestamp: 2025-06-09T17:33:52.234Z
Learning: The ChatCompletionRequest method in the Bifrost client follows a contract where the result parameter will never be nil if the error parameter is nil. This means when error checking passes (err == nil), the result is guaranteed to be valid and can be safely used without additional nil checks.
🧬 Code Graph Analysis (2)
core/utils.go (1)
core/schemas/bifrost.go (2)
BifrostError
(319-325)ErrorField
(328-335)
core/schemas/plugin.go (1)
core/schemas/bifrost.go (2)
BifrostRequest
(54-64)BifrostResponse
(191-201)
🔇 Additional comments (1)
core/bifrost.go (1)
520-537
:❌ Incorrect review comment
Propagate the context-pointer fix to hook invocations
After switching the interface to take
context.Context
by value, adjust the calls:-req, resp, err = plugin.PreHook(&ctx, req) +req, resp, err = plugin.PreHook(ctx, req) … -resp, err = bifrost.plugins[j].PostHook(&ctx, resp) +resp, err = bifrost.plugins[j].PostHook(ctx, resp)(The same substitution is required in
tryChatCompletion
and the post-provider hook loop.)Without this, the code will no longer compile once the interface is corrected.
Let’s confirm the current signatures of
PreHook
/PostHook
and where the plugin interface is defined:
🏁 Script executed:
#!/bin/bash # List all interface blocks (to locate the plugin interface) rg -n "interface" -n . # Find all PreHook signatures and references rg -n -C2 "PreHook(" -n . # Find all PostHook signatures and references rg -n -C2 "PostHook(" -n .Length of output: 26310
Let’s confirm the Plugin interface signatures and how
ctx
is declared before these calls:
🏁 Script executed:
#!/bin/bash # Show the Plugin interface definition around PreHook/PostHook rg -A5 -n "type Plugin interface" core/schemas/plugin.go # Show PreHook signature in Plugin interface rg -A3 -n "PreHook" core/schemas/plugin.go # Show PostHook signature in Plugin interface rg -A3 -n "PostHook" core/schemas/plugin.go # Inspect ctx declaration and hook invocations in core/bifrost.go around line 520 sed -n '480,550p' core/bifrost.goLength of output: 5214
Ignore context-pointer invocation suggestion
The
Plugin
interface still expects*context.Context
(see core/schemas/plugin.go), and all current calls incore/bifrost.go
correctly pass&ctx
to bothPreHook
andPostHook
. No changes are required until the interface itself is updated.Likely an incorrect or invalid review comment.
58dfdd3
to
9150fa1
Compare
There was a problem hiding this 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
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (4)
core/bifrost.go
(11 hunks)core/schemas/plugin.go
(1 hunks)core/utils.go
(1 hunks)docs/plugins.md
(5 hunks)
🧰 Additional context used
🧠 Learnings (1)
core/bifrost.go (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#65
File: transports/bifrost-http/integrations/utils.go:169-173
Timestamp: 2025-06-09T17:33:52.234Z
Learning: The ChatCompletionRequest method in the Bifrost client follows a contract where the result parameter will never be nil if the error parameter is nil. This means when error checking passes (err == nil), the result is guaranteed to be valid and can be safely used without additional nil checks.
🧬 Code Graph Analysis (2)
core/utils.go (1)
core/schemas/bifrost.go (2)
BifrostError
(365-371)ErrorField
(374-381)
core/schemas/plugin.go (1)
core/schemas/bifrost.go (2)
BifrostRequest
(59-69)BifrostResponse
(237-247)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: Graphite / mergeability_check
🔇 Additional comments (10)
core/schemas/plugin.go (3)
19-20
: Good documentation addition.This comment clearly states the error handling behavior for plugins, which is important for developers to understand.
25-27
: Well-documented API enhancement.The PreHook signature change is clearly documented with the short-circuit behavior explained. The implementation aligns with the PR objectives.
34-38
: Excellent addition for resource management.The Cleanup method provides a proper lifecycle hook for plugins to release resources during shutdown. The documentation clearly states the error handling behavior.
core/utils.go (1)
9-30
: Clean helper functions for consistent error handling.These helpers effectively reduce code duplication when creating BifrostError instances. The implementation correctly sets
IsBifrostError
to false for non-Bifrost errors.core/bifrost.go (3)
520-538
: Correct implementation of short-circuit behavior.The logic properly tracks which plugins had their PreHook executed and ensures only their PostHooks are called in reverse order when short-circuiting. This maintains the documented symmetry between PreHook and PostHook calls.
750-757
: Proper plugin cleanup implementation.The code correctly iterates through all plugins to call their Cleanup methods and logs any errors as warnings, consistent with the documented plugin error handling behavior.
604-613
: Consistent error handling refactoring.Good use of the
newBifrostErrorFromMsg
helper for static error messages, maintaining consistency throughout the codebase.docs/plugins.md (3)
22-23
: Important clarification for plugin developers.This note clearly explains the PostHook execution behavior during short-circuiting, which is crucial for understanding the plugin lifecycle.
27-44
: Accurate interface documentation.The plugin interface documentation correctly reflects the changes to PreHook and the addition of the Cleanup method, matching the actual interface definition.
56-70
: Well-updated examples demonstrating the new API.All example plugins correctly implement the new PreHook signature (returning
nil
for the response to continue normal processing) and include appropriate Cleanup methods. These examples provide clear guidance for plugin developers.Also applies to: 86-101, 114-127, 263-277
ead45eb
to
fc217ab
Compare
9150fa1
to
bd7a68a
Compare
bd7a68a
to
a0b4c6d
Compare
fc217ab
to
05c93c4
Compare
a0b4c6d
to
a58b1c6
Compare
72a4006
to
e437920
Compare
a58b1c6
to
c4aee9d
Compare
Merge activity
|
c4aee9d
to
f69a51c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅ BugBot reviewed your changes and found no bugs!
BugBot free trial expires on June 17, 2025
You have used $0.00 of your $50.00 spend limit so far. Manage your spend limit in the Cursor dashboard.
Was this report helpful? Give feedback by reacting with 👍 or 👎
Allow plugins to short-circuit request processing
This PR enhances the plugin system by allowing plugins to short-circuit the request processing flow. The
PreHook
method signature has been updated to return an optional response in addition to the modified request.When a plugin returns a non-nil response from its
PreHook
method, Bifrost will skip the provider call and immediately run all remaining plugins'PostHook
methods in reverse order before returning the response to the client.This change enables plugins to:
The implementation maintains the existing error handling pattern while adding the new short-circuit capability.