import * as fs from "node:fs/promises";
import * as path from "node:path";
import { defineTool } from "../extensions/types.js";
export const STRUCTURED_OUTPUT_TOOL_NAME = "structured_output";
function stringifyParams(params) {
    try {
        return JSON.stringify(params, null, 2);
    }
    catch (error) {
        throw new Error(`Structured output must be JSON-serializable: ${error instanceof Error ? error.message : String(error)}`);
    }
}
async function writePrivateJsonFile(filePath, serializedJson) {
    await fs.mkdir(path.dirname(filePath), { recursive: true });
    await fs.writeFile(filePath, serializedJson, { mode: 0o600 });
    // Re-apply the private mode after writing so pre-existing looser files are tightened too.
    await fs.chmod(filePath, 0o600);
}
async function writeCapturedOutput(output, serializedParams) {
    try {
        await writePrivateJsonFile(output.outputPath, serializedParams);
    }
    catch (error) {
        throw new Error(`Failed to write structured output capture: ${error instanceof Error ? error.message : String(error)}`);
    }
}
export function createStructuredOutputCapture() {
    return { value: undefined, called: false };
}
export function createStructuredOutputTool(options) {
    const name = options.name ?? STRUCTURED_OUTPUT_TOOL_NAME;
    return defineTool({
        name,
        label: "Structured Output",
        description: "Return the final machine-readable result.",
        promptSnippet: "Return final machine-readable output",
        promptGuidelines: [
            `${name} is the final machine-readable result channel; call ${name} exactly once when done.`,
            `Do not write a prose final answer after calling ${name}.`,
        ],
        parameters: options.schema,
        maxResultSizeChars: Infinity,
        structuredOutput: true,
        async execute(_toolCallId, params) {
            const serializedParams = stringifyParams(params);
            if (options.output) {
                await writeCapturedOutput(options.output, serializedParams);
            }
            if (options.capture) {
                options.capture.value = params;
                options.capture.called = true;
            }
            return {
                content: [{ type: "text", text: serializedParams }],
                details: params,
                terminate: true,
            };
        },
    });
}
//# sourceMappingURL=structured-output.js.map