🐋 fix: Improve Deepseek Compatbility (#7132)

* refactor: Update schema conversion to allow nullable optional fields

* feat: Add support for 'Deepseek' model in response sender logic

* fix: Normalize endpoint case for legacy content handling in AgentClient (fixes `deepseek-chat` followup issues)
This commit is contained in:
Danny Avila 2025-04-29 09:55:43 -04:00 committed by GitHub
parent 55f5f2d11a
commit a89a3f4146
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 27 additions and 24 deletions

View file

@ -673,7 +673,7 @@ class AgentClient extends BaseClient {
this.indexTokenCountMap,
toolSet,
);
if (legacyContentEndpoints.has(this.options.agent.endpoint)) {
if (legacyContentEndpoints.has(this.options.agent.endpoint?.toLowerCase())) {
initialMessages = formatContentStrings(initialMessages);
}

View file

@ -253,6 +253,8 @@ export const getResponseSender = (endpointOption: t.TEndpointOption): string =>
return extractOmniVersion(model);
} else if (model && (model.includes('mistral') || model.includes('codestral'))) {
return 'Mistral';
} else if (model && model.includes('deepseek')) {
return 'Deepseek';
} else if (model && model.includes('gpt-')) {
const gptVersion = extractGPTVersion(model);
return gptVersion || 'GPT';
@ -289,6 +291,8 @@ export const getResponseSender = (endpointOption: t.TEndpointOption): string =>
return extractOmniVersion(model);
} else if (model && (model.includes('mistral') || model.includes('codestral'))) {
return 'Mistral';
} else if (model && model.includes('deepseek')) {
return 'Deepseek';
} else if (model && model.includes('gpt-')) {
const gptVersion = extractGPTVersion(model);
return gptVersion || 'GPT';

View file

@ -29,7 +29,9 @@ function dropSchemaFields(
schema: JsonSchemaType | undefined,
fields: string[],
): JsonSchemaType | undefined {
if (schema == null || typeof schema !== 'object') {return schema;}
if (schema == null || typeof schema !== 'object') {
return schema;
}
// Handle arrays (should only occur for enum, required, etc.)
if (Array.isArray(schema)) {
// This should not happen for the root schema, but for completeness:
@ -37,33 +39,25 @@ function dropSchemaFields(
}
const result: Record<string, unknown> = {};
for (const [key, value] of Object.entries(schema)) {
if (fields.includes(key)) {continue;}
if (fields.includes(key)) {
continue;
}
// Recursively process nested schemas
if (
key === 'items' ||
key === 'additionalProperties' ||
key === 'properties'
) {
if (key === 'items' || key === 'additionalProperties' || key === 'properties') {
if (key === 'properties' && value && typeof value === 'object') {
// properties is a record of string -> JsonSchemaType
const newProps: Record<string, JsonSchemaType> = {};
for (const [propKey, propValue] of Object.entries(
value as Record<string, JsonSchemaType>,
)) {
const dropped = dropSchemaFields(
propValue,
fields,
);
const dropped = dropSchemaFields(propValue, fields);
if (dropped !== undefined) {
newProps[propKey] = dropped;
}
}
result[key] = newProps;
} else if (key === 'items' || key === 'additionalProperties') {
const dropped = dropSchemaFields(
value as JsonSchemaType,
fields,
);
const dropped = dropSchemaFields(value as JsonSchemaType, fields);
if (dropped !== undefined) {
result[key] = dropped;
}
@ -141,9 +135,11 @@ function convertToZodUnion(
// For the special case of { optional: true }
if ('optional' in (subSchema.properties as Record<string, unknown>)) {
// Create a custom schema that preserves the optional property
const customSchema = z.object({
const customSchema = z
.object({
optional: z.boolean(),
}).passthrough();
})
.passthrough();
return customSchema;
}
@ -362,12 +358,15 @@ export function convertJsonSchemaToZod(
const partial = Object.fromEntries(
Object.entries(shape).map(([key, value]) => [
key,
schema.required?.includes(key) === true ? value : value.optional(),
schema.required?.includes(key) === true ? value : value.optional().nullable(),
]),
);
objectSchema = z.object(partial);
} else {
objectSchema = objectSchema.partial();
const partialNullable = Object.fromEntries(
Object.entries(shape).map(([key, value]) => [key, value.optional().nullable()]),
);
objectSchema = z.object(partialNullable);
}
// Handle additionalProperties for open-ended objects