Initial commit
This commit is contained in:
15
.claude-plugin/plugin.json
Normal file
15
.claude-plugin/plugin.json
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"name": "api-response-validator",
|
||||||
|
"description": "Validate API responses against schemas and contracts",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"author": {
|
||||||
|
"name": "Jeremy Longshore",
|
||||||
|
"email": "[email protected]"
|
||||||
|
},
|
||||||
|
"skills": [
|
||||||
|
"./skills"
|
||||||
|
],
|
||||||
|
"commands": [
|
||||||
|
"./commands"
|
||||||
|
]
|
||||||
|
}
|
||||||
3
README.md
Normal file
3
README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# api-response-validator
|
||||||
|
|
||||||
|
Validate API responses against schemas and contracts
|
||||||
579
commands/validate-api-responses.md
Normal file
579
commands/validate-api-responses.md
Normal file
@@ -0,0 +1,579 @@
|
|||||||
|
---
|
||||||
|
description: Validate API responses against schemas
|
||||||
|
shortcut: validate
|
||||||
|
---
|
||||||
|
|
||||||
|
# Validate API Responses
|
||||||
|
|
||||||
|
Implement comprehensive API response validation using JSON Schema, OpenAPI specifications, and custom business rules to ensure data integrity and contract compliance.
|
||||||
|
|
||||||
|
## When to Use This Command
|
||||||
|
|
||||||
|
Use `/validate-api-responses` when you need to:
|
||||||
|
- Ensure API responses conform to documented schemas
|
||||||
|
- Catch contract violations before they reach clients
|
||||||
|
- Validate response data types, formats, and constraints
|
||||||
|
- Implement runtime schema validation in production
|
||||||
|
- Create automated contract testing pipelines
|
||||||
|
- Monitor API compatibility across versions
|
||||||
|
|
||||||
|
DON'T use this when:
|
||||||
|
- Building prototypes without defined schemas (premature optimization)
|
||||||
|
- Working with highly dynamic responses (consider runtime type checking instead)
|
||||||
|
- Validating simple scalar responses (overkill for basic types)
|
||||||
|
|
||||||
|
## Design Decisions
|
||||||
|
|
||||||
|
This command implements **JSON Schema + Ajv** as the primary approach because:
|
||||||
|
- Industry-standard schema format with wide ecosystem support
|
||||||
|
- Blazing fast validation with compiled schemas (10x faster than alternatives)
|
||||||
|
- Comprehensive format validators for dates, emails, UUIDs, etc.
|
||||||
|
- Custom keyword support for business-specific validation
|
||||||
|
- Clear, actionable error messages for debugging
|
||||||
|
|
||||||
|
**Alternative considered: OpenAPI/Swagger validation**
|
||||||
|
- Better for full API contract validation
|
||||||
|
- Includes request validation, not just responses
|
||||||
|
- More complex setup and configuration
|
||||||
|
- Recommended when using OpenAPI for documentation
|
||||||
|
|
||||||
|
**Alternative considered: Joi/Yup validation**
|
||||||
|
- More intuitive API for JavaScript developers
|
||||||
|
- Better TypeScript integration
|
||||||
|
- Limited to JavaScript ecosystem
|
||||||
|
- Recommended for Node.js-only projects
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
Before running this command:
|
||||||
|
1. Define response schemas (JSON Schema or OpenAPI)
|
||||||
|
2. Identify validation points (middleware, tests, runtime)
|
||||||
|
3. Determine error handling strategy
|
||||||
|
4. Plan performance impact for large payloads
|
||||||
|
5. Consider validation modes (strict vs. permissive)
|
||||||
|
|
||||||
|
## Implementation Process
|
||||||
|
|
||||||
|
### Step 1: Define Response Schemas
|
||||||
|
Create JSON Schema definitions for all API responses with proper constraints.
|
||||||
|
|
||||||
|
### Step 2: Configure Validation Middleware
|
||||||
|
Set up validation middleware to intercept and validate responses automatically.
|
||||||
|
|
||||||
|
### Step 3: Implement Custom Validators
|
||||||
|
Add business-specific validation rules beyond structural validation.
|
||||||
|
|
||||||
|
### Step 4: Set Up Error Handling
|
||||||
|
Configure how validation errors are reported to clients and logged.
|
||||||
|
|
||||||
|
### Step 5: Create Test Suites
|
||||||
|
Build comprehensive test suites for schema validation and edge cases.
|
||||||
|
|
||||||
|
## Output Format
|
||||||
|
|
||||||
|
The command generates:
|
||||||
|
- `schemas/` - JSON Schema definitions for all endpoints
|
||||||
|
- `validators/` - Compiled validator functions
|
||||||
|
- `middleware/response-validator.js` - Express/Koa middleware
|
||||||
|
- `tests/schema-validation.test.js` - Validation test suites
|
||||||
|
- `docs/api-schemas.md` - Human-readable schema documentation
|
||||||
|
- `monitoring/validation-metrics.js` - Validation failure tracking
|
||||||
|
|
||||||
|
## Code Examples
|
||||||
|
|
||||||
|
### Example 1: JSON Schema Validation with Ajv
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// schemas/user-response.json
|
||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"$id": "UserResponse",
|
||||||
|
"type": "object",
|
||||||
|
"required": ["id", "email", "createdAt"],
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uuid"
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "email",
|
||||||
|
"maxLength": 255
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"minLength": 1,
|
||||||
|
"maxLength": 100
|
||||||
|
},
|
||||||
|
"age": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 150
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["admin", "user", "moderator"]
|
||||||
|
},
|
||||||
|
"minItems": 1,
|
||||||
|
"uniqueItems": true
|
||||||
|
},
|
||||||
|
"preferences": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"theme": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["light", "dark", "auto"]
|
||||||
|
},
|
||||||
|
"notifications": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"createdAt": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time"
|
||||||
|
},
|
||||||
|
"updatedAt": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
|
||||||
|
// validators/response-validator.js
|
||||||
|
const Ajv = require('ajv');
|
||||||
|
const addFormats = require('ajv-formats');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
class ResponseValidator {
|
||||||
|
constructor() {
|
||||||
|
this.ajv = new Ajv({
|
||||||
|
allErrors: true,
|
||||||
|
removeAdditional: 'failing',
|
||||||
|
useDefaults: true,
|
||||||
|
coerceTypes: false,
|
||||||
|
strict: true
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add format validators
|
||||||
|
addFormats(this.ajv);
|
||||||
|
|
||||||
|
// Add custom keywords
|
||||||
|
this.addCustomKeywords();
|
||||||
|
|
||||||
|
// Load and compile schemas
|
||||||
|
this.schemas = this.loadSchemas();
|
||||||
|
this.validators = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
addCustomKeywords() {
|
||||||
|
// Custom business rule validator
|
||||||
|
this.ajv.addKeyword({
|
||||||
|
keyword: 'businessRule',
|
||||||
|
schemaType: 'string',
|
||||||
|
compile: function(schemaValue) {
|
||||||
|
return function validate(data, dataCxt) {
|
||||||
|
switch(schemaValue) {
|
||||||
|
case 'validSubscription':
|
||||||
|
return data.subscriptionEnd > new Date().toISOString();
|
||||||
|
case 'activeUser':
|
||||||
|
return !data.deleted && data.verified;
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
loadSchemas() {
|
||||||
|
const schemaDir = path.join(__dirname, '../schemas');
|
||||||
|
const schemas = {};
|
||||||
|
|
||||||
|
fs.readdirSync(schemaDir).forEach(file => {
|
||||||
|
if (file.endsWith('.json')) {
|
||||||
|
const schema = JSON.parse(
|
||||||
|
fs.readFileSync(path.join(schemaDir, file), 'utf8')
|
||||||
|
);
|
||||||
|
schemas[schema.$id] = schema;
|
||||||
|
this.ajv.addSchema(schema);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return schemas;
|
||||||
|
}
|
||||||
|
|
||||||
|
getValidator(schemaId) {
|
||||||
|
if (!this.validators[schemaId]) {
|
||||||
|
const schema = this.schemas[schemaId];
|
||||||
|
if (!schema) {
|
||||||
|
throw new Error(`Schema not found: ${schemaId}`);
|
||||||
|
}
|
||||||
|
this.validators[schemaId] = this.ajv.compile(schema);
|
||||||
|
}
|
||||||
|
return this.validators[schemaId];
|
||||||
|
}
|
||||||
|
|
||||||
|
validate(schemaId, data) {
|
||||||
|
const validator = this.getValidator(schemaId);
|
||||||
|
const valid = validator(data);
|
||||||
|
|
||||||
|
if (!valid) {
|
||||||
|
return {
|
||||||
|
valid: false,
|
||||||
|
errors: this.formatErrors(validator.errors),
|
||||||
|
rawErrors: validator.errors
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return { valid: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
formatErrors(errors) {
|
||||||
|
return errors.map(err => ({
|
||||||
|
field: err.instancePath || 'root',
|
||||||
|
message: err.message,
|
||||||
|
params: err.params,
|
||||||
|
keyword: err.keyword,
|
||||||
|
schemaPath: err.schemaPath
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// middleware/response-validator.js
|
||||||
|
const ResponseValidator = require('../validators/response-validator');
|
||||||
|
|
||||||
|
function createResponseValidationMiddleware(options = {}) {
|
||||||
|
const validator = new ResponseValidator();
|
||||||
|
const {
|
||||||
|
enabled = true,
|
||||||
|
strict = false,
|
||||||
|
logErrors = true,
|
||||||
|
includeErrorDetails = process.env.NODE_ENV !== 'production'
|
||||||
|
} = options;
|
||||||
|
|
||||||
|
return function responseValidationMiddleware(req, res, next) {
|
||||||
|
if (!enabled) return next();
|
||||||
|
|
||||||
|
// Store original json method
|
||||||
|
const originalJson = res.json;
|
||||||
|
|
||||||
|
res.json = function(data) {
|
||||||
|
// Determine schema based on route
|
||||||
|
const schemaId = determineSchema(req.route, res.statusCode);
|
||||||
|
|
||||||
|
if (schemaId) {
|
||||||
|
const result = validator.validate(schemaId, data);
|
||||||
|
|
||||||
|
if (!result.valid) {
|
||||||
|
if (logErrors) {
|
||||||
|
console.error('Response validation failed:', {
|
||||||
|
endpoint: req.originalUrl,
|
||||||
|
method: req.method,
|
||||||
|
schemaId,
|
||||||
|
errors: result.errors
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strict) {
|
||||||
|
// In strict mode, return validation error
|
||||||
|
return originalJson.call(this, {
|
||||||
|
error: 'Response validation failed',
|
||||||
|
details: includeErrorDetails ? result.errors : undefined
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// In non-strict mode, log but send response
|
||||||
|
// Could also send to monitoring service
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return originalJson.call(this, data);
|
||||||
|
};
|
||||||
|
|
||||||
|
next();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function determineSchema(route, statusCode) {
|
||||||
|
// Map routes to schemas
|
||||||
|
const schemaMap = {
|
||||||
|
'GET /users/:id': 'UserResponse',
|
||||||
|
'GET /users': 'UserListResponse',
|
||||||
|
'POST /users': 'UserResponse',
|
||||||
|
'GET /products': 'ProductListResponse',
|
||||||
|
'GET /orders/:id': 'OrderResponse'
|
||||||
|
};
|
||||||
|
|
||||||
|
const routeKey = `${route.method} ${route.path}`;
|
||||||
|
return schemaMap[routeKey];
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = createResponseValidationMiddleware;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example 2: OpenAPI Response Validation
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// validators/openapi-validator.js
|
||||||
|
const OpenAPIValidator = require('express-openapi-validator');
|
||||||
|
const SwaggerParser = require('@apidevtools/swagger-parser');
|
||||||
|
const fs = require('fs');
|
||||||
|
const yaml = require('js-yaml');
|
||||||
|
|
||||||
|
class OpenAPIResponseValidator {
|
||||||
|
constructor(specPath) {
|
||||||
|
this.specPath = specPath;
|
||||||
|
this.spec = null;
|
||||||
|
this.middleware = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
async initialize() {
|
||||||
|
// Parse and validate OpenAPI spec
|
||||||
|
this.spec = await SwaggerParser.validate(this.specPath);
|
||||||
|
|
||||||
|
// Create validation middleware
|
||||||
|
this.middleware = OpenAPIValidator.middleware({
|
||||||
|
apiSpec: this.specPath,
|
||||||
|
validateRequests: false, // Only validate responses
|
||||||
|
validateResponses: {
|
||||||
|
removeAdditional: 'failing',
|
||||||
|
coerceTypes: false,
|
||||||
|
onError: (error, body, req) => {
|
||||||
|
console.error('OpenAPI validation error:', {
|
||||||
|
endpoint: req.path,
|
||||||
|
method: req.method,
|
||||||
|
error: error.message,
|
||||||
|
errors: error.errors
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
validateSecurity: false
|
||||||
|
});
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
getMiddleware() {
|
||||||
|
return this.middleware;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Manual validation method
|
||||||
|
async validateResponse(path, method, status, response) {
|
||||||
|
const operation = this.getOperation(path, method);
|
||||||
|
if (!operation) {
|
||||||
|
throw new Error(`Operation not found: ${method} ${path}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const responseSpec = operation.responses[status];
|
||||||
|
if (!responseSpec) {
|
||||||
|
throw new Error(`Response not defined for status: ${status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const schema = responseSpec.content?.['application/json']?.schema;
|
||||||
|
if (!schema) {
|
||||||
|
return { valid: true }; // No schema defined
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate against schema
|
||||||
|
return this.validateAgainstSchema(response, schema);
|
||||||
|
}
|
||||||
|
|
||||||
|
getOperation(path, method) {
|
||||||
|
const pathItem = this.spec.paths[path];
|
||||||
|
return pathItem?.[method.toLowerCase()];
|
||||||
|
}
|
||||||
|
|
||||||
|
validateAgainstSchema(data, schema) {
|
||||||
|
// Implementation would use Ajv or similar
|
||||||
|
// This is simplified for brevity
|
||||||
|
const Ajv = require('ajv');
|
||||||
|
const ajv = new Ajv();
|
||||||
|
const valid = ajv.validate(schema, data);
|
||||||
|
|
||||||
|
return {
|
||||||
|
valid,
|
||||||
|
errors: ajv.errors
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Usage
|
||||||
|
const validator = await new OpenAPIResponseValidator('./openapi.yaml').initialize();
|
||||||
|
app.use(validator.getMiddleware());
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example 3: Custom Business Rule Validation
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// validators/business-rules.js
|
||||||
|
class BusinessRuleValidator {
|
||||||
|
constructor() {
|
||||||
|
this.rules = new Map();
|
||||||
|
this.registerDefaultRules();
|
||||||
|
}
|
||||||
|
|
||||||
|
registerDefaultRules() {
|
||||||
|
// User-related rules
|
||||||
|
this.addRule('user.ageRestriction', (user) => {
|
||||||
|
if (user.role === 'admin' && user.age < 21) {
|
||||||
|
return 'Admins must be at least 21 years old';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.addRule('user.emailDomain', (user) => {
|
||||||
|
if (user.role === 'employee' && !user.email.endsWith('@company.com')) {
|
||||||
|
return 'Employees must use company email';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Order-related rules
|
||||||
|
this.addRule('order.minimumAmount', (order) => {
|
||||||
|
const total = order.items.reduce((sum, item) =>
|
||||||
|
sum + (item.price * item.quantity), 0
|
||||||
|
);
|
||||||
|
if (total < 10) {
|
||||||
|
return 'Order must be at least $10';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.addRule('order.inventoryCheck', async (order) => {
|
||||||
|
for (const item of order.items) {
|
||||||
|
const available = await checkInventory(item.productId);
|
||||||
|
if (available < item.quantity) {
|
||||||
|
return `Insufficient inventory for product ${item.productId}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
addRule(name, validator) {
|
||||||
|
this.rules.set(name, validator);
|
||||||
|
}
|
||||||
|
|
||||||
|
async validate(context, data) {
|
||||||
|
const errors = [];
|
||||||
|
const applicableRules = Array.from(this.rules.entries())
|
||||||
|
.filter(([name]) => name.startsWith(context));
|
||||||
|
|
||||||
|
for (const [name, validator] of applicableRules) {
|
||||||
|
try {
|
||||||
|
const error = await validator(data);
|
||||||
|
if (error) {
|
||||||
|
errors.push({
|
||||||
|
rule: name,
|
||||||
|
message: error
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
errors.push({
|
||||||
|
rule: name,
|
||||||
|
message: `Rule execution failed: ${e.message}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
valid: errors.length === 0,
|
||||||
|
errors
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Integration with response validation
|
||||||
|
async function validateWithBusinessRules(req, res, next) {
|
||||||
|
const originalJson = res.json;
|
||||||
|
const validator = new BusinessRuleValidator();
|
||||||
|
|
||||||
|
res.json = async function(data) {
|
||||||
|
const context = determineContext(req.route);
|
||||||
|
|
||||||
|
if (context) {
|
||||||
|
const result = await validator.validate(context, data);
|
||||||
|
|
||||||
|
if (!result.valid) {
|
||||||
|
console.error('Business rule validation failed:', result.errors);
|
||||||
|
|
||||||
|
// Could return error or just log
|
||||||
|
if (process.env.STRICT_VALIDATION === 'true') {
|
||||||
|
return originalJson.call(this, {
|
||||||
|
error: 'Business rule validation failed',
|
||||||
|
violations: result.errors
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return originalJson.call(this, data);
|
||||||
|
};
|
||||||
|
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
| Error | Cause | Solution |
|
||||||
|
|-------|-------|----------|
|
||||||
|
| "Schema not found" | Missing schema file | Ensure schema exists in schemas/ directory |
|
||||||
|
| "Invalid schema" | Malformed JSON Schema | Validate schema with JSON Schema validator |
|
||||||
|
| "Circular reference" | Schema references itself | Refactor schema to avoid circular dependencies |
|
||||||
|
| "Performance degradation" | Large payload validation | Use streaming validation or async processing |
|
||||||
|
| "Memory leak" | Schema compilation on every request | Cache compiled validators |
|
||||||
|
|
||||||
|
## Configuration Options
|
||||||
|
|
||||||
|
**Validation Modes**
|
||||||
|
- `strict`: Reject invalid responses (production)
|
||||||
|
- `permissive`: Log but allow invalid responses (development)
|
||||||
|
- `monitor`: Send metrics without blocking (staging)
|
||||||
|
|
||||||
|
**Performance Tuning**
|
||||||
|
- `cacheSize`: Number of compiled schemas to cache (default: 100)
|
||||||
|
- `maxDepth`: Maximum recursion depth for nested objects (default: 10)
|
||||||
|
- `timeout`: Maximum validation time in ms (default: 1000)
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
DO:
|
||||||
|
- Version your schemas alongside API versions
|
||||||
|
- Use shared schema definitions for common types
|
||||||
|
- Validate at multiple layers (client, server, database)
|
||||||
|
- Include examples in schema definitions
|
||||||
|
- Monitor validation failures in production
|
||||||
|
- Use semantic versioning for schema changes
|
||||||
|
|
||||||
|
DON'T:
|
||||||
|
- Validate responses in production synchronously (use async)
|
||||||
|
- Include sensitive data in validation error messages
|
||||||
|
- Use overly strict validation that breaks compatibility
|
||||||
|
- Ignore validation errors in production
|
||||||
|
- Mix validation logic with business logic
|
||||||
|
|
||||||
|
## Performance Considerations
|
||||||
|
|
||||||
|
- Compile schemas once at startup, not per request
|
||||||
|
- Use references for shared schema components
|
||||||
|
- Consider async validation for large payloads
|
||||||
|
- Implement sampling for high-traffic endpoints
|
||||||
|
- Cache validation results for identical responses
|
||||||
|
|
||||||
|
## Related Commands
|
||||||
|
|
||||||
|
- `/api-contract-generator` - Generate schemas from code
|
||||||
|
- `/api-documentation-generator` - Document schemas
|
||||||
|
- `/api-testing-framework` - Test against schemas
|
||||||
|
- `/api-versioning-manager` - Handle schema evolution
|
||||||
|
|
||||||
|
## Version History
|
||||||
|
|
||||||
|
- v1.0.0 (2024-10): Initial implementation with JSON Schema validation
|
||||||
|
- Planned v1.1.0: GraphQL schema validation support
|
||||||
93
plugin.lock.json
Normal file
93
plugin.lock.json
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
{
|
||||||
|
"$schema": "internal://schemas/plugin.lock.v1.json",
|
||||||
|
"pluginId": "gh:jeremylongshore/claude-code-plugins-plus:plugins/api-development/api-response-validator",
|
||||||
|
"normalized": {
|
||||||
|
"repo": null,
|
||||||
|
"ref": "refs/tags/v20251128.0",
|
||||||
|
"commit": "28408ec737fcc2439009417ccb68bdee68133f90",
|
||||||
|
"treeHash": "6753081541647469442e95387ad5bf232c88aae393511f0b745c2c142ce07a7b",
|
||||||
|
"generatedAt": "2025-11-28T10:18:08.174582Z",
|
||||||
|
"toolVersion": "publish_plugins.py@0.2.0"
|
||||||
|
},
|
||||||
|
"origin": {
|
||||||
|
"remote": "git@github.com:zhongweili/42plugin-data.git",
|
||||||
|
"branch": "master",
|
||||||
|
"commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390",
|
||||||
|
"repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data"
|
||||||
|
},
|
||||||
|
"manifest": {
|
||||||
|
"name": "api-response-validator",
|
||||||
|
"description": "Validate API responses against schemas and contracts",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"content": {
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "README.md",
|
||||||
|
"sha256": "7d6d361130ff3be58e7ac6f4cb3e35d694f81c4fd2587d286c67c827ede342bf"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": ".claude-plugin/plugin.json",
|
||||||
|
"sha256": "fe034772ee2e4ea1e9496f72bc119f250a658bac5e2879d1039c1fe0849390cc"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "commands/validate-api-responses.md",
|
||||||
|
"sha256": "fd77abc65bb60b4a12a13e5ae82d904c1da0bf5c1701b15199dd11b266a343ef"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/skill-adapter/references/examples.md",
|
||||||
|
"sha256": "922bbc3c4ebf38b76f515b5c1998ebde6bf902233e00e2c5a0e9176f975a7572"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/skill-adapter/references/best-practices.md",
|
||||||
|
"sha256": "c8f32b3566252f50daacd346d7045a1060c718ef5cfb07c55a0f2dec5f1fb39e"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/skill-adapter/references/README.md",
|
||||||
|
"sha256": "6a3efe5da6d93b9f10f74f2cd2a122ba4027d529c3753698ebf279ba20ac1eac"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/skill-adapter/scripts/helper-template.sh",
|
||||||
|
"sha256": "0881d5660a8a7045550d09ae0acc15642c24b70de6f08808120f47f86ccdf077"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/skill-adapter/scripts/validation.sh",
|
||||||
|
"sha256": "92551a29a7f512d2036e4f1fb46c2a3dc6bff0f7dde4a9f699533e446db48502"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/skill-adapter/scripts/README.md",
|
||||||
|
"sha256": "542b455a6c39a3bc814f78da6c1e74a1e88ef31f2ee1a06524797a0ba0edec19"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/skill-adapter/assets/test-data.json",
|
||||||
|
"sha256": "ac17dca3d6e253a5f39f2a2f1b388e5146043756b05d9ce7ac53a0042eee139d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/skill-adapter/assets/error_codes.json",
|
||||||
|
"sha256": "50e7790d00874912da11ddedf022db5d2722d1e7e51e19928ae521cec9eff3bd"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/skill-adapter/assets/README.md",
|
||||||
|
"sha256": "19efe4ebf5ae98c24cad55420aeb55145fc1b58721fbd1136c7c49c4a68b73a6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/skill-adapter/assets/validation_report_template.html",
|
||||||
|
"sha256": "cbb8e59fd251a6102a8f68e9dfc077b776182f78df0040d025b6fd91ee39d3ec"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/skill-adapter/assets/skill-schema.json",
|
||||||
|
"sha256": "f5639ba823a24c9ac4fb21444c0717b7aefde1a4993682897f5bf544f863c2cd"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/skill-adapter/assets/config-template.json",
|
||||||
|
"sha256": "0c2ba33d2d3c5ccb266c0848fc43caa68a2aa6a80ff315d4b378352711f83e1c"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dirSha256": "6753081541647469442e95387ad5bf232c88aae393511f0b745c2c142ce07a7b"
|
||||||
|
},
|
||||||
|
"security": {
|
||||||
|
"scannedAt": null,
|
||||||
|
"scannerVersion": null,
|
||||||
|
"flags": []
|
||||||
|
}
|
||||||
|
}
|
||||||
6
skills/skill-adapter/assets/README.md
Normal file
6
skills/skill-adapter/assets/README.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# Assets
|
||||||
|
|
||||||
|
Bundled resources for api-response-validator skill
|
||||||
|
|
||||||
|
- [ ] validation_report_template.html: HTML template for generating validation reports.
|
||||||
|
- [ ] error_codes.json: JSON file containing error codes and descriptions.
|
||||||
32
skills/skill-adapter/assets/config-template.json
Normal file
32
skills/skill-adapter/assets/config-template.json
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"skill": {
|
||||||
|
"name": "skill-name",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"enabled": true,
|
||||||
|
"settings": {
|
||||||
|
"verbose": false,
|
||||||
|
"autoActivate": true,
|
||||||
|
"toolRestrictions": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"triggers": {
|
||||||
|
"keywords": [
|
||||||
|
"example-trigger-1",
|
||||||
|
"example-trigger-2"
|
||||||
|
],
|
||||||
|
"patterns": []
|
||||||
|
},
|
||||||
|
"tools": {
|
||||||
|
"allowed": [
|
||||||
|
"Read",
|
||||||
|
"Grep",
|
||||||
|
"Bash"
|
||||||
|
],
|
||||||
|
"restricted": []
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"author": "Plugin Author",
|
||||||
|
"category": "general",
|
||||||
|
"tags": []
|
||||||
|
}
|
||||||
|
}
|
||||||
83
skills/skill-adapter/assets/error_codes.json
Normal file
83
skills/skill-adapter/assets/error_codes.json
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
{
|
||||||
|
"_comment": "Error codes and descriptions for the API Response Validator plugin.",
|
||||||
|
"error_codes": [
|
||||||
|
{
|
||||||
|
"code": "SCHEMA_VALIDATION_FAILED",
|
||||||
|
"description": "The API response failed validation against the provided JSON Schema.",
|
||||||
|
"details": {
|
||||||
|
"_comment": "Example details structure. 'errors' will contain schema validation errors.",
|
||||||
|
"errors": [
|
||||||
|
{
|
||||||
|
"dataPath": ".data.id",
|
||||||
|
"schemaPath": "#/properties/id/type",
|
||||||
|
"keyword": "type",
|
||||||
|
"message": "should be string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"severity": "ERROR",
|
||||||
|
"resolution": "Review the API response and the JSON Schema to identify and correct any discrepancies. Ensure data types and required fields match the schema definition."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "OPENAPI_VALIDATION_FAILED",
|
||||||
|
"description": "The API response failed validation against the OpenAPI specification.",
|
||||||
|
"details": {
|
||||||
|
"_comment": "Example details structure. 'errors' will contain OpenAPI validation errors.",
|
||||||
|
"errors": [
|
||||||
|
{
|
||||||
|
"message": "Response body does not conform to schema for 200 response."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"operationId": "getUserById",
|
||||||
|
"path": "/users/{userId}",
|
||||||
|
"method": "GET"
|
||||||
|
},
|
||||||
|
"severity": "ERROR",
|
||||||
|
"resolution": "Review the API response and the OpenAPI specification to identify and correct any discrepancies. Check for missing or incorrect data types, required fields, and response codes."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "CONTRACT_VALIDATION_FAILED",
|
||||||
|
"description": "The API response failed validation against the custom contract rules.",
|
||||||
|
"details": {
|
||||||
|
"_comment": "Example details structure. 'failed_rules' contains information about the failed custom rules.",
|
||||||
|
"failed_rules": [
|
||||||
|
{
|
||||||
|
"rule_name": "response_time_limit",
|
||||||
|
"message": "Response time exceeded the allowed limit of 500ms. Actual time: 750ms",
|
||||||
|
"actual_value": 750,
|
||||||
|
"expected_value": 500
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"severity": "WARNING",
|
||||||
|
"resolution": "Review the API response and the custom contract rules to identify and correct any discrepancies. Adjust the rules or the API implementation as needed."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "MISSING_CONTENT_TYPE",
|
||||||
|
"description": "The API response is missing the 'Content-Type' header.",
|
||||||
|
"details": null,
|
||||||
|
"severity": "WARNING",
|
||||||
|
"resolution": "Ensure the API response includes the 'Content-Type' header to properly identify the response format."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "INVALID_JSON",
|
||||||
|
"description": "The API response body is not valid JSON.",
|
||||||
|
"details": {
|
||||||
|
"_comment": "Details might include the parsing error message.",
|
||||||
|
"error_message": "Unexpected token '}' at position 10."
|
||||||
|
},
|
||||||
|
"severity": "ERROR",
|
||||||
|
"resolution": "Ensure the API response returns a valid JSON payload. Check for syntax errors and proper formatting."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "UNEXPECTED_STATUS_CODE",
|
||||||
|
"description": "The API returned an unexpected HTTP status code.",
|
||||||
|
"details": {
|
||||||
|
"expected_status_code": 200,
|
||||||
|
"actual_status_code": 500
|
||||||
|
},
|
||||||
|
"severity": "WARNING",
|
||||||
|
"resolution": "Verify the expected HTTP status code against the actual status code returned by the API. Investigate the API logs for potential errors."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
28
skills/skill-adapter/assets/skill-schema.json
Normal file
28
skills/skill-adapter/assets/skill-schema.json
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"title": "Claude Skill Configuration",
|
||||||
|
"type": "object",
|
||||||
|
"required": ["name", "description"],
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[a-z0-9-]+$",
|
||||||
|
"maxLength": 64,
|
||||||
|
"description": "Skill identifier (lowercase, hyphens only)"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string",
|
||||||
|
"maxLength": 1024,
|
||||||
|
"description": "What the skill does and when to use it"
|
||||||
|
},
|
||||||
|
"allowed-tools": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Comma-separated list of allowed tools"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^\\d+\\.\\d+\\.\\d+$",
|
||||||
|
"description": "Semantic version (x.y.z)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
27
skills/skill-adapter/assets/test-data.json
Normal file
27
skills/skill-adapter/assets/test-data.json
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"testCases": [
|
||||||
|
{
|
||||||
|
"name": "Basic activation test",
|
||||||
|
"input": "trigger phrase example",
|
||||||
|
"expected": {
|
||||||
|
"activated": true,
|
||||||
|
"toolsUsed": ["Read", "Grep"],
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Complex workflow test",
|
||||||
|
"input": "multi-step trigger example",
|
||||||
|
"expected": {
|
||||||
|
"activated": true,
|
||||||
|
"steps": 3,
|
||||||
|
"toolsUsed": ["Read", "Write", "Bash"],
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fixtures": {
|
||||||
|
"sampleInput": "example data",
|
||||||
|
"expectedOutput": "processed result"
|
||||||
|
}
|
||||||
|
}
|
||||||
122
skills/skill-adapter/assets/validation_report_template.html
Normal file
122
skills/skill-adapter/assets/validation_report_template.html
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>API Validation Report</title>
|
||||||
|
<style>
|
||||||
|
/* Inline CSS for styling */
|
||||||
|
body {
|
||||||
|
font-family: sans-serif;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin: 20px;
|
||||||
|
background-color: #f8f9fa; /* Light gray background */
|
||||||
|
color: #343a40; /* Dark gray text */
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
color: #007bff; /* Primary color for headings */
|
||||||
|
border-bottom: 2px solid #007bff;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
color: #28a745; /* Success color for subheadings */
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
color: #dc3545; /* Danger color for sub-subheadings */
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.report-section {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding: 15px;
|
||||||
|
border: 1px solid #ced4da; /* Light gray border */
|
||||||
|
border-radius: 5px;
|
||||||
|
background-color: #fff; /* White background */
|
||||||
|
}
|
||||||
|
|
||||||
|
.validation-summary {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding: 15px;
|
||||||
|
border: 1px solid #ced4da; /* Light gray border */
|
||||||
|
border-radius: 5px;
|
||||||
|
background-color: #fff; /* White background */
|
||||||
|
}
|
||||||
|
|
||||||
|
.validation-summary p {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.success {
|
||||||
|
color: #28a745; /* Success color */
|
||||||
|
}
|
||||||
|
|
||||||
|
.failure {
|
||||||
|
color: #dc3545; /* Danger color */
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
th, td {
|
||||||
|
border: 1px solid #dee2e6; /* Lighter gray border for table cells */
|
||||||
|
padding: 8px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
background-color: #e9ecef; /* Light gray background for table headers */
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background-color: #f0f0f0; /* Light gray background for code blocks */
|
||||||
|
padding: 10px;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive design */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
body {
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h1>API Validation Report</h1>
|
||||||
|
|
||||||
|
<div class="validation-summary">
|
||||||
|
<p><strong>Total Requests:</strong> {{total_requests}}</p>
|
||||||
|
<p class="success"><strong>Successful Validations:</strong> {{successful_validations}}</p>
|
||||||
|
<p class="failure"><strong>Failed Validations:</strong> {{failed_validations}}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="report-section">
|
||||||
|
<h2>Validation Results</h2>
|
||||||
|
{{validation_results}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="report-section">
|
||||||
|
<h2>Detailed Errors</h2>
|
||||||
|
{{detailed_errors}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="report-section">
|
||||||
|
<h2>Summary</h2>
|
||||||
|
<p>This report summarizes the API validation results. Please review the details for any failed validations.</p>
|
||||||
|
<p>Report generated at: {{report_generation_time}}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
8
skills/skill-adapter/references/README.md
Normal file
8
skills/skill-adapter/references/README.md
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# References
|
||||||
|
|
||||||
|
Bundled resources for api-response-validator skill
|
||||||
|
|
||||||
|
- [ ] json_schema_example.json: Example JSON schema for API response validation.
|
||||||
|
- [ ] openapi_example.yaml: Example OpenAPI specification for API response validation.
|
||||||
|
- [ ] custom_rules_example.yaml: Example custom rules configuration file.
|
||||||
|
- [ ] api_response_validation_best_practices.md: Best practices for API response validation.
|
||||||
69
skills/skill-adapter/references/best-practices.md
Normal file
69
skills/skill-adapter/references/best-practices.md
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
# Skill Best Practices
|
||||||
|
|
||||||
|
Guidelines for optimal skill usage and development.
|
||||||
|
|
||||||
|
## For Users
|
||||||
|
|
||||||
|
### Activation Best Practices
|
||||||
|
|
||||||
|
1. **Use Clear Trigger Phrases**
|
||||||
|
- Match phrases from skill description
|
||||||
|
- Be specific about intent
|
||||||
|
- Provide necessary context
|
||||||
|
|
||||||
|
2. **Provide Sufficient Context**
|
||||||
|
- Include relevant file paths
|
||||||
|
- Specify scope of analysis
|
||||||
|
- Mention any constraints
|
||||||
|
|
||||||
|
3. **Understand Tool Permissions**
|
||||||
|
- Check allowed-tools in frontmatter
|
||||||
|
- Know what the skill can/cannot do
|
||||||
|
- Request appropriate actions
|
||||||
|
|
||||||
|
### Workflow Optimization
|
||||||
|
|
||||||
|
- Start with simple requests
|
||||||
|
- Build up to complex workflows
|
||||||
|
- Verify each step before proceeding
|
||||||
|
- Use skill consistently for related tasks
|
||||||
|
|
||||||
|
## For Developers
|
||||||
|
|
||||||
|
### Skill Development Guidelines
|
||||||
|
|
||||||
|
1. **Clear Descriptions**
|
||||||
|
- Include explicit trigger phrases
|
||||||
|
- Document all capabilities
|
||||||
|
- Specify limitations
|
||||||
|
|
||||||
|
2. **Proper Tool Permissions**
|
||||||
|
- Use minimal necessary tools
|
||||||
|
- Document security implications
|
||||||
|
- Test with restricted tools
|
||||||
|
|
||||||
|
3. **Comprehensive Documentation**
|
||||||
|
- Provide usage examples
|
||||||
|
- Document common pitfalls
|
||||||
|
- Include troubleshooting guide
|
||||||
|
|
||||||
|
### Maintenance
|
||||||
|
|
||||||
|
- Keep version updated
|
||||||
|
- Test after tool updates
|
||||||
|
- Monitor user feedback
|
||||||
|
- Iterate on descriptions
|
||||||
|
|
||||||
|
## Performance Tips
|
||||||
|
|
||||||
|
- Scope skills to specific domains
|
||||||
|
- Avoid overlapping trigger phrases
|
||||||
|
- Keep descriptions under 1024 chars
|
||||||
|
- Test activation reliability
|
||||||
|
|
||||||
|
## Security Considerations
|
||||||
|
|
||||||
|
- Never include secrets in skill files
|
||||||
|
- Validate all inputs
|
||||||
|
- Use read-only tools when possible
|
||||||
|
- Document security requirements
|
||||||
70
skills/skill-adapter/references/examples.md
Normal file
70
skills/skill-adapter/references/examples.md
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
# Skill Usage Examples
|
||||||
|
|
||||||
|
This document provides practical examples of how to use this skill effectively.
|
||||||
|
|
||||||
|
## Basic Usage
|
||||||
|
|
||||||
|
### Example 1: Simple Activation
|
||||||
|
|
||||||
|
**User Request:**
|
||||||
|
```
|
||||||
|
[Describe trigger phrase here]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Skill Response:**
|
||||||
|
1. Analyzes the request
|
||||||
|
2. Performs the required action
|
||||||
|
3. Returns results
|
||||||
|
|
||||||
|
### Example 2: Complex Workflow
|
||||||
|
|
||||||
|
**User Request:**
|
||||||
|
```
|
||||||
|
[Describe complex scenario]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Workflow:**
|
||||||
|
1. Step 1: Initial analysis
|
||||||
|
2. Step 2: Data processing
|
||||||
|
3. Step 3: Result generation
|
||||||
|
4. Step 4: Validation
|
||||||
|
|
||||||
|
## Advanced Patterns
|
||||||
|
|
||||||
|
### Pattern 1: Chaining Operations
|
||||||
|
|
||||||
|
Combine this skill with other tools:
|
||||||
|
```
|
||||||
|
Step 1: Use this skill for [purpose]
|
||||||
|
Step 2: Chain with [other tool]
|
||||||
|
Step 3: Finalize with [action]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern 2: Error Handling
|
||||||
|
|
||||||
|
If issues occur:
|
||||||
|
- Check trigger phrase matches
|
||||||
|
- Verify context is available
|
||||||
|
- Review allowed-tools permissions
|
||||||
|
|
||||||
|
## Tips & Best Practices
|
||||||
|
|
||||||
|
- ✅ Be specific with trigger phrases
|
||||||
|
- ✅ Provide necessary context
|
||||||
|
- ✅ Check tool permissions match needs
|
||||||
|
- ❌ Avoid vague requests
|
||||||
|
- ❌ Don't mix unrelated tasks
|
||||||
|
|
||||||
|
## Common Issues
|
||||||
|
|
||||||
|
**Issue:** Skill doesn't activate
|
||||||
|
**Solution:** Use exact trigger phrases from description
|
||||||
|
|
||||||
|
**Issue:** Unexpected results
|
||||||
|
**Solution:** Check input format and context
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- Main SKILL.md for full documentation
|
||||||
|
- scripts/ for automation helpers
|
||||||
|
- assets/ for configuration examples
|
||||||
7
skills/skill-adapter/scripts/README.md
Normal file
7
skills/skill-adapter/scripts/README.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# Scripts
|
||||||
|
|
||||||
|
Bundled resources for api-response-validator skill
|
||||||
|
|
||||||
|
- [ ] validate_json_schema.py: Script to validate API responses against a JSON schema.
|
||||||
|
- [ ] validate_openapi.py: Script to validate API responses against an OpenAPI specification.
|
||||||
|
- [ ] validate_custom_rules.py: Script to validate API responses against custom rules defined in a configuration file.
|
||||||
42
skills/skill-adapter/scripts/helper-template.sh
Executable file
42
skills/skill-adapter/scripts/helper-template.sh
Executable file
@@ -0,0 +1,42 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Helper script template for skill automation
|
||||||
|
# Customize this for your skill's specific needs
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
function show_usage() {
|
||||||
|
echo "Usage: $0 [options]"
|
||||||
|
echo ""
|
||||||
|
echo "Options:"
|
||||||
|
echo " -h, --help Show this help message"
|
||||||
|
echo " -v, --verbose Enable verbose output"
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
VERBOSE=false
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
-h|--help)
|
||||||
|
show_usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
-v|--verbose)
|
||||||
|
VERBOSE=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1"
|
||||||
|
show_usage
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Your skill logic here
|
||||||
|
if [ "$VERBOSE" = true ]; then
|
||||||
|
echo "Running skill automation..."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✅ Complete"
|
||||||
32
skills/skill-adapter/scripts/validation.sh
Executable file
32
skills/skill-adapter/scripts/validation.sh
Executable file
@@ -0,0 +1,32 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Skill validation helper
|
||||||
|
# Validates skill activation and functionality
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "🔍 Validating skill..."
|
||||||
|
|
||||||
|
# Check if SKILL.md exists
|
||||||
|
if [ ! -f "../SKILL.md" ]; then
|
||||||
|
echo "❌ Error: SKILL.md not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Validate frontmatter
|
||||||
|
if ! grep -q "^---$" "../SKILL.md"; then
|
||||||
|
echo "❌ Error: No frontmatter found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check required fields
|
||||||
|
if ! grep -q "^name:" "../SKILL.md"; then
|
||||||
|
echo "❌ Error: Missing 'name' field"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! grep -q "^description:" "../SKILL.md"; then
|
||||||
|
echo "❌ Error: Missing 'description' field"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✅ Skill validation passed"
|
||||||
Reference in New Issue
Block a user