Dax Raad пре 6 месеци
родитељ
комит
1ffc8be2b6

+ 5 - 5
.opencode/tool/foo.ts

@@ -1,11 +1,11 @@
 import { tool } from "@opencode-ai/plugin"
 
-export default tool((z) => ({
-  description: "foo tool for fooing",
+export default tool({
+  description: "call this tool when you want to give up",
   args: {
-    foo: z.string().describe("foo"),
+    message: tool.schema.string().describe("give up message"),
   },
-  async execute() {
+  async execute(args) {
     return "Hey fuck you!"
   },
-}))
+})

+ 4 - 4
packages/plugin/src/example.ts

@@ -5,15 +5,15 @@ export const ExamplePlugin: Plugin = async (ctx) => {
   return {
     permission: {},
     tool: {
-      mytool: tool((zod) => ({
+      mytool: tool({
         description: "This is a custom tool tool",
         args: {
-          foo: zod.string(),
+          foo: tool.schema.string().describe("foo"),
         },
-        async execute(args, ctx) {
+        async execute(args) {
           return `Hello ${args.foo}!`
         },
-      })),
+      }),
     },
     async "chat.params"(_input, output) {
       output.topP = 1

+ 7 - 8
packages/plugin/src/tool.ts

@@ -7,14 +7,13 @@ export type ToolContext = {
   abort: AbortSignal
 }
 
-export function tool<Args extends z.ZodRawShape>(
-  input: (zod: typeof z) => {
-    description: string
-    args: Args
-    execute: (args: z.infer<z.ZodObject<Args>>, ctx: ToolContext) => Promise<string>
-  },
-) {
-  return input(z)
+export function tool<Args extends z.ZodRawShape>(input: {
+  description: string
+  args: Args
+  execute(args: z.infer<z.ZodObject<Args>>, context: ToolContext): Promise<string>
+}) {
+  return input
 }
+tool.schema = z
 
 export type ToolDefinition = ReturnType<typeof tool>

+ 50 - 28
packages/web/src/content/docs/custom-tools.mdx

@@ -9,27 +9,30 @@ Custom tools are functions you create that the LLM can call during conversations
 
 ## Tool structure
 
-The easiest way to create tools is using the `tool()` helper which provides type safety and validation:
+Tools are defined as `.ts/.js` files in the `.opencode/tool/` directory. They
+can also be defined globally in `~/.config/opencode/tool/`.
+
+The easiest way to create tools is using the `tool()` helper which provides type safety and validation. Use `tool.schema` (which is just [Zod](https://zod.dev)) to define argument types:
 
 ```ts title=".opencode/tool/database.ts"
 import { tool } from "@opencode-ai/plugin"
 
-export default tool((z) => ({
+export default tool({
   description: "Query the project database",
   args: {
-    query: z.string().describe("SQL query to execute"),
+    query: tool.schema.string().describe("SQL query to execute"),
   },
   async execute(args) {
     // Your database logic here
     return `Executed query: ${args.query}`
   },
-}))
+})
 ```
 
-You can also import Zod directly and return a plain object:
+You can also import [Zod](https://zod.dev) directly and return a plain object:
 
 ```ts
-import z from "zod/v4"
+import { z } from "zod"
 
 export default {
   description: "Tool description",
@@ -42,29 +45,62 @@ export default {
   },
 }
 ```
-
 The filename becomes the tool name. This creates a `database` tool.
 
 ---
 
+## Multiple tools per file
+
+You can export multiple tools from a single file. Each export becomes a separate tool with the name `<filename>_<exportname>`:
+
+```ts title=".opencode/tool/math.ts"
+import { tool } from "@opencode-ai/plugin"
+
+export const add = tool({
+  description: "Add two numbers",
+  args: {
+    a: tool.schema.number().describe("First number"),
+    b: tool.schema.number().describe("Second number"),
+  },
+  async execute(args) {
+    return args.a + args.b
+  },
+})
+
+export const multiply = tool({
+  description: "Multiply two numbers",
+  args: {
+    a: tool.schema.number().describe("First number"),
+    b: tool.schema.number().describe("Second number"),
+  },
+  async execute(args) {
+    return args.a * args.b
+  },
+})
+```
+
+This creates two tools: `math_add` and `math_multiply`.
+
+---
+
 ## Arguments
 
-Use the `z` parameter to define tool arguments with validation and descriptions:
+Use `tool.schema` (which is just [Zod](https://zod.dev)) to define tool arguments with validation and descriptions:
 
 ```ts title=".opencode/tool/calculator.ts"
 import { tool } from "@opencode-ai/plugin"
 
-export default tool((z) => ({
+export default tool({
   description: "Perform mathematical calculations",
   args: {
-    expression: z.string().describe("Mathematical expression to evaluate"),
-    precision: z.number().optional().describe("Decimal precision"),
+    expression: tool.schema.string().describe("Mathematical expression to evaluate"),
+    precision: tool.schema.number().optional().describe("Decimal precision"),
   },
   async execute(args) {
     // Your calculation logic here
     return `Result: ${eval(args.expression).toFixed(args.precision || 2)}`
   },
-}))
+})
 ```
 
 ---
@@ -76,7 +112,7 @@ Tools receive context about the current session:
 ```ts title=".opencode/tool/project.ts"
 import { tool } from "@opencode-ai/plugin"
 
-export default tool((z) => ({
+export default tool({
   description: "Get project information",
   args: {},
   async execute(args, context) {
@@ -84,22 +120,8 @@ export default tool((z) => ({
     const { project, directory, worktree } = context
     return `Project: ${project.name}, Directory: ${directory}`
   },
-}))
+})
 ```
 
----
-
-## Tool locations
-
-Custom tools are loaded from:
-
-- Project: `.opencode/tool/`
-- Global: `~/.config/opencode/tool/`
-
-Files must use `.js` or `.ts` extensions.
-
----
 
-## Built-in tools
 
-opencode includes several built-in tools: `read`, `write`, `edit`, `bash`, `glob`, `grep`, `list`, `patch`, `todo`, and `task`. [Learn more](/docs/tui#tools).

+ 4 - 4
packages/web/src/content/docs/plugins.mdx

@@ -108,7 +108,7 @@ export const EnvProtection = async ({ project, client, $, directory, worktree })
 
 ### Custom tools
 
-Create custom tools that opencode can use:
+Plugins can also add custom tools to opencode:
 
 ```ts title=".opencode/plugin/custom-tools.ts"
 import type { Plugin, tool } from "@opencode-ai/plugin"
@@ -116,15 +116,15 @@ import type { Plugin, tool } from "@opencode-ai/plugin"
 export const CustomToolsPlugin: Plugin = async (ctx) => {
   return {
     tool: {
-      mytool: tool((zod) => ({
+      mytool: tool({
         description: "This is a custom tool",
         args: {
-          foo: zod.string(),
+          foo: tool.schema.string(),
         },
         async execute(args, ctx) {
           return `Hello ${args.foo}!`
         },
-      })),
+      }),
     },
   }
 }