🐛 fix: Never queue text-source records for provisioning

Legacy context files keep their content in the database with no backing object,
which the download route reconstructs from the stored text. Queueing them sent
them to a storage stream that correctly refuses the source, and since a code
provisioning failure now aborts the preflight, an agent holding one could not
run code at all. They are skipped rather than queued; provisioning them from
their stored text needs a text re-fetch and is tracked as follow-up work.
This commit is contained in:
Danny Avila 2026-08-31 11:54:20 -04:00
parent 3f15250f6b
commit 9bc01f40e9
2 changed files with 28 additions and 0 deletions

View file

@ -2131,6 +2131,26 @@ describe('primeResources', () => {
expect(searchResource?.files?.map((f) => f.file_id) ?? []).not.toContain('embedded-context');
});
it('never queues a text-source record, which has no streamable backing', async () => {
process.env.CODEAPI_AUTH_PROVIDER = 'librechat-jwt';
const textFile = makeCodeFile({ file_id: 'text-record', source: FileSources.text });
const result = await primeResources({
req: mockReq,
appConfig: mockAppConfig,
getFiles: mockGetFiles,
filterFiles: mockFilterFiles,
tool_resources: {},
attachments: Promise.resolve([textFile]),
requestFileSet,
agentId: 'agent1',
enabledToolResources: new Set([EToolResources.execute_code, EToolResources.file_search]),
});
expect(result.provisionState).toBeUndefined();
expect(result.attachments?.map((f) => f?.file_id)).toContain('text-record');
});
it('grants agent scope only to agent setup files', () => {
expect(isAgentScopedFile({ context: FileContext.agents })).toBe(true);
expect(isAgentScopedFile({ context: FileContext.execute_code })).toBe(false);

View file

@ -4,6 +4,7 @@ import {
EToolResources,
AgentCapabilities,
FileContext,
FileSources,
} from 'librechat-data-provider';
import type {
AgentToolResources,
@ -366,6 +367,13 @@ const computeProvisionState = async ({
continue;
}
/** Text-source records keep their content in the database with no backing object
* to stream, so provisioning them would fail and, for code, abort the turn.
* Provisioning them from their stored text is tracked as follow-up work. */
if (file.source === FileSources.text) {
continue;
}
if (needsCodeEnv) {
const legacyRef = file.metadata?.codeEnvRef;
const isDefaultRoute = legacyRef != null && codeEnvRouteKey(legacyRef) === 'default';