Fix/multiple generation (#104)

* fixes #100

* Fix test

* fix: fix bad configuration issue
This commit is contained in:
Abhishek 2026-01-03 12:59:18 +05:30 committed by GitHub
parent 90b690efff
commit 56953bbd09
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 758 additions and 460 deletions

View file

@ -10,6 +10,8 @@ import {
HttpMethodSelector,
KeyValueEditor,
type KeyValueItem,
UrlInput,
validateUrl,
} from "@/components/http";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
@ -57,8 +59,9 @@ export const WebhookNode = memo(({ data, selected, id }: WebhookNodeProps) => {
const handleSave = async () => {
// Validate endpoint URL
if (!endpointUrl.trim()) {
setEndpointError('Endpoint URL is required');
const urlValidation = validateUrl(endpointUrl);
if (!urlValidation.valid) {
setEndpointError(urlValidation.error || 'Invalid URL');
return;
}
setEndpointError(null);
@ -284,10 +287,11 @@ const WebhookNodeEditForm = ({
<Label className="text-xs text-muted-foreground">
The URL to send the webhook request to.
</Label>
<Input
<UrlInput
value={endpointUrl}
onChange={(e) => setEndpointUrl(e.target.value)}
onChange={setEndpointUrl}
placeholder="https://api.example.com/webhook"
showValidation
/>
</div>
</TabsContent>

View file

@ -3,3 +3,4 @@ export { CredentialSelector } from "./credential-selector";
export { type HttpMethod, HttpMethodSelector } from "./http-method-selector";
export { KeyValueEditor, type KeyValueItem } from "./key-value-editor";
export { ParameterEditor, type ParameterType,type ToolParameter } from "./parameter-editor";
export { UrlInput, type UrlValidationResult,validateUrl } from "./url-input";

View file

@ -0,0 +1,106 @@
"use client";
import { useCallback, useState } from "react";
import { Input } from "@/components/ui/input";
import { cn } from "@/lib/utils";
// URL regex pattern that validates:
// - http:// or https:// protocol (required)
// - Optional username:password@
// - Domain name or IP address
// - Optional port number
// - Optional path, query string, and fragment
const URL_REGEX =
/^https?:\/\/(?:[\w-]+(?::[\w-]+)?@)?(?:[\w-]+\.)*[\w-]+(?::\d{1,5})?(?:\/[^\s]*)?$/i;
export interface UrlValidationResult {
valid: boolean;
error?: string;
}
export function validateUrl(url: string): UrlValidationResult {
const trimmedUrl = url.trim();
if (!trimmedUrl) {
return { valid: false, error: "URL is required" };
}
if (!URL_REGEX.test(trimmedUrl)) {
return {
valid: false,
error: "Invalid URL format. Must start with http:// or https://",
};
}
return { valid: true };
}
interface UrlInputProps {
value: string;
onChange: (value: string) => void;
placeholder?: string;
disabled?: boolean;
className?: string;
/** Show validation error styling and message inline */
showValidation?: boolean;
/** Called when validation state changes */
onValidationChange?: (result: UrlValidationResult) => void;
}
export function UrlInput({
value,
onChange,
placeholder = "https://api.example.com/endpoint",
disabled = false,
className,
showValidation = false,
onValidationChange,
}: UrlInputProps) {
const [touched, setTouched] = useState(false);
const handleChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
const newValue = e.target.value;
onChange(newValue);
if (onValidationChange && (touched || newValue)) {
onValidationChange(validateUrl(newValue));
}
},
[onChange, onValidationChange, touched]
);
const handleBlur = useCallback(() => {
setTouched(true);
const trimmedValue = value.trim();
if (trimmedValue !== value) {
onChange(trimmedValue);
}
if (onValidationChange && trimmedValue) {
onValidationChange(validateUrl(trimmedValue));
}
}, [onChange, onValidationChange, value]);
const validation = validateUrl(value);
const showError = showValidation && touched && !validation.valid && value;
return (
<div className="space-y-1">
<Input
value={value}
onChange={handleChange}
onBlur={handleBlur}
placeholder={placeholder}
disabled={disabled}
className={cn(
showError && "border-destructive focus-visible:ring-destructive",
className
)}
/>
{showError && (
<p className="text-xs text-destructive">{validation.error}</p>
)}
</div>
);
}