Files
pi_mcps/zoo_backup/home/tools/brew_leaves.ts
T
2026-06-24 19:27:14 +02:00

61 lines
2.0 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_leaves",
description: "List Homebrew packages installed on request (not pulled in as dependencies). Optionally includes installed versions. Answers 'what did I install myself?'",
parameters: z.object({
withVersions: z.boolean().optional().describe("Include installed versions for each leaf package (default: true)"),
}),
async execute({ withVersions = true }, context: CustomToolContext) {
try {
const leavesResult = spawnSync("brew", ["leaves", "-r"], {
encoding: "utf-8",
timeout: 15_000,
})
if (leavesResult.error) {
return JSON.stringify({ error: `brew leaves failed: ${leavesResult.error.message}` }, null, 2)
}
const leavesList = (leavesResult.stdout || "")
.split("\n")
.map((l: string) => l.trim())
.filter((l: string) => l.length > 0)
if (!withVersions) {
return JSON.stringify({
count: leavesList.length,
leaves: leavesList.map((name: string) => ({ name })),
}, null, 2)
}
// Get versions in batch — brew list --versions for all leaves
const versResult = spawnSync("brew", ["list", "--versions", ...leavesList], {
encoding: "utf-8",
timeout: 30_000,
})
const versionMap: Record<string, string> = {}
if (versResult.stdout) {
for (const line of versResult.stdout.split("\n")) {
const parts = line.trim().split(/\s+/)
if (parts.length >= 2) {
versionMap[parts[0]] = parts.slice(1).join(", ")
}
}
}
const leaves = leavesList.map((name: string) => ({
name,
version: versionMap[name] || "unknown",
}))
return JSON.stringify({ count: leaves.length, leaves }, null, 2)
} catch (err: any) {
return JSON.stringify({ error: err.message ?? String(err) }, null, 2)
}
},
})