Skip to content

Commit 295e81e

Browse files
4754 - added required property
1 parent bfc0dfd commit 295e81e

5 files changed

Lines changed: 68 additions & 11 deletions

File tree

client/src/pages/platform/workflow-editor/components/properties/hooks/useProperty.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -400,12 +400,10 @@ export const useProperty = ({
400400
mapEntries.push(`'options': {${optionValues}}`);
401401
}
402402

403-
if (mapEntries.length === 0) {
404-
return `=fromAi('${name}', '${type}')`;
405-
}
403+
mapEntries.push(`'required': ${required}`);
406404

407405
return `=fromAi('${name}', '${type}', {${mapEntries.join(', ')}})`;
408-
}, [defaultValue, description, formattedOptions, name, type]);
406+
}, [defaultValue, description, formattedOptions, name, required, type]);
409407

410408
const isValidControlType = useMemo(
411409
() => controlType && INPUT_PROPERTY_CONTROL_TYPES.includes(controlType),

server/libs/ai/ai-tool-api/src/main/java/com/bytechef/ai/tool/FromAi.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ public TypedValue execute(EvaluationContext context, Object target, Object... ar
8080
String description = null;
8181
Object defaultValue = null;
8282
List<Object> options = null;
83+
boolean required = false;
8384

8485
if (arguments.length > 2) {
8586
Object thirdArgument = arguments[2];
@@ -106,6 +107,16 @@ public TypedValue execute(EvaluationContext context, Object target, Object... ar
106107

107108
options = castedOptions;
108109
}
110+
111+
Object requiredArg = paramMap.get("required");
112+
113+
if (requiredArg != null && !(requiredArg instanceof Boolean)) {
114+
throw new IllegalArgumentException("fromAi 'required' in map must be a boolean.");
115+
}
116+
117+
if (requiredArg instanceof Boolean requiredBool) {
118+
required = requiredBool;
119+
}
109120
} else {
110121
if (thirdArgument != null && !(thirdArgument instanceof String)) {
111122
throw new IllegalArgumentException("fromAi description argument must be a String or null.");
@@ -134,6 +145,6 @@ public TypedValue execute(EvaluationContext context, Object target, Object... ar
134145
}
135146
}
136147

137-
return new TypedValue(new FromAiResult(name, type, description, defaultValue, options));
148+
return new TypedValue(new FromAiResult(name, type, description, defaultValue, options, required));
138149
}
139150
}

server/libs/ai/ai-tool-api/src/main/java/com/bytechef/ai/tool/FromAiResult.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
* @param defaultValue fallback value when the AI model does not provide one (nullable)
3131
* @author Ivica Cardic
3232
*/
33-
public record FromAiResult(String name, String type, String description, Object defaultValue, List<Object> options) {
33+
public record FromAiResult(String name, String type, String description, Object defaultValue, List<Object> options, boolean required) {
3434

3535
private static final String DEFAULT_TYPE = "STRING";
3636

@@ -40,18 +40,18 @@ public record FromAiResult(String name, String type, String description, Object
4040
}
4141

4242
public FromAiResult(String name) {
43-
this(name, DEFAULT_TYPE, null, null, null);
43+
this(name, DEFAULT_TYPE, null, null, null, false);
4444
}
4545

4646
public FromAiResult(String name, String type) {
47-
this(name, type, null, null, null);
47+
this(name, type, null, null, null, false);
4848
}
4949

5050
public FromAiResult(String name, String type, String description) {
51-
this(name, type, description, null, null);
51+
this(name, type, description, null, null, false);
5252
}
5353

5454
public FromAiResult(String name, String type, String description, Object defaultValue) {
55-
this(name, type, description, defaultValue, null);
55+
this(name, type, description, defaultValue, null, false);
5656
}
5757
}

server/libs/ai/ai-tool-api/src/main/java/com/bytechef/ai/tool/util/FromAiInputSchemaUtils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ public static String generateInputSchema(List<FromAiResult> fromAiResults) {
7878

7979
propertiesObjectNode.set(fromAiResult.name(), parameterObjectNode);
8080

81-
if (defaultValue == null) {
81+
if (fromAiResult.required()) {
8282
requiredArray.add(fromAiResult.name());
8383
}
8484
}

server/libs/ai/ai-tool-api/src/test/java/com/bytechef/ai/tool/FromAiTest.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,54 @@ public void testFromAiWithNullDescription() {
134134
assertEquals(true, fromAiResult.defaultValue());
135135
}
136136

137+
@Test
138+
public void testFromAiWithRequiredTrue() {
139+
Map<String, Object> map = EVALUATOR.evaluate(
140+
Map.of("param", "=fromAi('title', 'STRING', {'description': 'The title.', 'required': true})"),
141+
Collections.emptyMap());
142+
143+
Object result = MapUtils.get(map, "param");
144+
145+
assertInstanceOf(FromAiResult.class, result);
146+
147+
FromAiResult fromAiResult = (FromAiResult) result;
148+
149+
assertEquals("title", fromAiResult.name());
150+
assertEquals("STRING", fromAiResult.type());
151+
assertEquals("The title.", fromAiResult.description());
152+
assertEquals(true, fromAiResult.required());
153+
}
154+
155+
@Test
156+
public void testFromAiWithRequiredFalse() {
157+
Map<String, Object> map = EVALUATOR.evaluate(
158+
Map.of("param", "=fromAi('title', 'STRING', {'description': 'The title.', 'required': false})"),
159+
Collections.emptyMap());
160+
161+
Object result = MapUtils.get(map, "param");
162+
163+
assertInstanceOf(FromAiResult.class, result);
164+
165+
FromAiResult fromAiResult = (FromAiResult) result;
166+
167+
assertEquals(false, fromAiResult.required());
168+
}
169+
170+
@Test
171+
public void testFromAiWithoutRequiredDefaultsFalse() {
172+
Map<String, Object> map = EVALUATOR.evaluate(
173+
Map.of("param", "=fromAi('title', 'STRING', {'description': 'The title.'})"),
174+
Collections.emptyMap());
175+
176+
Object result = MapUtils.get(map, "param");
177+
178+
assertInstanceOf(FromAiResult.class, result);
179+
180+
FromAiResult fromAiResult = (FromAiResult) result;
181+
182+
assertEquals(false, fromAiResult.required());
183+
}
184+
137185
@Test
138186
public void testFromAiWithNullTypeDefaultsToString() {
139187
Map<String, Object> map = EVALUATOR.evaluate(

0 commit comments

Comments
 (0)