Skip to content

feat(plugin): let tool.execute.before short-circuit with a result - #32679

Closed
OddballGreg wants to merge 1 commit into
anomalyco:devfrom
OddballGreg:feat/tool-before-short-circuit
Closed

OddballGreg wants to merge 1 commit into
anomalyco:devfrom
OddballGreg:feat/tool-before-short-circuit

Conversation

@OddballGreg

Copy link
Copy Markdown

Issue for this PR

Refs #5148

Type of change

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

What does this PR do?

It lets a plugin short-circuit a tool call from tool.execute.before by supplying the result itself.

tool.execute.before currently only exposes { args }, so a plugin can rewrite arguments but cannot prevent the tool from running. In SessionTools.resolve the runtime always calls the tool after the hook (the native path around L92 and the MCP path around L135). tool.execute.after can rewrite the output, but only after the work already happened, and permission.ask can deny a call but returns an error rather than a usable result.

This adds an optional result?: string to the before-hook output. If a plugin sets it, the tool is not executed and that string is returned as the tool output instead; tool.execute.after still runs on the substituted result. It is wired through both the native and MCP tool paths. Hooks that do not set result behave exactly as before, so it is backwards compatible.

The motivating case is a cache/memory plugin that already holds the answer for a read/grep and wants to return it instead of doing the read. This is the minimal "early termination" slice of the broader middleware pipeline discussed in #5148 (a prior attempt, #18689, implemented a larger version but was auto-closed before review). The Hooks interface is hand-written in packages/plugin, so no SDK regeneration applies.

How did you verify your code works?

bun run typecheck passes for both the opencode and plugin packages (no errors in the changed files), prettier --check is clean, and oxlint reports no errors on the two files. I did not add an automated test: the SessionTools.resolve plugin-hook path has no existing unit-test harness and a full session/plugin integration test would be disproportionate to the change, so I verified by typechecking and tracing both branches. Happy to add coverage if you can point me at the right harness.

Screenshots / recordings

Not a UI change.

Checklist

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

Extend the tool.execute.before hook output with an optional result string.
When a plugin sets it, the tool is not executed and the supplied string is
returned as the tool output instead; the tool.execute.after hook still runs on
the substituted result. Wired through both the native and MCP tool paths in
SessionTools.resolve. Backwards compatible: hooks that don't set result behave
exactly as before.

Enables cache/memory plugins to answer a tool call they already hold the result
for (e.g. returning an indexed summary instead of doing a read), which today is
impossible: tool.execute.before can only mutate args, tool.execute.after runs
after the work happened, and permission.ask only denies with an error.

Refs anomalyco#5148.
@github-actions

Copy link
Copy Markdown
Contributor

Automated PR Cleanup

Thank you for contributing to opencode.

Due to the high volume of PRs from users and AI agents, we periodically close older PRs using automated criteria so maintainers can focus review time on the most active and community-supported contributions.

This PR was closed because it matched the following cleanup criteria:

  • The PR was created more than 1 month ago
  • The PR had fewer than 2 positive reactions
  • Positive reactions are counted as thumbs-up, heart, celebration, or rocket reactions on the PR

PRs created within the last month are not affected by this cleanup.

If you believe this PR was closed incorrectly, or if you are still actively working on it, please leave a comment explaining why it should be reopened. A maintainer can review and reopen it if appropriate.

Thanks again for taking the time to contribute.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant