import { mkdir, writeFile } from "node:fs/promises";
import { createServer } from "node:http";
import { dirname } from "node:path";
export class A2AAgent {
    static agent;
    static auth = publicAuth();
    static skills = [];
    static capabilities = {};
    static inputModes = ["application/json"];
    static outputModes = ["application/json"];
    static requiredSecrets = [];
    static requiredEnv = [];
    static consumerSetup = { fields: [] };
    static runtime = {};
    static workspaceAccess = { enabled: false };
    static configSchema = null;
    static stateSchema = null;
    static templateLineage = null;
    static metaAgentManifest = null;
    async dispatch(request) {
        const handler = this[request.handler];
        if (typeof handler !== "function") {
            throw new Error(`agent does not implement handler method: ${request.handler}`);
        }
        return normalizeWorkerResponse(await handler.call(this, request));
    }
}
export function publicAuth() {
    return {
        model: "NoAuth",
        strategy: "public",
        principal_schema: { title: "NoAuth", type: "object", properties: {}, additionalProperties: false },
        required: false
    };
}
export function skill(declaration) {
    validateSkill(declaration);
    return declaration;
}
export function compileAgent(agentClass, options = {}) {
    const identity = agentClass.agent;
    if (!identity?.name)
        throw new Error("agent.agent.name is required");
    const skills = agentClass.skills.map(normalizeSkill);
    if (skills.length === 0)
        throw new Error("agent must declare at least one skill");
    const names = new Set();
    for (const item of skills) {
        if (names.has(item.name))
            throw new Error(`duplicate skill: ${item.name}`);
        names.add(item.name);
    }
    return {
        schema_version: "2026-06-04",
        language: options.language ?? "typescript",
        name: identity.name,
        description: identity.description ?? "",
        version: identity.version ?? "0.1.0",
        entrypoint: options.entrypoint ?? {},
        skills,
        capabilities: agentClass.capabilities,
        input_modes: agentClass.inputModes,
        output_modes: agentClass.outputModes,
        required_secrets: agentClass.requiredSecrets,
        required_env: agentClass.requiredEnv,
        consumer_setup: agentClass.consumerSetup,
        runtime: { sandbox: "microsandbox", ...agentClass.runtime },
        template_lineage: agentClass.templateLineage,
        meta_agent_manifest: agentClass.metaAgentManifest,
        state_schema: agentClass.stateSchema,
        workspace_access: agentClass.workspaceAccess,
        config_schema: agentClass.configSchema,
        auth: agentClass.auth,
        metadata: options.metadata ?? {}
    };
}
export async function writeAgentDsl(agentClass, path = ".a2a/agent.dsl.json", options = {}) {
    const dsl = compileAgent(agentClass, options);
    await mkdir(dirname(path), { recursive: true });
    await writeFile(path, `${JSON.stringify(dsl, null, 2)}\n`, "utf8");
    return dsl;
}
export function serveWorker(agentClass, handlers, options = {}) {
    const dsl = compileAgent(agentClass);
    const handlerNames = new Set(dsl.skills.map((item) => item.handler));
    const server = createServer(async (req, res) => {
        try {
            if (req.method !== "POST" || !req.url?.startsWith("/_a2a/invoke/")) {
                writeJson(res, 404, { error: "not found" });
                return;
            }
            const handlerName = decodeURIComponent(req.url.slice("/_a2a/invoke/".length));
            if (!handlerNames.has(handlerName) || typeof handlers[handlerName] !== "function") {
                writeJson(res, 404, { error: `unknown handler: ${handlerName}` });
                return;
            }
            const body = await readJson(req);
            const request = body;
            const raw = await handlers[handlerName](request);
            const response = normalizeWorkerResponse(raw);
            writeJson(res, 200, response);
        }
        catch (error) {
            writeJson(res, 500, { error: error instanceof Error ? error.message : String(error) });
        }
    });
    server.listen(options.port ?? 9001, options.host ?? "127.0.0.1");
    return server;
}
export function serveAgent(agentClass, options = {}) {
    const dsl = compileAgent(agentClass);
    const agent = new agentClass();
    const handlerNames = new Set(dsl.skills.map((item) => item.handler));
    const server = createServer(async (req, res) => {
        try {
            if (req.method !== "POST" || !req.url?.startsWith("/_a2a/invoke/")) {
                writeJson(res, 404, { error: "not found" });
                return;
            }
            const handlerName = decodeURIComponent(req.url.slice("/_a2a/invoke/".length));
            if (!handlerNames.has(handlerName)) {
                writeJson(res, 404, { error: `unknown handler: ${handlerName}` });
                return;
            }
            const body = await readJson(req);
            const request = { ...body, handler: handlerName };
            const response = await agent.dispatch(request);
            writeJson(res, 200, response);
        }
        catch (error) {
            writeJson(res, 500, { error: error instanceof Error ? error.message : String(error) });
        }
    });
    server.listen(options.port ?? 9001, options.host ?? "127.0.0.1");
    return server;
}
function normalizeSkill(declaration) {
    validateSkill(declaration);
    return {
        name: declaration.name,
        description: declaration.description ?? "",
        handler: declaration.handler ?? declaration.name,
        tags: declaration.tags ?? [],
        scopes: declaration.scopes ?? [],
        stream: declaration.stream ?? false,
        policy: {
            timeout_seconds: declaration.policy?.timeout_seconds ?? null,
            idempotent: declaration.policy?.idempotent ?? false,
            max_retries: declaration.policy?.max_retries ?? 0,
            cost_class: declaration.policy?.cost_class ?? null,
            allow_scope_expansion: declaration.policy?.allow_scope_expansion ?? false,
            grant_mode: declaration.policy?.grant_mode ?? null,
            grant_allow_patterns: declaration.policy?.grant_allow_patterns ?? [],
            grant_deny_patterns: declaration.policy?.grant_deny_patterns ?? [],
            grant_outputs_prefix: declaration.policy?.grant_outputs_prefix ?? null,
            grant_write_prefixes: declaration.policy?.grant_write_prefixes ?? [],
            grant_ttl_seconds: declaration.policy?.grant_ttl_seconds ?? null,
            grant_run_timeout_seconds: declaration.policy?.grant_run_timeout_seconds ?? null,
            grant_approval_timeout_seconds: declaration.policy?.grant_approval_timeout_seconds ?? null,
            grant_scope_approval_timeout_seconds: declaration.policy?.grant_scope_approval_timeout_seconds ?? null
        },
        input_schema: declaration.input_schema,
        output_schema: declaration.output_schema
    };
}
function validateSkill(declaration) {
    if (!declaration.name)
        throw new Error("skill.name is required");
    if (declaration.input_schema?.type !== "object") {
        throw new Error(`skill ${declaration.name}: input_schema must be an object schema`);
    }
    if (typeof declaration.input_schema.properties !== "object" || declaration.input_schema.properties === null) {
        throw new Error(`skill ${declaration.name}: input_schema.properties is required`);
    }
    if (!Array.isArray(declaration.input_schema.required)) {
        throw new Error(`skill ${declaration.name}: input_schema.required must be an array`);
    }
    for (const key of declaration.input_schema.required) {
        if (typeof key !== "string")
            throw new Error(`skill ${declaration.name}: required values must be strings`);
        if (!(key in declaration.input_schema.properties)) {
            throw new Error(`skill ${declaration.name}: required field ${key} missing from properties`);
        }
    }
    if (!declaration.output_schema || Object.keys(declaration.output_schema).length === 0) {
        throw new Error(`skill ${declaration.name}: output_schema is required`);
    }
}
function normalizeWorkerResponse(value) {
    if (isObject(value) && "result" in value) {
        return value;
    }
    throw new Error("worker handler must return a Sidecar WorkerResponse object with a result field");
}
function isObject(value) {
    return typeof value === "object" && value !== null && !Array.isArray(value);
}
async function readJson(req) {
    const chunks = [];
    for await (const chunk of req)
        chunks.push(Buffer.from(chunk));
    const raw = Buffer.concat(chunks).toString("utf8");
    return raw ? JSON.parse(raw) : {};
}
function writeJson(res, status, body) {
    res.statusCode = status;
    res.setHeader("content-type", "application/json");
    res.end(JSON.stringify(body));
}
//# sourceMappingURL=index.js.map