@librechat/agents 3.3.8 → 3.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/graphs/Graph.cjs +47 -13
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/graphs/MultiAgentGraph.cjs +35 -2
- package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
- package/dist/cjs/hitl/askUserQuestion.cjs +3 -2
- package/dist/cjs/hitl/askUserQuestion.cjs.map +1 -1
- package/dist/cjs/instrumentation.cjs +18 -48
- package/dist/cjs/instrumentation.cjs.map +1 -1
- package/dist/cjs/langfuse.cjs +174 -29
- package/dist/cjs/langfuse.cjs.map +1 -1
- package/dist/cjs/langfuseConfig.cjs +12 -0
- package/dist/cjs/langfuseConfig.cjs.map +1 -1
- package/dist/cjs/langfuseRuntimeContext.cjs +23 -2
- package/dist/cjs/langfuseRuntimeContext.cjs.map +1 -1
- package/dist/cjs/langfuseRuntimeScope.cjs +39 -8
- package/dist/cjs/langfuseRuntimeScope.cjs.map +1 -1
- package/dist/cjs/langfuseSpanRegistry.cjs +95 -0
- package/dist/cjs/langfuseSpanRegistry.cjs.map +1 -0
- package/dist/cjs/langfuseTraceShaping.cjs +121 -4
- package/dist/cjs/langfuseTraceShaping.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +39 -15
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/utils/message_inputs.cjs +25 -5
- package/dist/cjs/llm/bedrock/utils/message_inputs.cjs.map +1 -1
- package/dist/cjs/llm/init.cjs +3 -3
- package/dist/cjs/llm/invoke.cjs +5 -5
- package/dist/cjs/llm/openai/index.cjs +1 -1
- package/dist/cjs/main.cjs +10 -10
- package/dist/cjs/messages/prune.cjs +13 -1
- package/dist/cjs/messages/prune.cjs.map +1 -1
- package/dist/cjs/prompts/activityLabel.cjs +24 -12
- package/dist/cjs/prompts/activityLabel.cjs.map +1 -1
- package/dist/cjs/run.cjs +47 -22
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/session/messageSerialization.cjs +6 -0
- package/dist/cjs/session/messageSerialization.cjs.map +1 -1
- package/dist/cjs/stream.cjs +21 -10
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/summarization/node.cjs +5 -0
- package/dist/cjs/summarization/node.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +253 -24
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/handlers.cjs +1 -1
- package/dist/cjs/tools/search/tool.cjs +1 -1
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs +1 -1
- package/dist/cjs/utils/index.cjs +2 -2
- package/dist/esm/graphs/Graph.mjs +48 -14
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/graphs/MultiAgentGraph.mjs +35 -2
- package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
- package/dist/esm/hitl/askUserQuestion.mjs +3 -2
- package/dist/esm/hitl/askUserQuestion.mjs.map +1 -1
- package/dist/esm/instrumentation.mjs +18 -48
- package/dist/esm/instrumentation.mjs.map +1 -1
- package/dist/esm/langfuse.mjs +176 -28
- package/dist/esm/langfuse.mjs.map +1 -1
- package/dist/esm/langfuseConfig.mjs +10 -1
- package/dist/esm/langfuseConfig.mjs.map +1 -1
- package/dist/esm/langfuseRuntimeContext.mjs +21 -3
- package/dist/esm/langfuseRuntimeContext.mjs.map +1 -1
- package/dist/esm/langfuseRuntimeScope.mjs +39 -10
- package/dist/esm/langfuseRuntimeScope.mjs.map +1 -1
- package/dist/esm/langfuseSpanRegistry.mjs +91 -0
- package/dist/esm/langfuseSpanRegistry.mjs.map +1 -0
- package/dist/esm/langfuseTraceShaping.mjs +121 -4
- package/dist/esm/langfuseTraceShaping.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs +39 -15
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
- package/dist/esm/llm/bedrock/utils/message_inputs.mjs +25 -5
- package/dist/esm/llm/bedrock/utils/message_inputs.mjs.map +1 -1
- package/dist/esm/llm/init.mjs +2 -2
- package/dist/esm/llm/invoke.mjs +5 -5
- package/dist/esm/llm/openai/index.mjs +1 -1
- package/dist/esm/main.mjs +8 -8
- package/dist/esm/messages/prune.mjs +13 -1
- package/dist/esm/messages/prune.mjs.map +1 -1
- package/dist/esm/prompts/activityLabel.mjs +24 -12
- package/dist/esm/prompts/activityLabel.mjs.map +1 -1
- package/dist/esm/run.mjs +47 -22
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/session/messageSerialization.mjs +6 -0
- package/dist/esm/session/messageSerialization.mjs.map +1 -1
- package/dist/esm/stream.mjs +21 -10
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/summarization/node.mjs +5 -0
- package/dist/esm/summarization/node.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +254 -25
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/handlers.mjs +1 -1
- package/dist/esm/tools/search/tool.mjs +1 -1
- package/dist/esm/tools/subagent/SubagentExecutor.mjs +1 -1
- package/dist/esm/utils/index.mjs +2 -2
- package/dist/types/graphs/Graph.d.ts +19 -0
- package/dist/types/hitl/askUserQuestion.d.ts +11 -1
- package/dist/types/langfuse.d.ts +16 -8
- package/dist/types/langfuseConfig.d.ts +6 -0
- package/dist/types/langfuseRuntimeContext.d.ts +27 -1
- package/dist/types/langfuseRuntimeScope.d.ts +17 -2
- package/dist/types/langfuseSpanRegistry.d.ts +17 -0
- package/dist/types/langfuseTraceShaping.d.ts +2 -1
- package/dist/types/llm/anthropic/utils/message_inputs.d.ts +1 -0
- package/dist/types/session/types.d.ts +1 -0
- package/dist/types/tools/ToolNode.d.ts +7 -1
- package/dist/types/types/hitl.d.ts +8 -0
- package/dist/types/types/tools.d.ts +30 -0
- package/package.json +7 -4
- package/src/__tests__/stream.eagerArgsDivergence.test.ts +753 -0
- package/src/graphs/Graph.ts +69 -20
- package/src/graphs/MultiAgentGraph.ts +56 -2
- package/src/graphs/__tests__/composition.smoke.test.ts +4 -0
- package/src/hitl/askUserQuestion.ts +14 -1
- package/src/instrumentation.ts +35 -77
- package/src/langfuse.ts +320 -43
- package/src/langfuseConfig.ts +24 -0
- package/src/langfuseRuntimeContext.ts +43 -1
- package/src/langfuseRuntimeScope.ts +94 -21
- package/src/langfuseSpanRegistry.ts +131 -0
- package/src/langfuseTraceShaping.ts +194 -7
- package/src/llm/anthropic/utils/message_inputs.ts +70 -19
- package/src/llm/anthropic/utils/streaming-tool-input.test.ts +186 -11
- package/src/llm/bedrock/utils/message_inputs.test.ts +120 -4
- package/src/llm/bedrock/utils/message_inputs.ts +32 -7
- package/src/messages/prune.ts +12 -1
- package/src/prompts/activityLabel.ts +23 -6
- package/src/run.ts +76 -45
- package/src/scripts/activity-labels/captured.json +56 -0
- package/src/scripts/activity-labels/checks.cjs +205 -0
- package/src/scripts/activity-labels/corpus.cjs +473 -0
- package/src/scripts/activity-labels/report.cjs +203 -0
- package/src/scripts/activity-labels/rescore.cjs +102 -0
- package/src/scripts/activity-labels/run.ts +705 -0
- package/src/scripts/activity-labels/variants.ts +71 -0
- package/src/session/messageSerialization.ts +12 -1
- package/src/session/types.ts +1 -0
- package/src/specs/activity-label-prompt.test.ts +26 -10
- package/src/specs/agent-handoffs.test.ts +306 -0
- package/src/specs/langfuse-callbacks.test.ts +456 -0
- package/src/specs/langfuse-routing.integration.test.ts +138 -1
- package/src/specs/langfuse-span-registry.test.ts +70 -0
- package/src/specs/langfuse-trace-shaping.test.ts +294 -0
- package/src/specs/prune.test.ts +38 -1
- package/src/stream.ts +70 -6
- package/src/summarization/node.ts +5 -0
- package/src/tools/ToolNode.ts +400 -9
- package/src/tools/__tests__/ToolNode.invalidToolCalls.test.ts +757 -0
- package/src/tools/__tests__/hitl.test.ts +58 -0
- package/src/types/hitl.ts +8 -0
- package/src/types/tools.ts +35 -1
|
@@ -35,6 +35,7 @@ import type * as t from '@/types';
|
|
|
35
35
|
import { Providers as providers, GraphEvents } from '@/common';
|
|
36
36
|
import * as events from '@/utils/events';
|
|
37
37
|
import { HookRegistry, createToolPolicyHook } from '@/hooks';
|
|
38
|
+
import { askUserQuestion } from '@/hitl';
|
|
38
39
|
import { ToolNode } from '../ToolNode';
|
|
39
40
|
|
|
40
41
|
async function flushAsyncWork(): Promise<void> {
|
|
@@ -4354,6 +4355,63 @@ describe('AskUserQuestion — interrupt + resume', () => {
|
|
|
4354
4355
|
expect(String(toolMessage!.content)).toBe('staging');
|
|
4355
4356
|
});
|
|
4356
4357
|
|
|
4358
|
+
it('askUserQuestion surfaces the calling tool_call_id on the interrupt payload when the body supplies it', async () => {
|
|
4359
|
+
/**
|
|
4360
|
+
* LangChain stamps the full ToolCall onto the config a `tool(fn, …)`
|
|
4361
|
+
* body receives, so the body can attribute its interrupt to the exact
|
|
4362
|
+
* call. Hosts use `payload.tool_call_id` to stamp the question/answer
|
|
4363
|
+
* onto the right content part when a model emits several ask calls in
|
|
4364
|
+
* one turn — positional guessing mislabels the cards.
|
|
4365
|
+
*/
|
|
4366
|
+
const askTool = tool(
|
|
4367
|
+
async (input: { question: string }, config) => {
|
|
4368
|
+
const resolution = askUserQuestion(input, {
|
|
4369
|
+
toolCallId: config.toolCall?.id,
|
|
4370
|
+
});
|
|
4371
|
+
return resolution.answer;
|
|
4372
|
+
},
|
|
4373
|
+
{
|
|
4374
|
+
name: 'ask_user_question',
|
|
4375
|
+
description: 'Ask the user a clarifying question.',
|
|
4376
|
+
schema: z.object({ question: z.string() }),
|
|
4377
|
+
}
|
|
4378
|
+
) as unknown as StructuredToolInterface;
|
|
4379
|
+
|
|
4380
|
+
const node = new ToolNode({ tools: [askTool] });
|
|
4381
|
+
const graph = buildHITLGraph(node, [
|
|
4382
|
+
{
|
|
4383
|
+
id: 'call_ask_id_1',
|
|
4384
|
+
name: 'ask_user_question',
|
|
4385
|
+
args: { question: 'Which region?' },
|
|
4386
|
+
},
|
|
4387
|
+
]);
|
|
4388
|
+
const config = { configurable: { thread_id: 'thread-ask-call-id' } };
|
|
4389
|
+
|
|
4390
|
+
const interrupted = await graph.invoke({ messages: [] }, config);
|
|
4391
|
+
if (!isInterrupted<t.HumanInterruptPayload>(interrupted)) {
|
|
4392
|
+
throw new Error('expected interrupt');
|
|
4393
|
+
}
|
|
4394
|
+
const payload = interrupted.__interrupt__[0].value!;
|
|
4395
|
+
if (payload.type !== 'ask_user_question') {
|
|
4396
|
+
throw new Error('expected ask_user_question payload');
|
|
4397
|
+
}
|
|
4398
|
+
expect(payload.tool_call_id).toBe('call_ask_id_1');
|
|
4399
|
+
expect(payload.question.question).toBe('Which region?');
|
|
4400
|
+
|
|
4401
|
+
const resumed = (await resumeGraph(
|
|
4402
|
+
graph,
|
|
4403
|
+
interrupted,
|
|
4404
|
+
{ answer: 'us-east' } satisfies t.AskUserQuestionResolution,
|
|
4405
|
+
config
|
|
4406
|
+
)) as MessagesUpdate;
|
|
4407
|
+
const toolMessage = resumed.messages.find(
|
|
4408
|
+
(m): m is ToolMessage =>
|
|
4409
|
+
m._getType() === 'tool' &&
|
|
4410
|
+
(m as ToolMessage).tool_call_id === 'call_ask_id_1'
|
|
4411
|
+
);
|
|
4412
|
+
expect(String(toolMessage!.content)).toBe('us-east');
|
|
4413
|
+
});
|
|
4414
|
+
|
|
4357
4415
|
it('isAskUserQuestionInterrupt narrows the payload union correctly', async () => {
|
|
4358
4416
|
const { isAskUserQuestionInterrupt, isToolApprovalInterrupt } =
|
|
4359
4417
|
await import('@/types/hitl');
|
package/src/types/hitl.ts
CHANGED
|
@@ -158,6 +158,14 @@ export interface AskUserQuestionRequest {
|
|
|
158
158
|
export interface AskUserQuestionInterruptPayload {
|
|
159
159
|
type: 'ask_user_question';
|
|
160
160
|
question: AskUserQuestionRequest;
|
|
161
|
+
/**
|
|
162
|
+
* The `tool_call_id` of the ask-tool call that raised this interrupt,
|
|
163
|
+
* when the tool body supplied it (see `askUserQuestion`'s `options`).
|
|
164
|
+
* Lets hosts attribute the question — and later the answer — to the
|
|
165
|
+
* exact tool-call content part instead of guessing by position, which
|
|
166
|
+
* mislabels cards when a model emits several ask calls in one turn.
|
|
167
|
+
*/
|
|
168
|
+
tool_call_id?: string;
|
|
161
169
|
}
|
|
162
170
|
|
|
163
171
|
/**
|
package/src/types/tools.ts
CHANGED
|
@@ -75,6 +75,28 @@ export type EagerEventToolCallChunkState = {
|
|
|
75
75
|
argsText: string;
|
|
76
76
|
index?: number;
|
|
77
77
|
lastArgsFragment?: string;
|
|
78
|
+
/**
|
|
79
|
+
* Cumulative length of every observed args fragment — the length of the
|
|
80
|
+
* plain in-order concatenation that LangChain's `AIMessageChunk.concat`
|
|
81
|
+
* performs to build the final tool call. Every reconciliation branch in
|
|
82
|
+
* `mergeToolCallArgsText` (and the repeat-fragment dedupe) produces text no
|
|
83
|
+
* longer than plain concatenation, with equality exactly when every merge
|
|
84
|
+
* was a pure append — so `argsText.length === rawArgsLength` proves
|
|
85
|
+
* `argsText` IS the canonical accumulation the final request will carry.
|
|
86
|
+
* Tracking only the length keeps cumulative/restating streams from
|
|
87
|
+
* retaining every prefix (quadratic growth) while still letting seal-time
|
|
88
|
+
* prestart verify the snapshot.
|
|
89
|
+
*/
|
|
90
|
+
rawArgsLength?: number;
|
|
91
|
+
/**
|
|
92
|
+
* The non-empty args fragment carried by a chunk whose explicit adapter
|
|
93
|
+
* seal covered this call. Some adapters restate the finished call's full
|
|
94
|
+
* args on the seal chunk (OpenAI Responses `function_call_arguments.done`);
|
|
95
|
+
* only such a restatement may override the canonical-accumulation check at
|
|
96
|
+
* seal time. Pure-signal seals (Bedrock `contentBlockStop`, `args: ''`)
|
|
97
|
+
* never set this.
|
|
98
|
+
*/
|
|
99
|
+
sealedArgsFragment?: string;
|
|
78
100
|
};
|
|
79
101
|
|
|
80
102
|
export type ToolNodeOptions = {
|
|
@@ -156,6 +178,14 @@ export type ToolNodeOptions = {
|
|
|
156
178
|
eagerEventToolExecutions?: Map<string, EagerEventToolExecution>;
|
|
157
179
|
/** Shared per-run per-tool turn counter used by eager and normal event dispatch. */
|
|
158
180
|
eagerEventToolUsageCount?: Map<string, number>;
|
|
181
|
+
/**
|
|
182
|
+
* Shared per-run circuit breaker for eager prestart. When a prestarted
|
|
183
|
+
* execution's args turn out to differ from the final request ("changed
|
|
184
|
+
* after eager execution started"), the ToolNode adds the tool name here
|
|
185
|
+
* and the stream handler stops prestarting that tool for the remainder of
|
|
186
|
+
* the run, so the model's retry executes normally instead of looping.
|
|
187
|
+
*/
|
|
188
|
+
eagerEventToolSuppressions?: Set<string>;
|
|
159
189
|
/**
|
|
160
190
|
* Hook registry for PreToolUse/PostToolUse/PostToolUseFailure/
|
|
161
191
|
* PermissionDenied lifecycle hooks. Fires for **every** tool the
|
|
@@ -241,7 +271,11 @@ export type ToolEndEvent = {
|
|
|
241
271
|
* present (see `ProcessedToolCall.outcome`) so `ON_RUN_STEP_COMPLETED`
|
|
242
272
|
* consumers can read it without an unsafe cast.
|
|
243
273
|
*/
|
|
244
|
-
tool_call: ToolCall & {
|
|
274
|
+
tool_call: ToolCall & {
|
|
275
|
+
output?: string;
|
|
276
|
+
progress?: number;
|
|
277
|
+
outcome?: string;
|
|
278
|
+
};
|
|
245
279
|
/** The content index of the tool call */
|
|
246
280
|
index: number;
|
|
247
281
|
type?: 'tool_call';
|