// server/modules/orchestration/a2a/validator.ts
// Hand-written validators for incoming A2A payloads.
// We deliberately avoid adding a new dep (zod, ajv) for the
// foundation; a follow-on plan can swap to a schema lib if needed.
//
// All path strings use JSONPath-style "$" as the document root so
// callers can map errors to wire-payload locations consistently.
export class A2AValidationError extends Error {
    path;
    constructor(message, path) {
        super(`${path}: ${message}`);
        this.path = path;
        this.name = 'A2AValidationError';
    }
}
function assertNonEmptyString(value, path) {
    if (typeof value !== 'string' || value.length === 0) {
        throw new A2AValidationError('expected non-empty string', path);
    }
}
function assertOptionalNonEmptyString(value, path) {
    if (value === undefined) {
        return;
    }
    assertNonEmptyString(value, path);
}
function assertPlainObject(value, path) {
    if (!value || typeof value !== 'object' || Array.isArray(value)) {
        throw new A2AValidationError('expected plain object', path);
    }
}
function assertPart(value, path) {
    if (!value || typeof value !== 'object') {
        throw new A2AValidationError('expected object', path);
    }
    const part = value;
    if (part.kind === 'text') {
        assertNonEmptyString(part.text, `${path}.text`);
        return;
    }
    if (part.kind === 'file') {
        assertNonEmptyString(part.name, `${path}.name`);
        return;
    }
    if (part.kind === 'data') {
        const data = part.data;
        if (!data || typeof data !== 'object' || Array.isArray(data)) {
            throw new A2AValidationError('data must be a plain object', `${path}.data`);
        }
        return;
    }
    throw new A2AValidationError('part.kind must be text|file|data', `${path}.kind`);
}
export function assertMessage(value, path = '$') {
    if (!value || typeof value !== 'object') {
        throw new A2AValidationError('expected object', path);
    }
    const m = value;
    assertNonEmptyString(m.messageId, `${path}.messageId`);
    if (m.role !== 'user' && m.role !== 'agent') {
        throw new A2AValidationError('role must be user|agent', `${path}.role`);
    }
    if (!Array.isArray(m.parts) || m.parts.length === 0) {
        throw new A2AValidationError('parts must be non-empty array', `${path}.parts`);
    }
    assertOptionalNonEmptyString(m.taskId, `${path}.taskId`);
    m.parts.forEach((p, i) => assertPart(p, `${path}.parts[${i}]`));
}
export function assertSubmitTaskInput(value) {
    if (!value || typeof value !== 'object') {
        throw new A2AValidationError('expected object', '$');
    }
    const v = value;
    assertMessage(v.message, '$.message');
    assertNonEmptyString(v.adapterId, '$.adapterId');
    assertOptionalNonEmptyString(v.contextId, '$.contextId');
    if (v.metadata !== undefined) {
        assertPlainObject(v.metadata, '$.metadata');
    }
}
export function assertAgentCard(value) {
    if (!value || typeof value !== 'object') {
        throw new A2AValidationError('expected object', '$');
    }
    const card = value;
    assertNonEmptyString(card.name, '$.name');
    assertNonEmptyString(card.description, '$.description');
    assertNonEmptyString(card.url, '$.url');
    assertNonEmptyString(card.version, '$.version');
    if (!Array.isArray(card.capabilities)) {
        throw new A2AValidationError('capabilities must be array', '$.capabilities');
    }
    if (!Array.isArray(card.skills)) {
        throw new A2AValidationError('skills must be array', '$.skills');
    }
    card.skills.forEach((s, i) => {
        assertNonEmptyString(s.id, `$.skills[${i}].id`);
        assertNonEmptyString(s.description, `$.skills[${i}].description`);
    });
}
//# sourceMappingURL=validator.js.map