mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-08-27 04:07:05 +00:00
🧷 fix: Bind Agent File Context to Current Turn (#13506)
* fix: Bind agent file context to current turn * fix: Avoid duplicating agent file context * fix: Export agent file context prepender * test: Use exported file context prepender * fix: Keep file context transient for memory and counts
This commit is contained in:
parent
a1bfa3b298
commit
dc42748813
4 changed files with 249 additions and 45 deletions
54
packages/api/src/agents/client.spec.ts
Normal file
54
packages/api/src/agents/client.spec.ts
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
import { ContentTypes } from 'librechat-data-provider';
|
||||
import { prependFileContext, type FormattedMessageWithContent } from './client';
|
||||
|
||||
describe('prependFileContext', () => {
|
||||
it('prepends file context to string content', () => {
|
||||
const message: FormattedMessageWithContent = { content: 'Answer this question.' };
|
||||
|
||||
prependFileContext(message, 'Attached file text');
|
||||
|
||||
expect(message.content).toBe('Attached file text\nAnswer this question.');
|
||||
});
|
||||
|
||||
it('prepends file context to the first text content part', () => {
|
||||
const message: FormattedMessageWithContent = {
|
||||
content: [
|
||||
{ type: ContentTypes.IMAGE_URL, image_url: { url: 'data:image/png;base64,abc' } },
|
||||
{ type: ContentTypes.TEXT, text: 'Answer this question.' },
|
||||
],
|
||||
};
|
||||
|
||||
prependFileContext(message, 'Attached file text');
|
||||
|
||||
expect(Array.isArray(message.content)).toBe(true);
|
||||
if (!Array.isArray(message.content)) {
|
||||
throw new Error('Expected array content');
|
||||
}
|
||||
expect(message.content[1].text).toBe('Attached file text\nAnswer this question.');
|
||||
expect(message.content[0]).toEqual({
|
||||
type: ContentTypes.IMAGE_URL,
|
||||
image_url: { url: 'data:image/png;base64,abc' },
|
||||
});
|
||||
});
|
||||
|
||||
it('adds a text content part when an array has no text part', () => {
|
||||
const message: FormattedMessageWithContent = {
|
||||
content: [{ type: ContentTypes.IMAGE_URL, image_url: { url: 'data:image/png;base64,abc' } }],
|
||||
};
|
||||
|
||||
prependFileContext(message, 'Attached file text');
|
||||
|
||||
expect(message.content).toEqual([
|
||||
{ type: ContentTypes.TEXT, text: 'Attached file text' },
|
||||
{ type: ContentTypes.IMAGE_URL, image_url: { url: 'data:image/png;base64,abc' } },
|
||||
]);
|
||||
});
|
||||
|
||||
it('leaves content unchanged when file context is empty', () => {
|
||||
const message: FormattedMessageWithContent = { content: 'Answer this question.' };
|
||||
|
||||
prependFileContext(message, '');
|
||||
|
||||
expect(message.content).toBe('Answer this question.');
|
||||
});
|
||||
});
|
||||
|
|
@ -56,6 +56,42 @@ type ContentBlock = {
|
|||
tool_call?: { name?: string; args?: string; output?: string };
|
||||
};
|
||||
|
||||
export type FormattedMessageContentPart = {
|
||||
type?: string;
|
||||
text?: string;
|
||||
[key: string]: unknown;
|
||||
};
|
||||
|
||||
export type FormattedMessageWithContent = {
|
||||
content?: string | FormattedMessageContentPart[];
|
||||
};
|
||||
|
||||
export function prependFileContext(
|
||||
formattedMessage: FormattedMessageWithContent,
|
||||
fileContext?: string | null,
|
||||
): void {
|
||||
if (!fileContext) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof formattedMessage.content === 'string') {
|
||||
formattedMessage.content = `${fileContext}\n${formattedMessage.content}`;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Array.isArray(formattedMessage.content)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const textPart = formattedMessage.content.find((part) => part.type === ContentTypes.TEXT);
|
||||
if (textPart != null && typeof textPart.text === 'string') {
|
||||
textPart.text = `${fileContext}\n${textPart.text}`;
|
||||
return;
|
||||
}
|
||||
|
||||
formattedMessage.content.unshift({ type: ContentTypes.TEXT, text: fileContext });
|
||||
}
|
||||
|
||||
function estimateImageDataTokens(data: string, isClaude: boolean): number {
|
||||
const dims = extractImageDimensions(data);
|
||||
if (dims == null) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue