45 lines
1.5 KiB
TypeScript
45 lines
1.5 KiB
TypeScript
import z from "zod";
|
|
import { ToolDef } from "../types"
|
|
import { isValidHost } from "../utils/logged";
|
|
import { exec } from "node:child_process";
|
|
import { promisify } from "node:util";
|
|
|
|
const execAsync = promisify(exec);
|
|
|
|
export const pingTool: ToolDef = {
|
|
title: "ping",
|
|
config: {
|
|
description: "ICMP-ping a host or IP address and return the result.",
|
|
inputSchema: {
|
|
host: z.string().describe("Hostname or IP address to ping"),
|
|
count: z.number().int().min(1).max(10).default(4).describe("Echo requests to send"),
|
|
},
|
|
},
|
|
handler: async ({ host, count }) => {
|
|
if (!isValidHost(host)) {
|
|
return {
|
|
isError: true,
|
|
content: [{ type: "text", text: `Invalid host: ${host}` }],
|
|
};
|
|
}
|
|
try {
|
|
// -c count, -w deadline(s) so we never hang the request
|
|
const { stdout } = await execAsync(`ping -r ${count} ${host}`, {
|
|
timeout: 12_000,
|
|
});
|
|
return { content: [{ type: "text", text: stdout.trim() }] };
|
|
} catch (err: unknown) {
|
|
const message =
|
|
err instanceof Error
|
|
? err.message
|
|
: typeof err === "object" && err !== null && "stdout" in err
|
|
? String((err as { stdout?: unknown }).stdout)
|
|
: String(err);
|
|
return {
|
|
isError: true,
|
|
content: [{ type: "text", text: `ping failed:\n${message}` }],
|
|
};
|
|
}
|
|
},
|
|
};
|