This commit is contained in:
Robin Shen 2025-09-25 15:10:13 +08:00
parent 207fcb65e8
commit 3e16c2fe66
3 changed files with 32 additions and 31 deletions

View File

@ -62,19 +62,11 @@ public class BuildSpecSchemaResource {
private final ImplementationRegistry implementationRegistry; private final ImplementationRegistry implementationRegistry;
private final Yaml yaml; private volatile String schema;
private String schema;
@Inject @Inject
public BuildSpecSchemaResource(ImplementationRegistry implementationRegistry) { public BuildSpecSchemaResource(ImplementationRegistry implementationRegistry) {
this.implementationRegistry = implementationRegistry; this.implementationRegistry = implementationRegistry;
// Configure YAML output
DumperOptions options = new DumperOptions();
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
options.setPrettyFlow(true);
this.yaml = new Yaml(options);
} }
private void processProperty(Map<String, Object> currentNode, Object bean, PropertyDescriptor property) { private void processProperty(Map<String, Object> currentNode, Object bean, PropertyDescriptor property) {
@ -91,6 +83,7 @@ public class BuildSpecSchemaResource {
descriptionSections.add("NOTE: If set, the value can only contain one line"); descriptionSections.add("NOTE: If set, the value can only contain one line");
} }
InputStream grammarStream = null; InputStream grammarStream = null;
try {
if (getter.getAnnotation(Patterns.class) != null) { if (getter.getAnnotation(Patterns.class) != null) {
if (getter.getAnnotation(Interpolative.class) != null) { if (getter.getAnnotation(Interpolative.class) != null) {
grammarStream = PatternSet.class.getResourceAsStream("InterpolativePatternSet.g4"); grammarStream = PatternSet.class.getResourceAsStream("InterpolativePatternSet.g4");
@ -110,6 +103,9 @@ public class BuildSpecSchemaResource {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
} finally {
IOUtils.closeQuietly(grammarStream);
}
} }
if (descriptionSections.size() != 0) if (descriptionSections.size() != 0)
@ -480,7 +476,10 @@ public class BuildSpecSchemaResource {
rootNode.put("required", requiredList); rootNode.put("required", requiredList);
rootNode.put("additionalProperties", false); rootNode.put("additionalProperties", false);
schema = yaml.dump(rootNode); DumperOptions options = new DumperOptions();
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
options.setPrettyFlow(true);
schema = new Yaml(options).dump(rootNode);
} }
return schema; return schema;
} }

View File

@ -1,5 +1,7 @@
package io.onedev.server.rest.resource; package io.onedev.server.rest.resource;
import static javax.ws.rs.core.Response.Status.NOT_ACCEPTABLE;
import java.io.Serializable; import java.io.Serializable;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.text.MessageFormat; import java.text.MessageFormat;
@ -2143,6 +2145,7 @@ public class McpHelperResource {
var project = getProject(projectPath); var project = getProject(projectPath);
Project.push(project); Project.push(project);
String schemaNotice = "\n\n**NOTE**: AI assistant may call the getBuildSpecSchema tool to know exact syntax of build spec";
try { try {
var buildSpec = BuildSpec.parse(buildSpecString.getBytes(StandardCharsets.UTF_8)); var buildSpec = BuildSpec.parse(buildSpecString.getBytes(StandardCharsets.UTF_8));
List<String> validationErrors = new ArrayList<>(); List<String> validationErrors = new ArrayList<>();
@ -2154,14 +2157,14 @@ public class McpHelperResource {
if (validationErrors.isEmpty()) { if (validationErrors.isEmpty()) {
return Response.ok(VersionedYamlDoc.fromBean(buildSpec).toYaml()).build(); return Response.ok(VersionedYamlDoc.fromBean(buildSpec).toYaml()).build();
} else { } else {
return Response.ok(Joiner.on("\n").join(validationErrors)).build(); return Response.status(NOT_ACCEPTABLE).entity(Joiner.on("\n").join(validationErrors) + schemaNotice).build();
} }
} catch (Exception e) { } catch (Exception e) {
var explicitException = ExceptionUtils.find(e, ExplicitException.class); var explicitException = ExceptionUtils.find(e, ExplicitException.class);
if (explicitException != null) { if (explicitException != null) {
return Response.ok(explicitException.getMessage()).build(); return Response.status(NOT_ACCEPTABLE).entity(explicitException.getMessage() + schemaNotice).build();
} else { } else {
return Response.ok(Throwables.getStackTraceAsString(e)).build(); return Response.status(NOT_ACCEPTABLE).entity(Throwables.getStackTraceAsString(e) + schemaNotice).build();
} }
} finally { } finally {
Project.pop(); Project.pop();

View File

@ -21,7 +21,6 @@ public class RegExValidator implements ConstraintValidator<RegEx, String> {
@Override @Override
public boolean isValid(String value, ConstraintValidatorContext constraintContext) { public boolean isValid(String value, ConstraintValidatorContext constraintContext) {
System.out.println("Validating value: " + value);
if (value == null) if (value == null)
return true; return true;
if (pattern.matcher(value).matches()) { if (pattern.matcher(value).matches()) {