import { randomUUID } from "crypto";
import YAML from "yaml";
const TOOL_MESSAGE_DEBUG_KEYS = new Set([
    "metadata",
    "additional_kwargs",
    "response_metadata",
]);
function getToolCallDebugPayload(outputRecord) {
    const lcKwargs = typeof outputRecord.lc_kwargs === "object" && outputRecord.lc_kwargs !== null
        ? outputRecord.lc_kwargs
        : null;
    if (lcKwargs && "tool_call_id" in lcKwargs) {
        return lcKwargs;
    }
    if ("tool_call_id" in outputRecord) {
        return outputRecord;
    }
    return null;
}
function sanitizeToolCallOutputForDebug(output) {
    if (typeof output !== "object" || output === null) {
        return output;
    }
    const outputRecord = output;
    const debugPayload = getToolCallDebugPayload(outputRecord);
    if (!debugPayload) {
        return output;
    }
    return Object.fromEntries(Object.entries(debugPayload).filter(([key]) => !TOOL_MESSAGE_DEBUG_KEYS.has(key)));
}
function serializeErrorForDebug(error) {
    if (!(error instanceof Error)) {
        return error;
    }
    const errorWithCause = error;
    const serialized = {
        name: error.name,
        message: error.message,
    };
    if (error.stack) {
        serialized.stack = error.stack;
    }
    if (errorWithCause.cause !== undefined) {
        serialized.cause = serializeErrorForDebug(errorWithCause.cause);
    }
    for (const key of Object.getOwnPropertyNames(error)) {
        if (key in serialized) {
            continue;
        }
        serialized[key] = error[key];
    }
    return serialized;
}
export function createToolCallTracker(params) {
    var _a, _b;
    const toolCallId = (_a = params.toolCallId) !== null && _a !== void 0 ? _a : randomUUID();
    const startedAt = (_b = params.startedAt) !== null && _b !== void 0 ? _b : Date.now();
    return {
        start() {
            var _a;
            params.emit({
                toolCallId,
                toolName: params.toolName,
                toolInfo: params.toolInfo,
                phase: "start",
                input: YAML.stringify((_a = params.input) !== null && _a !== void 0 ? _a : {}),
            });
        },
        finishSuccess(output) {
            params.emit({
                toolCallId,
                toolName: params.toolName,
                phase: "end",
                durationMs: Date.now() - startedAt,
                output: YAML.stringify(sanitizeToolCallOutputForDebug(output)).trimEnd(),
                error: null,
            });
        },
        finishError(error) {
            params.emit({
                toolCallId,
                toolName: params.toolName,
                phase: "end",
                durationMs: Date.now() - startedAt,
                output: null,
                error: YAML.stringify(serializeErrorForDebug(error)).trimEnd(),
            });
        },
    };
}
