Skip to content

Commit 8d149b2

Browse files
committed
Add real-time JSON validation and prevent tool execution on invalid input
1 parent 119922b commit 8d149b2

2 files changed

Lines changed: 39 additions & 8 deletions

File tree

client/src/components/DynamicJsonForm.tsx

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,17 @@ const DynamicJsonForm = forwardRef<DynamicJsonFormRef, DynamicJsonFormProps>(
106106
const parsed = JSON.parse(jsonString);
107107
onChange(parsed);
108108
setJsonError(undefined);
109-
} catch {
110-
// Don't set error during normal typing
109+
} catch (err) {
110+
// For invalid JSON, set error and reset to default if it's clearly malformed
111+
const errorMessage =
112+
err instanceof Error ? err.message : "Invalid JSON";
113+
setJsonError(errorMessage);
114+
115+
// Reset to default for clearly invalid JSON (not just incomplete typing)
116+
const trimmed = jsonString.trim();
117+
if (trimmed.length > 5 && !trimmed.match(/^[\s\[{]/)) {
118+
onChange(generateDefaultValue(schema));
119+
}
111120
}
112121
}, 300);
113122
},
@@ -164,7 +173,12 @@ const DynamicJsonForm = forwardRef<DynamicJsonFormRef, DynamicJsonFormProps>(
164173
try {
165174
const jsonStr = rawJsonValue.trim();
166175
if (!jsonStr) return { isValid: true, error: null };
167-
JSON.parse(jsonStr);
176+
const parsed = JSON.parse(jsonStr);
177+
// Clear any pending debounced update and immediately update parent
178+
if (timeoutRef.current) {
179+
clearTimeout(timeoutRef.current);
180+
}
181+
onChange(parsed);
168182
setJsonError(undefined);
169183
return { isValid: true, error: null };
170184
} catch (err) {

client/src/components/ToolsTab.tsx

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,20 @@ const ToolsTab = ({
6666
const [isToolRunning, setIsToolRunning] = useState(false);
6767
const [isOutputSchemaExpanded, setIsOutputSchemaExpanded] = useState(false);
6868
const [isMetaExpanded, setIsMetaExpanded] = useState(false);
69+
const [hasValidationErrors, setHasValidationErrors] = useState(false);
6970
const formRefs = useRef<Record<string, DynamicJsonFormRef | null>>({});
7071
const { toast } = useToast();
7172
const { copied, setCopied } = useCopy();
7273

74+
// Function to check if any form has validation errors
75+
const checkValidationErrors = () => {
76+
const errors = Object.values(formRefs.current).some(
77+
(ref) => ref && !ref.validateJson().isValid,
78+
);
79+
setHasValidationErrors(errors);
80+
return errors;
81+
};
82+
7383
useEffect(() => {
7484
const params = Object.entries(
7585
selectedTool?.inputSchema.properties ?? [],
@@ -82,6 +92,12 @@ const ToolsTab = ({
8292
),
8393
]);
8494
setParams(Object.fromEntries(params));
95+
96+
// Reset validation errors when switching tools
97+
setHasValidationErrors(false);
98+
99+
// Clear form refs for the previous tool
100+
formRefs.current = {};
85101
}, [selectedTool]);
86102

87103
return (
@@ -199,6 +215,8 @@ const ToolsTab = ({
199215
...params,
200216
[key]: newValue,
201217
});
218+
// Check validation after a short delay to allow form to update
219+
setTimeout(checkValidationErrors, 100);
202220
}}
203221
/>
204222
</div>
@@ -235,6 +253,8 @@ const ToolsTab = ({
235253
...params,
236254
[key]: newValue,
237255
});
256+
// Check validation after a short delay to allow form to update
257+
setTimeout(checkValidationErrors, 100);
238258
}}
239259
/>
240260
</div>
@@ -317,10 +337,7 @@ const ToolsTab = ({
317337
<Button
318338
onClick={async () => {
319339
// Validate JSON inputs before calling tool
320-
const hasValidationErrors = Object.values(
321-
formRefs.current,
322-
).some((ref) => ref && !ref.validateJson().isValid);
323-
if (hasValidationErrors) return;
340+
if (checkValidationErrors()) return;
324341

325342
try {
326343
setIsToolRunning(true);
@@ -329,7 +346,7 @@ const ToolsTab = ({
329346
setIsToolRunning(false);
330347
}
331348
}}
332-
disabled={isToolRunning}
349+
disabled={isToolRunning || hasValidationErrors}
333350
>
334351
{isToolRunning ? (
335352
<>

0 commit comments

Comments
 (0)