Skip to content

fix(tool): bridge custom tool zod metadata#27770

Merged
rekram1-node merged 1 commit into
devfrom
fix-custom-tool-zod-metadata-bridge
May 15, 2026
Merged

fix(tool): bridge custom tool zod metadata#27770
rekram1-node merged 1 commit into
devfrom
fix-custom-tool-zod-metadata-bridge

Conversation

@rekram1-node
Copy link
Copy Markdown
Collaborator

Summary

  • bridge Zod metadata from config-scoped custom tool schemas into the local JSON Schema conversion path
  • remove the plugin-side precomputed jsonSchema path added in fix(tool): preserve custom tool arg descriptions #27750 so stale installed plugin packages are handled too
  • update regression coverage to simulate an older config-scoped @opencode-ai/plugin package that only returns raw Zod args

Closes #4357

References #27750 and #19916.

Testing

  • bun test test/tool/registry.test.ts

@rekram1-node
Copy link
Copy Markdown
Collaborator Author

/review

@github-actions
Copy link
Copy Markdown
Contributor

lgtm

@rekram1-node rekram1-node merged commit 48122b3 into dev May 15, 2026
12 checks passed
@rekram1-node rekram1-node deleted the fix-custom-tool-zod-metadata-bridge branch May 15, 2026 19:50
zenoda pushed a commit to zenoda/opencode that referenced this pull request May 16, 2026
@khimaros
Copy link
Copy Markdown
Contributor

@rekram1-node thank you for merging this. however, there is still an issue with invalid enum values compared with my original PR.

@khimaros
Copy link
Copy Markdown
Contributor

khimaros commented May 17, 2026

the simplest fix i can come up with (to properly validate enums and return an error to the LLM when invalid):

diff --git a/packages/opencode/src/tool/registry.ts b/packages/opencode/src/tool/registry.ts
index 879855c36..b0f927053 100644
--- a/packages/opencode/src/tool/registry.ts
+++ b/packages/opencode/src/tool/registry.ts
@@ -156,13 +156,22 @@ export const layer: Layer.Layer<
             description: def.description,
             execute: (args, toolCtx) =>
               Effect.gen(function* () {
+                let input: unknown = args
+                if (zodParams) {
+                  const validated = zodParams.safeParse(args)
+                  if (!validated.success)
+                    throw new Error(
+                      `The ${id} tool was called with invalid arguments: ${validated.error}.\nPlease rewrite the input so it satisfies the expected schema.`,
+                    )
+                  input = validated.data
+                }
                 const pluginCtx: PluginToolContext = {
                   ...toolCtx,
                   ask: (req) => toolCtx.ask(req),
                   directory: ctx.directory,
                   worktree: ctx.worktree,
                 }
-                const result = yield* Effect.promise(() => def.execute(args as any, pluginCtx))
+                const result = yield* Effect.promise(() => def.execute(input as any, pluginCtx))
                 const output = typeof result === "string" ? result : result.output
                 const metadata = typeof result === "string" ? {} : (result.metadata ?? {})
                 const attachments = typeof result === "string" ? undefined : result.attachments

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.

Tool argument descriptions lost in schema conversion

2 participants