mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-10-24 03:09:26 +00:00
🥸 chore: Resolve Agents SDK Path Aliases That Masked Backend Types (#15160)
* 🐛 fix: Restore Agents SDK Type Resolution in Backend Type Checks * 🐛 fix: Preserve Typed Prompt Callback Assignability * 🐛 fix: Accept Agents Function Tool Calls in isImageVisionTool * 🐛 fix: Prove the Run Step Wire Contract at Compile Time
This commit is contained in:
parent
b6e3cf46d2
commit
6a7da61234
18 changed files with 241 additions and 142 deletions
|
|
@ -954,7 +954,7 @@ export default function useStepHandler({
|
|||
// Store tool call IDs if present
|
||||
if (runStep.stepDetails.type === StepTypes.TOOL_CALLS) {
|
||||
let updatedResponse = { ...response };
|
||||
(runStep.stepDetails.tool_calls as Agents.ToolCall[]).forEach((toolCall) => {
|
||||
((runStep.stepDetails.tool_calls ?? []) as Agents.ToolCall[]).forEach((toolCall) => {
|
||||
const toolCallId = toolCall.id ?? '';
|
||||
if ('id' in toolCall && toolCallId) {
|
||||
toolCallIdMap.current.set(runStep.id, toolCallId);
|
||||
|
|
|
|||
|
|
@ -139,7 +139,6 @@ liveDescribe('Graph subagent E2E (LibreChat)', () => {
|
|||
{
|
||||
configurable: { thread_id: runId },
|
||||
recursionLimit: 100,
|
||||
streamMode: 'values',
|
||||
version: 'v2',
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -212,7 +212,11 @@ async function runFullTurn({
|
|||
initialSummary,
|
||||
runId: `e2e-${Date.now()}`,
|
||||
signal: abortController.signal,
|
||||
customHandlers: buildHandlers(collectedUsage, aggregateContent, spies) as never,
|
||||
customHandlers: buildHandlers(
|
||||
collectedUsage,
|
||||
aggregateContent as (params: { event: string; data: unknown }) => void,
|
||||
spies,
|
||||
) as never,
|
||||
summarizationConfig,
|
||||
tokenCounter,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
phase: 'final_answer',
|
||||
},
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -112,7 +112,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
delta: {
|
||||
content: { type: ContentTypes.TEXT, text: 'A'.repeat(SUBSTANTIAL_TEXT_CHARS + 1) },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -185,13 +185,13 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: id, content_type: 'text', ...(phase && { phase }) },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
handlers?.[GraphEvents.ON_MESSAGE_DELTA]?.handle(
|
||||
GraphEvents.ON_MESSAGE_DELTA,
|
||||
{ id, delta: { content: { type: ContentTypes.TEXT, text } } },
|
||||
{ id, delta: { content: { type: ContentTypes.TEXT, text } } } as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -274,13 +274,16 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
handlers?.[GraphEvents.ON_MESSAGE_DELTA]?.handle(
|
||||
GraphEvents.ON_MESSAGE_DELTA,
|
||||
{ id: 'interleaved-text', delta: { content: { type: ContentTypes.TEXT, text: 'prefix' } } },
|
||||
{
|
||||
id: 'interleaved-text',
|
||||
delta: { content: { type: ContentTypes.TEXT, text: 'prefix' } },
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -291,7 +294,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
{
|
||||
id: 'interleaved-text',
|
||||
delta: { content: { type: ContentTypes.TEXT, text: 'x'.repeat(SUBSTANTIAL_TEXT_CHARS) } },
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -348,7 +351,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -360,7 +363,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'think' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -370,7 +373,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
{
|
||||
id: 'later-reasoning',
|
||||
delta: { content: { type: ContentTypes.THINK, think: 'Investigating the later tool.' } },
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -379,7 +382,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
{
|
||||
id: 'boundary-text',
|
||||
delta: { content: { type: ContentTypes.TEXT, text: substantialText('Boundary result.') } },
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -547,14 +550,14 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
const emitTextDelta = (id: string, text: string) =>
|
||||
handlers?.[GraphEvents.ON_MESSAGE_DELTA]?.handle(
|
||||
GraphEvents.ON_MESSAGE_DELTA,
|
||||
{ id, delta: { content: { type: ContentTypes.TEXT, text } } },
|
||||
{ id, delta: { content: { type: ContentTypes.TEXT, text } } } as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -572,7 +575,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text', phase: 'final_answer' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -626,7 +629,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text', phase: 'final_answer' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -678,7 +681,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text', phase: 'final_answer' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -736,7 +739,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'think' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -746,7 +749,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
{
|
||||
id: 'missing-tool-reasoning',
|
||||
delta: { content: { type: ContentTypes.THINK, think: repeatedReasoning } },
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -766,7 +769,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'think' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -776,7 +779,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
{
|
||||
id: 'current-reasoning',
|
||||
delta: { content: { type: ContentTypes.THINK, think: repeatedReasoning } },
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -789,7 +792,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text', phase: 'final_answer' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -826,7 +829,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text', phase: 'final_answer' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -858,7 +861,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'think' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -867,7 +870,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
{
|
||||
id: 'reasoning-step',
|
||||
delta: { content: { type: ContentTypes.THINK, think: 'Compared both auth paths.' } },
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -880,7 +883,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text', phase: 'commentary' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -907,7 +910,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text', phase: 'final_answer' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -948,7 +951,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text', phase: 'final_answer' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -985,7 +988,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'think' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -994,7 +997,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
{
|
||||
id: 'lane-reasoning',
|
||||
delta: { content: { type: ContentTypes.THINK, think: 'Checked the lane input.' } },
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -1009,7 +1012,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -1039,7 +1042,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -1083,7 +1086,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'think' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -1093,7 +1096,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
{
|
||||
id,
|
||||
delta: { content: { type: ContentTypes.THINK, think: text } },
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -1115,7 +1118,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text', phase: 'final_answer' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -1173,7 +1176,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text', phase: 'final_answer' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -1254,7 +1257,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'think' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -1266,7 +1269,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
delta: {
|
||||
content: { type: ContentTypes.THINK, think: 'Verified one more edge case.' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -1823,7 +1826,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -1874,7 +1877,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -1924,7 +1927,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -1979,7 +1982,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -2035,7 +2038,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -2090,7 +2093,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -2147,7 +2150,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -2216,7 +2219,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -2332,7 +2335,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -2408,7 +2411,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -2448,7 +2451,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'think' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -2485,13 +2488,13 @@ describe('createActivityPhaseWiring', () => {
|
|||
message_creation: { message_id: 'm', content_type: 'text', phase: 'final_answer' },
|
||||
},
|
||||
};
|
||||
handler?.handle(GraphEvents.ON_RUN_STEP, finalStep, undefined, undefined);
|
||||
handler?.handle(GraphEvents.ON_RUN_STEP, finalStep as never, undefined, undefined);
|
||||
await flushDetached();
|
||||
expect(generatePhase).not.toHaveBeenCalled();
|
||||
|
||||
handler?.handle(
|
||||
GraphEvents.ON_RUN_STEP,
|
||||
{ ...finalStep, id: 'root-final', groupId: undefined },
|
||||
{ ...finalStep, id: 'root-final', groupId: undefined } as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -2526,13 +2529,13 @@ describe('createActivityPhaseWiring', () => {
|
|||
message_creation: { message_id: 'm', content_type: 'text' },
|
||||
},
|
||||
};
|
||||
handler?.handle(GraphEvents.ON_RUN_STEP, textStep, undefined, undefined);
|
||||
handler?.handle(GraphEvents.ON_RUN_STEP, textStep as never, undefined, undefined);
|
||||
await flushDetached();
|
||||
expect(generatePhase).not.toHaveBeenCalled();
|
||||
|
||||
handler?.handle(
|
||||
GraphEvents.ON_RUN_STEP,
|
||||
{ ...textStep, id: 'root-text', groupId: undefined },
|
||||
{ ...textStep, id: 'root-text', groupId: undefined } as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -2579,7 +2582,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text', phase: 'commentary' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -2624,7 +2627,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -2639,7 +2642,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text', phase: 'commentary' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -2760,7 +2763,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -2778,7 +2781,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -2826,7 +2829,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -2880,7 +2883,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -2934,7 +2937,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text', phase: 'final_answer' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -2972,7 +2975,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text', phase: 'final_answer' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -3018,7 +3021,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -3027,7 +3030,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
{
|
||||
id: 'boundary',
|
||||
delta: { content: { type: ContentTypes.TEXT, text: substantialText('Boundary result.') } },
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -3123,7 +3126,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text', phase: 'final_answer' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -3132,7 +3135,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
{
|
||||
id: 'final-step',
|
||||
delta: { content: { type: ContentTypes.TEXT, text: 'Done.' } },
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -3194,7 +3197,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -3203,7 +3206,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
{
|
||||
id: 'early-text',
|
||||
delta: { content: { type: ContentTypes.TEXT, text: 'Context for the earlier work.' } },
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -3305,7 +3308,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -3319,7 +3322,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -3328,7 +3331,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
{
|
||||
id: 'parallel-text',
|
||||
delta: { content: { type: ContentTypes.TEXT, text: 'Context for the later work.' } },
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -3337,7 +3340,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
{
|
||||
id: 'boundary',
|
||||
delta: { content: { type: ContentTypes.TEXT, text: substantialText('Boundary result.') } },
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -3402,7 +3405,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -3412,7 +3415,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
{
|
||||
id: 'parallel-text',
|
||||
delta: { content: { type: ContentTypes.TEXT, text: 'Context for the later work.' } },
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -3421,7 +3424,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
{
|
||||
id: 'boundary',
|
||||
delta: { content: { type: ContentTypes.TEXT, text: substantialText('Boundary result.') } },
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -3484,7 +3487,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', content_type: 'text' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -3493,7 +3496,7 @@ describe('createActivityPhaseWiring', () => {
|
|||
{
|
||||
id: 'boundary',
|
||||
delta: { content: { type: ContentTypes.TEXT, text: substantialText('Boundary result.') } },
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -3528,7 +3531,7 @@ describe('createAssistantPhaseStampingHandlers', () => {
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { message_id: 'm', phase: 'commentary' },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -3537,7 +3540,7 @@ describe('createAssistantPhaseStampingHandlers', () => {
|
|||
{
|
||||
id: 'commentary-step',
|
||||
delta: { content: { type: ContentTypes.TEXT, text: 'I will compare both paths.' } },
|
||||
},
|
||||
} as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -415,13 +415,12 @@ export function createAssistantPhaseStampingHandlers(
|
|||
(part as { type?: string } | null)?.type === ContentTypes.TEXT
|
||||
? { ...(part as Record<string, unknown>), phase }
|
||||
: part;
|
||||
const forwarded = {
|
||||
...(data as Record<string, unknown>),
|
||||
const forwarded = Object.assign({}, data, {
|
||||
delta: {
|
||||
...delta,
|
||||
content: Array.isArray(raw) ? raw.map(stamp) : stamp(raw),
|
||||
},
|
||||
};
|
||||
});
|
||||
return messageHandler.handle(event, forwarded, metadata, graph);
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -324,7 +324,7 @@ type ResumableRunStep = {
|
|||
|
||||
export function normalizeResumeRunStepIndices<T extends ResumableRunStep>(
|
||||
runSteps: readonly T[],
|
||||
seedContent: readonly { type?: string; tool_call?: { id?: string } }[] = [],
|
||||
seedContent: readonly ({ type?: string; tool_call?: { id?: string } } | undefined)[] = [],
|
||||
): T[] {
|
||||
const toolCallIndices = new Map<string, number>();
|
||||
seedContent.forEach((part, index) => {
|
||||
|
|
@ -361,7 +361,7 @@ export function hydrateResumeRunSteps(
|
|||
runSteps: readonly RunStep[],
|
||||
stepMap: Map<string, RunStep | undefined> | undefined,
|
||||
graph: { toolCallStepIds?: Map<string, string> } | null | undefined,
|
||||
seedContent: readonly { type?: string; tool_call?: { id?: string } }[] = [],
|
||||
seedContent: readonly ({ type?: string; tool_call?: { id?: string } } | undefined)[] = [],
|
||||
): void {
|
||||
for (const runStep of normalizeResumeRunStepIndices(runSteps, seedContent)) {
|
||||
if (!runStep?.id) {
|
||||
|
|
|
|||
|
|
@ -91,21 +91,21 @@ function createHarness(
|
|||
type: StepTypes.MESSAGE_CREATION,
|
||||
message_creation: { content_type: ContentTypes.THINK },
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
metadata,
|
||||
);
|
||||
};
|
||||
const append = async (text: string, id = 'reasoning-1') => {
|
||||
await wrapped[GraphEvents.ON_REASONING_DELTA].handle(
|
||||
GraphEvents.ON_REASONING_DELTA,
|
||||
reasoningDelta(id, text),
|
||||
reasoningDelta(id, text) as never,
|
||||
);
|
||||
};
|
||||
const close = async (id = 'reasoning-1') => {
|
||||
await wrapped[GraphEvents.ON_RUN_STEP_CLOSED].handle(GraphEvents.ON_RUN_STEP_CLOSED, {
|
||||
id,
|
||||
status: 'completed',
|
||||
});
|
||||
} as never);
|
||||
};
|
||||
const settle = async () => {
|
||||
for (let i = 0; i < 5; i += 1) {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { randomUUID } from 'crypto';
|
||||
import { logger } from '@librechat/data-schemas';
|
||||
import { ensureHandler } from '@langchain/core/callbacks/manager';
|
||||
import { Run, Providers, Constants, HookRegistry } from '@librechat/agents';
|
||||
|
|
@ -1883,6 +1884,7 @@ export async function createRun({
|
|||
}
|
||||
|
||||
const streamLimits = resolveStreamLimits(agentsEndpointConfig);
|
||||
const resolvedRunId = runId ?? randomUUID();
|
||||
|
||||
/**
|
||||
* Built as a variable (not an inline literal) so the extra
|
||||
|
|
@ -1892,7 +1894,7 @@ export async function createRun({
|
|||
* the field at the call site once the dependency is bumped.
|
||||
*/
|
||||
const runConfig = {
|
||||
runId,
|
||||
runId: resolvedRunId,
|
||||
graphConfig,
|
||||
tokenCounter,
|
||||
customHandlers,
|
||||
|
|
@ -1959,7 +1961,7 @@ export async function createRun({
|
|||
// tracing is enabled. Requires @librechat/agents >= 3.2.21.
|
||||
langfuse: buildLangfuseConfig({
|
||||
appConfig,
|
||||
runId,
|
||||
runId: resolvedRunId,
|
||||
tenantId: tenantId ?? user?.tenantId,
|
||||
centralTraceExportEnabled,
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -27,11 +27,26 @@ describe('createSteerIndexOffsetHandlers', () => {
|
|||
);
|
||||
|
||||
const handler = wrapped![GraphEvents.ON_RUN_STEP];
|
||||
handler.handle(GraphEvents.ON_RUN_STEP, { id: 'step-1', index: 0 }, undefined, undefined);
|
||||
handler.handle(
|
||||
GraphEvents.ON_RUN_STEP,
|
||||
{ id: 'step-1', index: 0 } as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
state.offset = 1;
|
||||
handler.handle(GraphEvents.ON_RUN_STEP, { id: 'step-2', index: 1 }, undefined, undefined);
|
||||
handler.handle(
|
||||
GraphEvents.ON_RUN_STEP,
|
||||
{ id: 'step-2', index: 1 } as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
state.offset = 2;
|
||||
handler.handle(GraphEvents.ON_RUN_STEP, { id: 'step-3', index: 2 }, undefined, undefined);
|
||||
handler.handle(
|
||||
GraphEvents.ON_RUN_STEP,
|
||||
{ id: 'step-3', index: 2 } as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
||||
expect(calls.map((c) => (c.data as { index: number }).index)).toEqual([0, 2, 4]);
|
||||
});
|
||||
|
|
@ -47,14 +62,14 @@ describe('createSteerIndexOffsetHandlers', () => {
|
|||
const handler = wrapped![GraphEvents.ON_AGENT_UPDATE];
|
||||
handler.handle(
|
||||
GraphEvents.ON_AGENT_UPDATE,
|
||||
{ agent_update: { index: 3, runId: 'run-1' } },
|
||||
{ agent_update: { index: 3, runId: 'run-1' } } as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
state.offset = 2;
|
||||
handler.handle(
|
||||
GraphEvents.ON_AGENT_UPDATE,
|
||||
{ agent_update: { index: 4, runId: 'run-1' } },
|
||||
{ agent_update: { index: 4, runId: 'run-1' } } as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -79,7 +94,7 @@ describe('createSteerIndexOffsetHandlers', () => {
|
|||
expect(wrapped![GraphEvents.ON_MESSAGE_DELTA]).toBe(passthrough);
|
||||
wrapped![GraphEvents.ON_RUN_STEP].handle(
|
||||
GraphEvents.ON_RUN_STEP,
|
||||
{ id: 'step-x' },
|
||||
{ id: 'step-x' } as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
|
@ -99,9 +114,19 @@ describe('createSteerIndexOffsetHandlers', () => {
|
|||
);
|
||||
|
||||
const handler = wrapped![GraphEvents.ON_RUN_STEP];
|
||||
handler.handle(GraphEvents.ON_RUN_STEP, { id: 'step-1', index: 0 }, undefined, undefined);
|
||||
handler.handle(
|
||||
GraphEvents.ON_RUN_STEP,
|
||||
{ id: 'step-1', index: 0 } as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
state.offset = 1;
|
||||
handler.handle(GraphEvents.ON_RUN_STEP, { id: 'step-2', index: 1 }, undefined, undefined);
|
||||
handler.handle(
|
||||
GraphEvents.ON_RUN_STEP,
|
||||
{ id: 'step-2', index: 1 } as never,
|
||||
undefined,
|
||||
undefined,
|
||||
);
|
||||
|
||||
// seed offset (2) applies inside; steer offset applies on top
|
||||
expect(calls.map((c) => (c.data as { index: number }).index)).toEqual([2, 4]);
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ describe('createSteerDrainHook', () => {
|
|||
},
|
||||
});
|
||||
|
||||
const output: SteerDrainOutput = await hook(batchInput(), abortSignal);
|
||||
const output = (await hook(batchInput(), abortSignal)) as SteerDrainOutput;
|
||||
expect(applied).toEqual(['first', 'second']);
|
||||
expect(output.injectedMessages).toEqual([
|
||||
{ role: 'user', content: 'first', source: 'steer' },
|
||||
|
|
@ -156,7 +156,7 @@ describe('createSteerDrainHook', () => {
|
|||
},
|
||||
});
|
||||
|
||||
const output: SteerDrainOutput = await hook(batchInput(), abortSignal);
|
||||
const output = (await hook(batchInput(), abortSignal)) as SteerDrainOutput;
|
||||
expect(output).toEqual({});
|
||||
expect((await GenerationJobManager.steering.peek(streamId)).map((item) => item.text)).toEqual([
|
||||
'survives',
|
||||
|
|
@ -194,7 +194,7 @@ describe('createSteerDrainHook', () => {
|
|||
buildMedia,
|
||||
});
|
||||
|
||||
const output: SteerDrainOutput = await hook(batchInput(), abortSignal);
|
||||
const output = (await hook(batchInput(), abortSignal)) as SteerDrainOutput;
|
||||
// buildMedia is consulted only for items that carry files.
|
||||
expect(buildMedia).toHaveBeenCalledTimes(1);
|
||||
expect(calls).toEqual(['apply:s1', 'apply:s2', 'media:s1']);
|
||||
|
|
@ -227,7 +227,7 @@ describe('createSteerDrainHook', () => {
|
|||
},
|
||||
});
|
||||
|
||||
const output: SteerDrainOutput = await hook(batchInput(), abortSignal);
|
||||
const output = (await hook(batchInput(), abortSignal)) as SteerDrainOutput;
|
||||
expect(appliedBeforeEncode).toBe(true);
|
||||
expect(output.injectedMessages).toEqual([
|
||||
{ role: 'user', content: 'must land first', source: 'steer' },
|
||||
|
|
@ -251,7 +251,7 @@ describe('createSteerDrainHook', () => {
|
|||
},
|
||||
});
|
||||
|
||||
const output: SteerDrainOutput = await hook(batchInput(), abortSignal);
|
||||
const output = (await hook(batchInput(), abortSignal)) as SteerDrainOutput;
|
||||
expect(output.injectedMessages).toEqual([
|
||||
{ role: 'user', content: 'words survive', source: 'steer' },
|
||||
]);
|
||||
|
|
@ -300,7 +300,7 @@ describe('createSteerPreemptBoundaryHook', () => {
|
|||
},
|
||||
});
|
||||
|
||||
const output: SteerDrainOutput = await hook(boundaryInput(), abortSignal);
|
||||
const output = (await hook(boundaryInput(), abortSignal)) as SteerDrainOutput;
|
||||
expect(applied).toEqual(['first', 'second']);
|
||||
expect(output.injectedMessages).toEqual([
|
||||
{ role: 'user', content: 'first', source: 'steer' },
|
||||
|
|
@ -436,7 +436,7 @@ describe('createSteerPreemptBoundaryHook', () => {
|
|||
jobCreatedAt: job.createdAt,
|
||||
applySteer: jest.fn(),
|
||||
});
|
||||
const output: SteerDrainOutput = await hook(boundaryInput(), abortSignal);
|
||||
const output = (await hook(boundaryInput(), abortSignal)) as SteerDrainOutput;
|
||||
|
||||
expect(output.injectedMessages).toHaveLength(1);
|
||||
/** Both the drained id and the stale snapshot id are spent. */
|
||||
|
|
@ -485,7 +485,7 @@ describe('createSteerPreemptBoundaryHook', () => {
|
|||
},
|
||||
});
|
||||
|
||||
const output: SteerDrainOutput = await hook(boundaryInput(), abortSignal);
|
||||
const output = (await hook(boundaryInput(), abortSignal)) as SteerDrainOutput;
|
||||
expect(output).toEqual({});
|
||||
expect((await GenerationJobManager.steering.peek(streamId)).map((item) => item.text)).toEqual([
|
||||
'still injected',
|
||||
|
|
|
|||
|
|
@ -1146,7 +1146,7 @@ export class SubagentThreadTaskStore extends InMemorySubagentTaskStore {
|
|||
const snapshot = this.get(scopeId, taskId);
|
||||
const lockKey = snapshot?.threadId == null ? undefined : `${scopeId}\u0000${snapshot.threadId}`;
|
||||
const lease = lockKey == null ? undefined : this.activeThreads.get(lockKey);
|
||||
if (lease?.taskId === taskId && lease.settling) {
|
||||
if (snapshot != null && lease?.taskId === taskId && lease.settling) {
|
||||
return { status: 'not_running', task: snapshot };
|
||||
}
|
||||
const result = super.control(scopeId, taskId, command);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import {
|
|||
PAUSE_PERSISTENCE_TIMEOUT_ERROR,
|
||||
PAUSE_PERSISTENCE_TIMEOUT_MS,
|
||||
isPendingActionStale,
|
||||
toWireRunSteps,
|
||||
} from '~/stream/interfaces/IJobStore';
|
||||
import {
|
||||
isRecoveredSteerPayload,
|
||||
|
|
@ -1466,7 +1467,7 @@ export class InMemoryJobStore implements IJobStoreV2 {
|
|||
|
||||
// Dereference WeakRef - may return undefined if GC'd
|
||||
const graph = state.graphRef.deref();
|
||||
return graph?.contentData ?? [];
|
||||
return toWireRunSteps(graph?.contentData ?? []);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import {
|
|||
PAUSE_PERSISTENCE_TIMEOUT_ERROR,
|
||||
PAUSE_PERSISTENCE_TIMEOUT_MS,
|
||||
isPendingActionStale,
|
||||
toWireRunSteps,
|
||||
} from '~/stream/interfaces/IJobStore';
|
||||
import {
|
||||
MAX_COALESCED_BYTES,
|
||||
|
|
@ -3661,7 +3662,7 @@ export class RedisJobStore implements IJobStoreV2 {
|
|||
g.getRunSteps(),
|
||||
);
|
||||
if (localSteps && localSteps.length > 0) {
|
||||
return localSteps;
|
||||
return toWireRunSteps(localSteps);
|
||||
}
|
||||
}
|
||||
// Note: Don't delete from cache here - graph may still be valid
|
||||
|
|
|
|||
|
|
@ -4,12 +4,63 @@ import type {
|
|||
TPendingSteer,
|
||||
UserSubmittedMessageFieldPath,
|
||||
} from 'librechat-data-provider';
|
||||
import type { StandardGraph } from '@librechat/agents';
|
||||
import type { RunStep, StandardGraph } from '@librechat/agents';
|
||||
import type { ActivityPhaseSnapshot } from '~/agents/activityPhases/runtime';
|
||||
import type { ResolvedAskUserQuestion } from '~/agents/hitl/resume';
|
||||
import type { RecoveredSteerPayload } from '../SteerRecovery';
|
||||
import type { MCPRuntimeRequestBody } from '~/mcp/types';
|
||||
|
||||
/**
|
||||
* Rewrites string-enum members to their literal values, recursively. The SDK and
|
||||
* data-provider declare nominally distinct enums (`ContentTypes`, `StepTypes`, ...)
|
||||
* with identical string values; erasing that nominality is what lets the two run-step
|
||||
* contracts be compared structurally.
|
||||
*/
|
||||
type WireShape<T> = T extends string
|
||||
? `${T}`
|
||||
: T extends readonly (infer U)[]
|
||||
? WireShape<U>[]
|
||||
: T extends object
|
||||
? { [K in keyof T]: WireShape<T[K]> }
|
||||
: T;
|
||||
|
||||
type StaticAssert<T extends true> = T;
|
||||
|
||||
/**
|
||||
* Compile-time proof that the SDK run step and the wire contract (`Agents.RunStep`)
|
||||
* agree structurally once enum nominality is erased: any added, removed, retyped, or
|
||||
* newly optional SDK field fails these assertions, so drift cannot silently enter
|
||||
* resume state through `toWireRunSteps`.
|
||||
*
|
||||
* `summary.content` is the one deliberately unchecked field: the SDK reuses its full
|
||||
* `MessageContentComplex` union there, while the wire contract narrows it to the plain
|
||||
* text blocks summarization actually emits. That narrowing is the single semantic
|
||||
* judgment this conversion vouches for.
|
||||
*/
|
||||
type _WireRunStepContractHolds = StaticAssert<
|
||||
WireShape<Omit<RunStep, 'summary'>> extends WireShape<Omit<Agents.RunStep, 'summary'>>
|
||||
? true
|
||||
: false
|
||||
>;
|
||||
|
||||
type _WireSummaryContractHolds = StaticAssert<
|
||||
WireShape<Omit<NonNullable<RunStep['summary']>, 'content'>> extends WireShape<
|
||||
Omit<NonNullable<Agents.RunStep['summary']>, 'content'>
|
||||
>
|
||||
? true
|
||||
: false
|
||||
>;
|
||||
|
||||
/**
|
||||
* Run steps living on the SDK graph serialize to exactly the wire shape
|
||||
* `Agents.RunStep` describes; the assertion is safe because
|
||||
* `_WireRunStepContractHolds` above proves the contracts identical modulo the
|
||||
* nominally-split enums, which share their string values at runtime.
|
||||
*/
|
||||
export function toWireRunSteps(steps: readonly RunStep[]): Agents.RunStep[] {
|
||||
return steps as Agents.RunStep[];
|
||||
}
|
||||
|
||||
/**
|
||||
* A pause owner has this long to durably persist the interrupted turn before
|
||||
* the barrier is considered abandoned. An abandoned barrier must fail closed:
|
||||
|
|
|
|||
16
packages/api/src/types/agents.d.ts
vendored
16
packages/api/src/types/agents.d.ts
vendored
|
|
@ -1,16 +0,0 @@
|
|||
/**
|
||||
* `@librechat/agents` publishes its declaration files with its internal `@/*` path aliases
|
||||
* unrewritten, so a consumer cannot resolve them. `types/llm.d.ts` imports `Providers` that
|
||||
* way, which leaves `ProviderOptionsMap`'s computed keys unresolved and collapses
|
||||
* `keyof ProviderOptionsMap` to `number`. Until v3.6.16 that only degraded `LLMConfig`
|
||||
* silently; v3.6.16 made `SharedLLMConfig` generic over that key union, so `provider` became
|
||||
* `number | RuntimeProviderName` and no real provider was assignable to it.
|
||||
*
|
||||
* Declaring the one alias `llm.d.ts` needs restores the enum, and with it the provider key
|
||||
* union. Remove this once the SDK ships declarations with its aliases resolved — note that
|
||||
* mapping every `@/*` alias instead unmasks a large backlog of latent errors elsewhere in
|
||||
* this package, so widening it is a separate cleanup rather than a drop-in improvement.
|
||||
*/
|
||||
declare module '@/common' {
|
||||
export { Providers } from '@librechat/agents';
|
||||
}
|
||||
|
|
@ -19,7 +19,11 @@
|
|||
"noEmit": true,
|
||||
"sourceMap": true,
|
||||
"paths": {
|
||||
"~/*": ["./src/*"]
|
||||
"~/*": ["./src/*"],
|
||||
// @librechat/agents ships declaration files that import its internal "@/" alias, which
|
||||
// package exports cannot map; resolve them into its published types until the SDK
|
||||
// rewrites the aliases at build time.
|
||||
"@/*": ["../../node_modules/@librechat/agents/dist/types/*"]
|
||||
}
|
||||
},
|
||||
"ts-node": {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,5 @@
|
|||
import { z } from 'zod';
|
||||
import type {
|
||||
TMessageContentParts,
|
||||
AgentSubagentGraph,
|
||||
FunctionToolCall,
|
||||
FunctionTool,
|
||||
} from './types/assistants';
|
||||
import type { TMessageContentParts, AgentSubagentGraph, FunctionTool } from './types/assistants';
|
||||
import type { SearchResultData } from './types/web';
|
||||
import type { TFile } from './types/files';
|
||||
import { userSubmittedMessageFieldPathSchema } from './filters';
|
||||
|
|
@ -391,7 +386,9 @@ export const ImageVisionTool: FunctionTool = {
|
|||
},
|
||||
};
|
||||
|
||||
export const isImageVisionTool = (tool: FunctionTool | FunctionToolCall) =>
|
||||
/** Structural on purpose: accepts assistants tools/tool calls and agents function tool
|
||||
* calls alike — the check only ever reads `type` and `function.name`. */
|
||||
export const isImageVisionTool = (tool: { type?: string; function?: { name?: string } }) =>
|
||||
tool.type === 'function' && tool.function?.name === ImageVisionTool.function?.name;
|
||||
|
||||
export const openAISettings = {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* eslint-disable @typescript-eslint/no-namespace */
|
||||
import type { TTokenUsageEvent, TContextUsageEvent, TPendingSteer } from './runs';
|
||||
import type { FunctionToolCall, SummaryContentPart } from './assistants';
|
||||
import type { TAttachment, TPlugin } from 'src/schemas';
|
||||
import type { SummaryContentPart } from './assistants';
|
||||
import { StepTypes, ContentTypes, ToolCallTypes } from './runs';
|
||||
|
||||
export namespace Agents {
|
||||
|
|
@ -67,8 +67,9 @@ export namespace Agents {
|
|||
* A call to a tool.
|
||||
*/
|
||||
export type ToolCall = {
|
||||
/** Type ("tool_call") according to Assistants Tool Call Structure */
|
||||
type: ToolCallTypes.TOOL_CALL;
|
||||
/** Type ("tool_call") according to Assistants Tool Call Structure; optional literal
|
||||
* form included to mirror langchain's ToolCall, whose `type` is optional. */
|
||||
type?: ToolCallTypes.TOOL_CALL | 'tool_call';
|
||||
/** The name of the tool to be called */
|
||||
name: string;
|
||||
|
||||
|
|
@ -203,7 +204,8 @@ export namespace Agents {
|
|||
groupId?: number; // #new
|
||||
stepDetails: StepDetails;
|
||||
summary?: SummaryContentPart;
|
||||
usage: null | object;
|
||||
/** Optional to mirror the agents SDK, which omits usage until a step reports it. */
|
||||
usage?: null | object;
|
||||
/** Epoch ms the step was opened. Emitted by `@librechat/agents` >= 3.4.6. */
|
||||
created_at?: number;
|
||||
status?: RunStepStatus;
|
||||
|
|
@ -324,7 +326,7 @@ export namespace Agents {
|
|||
};
|
||||
export type ToolCallsDetails = {
|
||||
type: StepTypes.TOOL_CALLS;
|
||||
tool_calls: AgentToolCall[];
|
||||
tool_calls?: AgentToolCall[];
|
||||
};
|
||||
export type ToolCallDelta = {
|
||||
type: StepTypes.TOOL_CALLS | string;
|
||||
|
|
@ -338,7 +340,22 @@ export namespace Agents {
|
|||
description?: string;
|
||||
};
|
||||
};
|
||||
export type AgentToolCall = FunctionToolCall | ToolCall;
|
||||
/**
|
||||
* Mirrors the agents SDK's function tool-call variant: `arguments` may arrive as a
|
||||
* parsed object, and `output` is attached by LibreChat aggregation only once available
|
||||
* (the legacy assistants `FunctionToolCall` requires both as string/present).
|
||||
*/
|
||||
export type AgentFunctionToolCall = {
|
||||
id: string;
|
||||
type: 'function';
|
||||
function: {
|
||||
name: string;
|
||||
arguments: string | object;
|
||||
output?: string | null;
|
||||
};
|
||||
};
|
||||
|
||||
export type AgentToolCall = AgentFunctionToolCall | ToolCall;
|
||||
|
||||
/**
|
||||
* Human-in-the-loop interrupt categories. The discriminator on
|
||||
|
|
@ -734,8 +751,20 @@ export type GraphEdge = {
|
|||
*
|
||||
* For handoff edges: Description for the input parameter that the handoff tool accepts,
|
||||
* allowing the supervisor to pass specific instructions/context to the transferred agent.
|
||||
*
|
||||
* The callback receives a minimal structural view of the run's messages (data-provider
|
||||
* cannot depend on langchain's BaseMessage): every langchain message satisfies
|
||||
* `{ content: unknown }`, and callbacks typed against richer structural message shapes
|
||||
* remain assignable. The promise branch mirrors the agents SDK signature exactly —
|
||||
* widening it (e.g. to `Promise<string | undefined>`) would break assignability of
|
||||
* stored edges into the SDK's `GraphEdge`.
|
||||
*/
|
||||
prompt?: string | ((messages: BaseMessage[], runStartIndex: number) => string | undefined);
|
||||
prompt?:
|
||||
| string
|
||||
| ((
|
||||
messages: { content: unknown }[],
|
||||
runStartIndex: number,
|
||||
) => string | Promise<string> | undefined);
|
||||
/**
|
||||
* When true, excludes messages from startIndex when adding prompt.
|
||||
* Automatically set to true when {results} variable is used in prompt.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue