48 lines
1.6 KiB
TypeScript
48 lines
1.6 KiB
TypeScript
import { parametersSchema as z, defineCustomTool, CustomToolContext } from "@roo-code/types"
|
|
// @ts-ignore - Node built-ins
|
|
import { spawnSync } from "child_process"
|
|
|
|
export default defineCustomTool({
|
|
name: "brew_search",
|
|
description: "Search Homebrew for formulae and/or casks matching a query. Returns structured JSON instead of raw terminal output.",
|
|
parameters: z.object({
|
|
query: z.string().describe("Search term (e.g. 'python', 'docker', 'ffmpeg')"),
|
|
casks: z.boolean().optional().describe("Include casks in search results (default: false, formula-only)"),
|
|
}),
|
|
async execute({ query, casks = false }, context: CustomToolContext) {
|
|
try {
|
|
// Search formulae
|
|
const formulaResult = spawnSync("brew", ["search", "--formula", query], {
|
|
encoding: "utf-8",
|
|
timeout: 15_000,
|
|
})
|
|
|
|
const formulae = (formulaResult.stdout || "")
|
|
.split("\n")
|
|
.map((l: string) => l.trim())
|
|
.filter((l: string) => l.length > 0 && !l.startsWith("==>"))
|
|
|
|
let caskList: string[] = []
|
|
if (casks) {
|
|
const caskResult = spawnSync("brew", ["search", "--cask", query], {
|
|
encoding: "utf-8",
|
|
timeout: 15_000,
|
|
})
|
|
caskList = (caskResult.stdout || "")
|
|
.split("\n")
|
|
.map((l: string) => l.trim())
|
|
.filter((l: string) => l.length > 0 && !l.startsWith("==>"))
|
|
}
|
|
|
|
return JSON.stringify({
|
|
query,
|
|
formulae,
|
|
casks: caskList,
|
|
totalCount: formulae.length + caskList.length,
|
|
}, null, 2)
|
|
} catch (err: any) {
|
|
return JSON.stringify({ error: err.message ?? String(err) }, null, 2)
|
|
}
|
|
},
|
|
})
|