| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071 |
- import { z } from "zod"
- import { Tool } from "./tool"
- import DESCRIPTION from "./bash.txt"
- const MAX_OUTPUT_LENGTH = 30000
- const BANNED_COMMANDS = [
- "alias",
- "curl",
- "curlie",
- "wget",
- "axel",
- "aria2c",
- "nc",
- "telnet",
- "lynx",
- "w3m",
- "links",
- "httpie",
- "xh",
- "http-prompt",
- "chrome",
- "firefox",
- "safari",
- ]
- const DEFAULT_TIMEOUT = 1 * 60 * 1000
- const MAX_TIMEOUT = 10 * 60 * 1000
- export const BashTool = Tool.define({
- id: "opencode.bash",
- description: DESCRIPTION,
- parameters: z.object({
- command: z.string().describe("The command to execute"),
- timeout: z
- .number()
- .min(0)
- .max(MAX_TIMEOUT)
- .describe("Optional timeout in milliseconds")
- .optional()
- .describe("Optional timeout in milliseconds"),
- description: z
- .string()
- .describe(
- "Clear, concise description of what this command does in 5-10 words. Examples:\nInput: ls\nOutput: Lists files in current directory\n\nInput: git status\nOutput: Shows working tree status\n\nInput: npm install\nOutput: Installs package dependencies\n\nInput: mkdir foo\nOutput: Creates directory 'foo'",
- ),
- }),
- async execute(params) {
- const timeout = Math.min(params.timeout ?? DEFAULT_TIMEOUT, MAX_TIMEOUT)
- if (BANNED_COMMANDS.some((item) => params.command.startsWith(item)))
- throw new Error(`Command '${params.command}' is not allowed`)
- const process = Bun.spawn({
- cmd: ["bash", "-c", params.command],
- maxBuffer: MAX_OUTPUT_LENGTH,
- timeout: timeout,
- stdout: "pipe",
- stderr: "pipe",
- })
- await process.exited
- const stdout = await new Response(process.stdout).text()
- const stderr = await new Response(process.stderr).text()
- return {
- metadata: {
- stderr,
- stdout,
- description: params.description,
- },
- output: stdout.replaceAll(/\x1b\[[0-9;]*m/g, ""),
- }
- },
- })
|