mirror of
https://github.com/dograh-hq/dograh.git
synced 2026-07-04 10:52:17 +02:00
fix: support object and array parameters in custom HTTP tools (#373)
* fix: support object and array parameters in custom HTTP tools * feat(ui): expose object and array types in the custom tool parameter editor * fix: error handling and schema generation --------- Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> Co-authored-by: Abhishek Kumar <abhishek@a6k.me>
This commit is contained in:
parent
98d2b24cba
commit
dd85c4a1b4
18 changed files with 308 additions and 67 deletions
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import { PlusIcon, Trash2Icon } from "lucide-react";
|
||||
|
||||
import type { ToolParameter as ApiToolParameter } from "@/client/types.gen";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
|
|
@ -14,7 +15,7 @@ import {
|
|||
} from "@/components/ui/select";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
|
||||
export type ParameterType = "string" | "number" | "boolean";
|
||||
export type ParameterType = ApiToolParameter["type"];
|
||||
|
||||
export interface ToolParameter {
|
||||
name: string;
|
||||
|
|
@ -124,6 +125,8 @@ export function ParameterEditor({
|
|||
<SelectItem value="string">String</SelectItem>
|
||||
<SelectItem value="number">Number</SelectItem>
|
||||
<SelectItem value="boolean">Boolean</SelectItem>
|
||||
<SelectItem value="object">Object</SelectItem>
|
||||
<SelectItem value="array">Array</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
|
@ -267,6 +270,8 @@ export function PresetParameterEditor({
|
|||
<SelectItem value="string">String</SelectItem>
|
||||
<SelectItem value="number">Number</SelectItem>
|
||||
<SelectItem value="boolean">Boolean</SelectItem>
|
||||
<SelectItem value="object">Object</SelectItem>
|
||||
<SelectItem value="array">Array</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import {
|
|||
} from "@/components/ui/select";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { detailFromError } from "@/lib/apiError";
|
||||
import { useAuth } from "@/lib/auth";
|
||||
|
||||
interface ConfigFormDialogProps {
|
||||
|
|
@ -132,7 +133,7 @@ export function ConfigFormDialog({
|
|||
body: { name: name || undefined, config: configPayload },
|
||||
},
|
||||
);
|
||||
if (res.error) throw new Error(detailFromError(res.error));
|
||||
if (res.error) throw new Error(detailFromError(res.error, "Failed to save configuration"));
|
||||
toast.success("Configuration updated");
|
||||
} else {
|
||||
const res = await createTelephonyConfigurationApiV1OrganizationsTelephonyConfigsPost(
|
||||
|
|
@ -145,7 +146,7 @@ export function ConfigFormDialog({
|
|||
},
|
||||
},
|
||||
);
|
||||
if (res.error) throw new Error(detailFromError(res.error));
|
||||
if (res.error) throw new Error(detailFromError(res.error, "Failed to save configuration"));
|
||||
toast.success("Configuration created");
|
||||
}
|
||||
onOpenChange(false);
|
||||
|
|
@ -345,16 +346,3 @@ function FieldInput({ field, value, onChange, isEdit }: FieldInputProps) {
|
|||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// FastAPI error responses come back as { detail: string } or
|
||||
// { detail: [{loc, msg, ...}] }. Surface a useful message either way.
|
||||
function detailFromError(err: unknown): string {
|
||||
if (typeof err === "string") return err;
|
||||
const e = err as { detail?: unknown };
|
||||
if (typeof e?.detail === "string") return e.detail;
|
||||
if (Array.isArray(e?.detail) && e.detail.length > 0) {
|
||||
const first = e.detail[0] as { msg?: string };
|
||||
if (first?.msg) return first.msg;
|
||||
}
|
||||
return "Failed to save configuration";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import {
|
|||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { detailFromError } from "@/lib/apiError";
|
||||
import { useAuth } from "@/lib/auth";
|
||||
|
||||
interface PhoneNumberDialogProps {
|
||||
|
|
@ -146,7 +147,7 @@ export function PhoneNumberDialog({
|
|||
},
|
||||
},
|
||||
);
|
||||
if (res.error) throw new Error(detailFromError(res.error));
|
||||
if (res.error) throw new Error(detailFromError(res.error, "Failed to save phone number"));
|
||||
providerSync = res.data?.provider_sync;
|
||||
toast.success("Phone number updated");
|
||||
} else {
|
||||
|
|
@ -164,7 +165,7 @@ export function PhoneNumberDialog({
|
|||
},
|
||||
},
|
||||
);
|
||||
if (res.error) throw new Error(detailFromError(res.error));
|
||||
if (res.error) throw new Error(detailFromError(res.error, "Failed to save phone number"));
|
||||
providerSync = res.data?.provider_sync;
|
||||
toast.success("Phone number added");
|
||||
}
|
||||
|
|
@ -302,14 +303,3 @@ export function PhoneNumberDialog({
|
|||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
function detailFromError(err: unknown): string {
|
||||
if (typeof err === "string") return err;
|
||||
const e = err as { detail?: unknown };
|
||||
if (typeof e?.detail === "string") return e.detail;
|
||||
if (Array.isArray(e?.detail) && e.detail.length > 0) {
|
||||
const first = e.detail[0] as { msg?: string };
|
||||
if (first?.msg) return first.msg;
|
||||
}
|
||||
return "Failed to save phone number";
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue