From b53dfe3601f05801644ea23c8918ff322b9d4089 Mon Sep 17 00:00:00 2001 From: jade Date: Fri, 14 Aug 2026 10:29:27 +0900 Subject: [PATCH] Enhance ToolScaffolder with Pattern and Examples validation, support AI prompt generation for Pattern --- .../presentation/ScaffoldingController.java | 22 ++--- .../main/resources/static/admin/scaffold.html | 58 +++++++++----- .../dap/lib/util/ToolScaffolder.java | 80 ++++++++++++++----- 3 files changed, 105 insertions(+), 55 deletions(-) diff --git a/dap-gateway/src/main/java/io/shinhanlife/dap/mcg/presentation/ScaffoldingController.java b/dap-gateway/src/main/java/io/shinhanlife/dap/mcg/presentation/ScaffoldingController.java index 21b00739..6c8932e0 100644 --- a/dap-gateway/src/main/java/io/shinhanlife/dap/mcg/presentation/ScaffoldingController.java +++ b/dap-gateway/src/main/java/io/shinhanlife/dap/mcg/presentation/ScaffoldingController.java @@ -39,7 +39,7 @@ import org.springframework.web.bind.annotation.*; public class ScaffoldingController { private static final Set SUPPORTED_FIELD_TYPES = Set.of( - "String", "Integer", "Long", "Double", "Boolean", "BigDecimal", "Enum", "List"); + "String", "Integer", "Long", "Double", "Boolean", "BigDecimal", "List"); private static final Set SUPPORTED_AI_MODELS = Set.of( "inclusionai/ling-3.0-flash:free", "openai/gpt-oss-20b:free", @@ -96,7 +96,7 @@ public class ScaffoldingController { List inputFields = parseFields(req.get("inputFields")); List outputFields = parseFields(req.get("outputFields")); if (inputFields.isEmpty()) { - inputFields = List.of(new ToolScaffolder.FieldDefinition("query", "String", "Search query", "example", false)); + inputFields = List.of(new ToolScaffolder.FieldDefinition("query", "String", "Search query", List.of("example"), "", false)); } ToolScaffolder.ToolDefinitionOptions definitionOptions = new ToolScaffolder.ToolDefinitionOptions( req.get("functionDescription"), @@ -187,9 +187,10 @@ public class ScaffoldingController { Generate Java DTO fields for an MCP tool. Return JSON only. Do not add Markdown, explanations, or code fences. The response must have this exact shape: - {"fields":[{"name":"camelCaseName","type":"String","description":"short description","example":"example","required":true,"enumValues":[],"itemType":null,"itemFields":[]}]} - Allowed type values: String, Integer, Long, Double, Boolean, BigDecimal, Enum, List. - Enum fields must include enumValues. List fields must include itemType; use Object plus itemFields for object lists. + {"fields":[{"name":"camelCaseName","type":"String","description":"short description","examples":["example1","example2"],"pattern":"^regex$","required":true,"enumValues":[],"itemType":null,"itemFields":[]}]} + Allowed type values: String, Integer, Long, Double, Boolean, BigDecimal, List. + Finite values should be enforced by populating enumValues on standard types. List fields must include itemType; use Object plus itemFields for object lists. + If applicable, provide a regex for pattern. Generate fields only for the requested target: %s. For OUTPUT fields, include resultCode and resultMessage when appropriate. Keep field names valid Java camelCase identifiers. Generate at most 10 fields. @@ -217,12 +218,13 @@ public class ScaffoldingController { Generate an MCP Tool scaffold from the user request. Return JSON only. Do not add Markdown, explanations, or code fences. The response must have this exact shape: - {"baseName":"PascalCaseName","title":"short Korean title","description":"clear Korean LLM tool guidance","categoryKey":"cmm","routingType":"HTTP","httpApiName":"simple-api-name","functionDescription":"core business function","displayDescription":"short portal description","whenToUse":"specific user requests that should select this tool","whenNotToUse":"requests or conditions that must not select this tool","ioLimits":"allowed input and output scope and limits","exampleQueries":["query 1","query 2","query 3"],"tags":["domain","action"],"ownerOrg":"MCP_TOOL","inputFields":[{"name":"camelCaseName","type":"String","description":"short description","example":"example","required":true,"enumValues":[],"itemType":null,"itemFields":[]}],"outputFields":[{"name":"resultCode","type":"String","description":"result code","example":"SUCCESS","required":true,"enumValues":[],"itemType":null,"itemFields":[]}]} + {"baseName":"PascalCaseName","title":"short Korean title","description":"clear Korean LLM tool guidance","categoryKey":"cmm","routingType":"HTTP","httpApiName":"simple-api-name","functionDescription":"core business function","displayDescription":"short portal description","whenToUse":"specific user requests that should select this tool","whenNotToUse":"requests or conditions that must not select this tool","ioLimits":"allowed input and output scope and limits","exampleQueries":["query 1","query 2","query 3"],"tags":["domain","action"],"ownerOrg":"MCP_TOOL","inputFields":[{"name":"camelCaseName","type":"String","description":"short description","examples":["example1","example2"],"pattern":"^regex$","required":true,"enumValues":[],"itemType":null,"itemFields":[]}],"outputFields":[{"name":"resultCode","type":"String","description":"result code","examples":["SUCCESS"],"pattern":"","required":true,"enumValues":[],"itemType":null,"itemFields":[]}]} categoryKey must be exactly three lowercase letters or digits. routingType must be either HTTP or MCI. httpApiName can contain only letters, digits, hyphens, and underscores. Write every V17 metadata field for its distinct purpose; do not copy the same sentence into all fields. Generate 3 to 10 realistic exampleQueries and concise search tags. Use MCP_TOOL for ownerOrg unless the user names an owner. - Allowed field type values: String, Integer, Long, Double, Boolean, BigDecimal, Enum, List. Enum must include enumValues; List must include itemType and object lists include itemFields. + Allowed field type values: String, Integer, Long, Double, Boolean, BigDecimal, List. Finite values should be enforced by populating enumValues. List must include itemType and object lists include itemFields. + If applicable, provide a regex for pattern. Keep all field names valid Java camelCase identifiers. Generate at most 10 fields per list. Do not generate interfaceId or clientSystemCode; those must come from a real integration contract. User request: %s @@ -302,7 +304,8 @@ public class ScaffoldingController { field.name().trim(), field.type() == null ? "String" : field.type().trim(), field.description() == null ? "" : field.description().trim(), - field.example() == null ? "" : field.example().trim(), + field.examples() == null ? List.of() : field.examples().stream().map(String::trim).toList(), + field.pattern() == null ? "" : field.pattern().trim(), field.required(), field.enumValues() == null ? List.of() : field.enumValues(), field.itemType(), @@ -323,9 +326,6 @@ public class ScaffoldingController { } private void validateStructuredField(ToolScaffolder.FieldDefinition field) { - if ("Enum".equals(field.type()) && field.enumValues().isEmpty()) { - throw new IllegalArgumentException("Enum field needs enumValues: " + field.name()); - } if ("List".equals(field.type()) && (field.itemType() == null || field.itemType().isBlank())) { throw new IllegalArgumentException("List field needs itemType: " + field.name()); } diff --git a/dap-gateway/src/main/resources/static/admin/scaffold.html b/dap-gateway/src/main/resources/static/admin/scaffold.html index f2bae4cb..e2ba3af6 100644 --- a/dap-gateway/src/main/resources/static/admin/scaffold.html +++ b/dap-gateway/src/main/resources/static/admin/scaffold.html @@ -1181,7 +1181,8 @@ Enum values / List item type Object list item fields (JSON) Description - Example + Pattern (Regex) + Examples (Enter 단위 구분) Required 삭제 @@ -1205,7 +1206,7 @@