mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-03 03:03:24 -04:00
refactor(schema): share gemini union cleanup
This commit is contained in:
@@ -29,6 +29,16 @@ export const GEMINI_UNSUPPORTED_SCHEMA_KEYWORDS = new Set([
|
||||
"maxProperties",
|
||||
]);
|
||||
|
||||
const SCHEMA_META_KEYS = ["description", "title", "default"] as const;
|
||||
|
||||
function copySchemaMeta(from: Record<string, unknown>, to: Record<string, unknown>): void {
|
||||
for (const key of SCHEMA_META_KEYS) {
|
||||
if (key in from && from[key] !== undefined) {
|
||||
to[key] = from[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if an anyOf/oneOf array contains only literal values that can be flattened.
|
||||
// TypeBox Type.Literal generates { const: "value", type: "string" }.
|
||||
// Some schemas may use { enum: ["value"], type: "string" }.
|
||||
@@ -164,6 +174,39 @@ function tryResolveLocalRef(ref: string, defs: SchemaDefs | undefined): unknown
|
||||
return defs.get(name);
|
||||
}
|
||||
|
||||
function simplifyUnionVariants(params: { obj: Record<string, unknown>; variants: unknown[] }): {
|
||||
variants: unknown[];
|
||||
simplified?: unknown;
|
||||
} {
|
||||
const { obj, variants } = params;
|
||||
|
||||
const { variants: nonNullVariants, stripped } = stripNullVariants(variants);
|
||||
|
||||
const flattened = tryFlattenLiteralAnyOf(nonNullVariants);
|
||||
if (flattened) {
|
||||
const result: Record<string, unknown> = {
|
||||
type: flattened.type,
|
||||
enum: flattened.enum,
|
||||
};
|
||||
copySchemaMeta(obj, result);
|
||||
return { variants: nonNullVariants, simplified: result };
|
||||
}
|
||||
|
||||
if (stripped && nonNullVariants.length === 1) {
|
||||
const lone = nonNullVariants[0];
|
||||
if (lone && typeof lone === "object" && !Array.isArray(lone)) {
|
||||
const result: Record<string, unknown> = {
|
||||
...(lone as Record<string, unknown>),
|
||||
};
|
||||
copySchemaMeta(obj, result);
|
||||
return { variants: nonNullVariants, simplified: result };
|
||||
}
|
||||
return { variants: nonNullVariants, simplified: lone };
|
||||
}
|
||||
|
||||
return { variants: stripped ? nonNullVariants : variants };
|
||||
}
|
||||
|
||||
function cleanSchemaForGeminiWithDefs(
|
||||
schema: unknown,
|
||||
defs: SchemaDefs | undefined,
|
||||
@@ -198,20 +241,12 @@ function cleanSchemaForGeminiWithDefs(
|
||||
const result: Record<string, unknown> = {
|
||||
...(cleaned as Record<string, unknown>),
|
||||
};
|
||||
for (const key of ["description", "title", "default"]) {
|
||||
if (key in obj && obj[key] !== undefined) {
|
||||
result[key] = obj[key];
|
||||
}
|
||||
}
|
||||
copySchemaMeta(obj, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
const result: Record<string, unknown> = {};
|
||||
for (const key of ["description", "title", "default"]) {
|
||||
if (key in obj && obj[key] !== undefined) {
|
||||
result[key] = obj[key];
|
||||
}
|
||||
}
|
||||
copySchemaMeta(obj, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -229,74 +264,18 @@ function cleanSchemaForGeminiWithDefs(
|
||||
: undefined;
|
||||
|
||||
if (hasAnyOf) {
|
||||
const { variants: nonNullVariants, stripped } = stripNullVariants(cleanedAnyOf ?? []);
|
||||
if (stripped) {
|
||||
cleanedAnyOf = nonNullVariants;
|
||||
}
|
||||
|
||||
const flattened = tryFlattenLiteralAnyOf(nonNullVariants);
|
||||
if (flattened) {
|
||||
const result: Record<string, unknown> = {
|
||||
type: flattened.type,
|
||||
enum: flattened.enum,
|
||||
};
|
||||
for (const key of ["description", "title", "default"]) {
|
||||
if (key in obj && obj[key] !== undefined) {
|
||||
result[key] = obj[key];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
if (stripped && nonNullVariants.length === 1) {
|
||||
const lone = nonNullVariants[0];
|
||||
if (lone && typeof lone === "object" && !Array.isArray(lone)) {
|
||||
const result: Record<string, unknown> = {
|
||||
...(lone as Record<string, unknown>),
|
||||
};
|
||||
for (const key of ["description", "title", "default"]) {
|
||||
if (key in obj && obj[key] !== undefined) {
|
||||
result[key] = obj[key];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return lone;
|
||||
const simplified = simplifyUnionVariants({ obj, variants: cleanedAnyOf ?? [] });
|
||||
cleanedAnyOf = simplified.variants;
|
||||
if ("simplified" in simplified) {
|
||||
return simplified.simplified;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasOneOf) {
|
||||
const { variants: nonNullVariants, stripped } = stripNullVariants(cleanedOneOf ?? []);
|
||||
if (stripped) {
|
||||
cleanedOneOf = nonNullVariants;
|
||||
}
|
||||
|
||||
const flattened = tryFlattenLiteralAnyOf(nonNullVariants);
|
||||
if (flattened) {
|
||||
const result: Record<string, unknown> = {
|
||||
type: flattened.type,
|
||||
enum: flattened.enum,
|
||||
};
|
||||
for (const key of ["description", "title", "default"]) {
|
||||
if (key in obj && obj[key] !== undefined) {
|
||||
result[key] = obj[key];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
if (stripped && nonNullVariants.length === 1) {
|
||||
const lone = nonNullVariants[0];
|
||||
if (lone && typeof lone === "object" && !Array.isArray(lone)) {
|
||||
const result: Record<string, unknown> = {
|
||||
...(lone as Record<string, unknown>),
|
||||
};
|
||||
for (const key of ["description", "title", "default"]) {
|
||||
if (key in obj && obj[key] !== undefined) {
|
||||
result[key] = obj[key];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return lone;
|
||||
const simplified = simplifyUnionVariants({ obj, variants: cleanedOneOf ?? [] });
|
||||
cleanedOneOf = simplified.variants;
|
||||
if ("simplified" in simplified) {
|
||||
return simplified.simplified;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user