export const mouseEmulationDescriptor = {
    toolId: "computeruse.mouseEmulation",
    capability: "simulate-mouse-operations",
    route: "agent_executionEngine.basic_toolLayer.baseTools.computeruseBase.mouseEmulation",
    defaultDryRun: true,
    defaultCoordinateSpace: "screen",
    defaultButton: "left",
    defaultClickCount: 1,
    maxCoordinate: 100_000,
    defaultMaxSteps: 16,
    tapOwnsApproval: true,
    runtimeEntry: [
        "BaseToolExecutorPort.computeruse.locateCursor",
        "BaseToolExecutorPort.computeruse.pointerAction",
    ],
    permissionsRequired: ["pointer:read", "pointer:write", "ui:action"],
    unsafeSideEffects: true,
};
function isRecord(value) {
    return typeof value === "object" && value !== null && !Array.isArray(value);
}
function cleanString(value) {
    return typeof value === "string" && value.trim().length > 0 && !value.includes("\0") ? value.trim() : undefined;
}
function cleanStringList(value) {
    if (value === undefined)
        return undefined;
    if (!Array.isArray(value))
        return undefined;
    const cleaned = [];
    for (const item of value) {
        const text = cleanString(item);
        if (text === undefined)
            return undefined;
        if (!cleaned.includes(text))
            cleaned.push(text);
    }
    return cleaned;
}
function cleanGate(value) {
    if (value === undefined)
        return undefined;
    if (!isRecord(value))
        return undefined;
    const gate = {};
    if (typeof value.accepted === "boolean")
        gate.accepted = value.accepted;
    if (typeof value.allowed === "boolean")
        gate.allowed = value.allowed;
    const reason = cleanString(value.reason);
    if (reason !== undefined)
        gate.reason = reason;
    return gate;
}
function cleanAuditMetadata(value) {
    return isRecord(value) ? value : undefined;
}
function cleanCoordinateSpace(value) {
    if (value === undefined)
        return mouseEmulationDescriptor.defaultCoordinateSpace;
    return value === "screen" || value === "window" || value === "normalized" ? value : undefined;
}
function cleanProviderCoordinateSpace(value) {
    return value === "screen" || value === "window" || value === "normalized" ? value : undefined;
}
function cleanPoint(value) {
    if (!isRecord(value))
        return undefined;
    const x = value.x;
    const y = value.y;
    if (typeof x !== "number" ||
        typeof y !== "number" ||
        !Number.isFinite(x) ||
        !Number.isFinite(y) ||
        x < 0 ||
        y < 0 ||
        x > mouseEmulationDescriptor.maxCoordinate ||
        y > mouseEmulationDescriptor.maxCoordinate) {
        return undefined;
    }
    return { x: Math.round(x), y: Math.round(y) };
}
function cleanButton(value) {
    if (value === undefined)
        return mouseEmulationDescriptor.defaultButton;
    return value === "left" || value === "right" || value === "middle" || value === "back" || value === "forward"
        ? value
        : undefined;
}
function cleanClickCount(value) {
    if (value === undefined)
        return mouseEmulationDescriptor.defaultClickCount;
    return typeof value === "number" && Number.isInteger(value) && value >= 1 && value <= 3 ? value : undefined;
}
function cleanDuration(value) {
    if (value === undefined)
        return undefined;
    return typeof value === "number" && Number.isInteger(value) && value >= 0 ? value : undefined;
}
function auditEvent(type, context, metadata) {
    return {
        type,
        toolId: mouseEmulationDescriptor.toolId,
        invocationId: context?.invocationId ?? "computeruse.mouseEmulation:dry-run",
        dryRun: context?.dryRun !== false,
        metadata: {
            ...(context?.auditMetadata ?? {}),
            ...(metadata ?? {}),
        },
    };
}
function failure(code, message, boundary, context) {
    return {
        ok: false,
        toolId: mouseEmulationDescriptor.toolId,
        error: {
            code,
            message,
            boundary,
            publicSafe: true,
            safeForRuntimeInspection: true,
            internalDetailExposed: false,
        },
        audit: [auditEvent("agentCore.basicTool.computeruse.mouseEmulation.rejected", context, { code })],
        events: ["basicTool.computeruse.mouseEmulation.rejected"],
    };
}
function normalizeContext(value) {
    if (value === undefined)
        return {};
    if (!isRecord(value)) {
        return failure("INVALID_CONTEXT", "computeruse.mouseEmulation context must be an object", "input", undefined);
    }
    const requestedScopes = cleanStringList(value.requestedScopes);
    const allowedScopes = cleanStringList(value.allowedScopes);
    const guard = cleanGate(value.guard);
    const contract = cleanGate(value.contract);
    const governance = cleanGate(value.governance);
    if ((value.requestedScopes !== undefined && requestedScopes === undefined) ||
        (value.allowedScopes !== undefined && allowedScopes === undefined) ||
        (value.guard !== undefined && guard === undefined) ||
        (value.contract !== undefined && contract === undefined) ||
        (value.governance !== undefined && governance === undefined) ||
        (value.dryRun !== undefined && typeof value.dryRun !== "boolean")) {
        return failure("INVALID_CONTEXT", "computeruse.mouseEmulation context contains malformed guard, governance, or scope fields", "input", undefined);
    }
    return {
        runtimeId: cleanString(value.runtimeId),
        sessionId: cleanString(value.sessionId),
        invocationId: cleanString(value.invocationId),
        dryRun: typeof value.dryRun === "boolean" ? value.dryRun : undefined,
        guard,
        contract,
        governance,
        requestedScopes,
        allowedScopes,
        auditMetadata: cleanAuditMetadata(value.auditMetadata),
    };
}
function normalizeLocateStep(step, context) {
    const coordinateSpace = cleanCoordinateSpace(step.coordinateSpace);
    if (coordinateSpace === undefined) {
        return failure("INVALID_COORDINATE_SPACE", "computeruse.mouseEmulation locate coordinateSpace must be screen, window, or normalized", "input", context);
    }
    const displayId = cleanString(step.displayId);
    if (step.displayId !== undefined && displayId === undefined) {
        return failure("INVALID_TARGET", "computeruse.mouseEmulation locate displayId must be a safe string", "input", context);
    }
    return { kind: "locate", coordinateSpace, displayId };
}
function normalizeMoveStep(step, context) {
    const target = cleanPoint(step.target);
    if (target === undefined) {
        return failure("INVALID_TARGET", "computeruse.mouseEmulation move step requires finite non-negative target coordinates", "input", context);
    }
    const coordinateSpace = cleanCoordinateSpace(step.coordinateSpace);
    if (coordinateSpace === undefined) {
        return failure("INVALID_COORDINATE_SPACE", "computeruse.mouseEmulation move coordinateSpace must be screen, window, or normalized", "input", context);
    }
    const displayId = cleanString(step.displayId);
    const windowId = cleanString(step.windowId);
    const durationMs = cleanDuration(step.durationMs);
    if ((step.displayId !== undefined && displayId === undefined) ||
        (step.windowId !== undefined && windowId === undefined) ||
        (step.durationMs !== undefined && durationMs === undefined)) {
        return failure("INVALID_STEP", "computeruse.mouseEmulation move step has invalid target metadata", "input", context);
    }
    return { kind: "move", target, coordinateSpace, displayId, windowId, durationMs };
}
function normalizeClickStep(step, context) {
    const button = cleanButton(step.button);
    if (button === undefined) {
        return failure("INVALID_STEP", "computeruse.mouseEmulation click button is not supported", "input", context);
    }
    const clickCount = cleanClickCount(step.clickCount);
    if (clickCount === undefined) {
        return failure("INVALID_CLICK_COUNT", "computeruse.mouseEmulation clickCount must be an integer from 1 to 3", "input", context);
    }
    const atValue = step.at;
    const at = atValue === undefined ? undefined : cleanPoint(atValue);
    if (atValue !== undefined && at === undefined) {
        return failure("INVALID_TARGET", "computeruse.mouseEmulation click at must use finite non-negative coordinates", "input", context);
    }
    const coordinateSpace = cleanCoordinateSpace(step.coordinateSpace);
    if (coordinateSpace === undefined) {
        return failure("INVALID_COORDINATE_SPACE", "computeruse.mouseEmulation click coordinateSpace must be screen, window, or normalized", "input", context);
    }
    const displayId = cleanString(step.displayId);
    const windowId = cleanString(step.windowId);
    if ((step.displayId !== undefined && displayId === undefined) || (step.windowId !== undefined && windowId === undefined)) {
        return failure("INVALID_STEP", "computeruse.mouseEmulation click step has invalid target metadata", "input", context);
    }
    return { kind: "click", button, clickCount, at, coordinateSpace, displayId, windowId, usesCurrentCursor: at === undefined };
}
function normalizeSteps(value, maxSteps, context) {
    if (!Array.isArray(value) || value.length === 0) {
        return failure("MISSING_STEPS", "computeruse.mouseEmulation requires at least one mouse step", "input", context);
    }
    if (value.length > maxSteps) {
        return failure("STEP_LIMIT_EXCEEDED", "computeruse.mouseEmulation steps must stay within the declared runtime step limit", "scope", context);
    }
    const steps = [];
    for (const rawStep of value) {
        if (!isRecord(rawStep)) {
            return failure("INVALID_STEP", "computeruse.mouseEmulation steps must be objects", "input", context);
        }
        const kind = cleanString(rawStep.kind);
        const step = kind === "locate"
            ? normalizeLocateStep(rawStep, context)
            : kind === "move"
                ? normalizeMoveStep(rawStep, context)
                : kind === "click"
                    ? normalizeClickStep(rawStep, context)
                    : failure("INVALID_STEP", "computeruse.mouseEmulation step kind must be locate, move, or click", "input", context);
        if ("ok" in step)
            return step;
        steps.push(step);
    }
    return steps;
}
function ensureScopes(context) {
    const requested = context.requestedScopes ?? [];
    const allowed = context.allowedScopes ?? [];
    if (requested.length === 0)
        return undefined;
    const denied = requested.filter((scope) => !allowed.includes(scope));
    if (denied.length === 0)
        return undefined;
    return failure("SCOPE_DENIED", `computeruse.mouseEmulation scope ${denied[0]} is outside runtime governance`, "scope", context);
}
function ensureStaticGates(context) {
    if (context.contract?.accepted === false || context.contract?.allowed === false) {
        return failure("CONTRACT_REJECTED", context.contract.reason ?? "computeruse.mouseEmulation was rejected by runtime contract surface", "contract", context);
    }
    if (context.governance?.accepted === false || context.governance?.allowed === false) {
        return failure("GOVERNANCE_REJECTED", context.governance.reason ?? "computeruse.mouseEmulation was rejected by runtime governance", "governance", context);
    }
    return undefined;
}
function ensureRealExecutionGuard(context) {
    if (context.dryRun !== false)
        return undefined;
    if (context.guard?.accepted === true || context.guard?.allowed === true)
        return undefined;
    return failure("GOVERNANCE_REJECTED", context.guard?.reason ?? "computeruse.mouseEmulation dryRun:false requires an affirmative runtime guard", "governance", context);
}
function normalizeProviderResult(value, steps, context) {
    if (!isRecord(value) || !Array.isArray(value.stepResults) || value.stepResults.length !== steps.length) {
        return failure("PROVIDER_FAILURE", "computeruse.mouseEmulation runtime provider returned a malformed public-safe sequence envelope", "provider", context);
    }
    const stepResults = [];
    for (let index = 0; index < value.stepResults.length; index += 1) {
        const raw = value.stepResults[index];
        const expected = steps[index];
        if (!isRecord(raw) || raw.index !== index || raw.kind !== expected?.kind) {
            return failure("PROVIDER_FAILURE", "computeruse.mouseEmulation runtime provider returned a malformed step result", "provider", context);
        }
        const actionId = cleanString(raw.actionId);
        const position = isRecord(raw.position)
            ? {
                x: typeof raw.position.x === "number" && Number.isFinite(raw.position.x) ? raw.position.x : Number.NaN,
                y: typeof raw.position.y === "number" && Number.isFinite(raw.position.y) ? raw.position.y : Number.NaN,
                coordinateSpace: cleanProviderCoordinateSpace(raw.position.coordinateSpace),
                displayId: cleanString(raw.position.displayId),
            }
            : undefined;
        if (expected.kind === "locate") {
            if (position === undefined ||
                !Number.isFinite(position.x) ||
                !Number.isFinite(position.y) ||
                position.coordinateSpace === undefined) {
                return failure("PROVIDER_FAILURE", "computeruse.mouseEmulation locate result is malformed", "provider", context);
            }
            stepResults.push({ index, kind: expected.kind, position: position, metadata: cleanAuditMetadata(raw.metadata) });
            continue;
        }
        if (actionId === undefined) {
            return failure("PROVIDER_FAILURE", "computeruse.mouseEmulation pointer action result is missing actionId", "provider", context);
        }
        stepResults.push({ index, kind: expected.kind, actionId, metadata: cleanAuditMetadata(raw.metadata) });
    }
    return { stepResults, metadata: cleanAuditMetadata(value.metadata) };
}
const publicSafeProviderFailurePrefix = "PUBLIC_SAFE_PROVIDER_FAILURE:";
function publicSafeProviderFailureMessage(error) {
    const message = error instanceof Error && error.message.trim().length > 0 ? error.message.trim() : undefined;
    if (message === undefined || !message.startsWith(publicSafeProviderFailurePrefix))
        return undefined;
    const publicSafeMessage = message.slice(publicSafeProviderFailurePrefix.length).trim();
    return publicSafeMessage.length > 0 ? publicSafeMessage : undefined;
}
function normalizeRequest(request) {
    if (request === undefined)
        request = {};
    if (!isRecord(request)) {
        return failure("INVALID_REQUEST", "computeruse.mouseEmulation request must be an object", "input", undefined);
    }
    const context = normalizeContext(request.context);
    if ("ok" in context)
        return context;
    const maxSteps = request.maxSteps === undefined
        ? mouseEmulationDescriptor.defaultMaxSteps
        : typeof request.maxSteps === "number" && Number.isInteger(request.maxSteps) && request.maxSteps >= 1
            ? request.maxSteps
            : undefined;
    if (maxSteps === undefined) {
        return failure("STEP_LIMIT_EXCEEDED", "computeruse.mouseEmulation maxSteps must be a positive integer", "scope", context);
    }
    const steps = normalizeSteps(request.steps, maxSteps, context);
    if ("ok" in steps)
        return steps;
    const purpose = cleanString(request.purpose);
    if (purpose === undefined) {
        return failure("MISSING_PURPOSE", "computeruse.mouseEmulation requires an explicit purpose", "input", context);
    }
    if (context.runtimeId === undefined) {
        return failure("MISSING_RUNTIME_ID", "computeruse.mouseEmulation requires context.runtimeId for audit", "input", context);
    }
    const scopes = ensureScopes(context);
    if (scopes !== undefined)
        return scopes;
    const staticGates = ensureStaticGates(context);
    if (staticGates !== undefined)
        return staticGates;
    const realGuard = ensureRealExecutionGuard(context);
    if (realGuard !== undefined)
        return realGuard;
    return {
        steps,
        context,
        purpose,
        maxSteps,
        metadata: cleanAuditMetadata(request.metadata),
        provider: typeof request.provider === "function" ? request.provider : undefined,
    };
}
function baseOutput(steps, purpose, maxSteps, acceptedScopes, dryRun, providerCalled) {
    return {
        kind: "agentCore.basicTool.computeruse.mouseEmulation",
        operation: "simulate-mouse-operations",
        purpose,
        steps,
        dispatch: dryRun ? "dry-run" : "runtime-computeruse",
        dryRun,
        providerCalled,
        executionBlocked: dryRun,
        unsafeSideEffects: true,
        permissionsRequired: mouseEmulationDescriptor.permissionsRequired,
        requiresTapApproval: true,
        acceptedScopes,
        runtimeEntry: {
            ports: [
                "BaseToolExecutorPort.computeruse.locateCursor",
                "BaseToolExecutorPort.computeruse.pointerAction",
            ],
            operation: "computeruse.mouseEmulation.pointerSequence",
            runtimeOwnsPointerEvents: true,
            runtimeOwnsCursorObservation: true,
            runtimeOwnsInputPolicy: true,
            baseToolOwnsTapStrategy: false,
        },
    };
}
export async function executeMouseEmulation(request = {}) {
    const normalized = normalizeRequest(request);
    if ("ok" in normalized)
        return normalized;
    const { steps, context, purpose, maxSteps, metadata, provider } = normalized;
    const acceptedScopes = context.requestedScopes ?? [];
    const dryRun = context.dryRun !== false;
    if (dryRun) {
        return {
            ok: true,
            toolId: mouseEmulationDescriptor.toolId,
            output: {
                ...baseOutput(steps, purpose, maxSteps, acceptedScopes, true, false),
                sequenceEnvelope: {
                    maxSteps,
                    executed: false,
                    metadataOnly: true,
                    stepResults: steps.map((step, index) => ({
                        index,
                        kind: step.kind,
                        executed: false,
                        metadataOnly: true,
                    })),
                },
            },
            audit: [auditEvent("agentCore.basicTool.computeruse.mouseEmulation.dryRun", context, metadata)],
            events: ["basicTool.computeruse.mouseEmulation.dryRun"],
        };
    }
    if (provider === undefined) {
        return failure("PROVIDER_UNAVAILABLE", "computeruse.mouseEmulation requires runtime executor.computeruse locateCursor and pointerAction support for dryRun:false", "provider", context);
    }
    let providerResult;
    try {
        const result = await provider({
            operation: "computeruse.mouseEmulation.pointerSequence",
            steps,
            purpose,
            context: {
                runtimeId: context.runtimeId,
                sessionId: context.sessionId,
                invocationId: context.invocationId,
                auditMetadata: {
                    ...(context.auditMetadata ?? {}),
                    ...(metadata ?? {}),
                },
            },
        });
        const normalizedResult = normalizeProviderResult(result, steps, context);
        if ("ok" in normalizedResult)
            return normalizedResult;
        providerResult = normalizedResult;
    }
    catch (error) {
        const providerMessage = publicSafeProviderFailureMessage(error);
        return failure("PROVIDER_FAILURE", providerMessage === undefined
            ? "computeruse.mouseEmulation runtime provider failed without exposing private details"
            : `computeruse.mouseEmulation runtime provider failed: ${providerMessage}`, "provider", context);
    }
    return {
        ok: true,
        toolId: mouseEmulationDescriptor.toolId,
        output: {
            ...baseOutput(steps, purpose, maxSteps, acceptedScopes, false, true),
            sequenceEnvelope: {
                maxSteps,
                executed: true,
                metadataOnly: false,
                stepResults: providerResult.stepResults.map((stepResult) => ({
                    index: stepResult.index,
                    kind: stepResult.kind,
                    executed: true,
                    metadataOnly: false,
                    actionId: stepResult.actionId,
                    position: stepResult.position,
                })),
            },
            providerMetadata: providerResult.metadata,
        },
        audit: [
            auditEvent("agentCore.basicTool.computeruse.mouseEmulation.executed", context, {
                stepCount: providerResult.stepResults.length,
                ...(providerResult.metadata ?? {}),
            }),
        ],
        events: ["basicTool.computeruse.mouseEmulation.executed"],
    };
}
export function planMouseEmulation(request = {}) {
    return executeMouseEmulation(request);
}
