feat: add openai realtime models

This commit is contained in:
Abhishek Kumar 2026-05-16 08:42:43 +05:30
parent 53f1959edf
commit 4d7b681928
33 changed files with 1518 additions and 75 deletions

View file

@ -11,6 +11,8 @@ import {
KeyValueEditor,
type KeyValueItem,
ParameterEditor,
PresetParameterEditor,
type PresetToolParameter,
type ToolParameter,
UrlInput,
} from "@/components/http";
@ -35,6 +37,8 @@ export interface HttpApiToolConfigProps {
onHeadersChange: (headers: KeyValueItem[]) => void;
parameters: ToolParameter[];
onParametersChange: (parameters: ToolParameter[]) => void;
presetParameters: PresetToolParameter[];
onPresetParametersChange: (parameters: PresetToolParameter[]) => void;
timeoutMs: number;
onTimeoutMsChange: (timeout: number) => void;
customMessage: string;
@ -61,6 +65,8 @@ export function HttpApiToolConfig({
onHeadersChange,
parameters,
onParametersChange,
presetParameters,
onPresetParametersChange,
timeoutMs,
onTimeoutMsChange,
customMessage,
@ -182,7 +188,7 @@ export function HttpApiToolConfig({
<TabsContent value="parameters" className="space-y-4 mt-4">
<div className="grid gap-2">
<Label>Tool Parameters</Label>
<Label>LLM Parameters</Label>
<Label className="text-xs text-muted-foreground">
Define the parameters that the LLM will provide when calling this tool.
These will be sent as JSON body for POST/PUT/PATCH or as URL query params for GET/DELETE.
@ -193,6 +199,18 @@ export function HttpApiToolConfig({
/>
</div>
<div className="grid gap-2 pt-4 border-t">
<Label>Preset Parameters</Label>
<Label className="text-xs text-muted-foreground">
Add values that Dograh should inject at runtime. These are not exposed to the LLM and can use
workflow templates like {`{{initial_context.phone_number}}`} or fixed literals.
</Label>
<PresetParameterEditor
parameters={presetParameters}
onChange={onPresetParametersChange}
/>
</div>
<div className="grid gap-2 pt-4 border-t">
<Label>Custom Headers</Label>
<Label className="text-xs text-muted-foreground">

View file

@ -11,7 +11,13 @@ import {
} from "@/client/sdk.gen";
import type { RecordingResponseSchema, ToolResponse, TransferCallConfig as APITransferCallConfig } from "@/client/types.gen";
import type { EndCallConfig } from "@/client/types.gen";
import { type HttpMethod, type KeyValueItem, type ToolParameter, validateUrl } from "@/components/http";
import {
type HttpMethod,
type KeyValueItem,
type PresetToolParameter,
type ToolParameter,
validateUrl,
} from "@/components/http";
import { Button } from "@/components/ui/button";
import {
Dialog,
@ -41,6 +47,12 @@ interface HttpApiConfigWithParams {
headers?: Record<string, string>;
credential_uuid?: string;
parameters?: ToolParameter[];
preset_parameters?: Array<{
name?: string;
type?: PresetToolParameter["type"];
value_template?: string;
required?: boolean;
}>;
timeout_ms?: number;
customMessage?: string;
}
@ -70,6 +82,7 @@ export default function ToolDetailPage() {
const [credentialUuid, setCredentialUuid] = useState("");
const [headers, setHeaders] = useState<KeyValueItem[]>([]);
const [parameters, setParameters] = useState<ToolParameter[]>([]);
const [presetParameters, setPresetParameters] = useState<PresetToolParameter[]>([]);
const [timeoutMs, setTimeoutMs] = useState(5000);
// End Call form state
@ -209,6 +222,19 @@ export default function ToolDetailPage() {
} else {
setParameters([]);
}
if (config.preset_parameters && Array.isArray(config.preset_parameters)) {
setPresetParameters(
config.preset_parameters.map((p) => ({
name: p.name || "",
type: p.type || "string",
valueTemplate: p.value_template || "",
required: p.required ?? true,
}))
);
} else {
setPresetParameters([]);
}
}
}
};
@ -263,6 +289,14 @@ export default function ToolDetailPage() {
setError("All parameters must have a name");
return;
}
const invalidPresetParams = presetParameters.filter(
(p) => !p.name.trim() || !p.valueTemplate.trim()
);
if (invalidPresetParams.length > 0) {
setError("All preset parameters must have a name and a value");
return;
}
}
try {
@ -325,6 +359,9 @@ export default function ToolDetailPage() {
});
const validParameters = parameters.filter((p) => p.name.trim());
const validPresetParameters = presetParameters.filter(
(p) => p.name.trim() && p.valueTemplate.trim()
);
requestBody = {
name,
@ -342,6 +379,15 @@ export default function ToolDetailPage() {
: undefined,
parameters:
validParameters.length > 0 ? validParameters : undefined,
preset_parameters:
validPresetParameters.length > 0
? validPresetParameters.map((p) => ({
name: p.name,
type: p.type,
value_template: p.valueTemplate,
required: p.required,
}))
: undefined,
timeout_ms: timeoutMs,
customMessage: customMessageType === 'text' ? (customMessage || undefined) : undefined,
customMessageType,
@ -394,8 +440,20 @@ export default function ToolDetailPage() {
exampleBody[p.name] = `<${p.name}>`;
}
});
presetParameters.forEach((p) => {
if (p.type === "number") {
exampleBody[p.name] = p.valueTemplate || 0;
} else if (p.type === "boolean") {
exampleBody[p.name] = p.valueTemplate || true;
} else {
exampleBody[p.name] = p.valueTemplate || `<${p.name}>`;
}
});
const hasBody = httpMethod !== "GET" && httpMethod !== "DELETE" && parameters.length > 0;
const hasBody =
httpMethod !== "GET" &&
httpMethod !== "DELETE" &&
(parameters.length > 0 || presetParameters.length > 0);
return `// ${tool.name}
// ${tool.description || "HTTP API Tool"}
@ -571,6 +629,8 @@ const data = await response.json();`;
onHeadersChange={setHeaders}
parameters={parameters}
onParametersChange={setParameters}
presetParameters={presetParameters}
onPresetParametersChange={setPresetParameters}
timeoutMs={timeoutMs}
onTimeoutMsChange={setTimeoutMs}
customMessage={customMessage}