mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-08-03 22:32:42 +00:00
🪵 chore: Log Subagent Limit Hits (#13068)
This commit is contained in:
parent
70b6bb69d3
commit
7631366f52
4 changed files with 92 additions and 1 deletions
|
|
@ -647,6 +647,12 @@ const initializeClient = async ({ req, res, signal, endpointOption }) => {
|
|||
return;
|
||||
}
|
||||
if (subagentGraphIds.size >= MAX_SUBAGENT_GRAPH_NODES) {
|
||||
logger.warn('[initializeClient] Subagent graph node limit exceeded', {
|
||||
agentId,
|
||||
primaryAgentId: primaryConfig.id,
|
||||
loadedSubagentCount: subagentGraphIds.size,
|
||||
maxSubagentGraphNodes: MAX_SUBAGENT_GRAPH_NODES,
|
||||
});
|
||||
throw new Error(
|
||||
`Subagent graph exceeds the maximum of ${MAX_SUBAGENT_GRAPH_NODES} unique agents.`,
|
||||
);
|
||||
|
|
@ -670,6 +676,13 @@ const initializeClient = async ({ req, res, signal, endpointOption }) => {
|
|||
|
||||
if (loadedSubagentConfigIds.has(config.id)) {
|
||||
if ((config.subagentAgentConfigs?.length ?? 0) > 0 && depth >= MAX_SUBAGENT_DEPTH) {
|
||||
logger.warn('[initializeClient] Subagent graph depth limit exceeded', {
|
||||
agentId: config.id,
|
||||
primaryAgentId: primaryConfig.id,
|
||||
depth,
|
||||
maxSubagentDepth: MAX_SUBAGENT_DEPTH,
|
||||
childCount: config.subagentAgentConfigs.length,
|
||||
});
|
||||
throw new Error(
|
||||
`Subagent graph exceeds the maximum depth of ${MAX_SUBAGENT_DEPTH} at agent ${config.id}.`,
|
||||
);
|
||||
|
|
@ -690,6 +703,13 @@ const initializeClient = async ({ req, res, signal, endpointOption }) => {
|
|||
);
|
||||
|
||||
if (explicitSubagentIds.length > 0 && depth >= MAX_SUBAGENT_DEPTH) {
|
||||
logger.warn('[initializeClient] Subagent graph depth limit exceeded', {
|
||||
agentId: config.id,
|
||||
primaryAgentId: primaryConfig.id,
|
||||
depth,
|
||||
maxSubagentDepth: MAX_SUBAGENT_DEPTH,
|
||||
childCount: explicitSubagentIds.length,
|
||||
});
|
||||
throw new Error(
|
||||
`Subagent graph exceeds the maximum depth of ${MAX_SUBAGENT_DEPTH} at agent ${config.id}.`,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -68,9 +68,12 @@ jest.mock('~/cache', () => ({
|
|||
}));
|
||||
|
||||
const { initializeClient } = require('./initialize');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
const { User, AclEntry } = require('~/db/models');
|
||||
const { createAgent } = require('~/models');
|
||||
|
||||
jest.spyOn(logger, 'warn').mockImplementation(() => {});
|
||||
|
||||
const PRIMARY_ID = 'agent_primary';
|
||||
const TARGET_ID = 'agent_target';
|
||||
const AUTHORIZED_ID = 'agent_authorized';
|
||||
|
|
@ -504,6 +507,16 @@ describe('initializeClient — subagent loading', () => {
|
|||
endpointOption: makeEndpointOption(),
|
||||
}),
|
||||
).rejects.toThrow(`maximum depth of ${MAX_SUBAGENT_DEPTH}`);
|
||||
expect(logger.warn).toHaveBeenCalledWith(
|
||||
'[initializeClient] Subagent graph depth limit exceeded',
|
||||
expect.objectContaining({
|
||||
agentId: `agent_depth_${MAX_SUBAGENT_DEPTH - 1}`,
|
||||
primaryAgentId: PRIMARY_ID,
|
||||
depth: MAX_SUBAGENT_DEPTH,
|
||||
maxSubagentDepth: MAX_SUBAGENT_DEPTH,
|
||||
childCount: 1,
|
||||
}),
|
||||
);
|
||||
expect(agentClientArgs).toBeUndefined();
|
||||
});
|
||||
|
||||
|
|
@ -542,6 +555,15 @@ describe('initializeClient — subagent loading', () => {
|
|||
endpointOption: makeEndpointOption(),
|
||||
}),
|
||||
).rejects.toThrow(`maximum depth of ${MAX_SUBAGENT_DEPTH}`);
|
||||
expect(logger.warn).toHaveBeenCalledWith(
|
||||
'[initializeClient] Subagent graph depth limit exceeded',
|
||||
expect.objectContaining({
|
||||
primaryAgentId: PRIMARY_ID,
|
||||
depth: MAX_SUBAGENT_DEPTH,
|
||||
maxSubagentDepth: MAX_SUBAGENT_DEPTH,
|
||||
childCount: 1,
|
||||
}),
|
||||
);
|
||||
expect(agentClientArgs).toBeUndefined();
|
||||
});
|
||||
|
||||
|
|
@ -581,6 +603,14 @@ describe('initializeClient — subagent loading', () => {
|
|||
endpointOption: makeEndpointOption(),
|
||||
}),
|
||||
).rejects.toThrow(`maximum of ${MAX_SUBAGENT_GRAPH_NODES} unique agents`);
|
||||
expect(logger.warn).toHaveBeenCalledWith(
|
||||
'[initializeClient] Subagent graph node limit exceeded',
|
||||
expect.objectContaining({
|
||||
primaryAgentId: PRIMARY_ID,
|
||||
loadedSubagentCount: MAX_SUBAGENT_GRAPH_NODES,
|
||||
maxSubagentGraphNodes: MAX_SUBAGENT_GRAPH_NODES,
|
||||
}),
|
||||
);
|
||||
expect(agentClientArgs).toBeUndefined();
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { logger } from '@librechat/data-schemas';
|
||||
import type { AppConfig } from '@librechat/data-schemas';
|
||||
import type { SummarizationConfig, TEndpoint } from 'librechat-data-provider';
|
||||
import {
|
||||
|
|
@ -26,6 +27,16 @@ jest.mock('~/utils/env', () => ({
|
|||
createSafeUser: jest.fn(() => ({})),
|
||||
}));
|
||||
|
||||
jest.mock('@librechat/data-schemas', () => ({
|
||||
...jest.requireActual('@librechat/data-schemas'),
|
||||
logger: {
|
||||
debug: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
error: jest.fn(),
|
||||
info: jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
// Mock Run.create to capture the graphConfig it receives
|
||||
jest.mock('@librechat/agents', () => {
|
||||
const actual = jest.requireActual('@librechat/agents');
|
||||
|
|
@ -1007,6 +1018,14 @@ describe('subagentConfigs', () => {
|
|||
}),
|
||||
).rejects.toThrow(`maximum depth of ${MAX_SUBAGENT_DEPTH}`);
|
||||
|
||||
expect(logger.warn).toHaveBeenCalledWith(
|
||||
'[createRun] Subagent graph depth limit exceeded',
|
||||
expect.objectContaining({
|
||||
agentId: `agent_chain_${MAX_SUBAGENT_DEPTH + 1}`,
|
||||
depth: MAX_SUBAGENT_DEPTH + 1,
|
||||
maxSubagentDepth: MAX_SUBAGENT_DEPTH,
|
||||
}),
|
||||
);
|
||||
expect(Run.create).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
|
@ -1020,6 +1039,14 @@ describe('subagentConfigs', () => {
|
|||
}),
|
||||
).rejects.toThrow(`maximum of ${MAX_SUBAGENT_RUN_CONFIGS} expanded entries`);
|
||||
|
||||
expect(logger.warn).toHaveBeenCalledWith(
|
||||
'[createRun] Subagent run configuration limit exceeded',
|
||||
expect.objectContaining({
|
||||
expandedConfigCount: MAX_SUBAGENT_RUN_CONFIGS + 1,
|
||||
maxSubagentRunConfigs: MAX_SUBAGENT_RUN_CONFIGS,
|
||||
rootAgentIds: ['agent_dag_root'],
|
||||
}),
|
||||
);
|
||||
expect(Run.create).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -551,11 +551,17 @@ const SELF_SUBAGENT_TYPE = 'self';
|
|||
|
||||
interface SubagentBuildState {
|
||||
configCount: number;
|
||||
rootAgentIds: string[];
|
||||
}
|
||||
|
||||
function countSubagentConfig(state: SubagentBuildState): void {
|
||||
state.configCount += 1;
|
||||
if (state.configCount > MAX_SUBAGENT_RUN_CONFIGS) {
|
||||
logger.warn('[createRun] Subagent run configuration limit exceeded', {
|
||||
expandedConfigCount: state.configCount,
|
||||
maxSubagentRunConfigs: MAX_SUBAGENT_RUN_CONFIGS,
|
||||
rootAgentIds: state.rootAgentIds,
|
||||
});
|
||||
throw new Error(
|
||||
`Subagent run configuration exceeds the maximum of ${MAX_SUBAGENT_RUN_CONFIGS} expanded entries.`,
|
||||
);
|
||||
|
|
@ -564,6 +570,11 @@ function countSubagentConfig(state: SubagentBuildState): void {
|
|||
|
||||
function assertSubagentDepth(depth: number, agentId: string): void {
|
||||
if (depth > MAX_SUBAGENT_DEPTH) {
|
||||
logger.warn('[createRun] Subagent graph depth limit exceeded', {
|
||||
agentId,
|
||||
depth,
|
||||
maxSubagentDepth: MAX_SUBAGENT_DEPTH,
|
||||
});
|
||||
throw new Error(
|
||||
`Subagent graph exceeds the maximum depth of ${MAX_SUBAGENT_DEPTH} at agent ${agentId}.`,
|
||||
);
|
||||
|
|
@ -922,7 +933,10 @@ export async function createRun({
|
|||
};
|
||||
|
||||
const agentInputs: AgentInputs[] = [];
|
||||
const subagentBuildState: SubagentBuildState = { configCount: 0 };
|
||||
const subagentBuildState: SubagentBuildState = {
|
||||
configCount: 0,
|
||||
rootAgentIds: agents.map((agent) => agent.id),
|
||||
};
|
||||
for (const agent of agents) {
|
||||
const agentInput = buildAgentInput(agent);
|
||||
const subagentConfigs = buildSubagentConfigs(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue