@librechat/agents 3.1.96 → 3.1.97

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.
Files changed (56) hide show
  1. package/dist/cjs/graphs/Graph.cjs +54 -21
  2. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  3. package/dist/cjs/instrumentation.cjs +120 -9
  4. package/dist/cjs/instrumentation.cjs.map +1 -1
  5. package/dist/cjs/langfuse.cjs +30 -226
  6. package/dist/cjs/langfuse.cjs.map +1 -1
  7. package/dist/cjs/langfuseToolOutputTracing.cjs +465 -0
  8. package/dist/cjs/langfuseToolOutputTracing.cjs.map +1 -0
  9. package/dist/cjs/run.cjs +142 -69
  10. package/dist/cjs/run.cjs.map +1 -1
  11. package/dist/cjs/tools/ToolNode.cjs +20 -8
  12. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  13. package/dist/cjs/tools/subagent/SubagentExecutor.cjs +10 -6
  14. package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
  15. package/dist/esm/graphs/Graph.mjs +56 -23
  16. package/dist/esm/graphs/Graph.mjs.map +1 -1
  17. package/dist/esm/instrumentation.mjs +118 -9
  18. package/dist/esm/instrumentation.mjs.map +1 -1
  19. package/dist/esm/langfuse.mjs +28 -224
  20. package/dist/esm/langfuse.mjs.map +1 -1
  21. package/dist/esm/langfuseToolOutputTracing.mjs +457 -0
  22. package/dist/esm/langfuseToolOutputTracing.mjs.map +1 -0
  23. package/dist/esm/run.mjs +144 -71
  24. package/dist/esm/run.mjs.map +1 -1
  25. package/dist/esm/tools/ToolNode.mjs +20 -8
  26. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  27. package/dist/esm/tools/subagent/SubagentExecutor.mjs +10 -6
  28. package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
  29. package/dist/types/graphs/Graph.d.ts +5 -1
  30. package/dist/types/instrumentation.d.ts +5 -1
  31. package/dist/types/langfuse.d.ts +6 -28
  32. package/dist/types/langfuseToolOutputTracing.d.ts +20 -0
  33. package/dist/types/run.d.ts +5 -1
  34. package/dist/types/tools/ToolNode.d.ts +4 -1
  35. package/dist/types/tools/subagent/SubagentExecutor.d.ts +2 -0
  36. package/dist/types/types/graph.d.ts +30 -0
  37. package/dist/types/types/run.d.ts +6 -0
  38. package/dist/types/types/tools.d.ts +7 -0
  39. package/package.json +2 -1
  40. package/src/graphs/Graph.ts +90 -34
  41. package/src/instrumentation.ts +172 -11
  42. package/src/langfuse.ts +59 -324
  43. package/src/langfuseToolOutputTracing.ts +683 -0
  44. package/src/run.ts +190 -87
  45. package/src/specs/langfuse-callbacks.test.ts +178 -1
  46. package/src/specs/langfuse-config.test.ts +112 -76
  47. package/src/specs/langfuse-instrumentation.test.ts +283 -0
  48. package/src/specs/langfuse-metadata.test.ts +54 -1
  49. package/src/specs/langfuse-tool-output-tracing.test.ts +588 -0
  50. package/src/tools/ToolNode.ts +28 -7
  51. package/src/tools/__tests__/SubagentExecutor.test.ts +32 -0
  52. package/src/tools/__tests__/ToolNode.langfuse.test.ts +41 -0
  53. package/src/tools/subagent/SubagentExecutor.ts +11 -6
  54. package/src/types/graph.ts +32 -0
  55. package/src/types/run.ts +6 -0
  56. package/src/types/tools.ts +7 -0
@@ -0,0 +1,41 @@
1
+ const mockWithLangfuseToolOutputTracingConfig = jest.fn(
2
+ (_runLangfuse: unknown, action: () => unknown, _agentLangfuse: unknown) =>
3
+ action()
4
+ );
5
+
6
+ jest.mock('@/langfuseToolOutputTracing', () => ({
7
+ ...jest.requireActual('@/langfuseToolOutputTracing'),
8
+ withLangfuseToolOutputTracingConfig: mockWithLangfuseToolOutputTracingConfig,
9
+ }));
10
+
11
+ import { ToolNode } from '../ToolNode';
12
+
13
+ describe('ToolNode Langfuse redaction context', () => {
14
+ beforeEach(() => {
15
+ mockWithLangfuseToolOutputTracingConfig.mockClear();
16
+ });
17
+
18
+ it('scopes ToolNode invocation with run and agent Langfuse config', async () => {
19
+ const runLangfuse = {
20
+ toolOutputTracing: { enabled: true },
21
+ };
22
+ const agentLangfuse = {
23
+ toolOutputTracing: { enabled: false },
24
+ };
25
+ const node = new ToolNode({
26
+ tools: [],
27
+ runLangfuse,
28
+ agentLangfuse,
29
+ });
30
+
31
+ await expect(node.invoke([])).rejects.toThrow(
32
+ 'ToolNode only accepts AIMessages'
33
+ );
34
+
35
+ expect(mockWithLangfuseToolOutputTracingConfig).toHaveBeenCalledWith(
36
+ runLangfuse,
37
+ expect.any(Function),
38
+ agentLangfuse
39
+ );
40
+ });
41
+ });
@@ -213,6 +213,7 @@ export type SubagentExecutorOptions = {
213
213
  hookRegistry?: HookRegistry;
214
214
  parentRunId: string;
215
215
  parentAgentId?: string;
216
+ langfuse?: StandardGraphInput['langfuse'];
216
217
  tokenCounter?: TokenCounter;
217
218
  /** Remaining nesting budget. 0 or negative blocks execution. */
218
219
  maxDepth?: number;
@@ -243,6 +244,7 @@ export class SubagentExecutor {
243
244
  private readonly hookRegistry?: HookRegistry;
244
245
  private readonly parentRunId: string;
245
246
  private readonly parentAgentId?: string;
247
+ private readonly langfuse?: StandardGraphInput['langfuse'];
246
248
  private readonly tokenCounter?: TokenCounter;
247
249
  private readonly maxDepth: number;
248
250
  private readonly createChildGraph: ChildGraphFactory;
@@ -256,6 +258,7 @@ export class SubagentExecutor {
256
258
  this.hookRegistry = options.hookRegistry;
257
259
  this.parentRunId = options.parentRunId;
258
260
  this.parentAgentId = options.parentAgentId;
261
+ this.langfuse = options.langfuse;
259
262
  this.tokenCounter = options.tokenCounter;
260
263
  this.maxDepth = options.maxDepth ?? 1;
261
264
  this.createChildGraph = options.createChildGraph;
@@ -352,18 +355,20 @@ export class SubagentExecutor {
352
355
  runId: childRunId,
353
356
  signal: this.parentSignal,
354
357
  agents: [childInputs],
358
+ langfuse: this.langfuse,
355
359
  tokenCounter: this.tokenCounter,
356
360
  });
357
361
 
358
- const forwarding = forwardingEnabled
359
- ? this.createForwarderCallback({
362
+ let forwarding: ForwarderCallback | undefined;
363
+ if (forwardingEnabled) {
364
+ forwarding = this.createForwarderCallback({
360
365
  parentRegistry: parentRegistry!,
361
366
  subagentType,
362
367
  subagentAgentId: childAgentId,
363
368
  childRunId,
364
369
  parentToolCallId,
365
- })
366
- : undefined;
370
+ });
371
+ }
367
372
  const forwarder = forwarding?.handler;
368
373
 
369
374
  if (forwarder) {
@@ -444,7 +449,7 @@ export class SubagentExecutor {
444
449
  );
445
450
  } catch (error) {
446
451
  const errorMessage = truncateErrorMessage(error);
447
- if (forwarder) {
452
+ if (forwarding) {
448
453
  await forwarding.drain();
449
454
  await this.emitSubagentUpdate(parentRegistry!, {
450
455
  childRunId,
@@ -491,7 +496,7 @@ export class SubagentExecutor {
491
496
  });
492
497
  }
493
498
 
494
- if (forwarder) {
499
+ if (forwarding) {
495
500
  await forwarding.drain();
496
501
  await this.emitSubagentUpdate(parentRegistry!, {
497
502
  childRunId,
@@ -295,6 +295,7 @@ export type StandardGraphInput = {
295
295
  runId?: string;
296
296
  signal?: AbortSignal;
297
297
  agents: AgentInputs[];
298
+ langfuse?: LangfuseConfig;
298
299
  tokenCounter?: TokenCounter;
299
300
  indexTokenCountMap?: Record<string, number>;
300
301
  calibrationRatio?: number;
@@ -408,11 +409,42 @@ export interface SubagentUpdateEvent {
408
409
  timestamp: string;
409
410
  }
410
411
 
412
+ export type LangfuseToolOutputTracingConfig = {
413
+ /**
414
+ * Whether tool outputs should be exported to Langfuse. Defaults to
415
+ * `true`. Set to `false` to keep tool spans and redact their output.
416
+ */
417
+ enabled?: boolean;
418
+ /**
419
+ * Optional allowlist of tool names whose outputs should be redacted even
420
+ * when `enabled` is true.
421
+ */
422
+ redactedToolNames?: string[];
423
+ /**
424
+ * Match strategy for `redactedToolNames`. Defaults to `exact`; use
425
+ * `partial` to redact tools whose names contain a configured value.
426
+ */
427
+ redactedToolNameMatchMode?: 'exact' | 'partial';
428
+ /** Replacement text used for redacted tool outputs. */
429
+ redactionText?: string;
430
+ };
431
+
432
+ export type LangfuseToolNodeTracingConfig = {
433
+ /**
434
+ * Overrides ToolNode callback tracing. ToolNode spans are exported by the
435
+ * env-backed Langfuse callback, so this only enables tracing when that
436
+ * callback is configured.
437
+ */
438
+ enabled?: boolean;
439
+ };
440
+
411
441
  export interface LangfuseConfig {
412
442
  enabled?: boolean;
413
443
  publicKey?: string;
414
444
  secretKey?: string;
415
445
  baseUrl?: string;
446
+ toolNodeTracing?: LangfuseToolNodeTracingConfig;
447
+ toolOutputTracing?: LangfuseToolOutputTracingConfig;
416
448
  }
417
449
 
418
450
  export interface AgentInputs {
package/src/types/run.ts CHANGED
@@ -118,6 +118,12 @@ export type StandardGraphConfig = Omit<
118
118
  export type RunConfig = {
119
119
  runId: string;
120
120
  graphConfig: LegacyGraphConfig | StandardGraphConfig | MultiAgentGraphConfig;
121
+ /**
122
+ * Run-scoped Langfuse configuration. Per-agent `AgentInputs.langfuse`
123
+ * takes precedence for agent-specific spans; this object supplies defaults
124
+ * for run-wide tracing controls such as tool-output redaction.
125
+ */
126
+ langfuse?: g.LangfuseConfig;
121
127
  customHandlers?: Record<string, g.EventHandler>;
122
128
  /**
123
129
  * Pre-constructed hook registry for this run. Hooks fire at lifecycle
@@ -6,6 +6,7 @@ import type { HookRegistry } from '@/hooks';
6
6
  import type { ToolOutputReferenceRegistry } from '@/tools/toolOutputReferences';
7
7
  import type { MessageContentComplex, ToolErrorData } from './stream';
8
8
  import type { HumanInTheLoopConfig } from './hitl';
9
+ import type { LangfuseConfig } from './graph';
9
10
 
10
11
  /** Replacement type for `import type { ToolCall } from '@langchain/core/messages/tool'` in order to have stringified args typed */
11
12
  export type CustomToolCall = {
@@ -69,6 +70,12 @@ export type EagerEventToolCallChunkState = {
69
70
  export type ToolNodeOptions = {
70
71
  name?: string;
71
72
  tags?: string[];
73
+ /** Enables LangChain/LangGraph tracing for this ToolNode. Defaults to false. */
74
+ trace?: boolean;
75
+ /** Run-level Langfuse config used to scope ToolNode trace redaction. */
76
+ runLangfuse?: LangfuseConfig;
77
+ /** Agent-level Langfuse config used to scope ToolNode trace redaction. */
78
+ agentLangfuse?: LangfuseConfig;
72
79
  handleToolErrors?: boolean;
73
80
  loadRuntimeTools?: ToolRefGenerator;
74
81
  toolCallStepIds?: Map<string, string>;