Skip to content

fix(opencode): run live metadata updates from plugin tools - #47486

Closed
llucax wants to merge 1 commit into
anomalyco:devfrom
llucax:bridge-plugin-metadata
Closed

llucax wants to merge 1 commit into
anomalyco:devfrom
llucax:bridge-plugin-metadata

Conversation

@llucax

@llucax llucax commented Sep 5, 2026 •

Copy link
Copy Markdown

Issue for this PR

Closes #50313

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

ToolContext.metadata() is a plain void call in the plugin API, but the host context returns an Effect. fromPlugin() bridges ask() and spreads the rest, so a plugin calling context.metadata() builds an Effect that nobody runs and
the update is dropped. Metadata only shows up once the tool returns it in its final result, which is too late for anything that wants to report progress, or publish a child session id while it is still working.

This bridges metadata() the same way ask() is bridged. It is forked rather than awaited because the public signature is synchronous while the host update is not.

How did you verify your code works?

Added a regression test in packages/opencode/test/tool/registry.test.ts that loads a real custom tool calling context.metadata() mid-execution and asserts the host callback receives the update before the tool returns. It fails on dev and passes with the fix.

  • bun test test/tool/registry.test.ts in packages/opencode: 16 pass
  • same, with the registry.ts change reverted: 1 fail, so the test covers the bug
  • bun test test/tool/: 342 pass
  • bun typecheck in packages/opencode: clean

Screenshots / recordings

Not applicable, this is a server-side plugin bridge.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

@wulart

wulart commented Sep 19, 2026 •

Copy link
Copy Markdown

Ran into this with a plugin tool that publishes progress mid-execution — can confirm the diagnosis and the fix still hold against current dev (verified on 9a53565):

  • Without the patch, a custom tool calling context.metadata({ title: "step 1" }) during execution never reaches the host callback — the unexecuted Effect is returned to the plugin and silently dropped.
  • With the same one-line bridge.fork bridge (plus a regression test of the same shape in test/tool/registry.test.ts): bun test test/tool/registry.test.ts 16/16, bun test test/plugin/ 210/210, tsgo --noEmit clean.

The fork-not-await shape matches the ask bridge from #28217, which is exactly right for the sync-void public signature. Hope this can get a review — happy to help land it if anything is needed.

@llucax

llucax commented Sep 20, 2026

Copy link
Copy Markdown
Author

Not sure how to get some attention from maintainers here.

@wulart

wulart commented Sep 20, 2026

Copy link
Copy Markdown

Two things that might help:

  1. Heads-up on the linked issue: [BUG]: Plugin tool context.metadata() does not publish live updates after Effect migration #37877 was closed by the stale bot on Sep 20 (60-day inactivity), not by a maintainer — so the Closes #37877 in the description won't do anything on merge now. Might be worth a note in the PR body, otherwise a reviewer glancing at "linked issue: closed" could read it as already handled.

  2. FWIW we hit the same bug in a downstream fork and independently shipped the identical bridge last week — bridge.fork(toolCtx.metadata(input)) in registry.ts, line-for-line the same shape as yours apart from comments. So beyond my earlier one-off repro, the patch has convergent-implementation backing.

On getting attention: with ~6k open PRs the review queue doesn't seem to move on its own — the project Discord is probably the realistic channel for a ping with the PR link.

@llucax

llucax commented Sep 21, 2026 •

Copy link
Copy Markdown
Author

It seems the first important step is to get good reactions to this PR to avoid getting closed automatically.

The repo has .github/workflows/close-prs.yml running daily at 22:00 UTC, calling script/github/close-prs.ts --threshold 2 --age-months 1. It closes every open PR older than one month with fewer than 2 positive reactions. Positive means 👍, ❤️, 🎉 or 🚀 counted on the PR itself; reactions on comments don't count. This PR opened on Sep 5 with no reactions, so the first run that matches it is 2026-10-05 at 22:00 UTC.

#18631 (#18631) fixed the same thing and was closed by exactly that cleanup on 2026-05-15. #38365 (#38365) fixed it again in July and was auto-closed two hours later because the template checkboxes weren't ticked. This is the third attempt and the first compliant one.

Will create a new issue and send a small message to discord.

@llucax

llucax commented Sep 21, 2026

Copy link
Copy Markdown
Author

Re-filed as #50313 against current dev, and the description here closes that one now. @wulart you might want to add a reaction to avoid getting it automatically closed.

The plugin API declares ToolContext.metadata() as a plain void call, but
the host context returns an Effect. fromPlugin() bridged ask() and spread
the rest, so a plugin calling context.metadata() built an Effect nobody
ran and the update was dropped: clients only saw metadata once the tool
returned it in its final result.

Bridge metadata() the same way ask() is bridged, forking it because the
public signature is synchronous and the host update is not.
@llucax
llucax force-pushed the bridge-plugin-metadata branch from 433b15e to f947562 Compare September 28, 2026 07:08
@thdxr

thdxr commented Oct 10, 2026

Copy link
Copy Markdown
Member

This branch has been upgraded to V2. We're no longer taking PRs for V1. If you think this is still relevant, please port it over and open it for V2.

— from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊

@thdxr thdxr closed this Oct 10, 2026
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.

[BUG]: Plugin tool context.metadata() is never executed, so live updates are dropped

3 participants