aura-protocol
Version:
Core TypeScript definitions and JSON Schema for the AURA protocol - making websites machine-readable for AI agents
238 lines (237 loc) • 10.1 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const citty_1 = require("citty");
const Ajv = __importStar(require("ajv"));
const kleur_1 = require("kleur");
const main = (0, citty_1.defineCommand)({
meta: {
name: 'aura-validate',
description: 'Validate AURA manifest files against the official schema',
version: '1.0.0',
},
args: {
file: {
type: 'positional',
description: 'Path to the manifest file (default: .well-known/aura.json)',
required: false,
},
url: {
type: 'string',
description: 'Validate manifest from URL',
alias: 'u',
},
schema: {
type: 'string',
description: 'Path to custom schema file',
alias: 's',
},
verbose: {
type: 'boolean',
description: 'Show detailed validation output',
alias: 'v',
},
json: {
type: 'boolean',
description: 'Output machine-readable JSON',
alias: 'j',
},
},
async run({ args }) {
var _a, _b;
const result = {
valid: false,
warnings: [],
};
try {
// Determine manifest source
let manifestData;
let manifestSource;
if (args.url) {
// Fetch from URL - temporarily disabled
const error = 'URL validation is temporarily disabled. Please use local file validation.';
if (args.json) {
console.log(JSON.stringify({ valid: false, error }, null, 2));
}
else {
console.error((0, kleur_1.red)(error));
}
process.exit(1);
}
else {
// Read from file
const manifestPath = args.file || path.join(process.cwd(), '.well-known', 'aura.json');
if (!fs.existsSync(manifestPath)) {
const error = `Manifest file not found: ${manifestPath}`;
if (args.json) {
console.log(JSON.stringify({ valid: false, error }, null, 2));
}
else {
console.error((0, kleur_1.red)(error));
}
process.exit(1);
}
manifestData = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
manifestSource = manifestPath;
}
result.manifest = manifestData;
result.source = manifestSource;
if (!args.json) {
console.log((0, kleur_1.blue)(`Validating manifest from: ${manifestSource}`));
}
// Load schema
let schema;
if (args.schema) {
// Custom schema
if (!fs.existsSync(args.schema)) {
const error = `Schema file not found: ${args.schema}`;
if (args.json) {
console.log(JSON.stringify({ valid: false, error }, null, 2));
}
else {
console.error((0, kleur_1.red)(error));
}
process.exit(1);
}
schema = JSON.parse(fs.readFileSync(args.schema, 'utf-8'));
}
else {
// Default schema from dist
const schemaPath = path.join(__dirname, '../../dist/aura-v1.0.schema.json');
if (!fs.existsSync(schemaPath)) {
const error = 'Default schema not found. Run "npm run build" first.';
if (args.json) {
console.log(JSON.stringify({ valid: false, error }, null, 2));
}
else {
console.error((0, kleur_1.red)(error));
}
process.exit(1);
}
schema = JSON.parse(fs.readFileSync(schemaPath, 'utf-8'));
}
// Validate
const ajv = new Ajv.default({
allErrors: true,
verbose: args.verbose,
strict: false // Allow additional keywords from TypeScript JSON Schema
});
const validate = ajv.compile(schema);
const valid = validate(manifestData);
result.valid = valid;
if (valid) {
if (!args.json) {
console.log((0, kleur_1.green)('✓ Manifest is valid!'));
// Show summary
console.log((0, kleur_1.cyan)('\nManifest Summary:'));
console.log(` Protocol: ${manifestData.protocol} v${manifestData.version}`);
console.log(` Site: ${manifestData.site.name}`);
console.log(` Resources: ${Object.keys(manifestData.resources || {}).length}`);
console.log(` Capabilities: ${Object.keys(manifestData.capabilities || {}).length}`);
if (args.verbose) {
console.log((0, kleur_1.cyan)('\nCapabilities:'));
Object.entries(manifestData.capabilities || {}).forEach(([id, cap]) => {
console.log(` - ${id}: ${cap.description}`);
});
}
}
}
else {
result.errors = validate.errors;
if (!args.json) {
console.log((0, kleur_1.red)('✗ Manifest is invalid!'));
console.log((0, kleur_1.red)('\nValidation errors:'));
(_a = validate.errors) === null || _a === void 0 ? void 0 : _a.forEach((error) => {
const instancePath = error.instancePath || '/';
console.log((0, kleur_1.red)(` ${instancePath}: ${error.message}`));
if (error.params && args.verbose) {
console.log((0, kleur_1.gray)(` Details: ${JSON.stringify(error.params)}`));
}
});
}
}
// Additional checks
if (manifestData.capabilities) {
if (!args.json) {
console.log((0, kleur_1.cyan)('\nPerforming additional checks...'));
}
// Check for referenced capabilities in resources
const referencedCapabilities = new Set();
Object.values(manifestData.resources || {}).forEach((resource) => {
Object.values(resource.operations || {}).forEach((op) => {
if (op.capabilityId) {
referencedCapabilities.add(op.capabilityId);
}
});
});
// Check for unreferenced capabilities
const definedCapabilities = new Set(Object.keys(manifestData.capabilities));
const unreferenced = Array.from(definedCapabilities).filter(id => !referencedCapabilities.has(id));
if (unreferenced.length > 0) {
const warning = `Unreferenced capabilities: ${unreferenced.join(', ')}`;
(_b = result.warnings) === null || _b === void 0 ? void 0 : _b.push(warning);
if (!args.json) {
console.log((0, kleur_1.yellow)(` ⚠ ${warning}`));
}
}
// Check for undefined capability references
const undefined = Array.from(referencedCapabilities).filter(id => !definedCapabilities.has(id));
if (undefined.length > 0) {
const error = `Undefined capability references: ${undefined.join(', ')}`;
result.errors = result.errors || [];
result.errors.push({ message: error });
result.valid = false;
if (!args.json) {
console.log((0, kleur_1.red)(` ✗ ${error}`));
}
}
}
if (args.json) {
console.log(JSON.stringify(result, null, 2));
}
else {
if (result.valid) {
console.log((0, kleur_1.green)('\n✓ All checks passed!'));
}
}
if (!result.valid) {
process.exit(1);
}
}
catch (error) {
if (args.json) {
console.log(JSON.stringify({ valid: false, error: error.message }, null, 2));
}
else {
console.error((0, kleur_1.red)(`Error: ${error.message}`));
}
process.exit(1);
}
},
});
(0, citty_1.runMain)(main);