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

122 lines
4.5 KiB
TypeScript

import { parametersSchema as z, defineCustomTool, CustomToolContext } from "@roo-code/types"
// @ts-ignore - Node built-ins
import { readFileSync } from "fs"
// @ts-ignore - Node built-ins
import path from "path"
export default defineCustomTool({
name: "pom_inspect",
description: "Parse a pom.xml and return structured JSON with groupId, artifactId, version, modules, properties, parent, and optionally dependencies. Saves reading raw XML just to extract Maven coordinates.",
parameters: z.object({
pomPath: z.string().describe("Absolute or relative path to pom.xml"),
includeDependencies: z.boolean().optional().describe("Include <dependencies> list in output (default: false)"),
}),
async execute({ pomPath, includeDependencies = false }, context: CustomToolContext) {
try {
// @ts-ignore - installed dependency
const { XMLParser } = require("fast-xml-parser")
// Resolve relative paths against the task's working directory
// @ts-ignore - task.cwd exists at runtime
const cwd = context?.task?.cwd ?? process.cwd()
const absPath = path.isAbsolute(pomPath) ? pomPath : path.resolve(cwd, pomPath)
const xml = readFileSync(absPath, "utf-8")
const parser = new XMLParser({
ignoreAttributes: false,
attributeNamePrefix: "@_",
textNodeName: "#text",
isArray: (name: string) => ["module", "dependency"].includes(name),
})
const doc = parser.parse(xml)
const project = doc.project
if (!project) {
return JSON.stringify({ error: "No <project> root element found in POM" }, null, 2)
}
// Extract properties for placeholder resolution
const properties: Record<string, string> = {}
if (project.properties) {
for (const [key, val] of Object.entries(project.properties)) {
if (typeof val === "string" || typeof val === "number") {
properties[key] = String(val)
}
}
}
const resolvePlaceholder = (val: any): string | null => {
if (val == null) return null
let s = String(val)
const match = s.match(/^\$\{(.+)\}$/)
if (match) {
const propKey = match[1]
if (properties[propKey]) return properties[propKey]
// Check project-level refs
if (propKey === "project.version" && project.version) return String(project.version)
if (propKey === "project.groupId" && project.groupId) return String(project.groupId)
}
return s
}
// Parent
let parent = null
if (project.parent) {
parent = {
groupId: String(project.parent.groupId || ""),
artifactId: String(project.parent.artifactId || ""),
version: resolvePlaceholder(project.parent.version),
}
}
// Modules
let modules: string[] = []
if (project.modules?.module) {
modules = project.modules.module.map((m: any) => String(m))
}
// Dependencies
let dependencies: any[] | undefined = undefined
if (includeDependencies && project.dependencies?.dependency) {
dependencies = project.dependencies.dependency.map((d: any) => ({
groupId: String(d.groupId || ""),
artifactId: String(d.artifactId || ""),
version: resolvePlaceholder(d.version),
scope: d.scope ? String(d.scope) : "compile",
}))
}
// Also check dependencyManagement
if (includeDependencies && project.dependencyManagement?.dependencies?.dependency) {
const managed = project.dependencyManagement.dependencies.dependency.map((d: any) => ({
groupId: String(d.groupId || ""),
artifactId: String(d.artifactId || ""),
version: resolvePlaceholder(d.version),
scope: d.scope ? String(d.scope) : "managed",
}))
if (!dependencies) dependencies = managed
else dependencies = [...dependencies, ...managed]
}
const result: any = {
groupId: resolvePlaceholder(project.groupId) || parent?.groupId || "",
artifactId: String(project.artifactId || ""),
version: resolvePlaceholder(project.version) || parent?.version || "",
packaging: String(project.packaging || "jar"),
name: project.name ? String(project.name) : null,
parent,
modules,
properties,
}
if (includeDependencies && dependencies) {
result.dependencies = dependencies
}
return JSON.stringify(result, null, 2)
} catch (err: any) {
return JSON.stringify({ error: err.message ?? String(err) }, null, 2)
}
},
})