Browse Source

feat: add audio input detection to schema extraction

Add AUDIO_INPUT_PATTERNS, isAudioInput() function modeled after
isImageInput(), and integrate into extractParametersFromSchema() to
detect audio inputs from model schemas. Audio inputs are sorted
between image and text inputs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
handoff-20260429-1057
shrimbly 3 months ago
parent
commit
10ad401279
  1. 66
      src/app/api/models/[modelId]/route.ts

66
src/app/api/models/[modelId]/route.ts

@ -54,6 +54,15 @@ const IMAGE_INPUT_PATTERNS = [
"control_image",
];
// Audio input property patterns
const AUDIO_INPUT_PATTERNS = [
"audio_url",
"audio_urls",
"audio_input",
"audio_file",
"audio",
];
// Text input properties
const TEXT_INPUT_NAMES = ["prompt", "negative_prompt"];
@ -192,6 +201,43 @@ function isImageInput(name: string, prop: Record<string, unknown>, schemaCompone
name.includes("_image_");
}
/**
* Check if property is an audio input based on schema type and name.
*
* Audio inputs must be strings (URLs or base64) or arrays of strings.
*/
function isAudioInput(name: string, prop: Record<string, unknown>, schemaComponents?: Record<string, unknown>): boolean {
const resolved = resolvePropertyType(prop, schemaComponents);
const propType = resolved.type;
if (propType !== "string" && propType !== "array") {
return false;
}
// For arrays, check if items are strings
if (propType === "array") {
const items = prop.items as Record<string, unknown> | undefined;
if (items && items.type && items.type !== "string") {
return false;
}
}
// Check explicit patterns
if (AUDIO_INPUT_PATTERNS.includes(name)) {
return true;
}
// Check description for audio-related keywords
const description = (prop.description as string || "").toLowerCase();
if (description.includes("audio url") ||
description.includes("audio file") ||
description.includes("url of the audio")) {
return true;
}
// Check name patterns
return name.endsWith("_audio") || name.startsWith("audio_");
}
/**
* Check if property is a text input
*/
@ -540,6 +586,19 @@ function extractParametersFromSchema(
continue;
}
if (isAudioInput(name, prop, schemaComponents)) {
const resolvedType = resolvePropertyType(prop, schemaComponents).type;
inputs.push({
name,
type: "audio",
required: required.includes(name),
label: toLabel(name),
description: prop.description as string | undefined,
isArray: resolvedType === "array",
});
continue;
}
if (isTextInput(name)) {
inputs.push({
name,
@ -568,10 +627,13 @@ function extractParametersFromSchema(
return a.name.localeCompare(b.name);
});
// Sort inputs: required first, then by type (image before text), then alphabetically
// Sort inputs: required first, then by type (image, audio, text), then alphabetically
const inputTypeOrder: Record<string, number> = { image: 0, audio: 1, text: 2 };
inputs.sort((a, b) => {
if (a.required !== b.required) return a.required ? -1 : 1;
if (a.type !== b.type) return a.type === "image" ? -1 : 1;
const aOrder = inputTypeOrder[a.type] ?? 3;
const bOrder = inputTypeOrder[b.type] ?? 3;
if (aOrder !== bOrder) return aOrder - bOrder;
return a.name.localeCompare(b.name);
});

Loading…
Cancel
Save