ai编程助手

This commit is contained in:
ageerle
2025-07-07 12:36:53 +08:00
parent c1a178c0be
commit 0eff37fa51
50 changed files with 11899 additions and 0 deletions

View File

@@ -0,0 +1,146 @@
package com.example.demo.schema;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.*;
/**
* JSON Schema definition class
* Used to define tool parameter structure and validation rules
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public class JsonSchema {
private String type;
private String description;
private String pattern;
private Number minimum;
private Number maximum;
private List<Object> enumValues;
@JsonProperty("properties")
private Map<String, JsonSchema> properties;
@JsonProperty("required")
private List<String> requiredFields;
@JsonProperty("items")
private JsonSchema items;
// Constructor
public JsonSchema() {}
// Static factory methods
public static JsonSchema object() {
JsonSchema schema = new JsonSchema();
schema.type = "object";
schema.properties = new HashMap<>();
return schema;
}
public static JsonSchema string(String description) {
JsonSchema schema = new JsonSchema();
schema.type = "string";
schema.description = description;
return schema;
}
public static JsonSchema number(String description) {
JsonSchema schema = new JsonSchema();
schema.type = "number";
schema.description = description;
return schema;
}
public static JsonSchema integer(String description) {
JsonSchema schema = new JsonSchema();
schema.type = "integer";
schema.description = description;
return schema;
}
public static JsonSchema bool(String description) {
JsonSchema schema = new JsonSchema();
schema.type = "boolean";
schema.description = description;
return schema;
}
public static JsonSchema array(JsonSchema items) {
JsonSchema schema = new JsonSchema();
schema.type = "array";
schema.items = items;
return schema;
}
public static JsonSchema array(String description, JsonSchema items) {
JsonSchema schema = new JsonSchema();
schema.type = "array";
schema.description = description;
schema.items = items;
return schema;
}
// Fluent methods
public JsonSchema addProperty(String name, JsonSchema property) {
if (this.properties == null) {
this.properties = new HashMap<>();
}
this.properties.put(name, property);
return this;
}
public JsonSchema required(String... fields) {
this.requiredFields = Arrays.asList(fields);
return this;
}
public JsonSchema pattern(String pattern) {
this.pattern = pattern;
return this;
}
public JsonSchema minimum(Number minimum) {
this.minimum = minimum;
return this;
}
public JsonSchema maximum(Number maximum) {
this.maximum = maximum;
return this;
}
public JsonSchema enumValues(Object... values) {
this.enumValues = Arrays.asList(values);
return this;
}
// Getters and Setters
public String getType() { return type; }
public void setType(String type) { this.type = type; }
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
public String getPattern() { return pattern; }
public void setPattern(String pattern) { this.pattern = pattern; }
public Number getMinimum() { return minimum; }
public void setMinimum(Number minimum) { this.minimum = minimum; }
public Number getMaximum() { return maximum; }
public void setMaximum(Number maximum) { this.maximum = maximum; }
public List<Object> getEnumValues() { return enumValues; }
public void setEnumValues(List<Object> enumValues) { this.enumValues = enumValues; }
public Map<String, JsonSchema> getProperties() { return properties; }
public void setProperties(Map<String, JsonSchema> properties) { this.properties = properties; }
public List<String> getRequiredFields() { return requiredFields; }
public void setRequiredFields(List<String> requiredFields) { this.requiredFields = requiredFields; }
public JsonSchema getItems() { return items; }
public void setItems(JsonSchema items) { this.items = items; }
}

View File

@@ -0,0 +1,134 @@
package com.example.demo.schema;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.networknt.schema.JsonSchemaFactory;
import com.networknt.schema.SpecVersion;
import com.networknt.schema.ValidationMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.Set;
import java.util.stream.Collectors;
/**
* JSON Schema validator
* Used to validate tool parameters against defined schema
*/
@Component
public class SchemaValidator {
private static final Logger logger = LoggerFactory.getLogger(SchemaValidator.class);
private final ObjectMapper objectMapper;
private final JsonSchemaFactory schemaFactory;
public SchemaValidator() {
this.objectMapper = new ObjectMapper();
this.schemaFactory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V7);
}
/**
* Validate data against schema
*
* @param schema JSON Schema definition
* @param data Data to validate
* @return Validation error message, null means validation passed
*/
public String validate(JsonSchema schema, Object data) {
try {
// Convert custom JsonSchema to standard JSON Schema string
String schemaJson = objectMapper.writeValueAsString(schema);
logger.debug("Schema JSON: {}", schemaJson);
// Create JSON Schema validator
com.networknt.schema.JsonSchema jsonSchema = schemaFactory.getSchema(schemaJson);
// Convert data to JsonNode
String dataJson = objectMapper.writeValueAsString(data);
JsonNode dataNode = objectMapper.readTree(dataJson);
logger.debug("Data JSON: {}", dataJson);
// Execute validation
Set<ValidationMessage> errors = jsonSchema.validate(dataNode);
if (errors.isEmpty()) {
logger.debug("Schema validation passed");
return null; // Validation passed
} else {
String errorMessage = errors.stream()
.map(ValidationMessage::getMessage)
.collect(Collectors.joining("; "));
logger.warn("Schema validation failed: {}", errorMessage);
return errorMessage;
}
} catch (Exception e) {
String errorMessage = "Schema validation error: " + e.getMessage();
logger.error(errorMessage, e);
return errorMessage;
}
}
/**
* Simple type validation (fallback solution)
* Used when JSON Schema validation fails
*/
public String validateSimple(JsonSchema schema, Object data) {
if (schema == null || data == null) {
return "Schema or data is null";
}
// Basic type checking
String expectedType = schema.getType();
if (expectedType != null) {
String actualType = getDataType(data);
if (!isTypeCompatible(expectedType, actualType)) {
return String.format("Type mismatch: expected %s, got %s", expectedType, actualType);
}
}
// Required field checking (only for object type)
if ("object".equals(expectedType) && schema.getRequiredFields() != null) {
if (!(data instanceof java.util.Map)) {
return "Expected object type for required field validation";
}
@SuppressWarnings("unchecked")
java.util.Map<String, Object> dataMap = (java.util.Map<String, Object>) data;
for (String requiredField : schema.getRequiredFields()) {
if (!dataMap.containsKey(requiredField) || dataMap.get(requiredField) == null) {
return "Missing required field: " + requiredField;
}
}
}
return null; // Validation passed
}
private String getDataType(Object data) {
if (data == null) return "null";
if (data instanceof String) return "string";
if (data instanceof Integer || data instanceof Long) return "integer";
if (data instanceof Number) return "number";
if (data instanceof Boolean) return "boolean";
if (data instanceof java.util.List) return "array";
if (data instanceof java.util.Map) return "object";
return "unknown";
}
private boolean isTypeCompatible(String expectedType, String actualType) {
if (expectedType.equals(actualType)) {
return true;
}
// Number type compatibility
if ("number".equals(expectedType) && "integer".equals(actualType)) {
return true;
}
return false;
}
}