🔃 refactor: Decouple Effects from AppService, move to data-schemas (#9974)

* chore: linting for `loadCustomConfig`

* refactor: decouple CDN init and variable/health checks from AppService

* refactor: move AppService to packages/data-schemas

* chore: update AppConfig import path to use data-schemas

* chore: update JsonSchemaType import path to use data-schemas

* refactor: update UserController to import webSearchKeys and redefine FunctionTool typedef

* chore: remove AppService.js

* refactor: update AppConfig interface to use Partial<TCustomConfig> and make paths and fileStrategies optional

* refactor: update checkConfig function to accept Partial<TCustomConfig>

* chore: fix types

* refactor: move handleRateLimits to startup checks as is an effect

* test: remove outdated rate limit tests from AppService.spec and add new handleRateLimits tests in checks.spec
This commit is contained in:
Danny Avila 2025-10-05 06:37:57 -04:00 committed by GitHub
parent 9ff608e6af
commit 838fb53208
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
73 changed files with 1383 additions and 1326 deletions

View file

@ -10,44 +10,6 @@ import { extractEnvVariable, envVarRegex } from '../src/utils';
import { azureGroupConfigsSchema } from '../src/config';
import { errorsToString } from '../src/parsers';
export const deprecatedAzureVariables = [
/* "related to" precedes description text */
{ key: 'AZURE_OPENAI_DEFAULT_MODEL', description: 'setting a default model' },
{ key: 'AZURE_OPENAI_MODELS', description: 'setting models' },
{
key: 'AZURE_USE_MODEL_AS_DEPLOYMENT_NAME',
description: 'using model names as deployment names',
},
{ key: 'AZURE_API_KEY', description: 'setting a single Azure API key' },
{ key: 'AZURE_OPENAI_API_INSTANCE_NAME', description: 'setting a single Azure instance name' },
{
key: 'AZURE_OPENAI_API_DEPLOYMENT_NAME',
description: 'setting a single Azure deployment name',
},
{ key: 'AZURE_OPENAI_API_VERSION', description: 'setting a single Azure API version' },
{
key: 'AZURE_OPENAI_API_COMPLETIONS_DEPLOYMENT_NAME',
description: 'setting a single Azure completions deployment name',
},
{
key: 'AZURE_OPENAI_API_EMBEDDINGS_DEPLOYMENT_NAME',
description: 'setting a single Azure embeddings deployment name',
},
{
key: 'PLUGINS_USE_AZURE',
description: 'using Azure for Plugins',
},
];
export const conflictingAzureVariables = [
{
key: 'INSTANCE_NAME',
},
{
key: 'DEPLOYMENT_NAME',
},
];
export function validateAzureGroups(configs: TAzureGroups): TAzureConfigValidationResult {
let isValid = true;
const modelNames: string[] = [];
@ -239,13 +201,13 @@ export function mapModelToAzureConfig({
const { deploymentName = '', version = '' } =
typeof modelDetails === 'object'
? {
deploymentName: modelDetails.deploymentName ?? groupConfig.deploymentName,
version: modelDetails.version ?? groupConfig.version,
}
deploymentName: modelDetails.deploymentName ?? groupConfig.deploymentName,
version: modelDetails.version ?? groupConfig.version,
}
: {
deploymentName: groupConfig.deploymentName,
version: groupConfig.version,
};
deploymentName: groupConfig.deploymentName,
version: groupConfig.version,
};
if (!deploymentName || !version) {
throw new Error(
@ -335,13 +297,13 @@ export function mapGroupToAzureConfig({
const { deploymentName = '', version = '' } =
typeof modelDetails === 'object'
? {
deploymentName: modelDetails.deploymentName ?? groupConfig.deploymentName,
version: modelDetails.version ?? groupConfig.version,
}
deploymentName: modelDetails.deploymentName ?? groupConfig.deploymentName,
version: modelDetails.version ?? groupConfig.version,
}
: {
deploymentName: groupConfig.deploymentName,
version: groupConfig.version,
};
deploymentName: groupConfig.deploymentName,
version: groupConfig.version,
};
if (!deploymentName || !version) {
throw new Error(

View file

@ -155,8 +155,10 @@ export type TAzureGroupMap = Record<
export type TValidatedAzureConfig = {
modelNames: string[];
modelGroupMap: TAzureModelGroupMap;
groupMap: TAzureGroupMap;
assistantModels?: string[];
assistantGroups?: string[];
modelGroupMap: TAzureModelGroupMap;
};
export type TAzureConfigValidationResult = TValidatedAzureConfig & {
@ -752,7 +754,7 @@ export const webSearchSchema = z.object({
.optional(),
});
export type TWebSearchConfig = z.infer<typeof webSearchSchema>;
export type TWebSearchConfig = DeepPartial<z.infer<typeof webSearchSchema>>;
export const ocrSchema = z.object({
mistralModel: z.string().optional(),
@ -799,7 +801,7 @@ export const memorySchema = z.object({
.optional(),
});
export type TMemoryConfig = z.infer<typeof memorySchema>;
export type TMemoryConfig = DeepPartial<z.infer<typeof memorySchema>>;
const customEndpointsSchema = z.array(endpointSchema.partial()).optional();
@ -862,9 +864,27 @@ export const configSchema = z.object({
.optional(),
});
export const getConfigDefaults = () => getSchemaDefaults(configSchema);
/**
* Recursively makes all properties of T optional, including nested objects.
* Handles arrays, primitives, functions, and Date objects correctly.
*/
export type DeepPartial<T> = T extends (infer U)[]
? DeepPartial<U>[]
: T extends ReadonlyArray<infer U>
? ReadonlyArray<DeepPartial<U>>
: // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
T extends Function
? T
: T extends Date
? T
: T extends object
? {
[P in keyof T]?: DeepPartial<T[P]>;
}
: T;
export type TCustomConfig = z.infer<typeof configSchema>;
export const getConfigDefaults = () => getSchemaDefaults(configSchema);
export type TCustomConfig = DeepPartial<z.infer<typeof configSchema>>;
export type TCustomEndpoints = z.infer<typeof customEndpointsSchema>;
export type TProviderSchema =