fix(plugin): run awaited plugin ctx.ask + ctx.metadata through EffectBridge#1127
Conversation
|
Warning Review limit reached
More reviews will be available in 1 minute and 26 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Code Review
This pull request changes the plugin tool context's ask method signature from returning an Effect to returning a Promise, and introduces EffectBridge in the tool registry to bridge the framework's Effect-based ask implementation. A corresponding test has been added to verify that the bridged permission request actually runs. The reviewer pointed out that toolCtx.metadata is also an Effect-returning function in the framework but is typed as returning void in the plugin context, which makes it a silent no-op. They suggested bridging metadata using bridge.promise as well to ensure it executes correctly.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
340320d to
08c7c7e
Compare
…Bridge Plugin tools declare ctx.ask as Promise<void> and ctx.metadata as void, but the framework versions are Effects. The fromPlugin bridge spread toolCtx straight through, so the returned Effects were never executed: an awaited ctx.ask(...) resolved an inert Effect (permission prompt a silent no-op, tool ran as if granted) and ctx.metadata(...) discarded its Effect (title/metadata never applied). Bridge both through EffectBridge.make().promise(): ask is awaited, metadata is fire-and-forget (void contract) with a warn on failure. Update the plugin ToolContext ask contract to Promise<void> (dropping the now-unused Effect import); metadata was already typed void. Regression test: a .opencode/tool plugin whose execute awaits ctx.ask and calls ctx.metadata now observes both framework Effects run exactly once (0 before the bridge, 1 after). Semantic port of anomalyco/opencode#28217 (ctx.metadata gap caught in review).
08c7c7e to
b119c55
Compare
Review notesCodex review (xhigh): PASS — one P2 advisory, no P1. Two judgment calls relative to the raw upstream port (
|
What
Plugin tools declare
ctx.askasPromise<void>andctx.metadataasvoid, but the framework versions are Effects. ThefromPluginbridge spreadtoolCtxstraight through (...toolCtx), so the returned Effects were never executed:await ctx.ask(...)resolved an inert Effect object — the permission prompt was a silent no-op and the tool proceeded as if every request had been granted.ctx.metadata(...)discarded its Effect — the tool's title/metadata was never applied.Both are bridged through
EffectBridge.make().promise():askis awaited;metadatais fire-and-forget (matching itsvoidcontract) with alog.warnon failure. The pluginToolContextaskcontract becomesPromise<void>(dropping the now-unusedEffectimport);metadatawas already typedvoid.Why
Semantic port of anomalyco/opencode#28217. PawWork has the same
fromPluginshape, so the same silent-no-op bug applies. Thectx.metadatahalf was caught in review (gemini-code-assist) — same file, same bug class, same fix.Boundary
Three files, all within the plugin/tool surface:
packages/opencode/src/tool/registry.ts— bridge the pluginask+metadatapackages/plugin/src/tool.ts—askcontractEffect.Effect<void>→Promise<void>packages/opencode/test/tool/registry.test.ts— regression testVerification
bun test test/tool/registry.test.ts— 23 pass. New test red→green confirmed for both: with the un-bridged spread, each framework Effect runs 0 times (silent no-op); with the bridge, each runs exactly once (askawaited,metadatafire-and-forget then flushed).bun run typecheck— clean in bothpackages/opencodeandpackages/plugin.packages/opencode/src/tool/*.ts) use the frameworkTool.Context(yield* ctx.ask/ctx.metadata), not the pluginToolContext, so they are unaffected.Risk
Low. Only the plugin-tool execution path changes; the bridge provides full Effect context, so the permission service and instance are intact when the bridged Effects run.