mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-08-27 12:13:30 +00:00
🧫 test: Lock Subagent File Context Propagation (#15126)
This commit is contained in:
parent
c411eb4cc6
commit
2018c70040
2 changed files with 108 additions and 0 deletions
|
|
@ -3838,6 +3838,50 @@ describe('AgentClient - titleConvo', () => {
|
|||
|
||||
expect(mockAgent.additional_instructions).toContain('Direct primary context');
|
||||
});
|
||||
|
||||
it('hydrates a pure lazy subagent with its own File Context when selected', async () => {
|
||||
const childContext = makeTextFile('child-context', 'child.txt', 'Pure child private context');
|
||||
const resolvedChild = {
|
||||
id: 'pure-child-agent',
|
||||
endpoint: EModelEndpoint.openAI,
|
||||
provider: EModelEndpoint.openAI,
|
||||
instructions: 'Pure child instructions',
|
||||
model_parameters: { model: 'gpt-4' },
|
||||
tools: [],
|
||||
agentContextAttachments: [childContext],
|
||||
};
|
||||
const descriptor = {
|
||||
id: resolvedChild.id,
|
||||
resolve: jest.fn().mockResolvedValue(resolvedChild),
|
||||
};
|
||||
mockAgent.lazySubagentConfigs = [descriptor];
|
||||
client.agentConfigs = new Map();
|
||||
|
||||
await client.buildMessages(
|
||||
[
|
||||
{
|
||||
messageId: 'msg-1',
|
||||
parentMessageId: null,
|
||||
sender: 'User',
|
||||
text: 'Answer from the child context.',
|
||||
isCreatedByUser: true,
|
||||
},
|
||||
],
|
||||
'msg-1',
|
||||
{},
|
||||
);
|
||||
const resolved = await descriptor.resolve({ signal: new AbortController().signal });
|
||||
|
||||
expect(resolved).toBe(resolvedChild);
|
||||
expect(resolvedChild.additional_instructions).toContain('Pure child private context');
|
||||
expect(mockAgent.additional_instructions ?? '').not.toContain('Pure child private context');
|
||||
expect(mockBuildAgentScopedContext).toHaveBeenLastCalledWith(
|
||||
expect.objectContaining({
|
||||
agentIds: ['pure-child-agent'],
|
||||
attachmentsByAgentId: new Map([['pure-child-agent', [childContext]]]),
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('provider-native YouTube file preflight', () => {
|
||||
|
|
|
|||
|
|
@ -1251,6 +1251,70 @@ describe('subagentConfigs', () => {
|
|||
expect(childInputs.name).toBe('Researcher');
|
||||
});
|
||||
|
||||
it.each([
|
||||
['foreground', undefined],
|
||||
[
|
||||
'detached',
|
||||
{
|
||||
store: new InMemorySubagentTaskStore(),
|
||||
scopeId: 'file-context-task-scope',
|
||||
} satisfies SubagentTaskConfig,
|
||||
],
|
||||
])("preserves a lazy child's prepared File Context in %s execution", async (_mode, tasks) => {
|
||||
const fileContext = 'Attached document(s):\n```md\n# "child.txt"\nChild-only facts\n\n```';
|
||||
const resolve = jest.fn().mockResolvedValue(
|
||||
makeAgent({
|
||||
id: 'agent_child',
|
||||
name: 'Researcher',
|
||||
additional_instructions: fileContext,
|
||||
}),
|
||||
);
|
||||
const agents = await callAndCapture({
|
||||
subagentTasks: tasks,
|
||||
agents: [
|
||||
makeAgent({
|
||||
subagents: { enabled: true, allowSelf: false, agent_ids: ['agent_child'] },
|
||||
lazySubagentConfigs: [
|
||||
{
|
||||
id: 'agent_child',
|
||||
name: 'Researcher',
|
||||
description: 'Uses private File Context',
|
||||
configId: 'agent_child:3:fingerprint',
|
||||
resolve,
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
});
|
||||
const [config] = agents[0].subagentConfigs as Array<Record<string, unknown>>;
|
||||
const childInputs = await (
|
||||
config.resolveAgentInputs as (context: never) => Promise<Record<string, unknown>>
|
||||
)({ signal: new AbortController().signal } as never);
|
||||
|
||||
expect(childInputs.additional_instructions).toBe(fileContext);
|
||||
});
|
||||
|
||||
it('preserves prepared File Context for an eager legacy subagent', async () => {
|
||||
const fileContext = 'Attached document(s):\n```md\n# "child.txt"\nLegacy child facts\n\n```';
|
||||
const child = makeAgent({
|
||||
id: 'agent_child',
|
||||
name: 'Researcher',
|
||||
additional_instructions: fileContext,
|
||||
});
|
||||
const agents = await callAndCapture({
|
||||
agents: [
|
||||
makeAgent({
|
||||
subagents: { enabled: true, allowSelf: false, agent_ids: ['agent_child'] },
|
||||
subagentAgentConfigs: [child],
|
||||
}),
|
||||
],
|
||||
});
|
||||
const [config] = agents[0].subagentConfigs as Array<Record<string, unknown>>;
|
||||
const childInputs = config.agentInputs as Record<string, unknown>;
|
||||
|
||||
expect(childInputs.additional_instructions).toBe(fileContext);
|
||||
});
|
||||
|
||||
it('uses a fresh expansion budget for each lazy descriptor resolution', async () => {
|
||||
const nestedDescriptors = Array.from({ length: 99 }, (_, index) => ({
|
||||
id: `agent_nested_${index}`,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue