🧹 fix: Repair CI Failures on the PTC Tool Trace

Two failures on the previous head, both mine.

`Tests: api (shard 2/3)` — 46 failures in `initialize.spec.js`, all
`TypeError: createPtcProgressEmitter is not a function`. The suite mocks the
callbacks module with an object literal, and wiring the new emitter into
`initialize.js` without adding it there left the factory undefined at call
time. Added it alongside `createAttachmentEmitter`, plus an assertion that it
receives the same generation fence as every other resumable emitter — a stale
epoch would leak one run's inner calls into the next.

`Static checks` — import-order drift in `PtcToolTrace.tsx` and `handlers.ts`,
repaired with `scripts/sort-imports.mts`. ESLint and Prettier both passed, so
only the dedicated check caught it.

`openai.js` and `responses.js` never take the emitter, so their specs were
unaffected; verified the initialize mock now covers every name the module
destructures.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MBRQUsPXSvDBnjrSDoXWHP
This commit is contained in:
Claude 2026-08-22 05:49:29 +00:00
parent edbbefe898
commit db0d333872
No known key found for this signature in database
3 changed files with 11 additions and 2 deletions

View file

@ -49,6 +49,7 @@ const mockArtifactToolEndCallback = jest.fn();
jest.mock('~/server/controllers/agents/callbacks', () => ({
createToolEndCallback: jest.fn(() => mockArtifactToolEndCallback),
createAttachmentEmitter: jest.fn(() => jest.fn()),
createPtcProgressEmitter: jest.fn(() => jest.fn()),
createBackgroundCodeResultHandler: jest.fn(() => jest.fn()),
getDefaultHandlers: jest.fn((opts) => {
capturedDefaultHandlerOptions = opts;
@ -206,6 +207,7 @@ describe('initializeClient — processAgent ACL gate', () => {
it('threads the owning job epoch into resumable event handlers', async () => {
const {
createAttachmentEmitter,
createPtcProgressEmitter,
createToolEndCallback,
} = require('~/server/controllers/agents/callbacks');
mockInitializeAgent.mockResolvedValue(makePrimaryConfig([]));
@ -237,6 +239,13 @@ describe('initializeClient — processAgent ACL gate', () => {
streamId: 'conv_1',
jobCreatedAt: 1234,
});
/** The PTC trace emitter is generation-fenced like every other resumable
* emitter; a stale epoch would leak one run's inner calls into the next. */
expect(createPtcProgressEmitter).toHaveBeenCalledWith({
res: {},
streamId: 'conv_1',
jobCreatedAt: 1234,
});
mockLoadToolsForExecution.mockResolvedValue({ loadedTools: [], configurable: {} });
await capturedToolExecuteOptions.loadTools([], PRIMARY_ID);

View file

@ -4,8 +4,8 @@ import { isReportableRunStepDuration } from 'librechat-data-provider';
import type { TranslationKeys } from '~/hooks';
import type { PtcTraceEntry } from '~/store';
import { cn, parseToolName, getRunStepDurationLabels } from '~/utils';
import { ptcTraceByToolCallId, ptcTraceKey } from '~/store';
import { useMessageContext } from '~/Providers/MessageContext';
import { ptcTraceByToolCallId, ptcTraceKey } from '~/store';
import { useMCPServerNames } from '~/hooks/MCP';
import { useLocalize } from '~/hooks';

View file

@ -14,8 +14,8 @@ import type {
SubagentTaskConfig,
} from '@librechat/agents';
import type { StructuredToolInterface } from '@librechat/agents/langchain/tools';
import type { ValidationIssue } from '@librechat/data-schemas';
import type { CodeEnvRef, PtcToolCallEvent } from 'librechat-data-provider';
import type { ValidationIssue } from '@librechat/data-schemas';
import type { SkillFileRecord, PrimeSkillFilesResult } from './skillFiles';
import type { CodeExecutionContext } from './execution';
import type { TextContentFragment } from '~/protection';