/**
 * Computer use MCP tools for desktop interaction.
 * Each coordinate-based tool: scale screenshot coords → display coords → execute → result screenshot.
 *
 * The model sees resized screenshots and outputs pixel positions in that
 * image space. The execution layer scales from screenshot coords to actual
 * display resolution, mirroring the android-use pattern.
 */
import { z } from "zod";
import { tool } from "@anthropic-ai/claude-agent-sdk";
import { captureScreen, getDisplaySize, isDisplaySizeInitialized, click, doubleClick, rightClick, moveTo, drag, typeText, pressKey, scroll, } from "./desktop-executor-factory.js";
import { takeScreenshot, getVisionScaleFactor } from "./screenshot.js";
import { logger } from "../logger.js";
/**
 * Gate every computer_use entry point on (a) a supported platform and
 * (b) a successfully-detected display size.
 */
function requireDesktop() {
    if (process.platform !== "darwin" && process.platform !== "win32") {
        return {
            content: [{ type: "text", text: "computer_use tools require macOS or Windows" }],
            isError: true,
        };
    }
    if (!isDisplaySizeInitialized()) {
        return {
            content: [
                {
                    type: "text",
                    text: "computer_use tools are disabled: display size could not be detected at startup. A best-effort notification was attempted at startup; ask the owner to check agent logs, fix the display-detection failure (e.g. wake the display, reinstall command-line tools), and restart the agent.",
                },
            ],
            isError: true,
        };
    }
    return null;
}
// ── Coordinate helpers (mirror android-use pattern) ─────────────────
/**
 * Compute the expected screenshot image dimensions after vision resize.
 * The screenshot pipeline resizes the raw capture to fit Claude's vision
 * constraints. This computes those dimensions deterministically from the
 * display resolution so we can map coordinates without reading the image.
 */
export function getScreenshotSize(displaySize) {
    const scale = getVisionScaleFactor(displaySize.width, displaySize.height);
    if (scale >= 1.0)
        return { ...displaySize };
    return {
        width: Math.max(1, Math.round(displaySize.width * scale)),
        height: Math.max(1, Math.round(displaySize.height * scale)),
    };
}
/**
 * Convert pixel coordinates in screenshot space to absolute display coordinates.
 * The model outputs coordinates based on the resized screenshot it sees;
 * we scale them to the actual display resolution for input events.
 */
export function screenshotToDisplay(point, screenshotSize, displaySize) {
    return {
        x: Math.round((point.x / screenshotSize.width) * displaySize.width),
        y: Math.round((point.y / screenshotSize.height) * displaySize.height),
    };
}
/** Zod schema for a pixel coordinate point in the screenshot image. */
const pointSchema = z.object({
    x: z
        .number()
        .min(0)
        .describe("X pixel coordinate in the screenshot image (0 = left edge)"),
    y: z
        .number()
        .min(0)
        .describe("Y pixel coordinate in the screenshot image (0 = top edge)"),
});
/**
 * Capture a post-action screenshot and return a standard result.
 */
async function actionResult(text, delayMs = 1000) {
    await new Promise((resolve) => setTimeout(resolve, delayMs));
    const { base64: resultScreenshot } = await captureScreen();
    logger.screenshot(resultScreenshot);
    return {
        content: [
            { type: "text", text },
            {
                type: "image",
                data: resultScreenshot,
                mimeType: "image/png",
            },
        ],
    };
}
/** Wrap a tool handler with desktop check and error handling. */
function withDesktopCheck(toolName, fn) {
    return (async () => {
        const err = requireDesktop();
        if (err)
            return err;
        try {
            return await fn();
        }
        catch (e) {
            logger.err(`${toolName} failed`, { error: String(e) });
            return {
                content: [
                    {
                        type: "text",
                        text: `${toolName} failed: ${e instanceof Error ? e.message : String(e)}`,
                    },
                ],
                isError: true,
            };
        }
    })();
}
export const computerUseClickTool = tool("computer_use_click", "Click at a point on the desktop screen. Coordinates are pixel positions in the screenshot image returned by computer_use_screenshot. Supports left-click, right-click, and double-click.", {
    point: pointSchema.describe("Pixel coordinates in the screenshot image to click"),
    button: z.enum(["left", "right", "double"]).optional().default("left"),
}, async (args) => {
    return withDesktopCheck("computer_use_click", async () => {
        const displaySize = getDisplaySize();
        const ssSize = getScreenshotSize(displaySize);
        const abs = screenshotToDisplay(args.point, ssSize, displaySize);
        if (args.button === "right") {
            await rightClick(abs.x, abs.y);
        }
        else if (args.button === "double") {
            await doubleClick(abs.x, abs.y);
        }
        else {
            await click(abs.x, abs.y);
        }
        return actionResult(`${args.button === "double" ? "Double-clicked" : args.button === "right" ? "Right-clicked" : "Clicked"} at screenshot (${Math.round(args.point.x)}, ${Math.round(args.point.y)}) → display (${abs.x}, ${abs.y})`);
    });
});
export const computerUseMoveTool = tool("computer_use_move", "Move the mouse cursor to a point on the desktop screen. Coordinates are pixel positions in the screenshot image.", {
    point: pointSchema.describe("Pixel coordinates in the screenshot image to move the cursor to"),
}, async (args) => {
    return withDesktopCheck("computer_use_move", async () => {
        const displaySize = getDisplaySize();
        const ssSize = getScreenshotSize(displaySize);
        const abs = screenshotToDisplay(args.point, ssSize, displaySize);
        await moveTo(abs.x, abs.y);
        return actionResult(`Moved cursor to screenshot (${Math.round(args.point.x)}, ${Math.round(args.point.y)}) → display (${abs.x}, ${abs.y})`);
    });
});
export const computerUseScrollTool = tool("computer_use_scroll", "Scroll at a point on the desktop screen in a direction. Coordinates are pixel positions in the screenshot image.", {
    point: pointSchema.describe("Pixel coordinates in the screenshot image for scroll origin"),
    direction: z.enum(["up", "down", "left", "right"]),
    amount: z.number().optional().default(3).describe("Scroll amount (default 3)"),
}, async (args) => {
    return withDesktopCheck("computer_use_scroll", async () => {
        const displaySize = getDisplaySize();
        const ssSize = getScreenshotSize(displaySize);
        const abs = screenshotToDisplay(args.point, ssSize, displaySize);
        await scroll(abs.x, abs.y, args.direction, args.amount);
        return actionResult(`Scrolled ${args.direction} at screenshot (${Math.round(args.point.x)}, ${Math.round(args.point.y)}) → display (${abs.x}, ${abs.y})`);
    });
});
export const computerUseDragTool = tool("computer_use_drag", "Drag from one point to another on the desktop screen. Coordinates are pixel positions in the screenshot image.", {
    startPoint: pointSchema.describe("Pixel coordinates in the screenshot image (drag source)"),
    endPoint: pointSchema.describe("Pixel coordinates in the screenshot image (drop target)"),
}, async (args) => {
    return withDesktopCheck("computer_use_drag", async () => {
        const displaySize = getDisplaySize();
        const ssSize = getScreenshotSize(displaySize);
        const start = screenshotToDisplay(args.startPoint, ssSize, displaySize);
        const end = screenshotToDisplay(args.endPoint, ssSize, displaySize);
        await drag(start.x, start.y, end.x, end.y);
        return actionResult(`Dragged from screenshot (${Math.round(args.startPoint.x)}, ${Math.round(args.startPoint.y)}) to (${Math.round(args.endPoint.x)}, ${Math.round(args.endPoint.y)}) → display (${start.x}, ${start.y}) to (${end.x}, ${end.y})`);
    });
});
export const computerUseTypeTool = tool("computer_use_type", "Type text into the focused field. Optionally clear the field first (replace) and/or press Enter after.", {
    text: z.string().describe("Text to type"),
    replace: z.boolean().optional().default(false).describe("If true, select-all and replace existing text first"),
    press_enter: z.boolean().optional().default(false).describe("If true, press Enter after typing"),
}, async (args) => {
    return withDesktopCheck("computer_use_type", async () => {
        if (args.replace) {
            await pressKey(process.platform === "win32" ? "ctrl+a" : "cmd+a");
        }
        await typeText(args.text);
        if (args.press_enter) {
            await pressKey("enter");
        }
        return actionResult(`Typed text${args.press_enter ? " and pressed Enter" : ""}`);
    });
});
export const computerUseKeyTool = tool("computer_use_key", "Press a key or key combination (e.g. 'enter', 'escape', 'cmd+s', 'ctrl+shift+t').", {
    key: z
        .string()
        .describe("Key or combo: 'enter', 'escape', 'cmd+s', 'ctrl+shift+t', etc."),
}, async (args) => {
    return withDesktopCheck("computer_use_key", async () => {
        await pressKey(args.key);
        return actionResult(`Pressed: ${args.key}`);
    });
});
export const computerUseScreenshotTool = tool("computer_use_screenshot", "Capture a screenshot of the current desktop screen. Returns the image as base64 PNG. Use the pixel coordinates from this image when calling click, move, scroll, or drag tools.", {}, async (_args) => {
    const err = requireDesktop();
    if (err)
        return err;
    try {
        const displaySize = getDisplaySize();
        const ssSize = getScreenshotSize(displaySize);
        const { base64, filePath } = await takeScreenshot();
        logger.screenshot(base64);
        return {
            content: [
                {
                    type: "text",
                    text: `Screenshot saved to ${filePath}\nScreenshot image size: ${ssSize.width}x${ssSize.height}px | Display resolution: ${displaySize.width}x${displaySize.height}px\nUse pixel coordinates from this image when calling click/move/scroll/drag tools.`,
                },
                {
                    type: "image",
                    data: base64,
                    mimeType: "image/png",
                },
            ],
        };
    }
    catch (err) {
        return {
            content: [
                {
                    type: "text",
                    text: `Screenshot failed: ${err instanceof Error ? err.message : String(err)}`,
                },
            ],
            isError: true,
        };
    }
});
//# sourceMappingURL=computer-use.js.map