@librechat/agents 3.1.90 → 3.1.92

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 (94) hide show
  1. package/dist/cjs/agents/AgentContext.cjs +9 -5
  2. package/dist/cjs/agents/AgentContext.cjs.map +1 -1
  3. package/dist/cjs/graphs/Graph.cjs +48 -14
  4. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  5. package/dist/cjs/instrumentation.cjs +2 -7
  6. package/dist/cjs/instrumentation.cjs.map +1 -1
  7. package/dist/cjs/langfuse.cjs +285 -0
  8. package/dist/cjs/langfuse.cjs.map +1 -0
  9. package/dist/cjs/main.cjs +25 -0
  10. package/dist/cjs/main.cjs.map +1 -1
  11. package/dist/cjs/run.cjs +75 -44
  12. package/dist/cjs/run.cjs.map +1 -1
  13. package/dist/cjs/stream.cjs +10 -3
  14. package/dist/cjs/stream.cjs.map +1 -1
  15. package/dist/cjs/tools/cloudflare/CloudflareBridgeRuntime.cjs +380 -0
  16. package/dist/cjs/tools/cloudflare/CloudflareBridgeRuntime.cjs.map +1 -0
  17. package/dist/cjs/tools/cloudflare/CloudflareProgrammaticToolCalling.cjs +997 -0
  18. package/dist/cjs/tools/cloudflare/CloudflareProgrammaticToolCalling.cjs.map +1 -0
  19. package/dist/cjs/tools/cloudflare/CloudflareSandboxExecutionEngine.cjs +575 -0
  20. package/dist/cjs/tools/cloudflare/CloudflareSandboxExecutionEngine.cjs.map +1 -0
  21. package/dist/cjs/tools/cloudflare/CloudflareSandboxTools.cjs +165 -0
  22. package/dist/cjs/tools/cloudflare/CloudflareSandboxTools.cjs.map +1 -0
  23. package/dist/cjs/tools/local/LocalExecutionEngine.cjs +17 -5
  24. package/dist/cjs/tools/local/LocalExecutionEngine.cjs.map +1 -1
  25. package/dist/cjs/tools/local/resolveLocalExecutionTools.cjs +110 -6
  26. package/dist/cjs/tools/local/resolveLocalExecutionTools.cjs.map +1 -1
  27. package/dist/cjs/utils/callbacks.cjs +27 -0
  28. package/dist/cjs/utils/callbacks.cjs.map +1 -0
  29. package/dist/esm/agents/AgentContext.mjs +9 -5
  30. package/dist/esm/agents/AgentContext.mjs.map +1 -1
  31. package/dist/esm/graphs/Graph.mjs +48 -14
  32. package/dist/esm/graphs/Graph.mjs.map +1 -1
  33. package/dist/esm/instrumentation.mjs +2 -7
  34. package/dist/esm/instrumentation.mjs.map +1 -1
  35. package/dist/esm/langfuse.mjs +275 -0
  36. package/dist/esm/langfuse.mjs.map +1 -0
  37. package/dist/esm/main.mjs +5 -1
  38. package/dist/esm/main.mjs.map +1 -1
  39. package/dist/esm/run.mjs +75 -44
  40. package/dist/esm/run.mjs.map +1 -1
  41. package/dist/esm/stream.mjs +10 -3
  42. package/dist/esm/stream.mjs.map +1 -1
  43. package/dist/esm/tools/cloudflare/CloudflareBridgeRuntime.mjs +378 -0
  44. package/dist/esm/tools/cloudflare/CloudflareBridgeRuntime.mjs.map +1 -0
  45. package/dist/esm/tools/cloudflare/CloudflareProgrammaticToolCalling.mjs +994 -0
  46. package/dist/esm/tools/cloudflare/CloudflareProgrammaticToolCalling.mjs.map +1 -0
  47. package/dist/esm/tools/cloudflare/CloudflareSandboxExecutionEngine.mjs +566 -0
  48. package/dist/esm/tools/cloudflare/CloudflareSandboxExecutionEngine.mjs.map +1 -0
  49. package/dist/esm/tools/cloudflare/CloudflareSandboxTools.mjs +155 -0
  50. package/dist/esm/tools/cloudflare/CloudflareSandboxTools.mjs.map +1 -0
  51. package/dist/esm/tools/local/LocalExecutionEngine.mjs +17 -6
  52. package/dist/esm/tools/local/LocalExecutionEngine.mjs.map +1 -1
  53. package/dist/esm/tools/local/resolveLocalExecutionTools.mjs +111 -7
  54. package/dist/esm/tools/local/resolveLocalExecutionTools.mjs.map +1 -1
  55. package/dist/esm/utils/callbacks.mjs +24 -0
  56. package/dist/esm/utils/callbacks.mjs.map +1 -0
  57. package/dist/types/agents/AgentContext.d.ts +4 -1
  58. package/dist/types/graphs/Graph.d.ts +6 -5
  59. package/dist/types/index.d.ts +1 -0
  60. package/dist/types/langfuse.d.ts +57 -0
  61. package/dist/types/tools/cloudflare/CloudflareBridgeRuntime.d.ts +23 -0
  62. package/dist/types/tools/cloudflare/CloudflareProgrammaticToolCalling.d.ts +4 -0
  63. package/dist/types/tools/cloudflare/CloudflareSandboxExecutionEngine.d.ts +21 -0
  64. package/dist/types/tools/cloudflare/CloudflareSandboxTools.d.ts +22 -0
  65. package/dist/types/tools/cloudflare/index.d.ts +4 -0
  66. package/dist/types/tools/local/LocalExecutionEngine.d.ts +1 -0
  67. package/dist/types/types/graph.d.ts +8 -0
  68. package/dist/types/types/run.d.ts +2 -2
  69. package/dist/types/types/tools.d.ts +118 -2
  70. package/dist/types/utils/callbacks.d.ts +5 -0
  71. package/package.json +4 -4
  72. package/src/__tests__/stream.eagerEventExecution.test.ts +66 -0
  73. package/src/agents/AgentContext.ts +13 -3
  74. package/src/graphs/Graph.ts +57 -16
  75. package/src/index.ts +1 -0
  76. package/src/instrumentation.ts +2 -7
  77. package/src/langfuse.ts +441 -0
  78. package/src/run.ts +105 -59
  79. package/src/specs/langfuse-callbacks.test.ts +75 -0
  80. package/src/specs/langfuse-config.test.ts +114 -0
  81. package/src/specs/langfuse-metadata.test.ts +19 -1
  82. package/src/stream.ts +13 -3
  83. package/src/tools/__tests__/CloudflareSandboxExecution.test.ts +537 -0
  84. package/src/tools/cloudflare/CloudflareBridgeRuntime.ts +480 -0
  85. package/src/tools/cloudflare/CloudflareProgrammaticToolCalling.ts +1162 -0
  86. package/src/tools/cloudflare/CloudflareSandboxExecutionEngine.ts +744 -0
  87. package/src/tools/cloudflare/CloudflareSandboxTools.ts +225 -0
  88. package/src/tools/cloudflare/index.ts +4 -0
  89. package/src/tools/local/LocalExecutionEngine.ts +20 -4
  90. package/src/tools/local/resolveLocalExecutionTools.ts +169 -7
  91. package/src/types/graph.ts +9 -0
  92. package/src/types/run.ts +2 -7
  93. package/src/types/tools.ts +141 -2
  94. package/src/utils/callbacks.ts +39 -0
@@ -0,0 +1,275 @@
1
+ import { CallbackHandler } from '@langfuse/langchain';
2
+ import { LangfuseSpanProcessor, isDefaultExportSpan } from '@langfuse/otel';
3
+ import { createObservationAttributes, LangfuseOtelSpanAttributes } from '@langfuse/tracing';
4
+ import { BaseCallbackHandler } from '@langchain/core/callbacks/base';
5
+ import { BasicTracerProvider } from '@opentelemetry/sdk-trace-base';
6
+ import { SpanStatusCode } from '@opentelemetry/api';
7
+ import { isPresent } from './utils/misc.mjs';
8
+
9
+ const TRACE_METADATA_MAX_LENGTH = 200;
10
+ const LANGFUSE_TRACER_NAME = 'langfuse-sdk';
11
+ function getEnvLangfuseBaseUrl() {
12
+ return process.env.LANGFUSE_BASE_URL ?? process.env.LANGFUSE_BASEURL;
13
+ }
14
+ function createTraceMetadata(metadata) {
15
+ const traceMetadata = {};
16
+ for (const [key, value] of Object.entries(metadata)) {
17
+ if (value == null) {
18
+ continue;
19
+ }
20
+ const stringValue = typeof value === 'string' ? value : String(value);
21
+ if (stringValue.trim() === '' ||
22
+ stringValue.length > TRACE_METADATA_MAX_LENGTH) {
23
+ continue;
24
+ }
25
+ traceMetadata[key] = stringValue;
26
+ }
27
+ return traceMetadata;
28
+ }
29
+ function createLangfuseTraceMetadata({ messageId, parentMessageId, agentId, agentName, }) {
30
+ return createTraceMetadata({
31
+ messageId,
32
+ parentMessageId,
33
+ agentId,
34
+ agentName,
35
+ });
36
+ }
37
+ function getModelName(serialized) {
38
+ const serializedRecord = serialized;
39
+ const kwargs = serializedRecord.kwargs;
40
+ const modelName = kwargs?.model ??
41
+ kwargs?.model_name ??
42
+ kwargs?.modelName ??
43
+ kwargs?.model_id ??
44
+ kwargs?.modelId ??
45
+ serializedRecord.name;
46
+ if (typeof modelName === 'string' && modelName.trim() !== '') {
47
+ return modelName;
48
+ }
49
+ if (Array.isArray(serializedRecord.id) && serializedRecord.id.length > 0) {
50
+ return String(serializedRecord.id[serializedRecord.id.length - 1]);
51
+ }
52
+ return 'ChatModel';
53
+ }
54
+ function getModelParameters(extraParams) {
55
+ const invocationParams = extraParams?.invocation_params;
56
+ const params = invocationParams != null && typeof invocationParams === 'object'
57
+ ? invocationParams
58
+ : (extraParams ?? {});
59
+ return Object.fromEntries(Object.entries(params).filter(([, value]) => {
60
+ return typeof value === 'string' || typeof value === 'number';
61
+ }));
62
+ }
63
+ function getOutput(output) {
64
+ return output.generations.map((generation) => generation.map((item) => {
65
+ if ('message' in item && item.message != null) {
66
+ return item.message.content;
67
+ }
68
+ return item.text;
69
+ }));
70
+ }
71
+ function getUsageDetails(output) {
72
+ const llmOutput = output.llmOutput;
73
+ const usage = llmOutput?.tokenUsage ?? llmOutput?.usage;
74
+ if (usage == null || typeof usage !== 'object') {
75
+ return undefined;
76
+ }
77
+ const usageEntries = Object.entries(usage).filter(([, value]) => typeof value === 'number');
78
+ return usageEntries.length > 0
79
+ ? Object.fromEntries(usageEntries)
80
+ : undefined;
81
+ }
82
+ function getLangfuseTraceName(traceMetadata, fallback = 'LibreChat Agent') {
83
+ const agentName = traceMetadata?.agentName;
84
+ return isPresent(agentName) ? `${fallback}: ${agentName}` : fallback;
85
+ }
86
+ function getTraceAttributes({ userId, sessionId, traceMetadata, tags, }) {
87
+ const attributes = {
88
+ [LangfuseOtelSpanAttributes.TRACE_NAME]: getLangfuseTraceName(traceMetadata),
89
+ };
90
+ if (isPresent(userId)) {
91
+ attributes[LangfuseOtelSpanAttributes.TRACE_USER_ID] = userId;
92
+ }
93
+ if (isPresent(sessionId)) {
94
+ attributes[LangfuseOtelSpanAttributes.TRACE_SESSION_ID] = sessionId;
95
+ }
96
+ if (tags != null && tags.length > 0) {
97
+ attributes[LangfuseOtelSpanAttributes.TRACE_TAGS] = tags;
98
+ }
99
+ for (const [key, value] of Object.entries(traceMetadata ?? {})) {
100
+ attributes[`${LangfuseOtelSpanAttributes.TRACE_METADATA}.${key}`] = value;
101
+ }
102
+ return attributes;
103
+ }
104
+ class LangfuseAgentCallbackHandler extends BaseCallbackHandler {
105
+ name = 'librechat_langfuse_agent_handler';
106
+ provider;
107
+ processor;
108
+ userId;
109
+ sessionId;
110
+ traceMetadata;
111
+ tags;
112
+ spans = new Map();
113
+ constructor({ langfuse, userId, sessionId, traceMetadata, tags, }) {
114
+ super();
115
+ this.userId = userId;
116
+ this.sessionId = sessionId;
117
+ this.traceMetadata = traceMetadata;
118
+ this.tags = tags;
119
+ this.processor = new LangfuseSpanProcessor({
120
+ publicKey: langfuse.publicKey,
121
+ secretKey: langfuse.secretKey,
122
+ ...(isPresent(langfuse.baseUrl) ? { baseUrl: langfuse.baseUrl } : {}),
123
+ environment: process.env.LANGFUSE_TRACING_ENVIRONMENT ??
124
+ process.env.NODE_ENV ??
125
+ 'development',
126
+ exportMode: 'immediate',
127
+ shouldExportSpan: ({ otelSpan }) => isDefaultExportSpan(otelSpan) ||
128
+ otelSpan.instrumentationScope.name === LANGFUSE_TRACER_NAME,
129
+ });
130
+ this.provider = new BasicTracerProvider({
131
+ spanProcessors: [this.processor],
132
+ });
133
+ }
134
+ startGenerationSpan({ llm, input, runId, extraParams, metadata, name, }) {
135
+ if (this.spans.has(runId)) {
136
+ return;
137
+ }
138
+ const tracer = this.provider.getTracer(LANGFUSE_TRACER_NAME);
139
+ const spanName = typeof name === 'string' && name.trim() !== '' ? name : getModelName(llm);
140
+ const span = tracer.startSpan(spanName, {
141
+ attributes: {
142
+ ...getTraceAttributes({
143
+ userId: this.userId,
144
+ sessionId: this.sessionId,
145
+ traceMetadata: this.traceMetadata,
146
+ tags: this.tags,
147
+ }),
148
+ ...createObservationAttributes('generation', {
149
+ input,
150
+ model: getModelName(llm),
151
+ modelParameters: getModelParameters(extraParams),
152
+ metadata: {
153
+ ...metadata,
154
+ ...this.traceMetadata,
155
+ },
156
+ }),
157
+ },
158
+ });
159
+ this.spans.set(runId, span);
160
+ }
161
+ async handleChatModelStart(llm, messages, runId, _parentRunId, extraParams, _tags, metadata, name) {
162
+ this.startGenerationSpan({
163
+ llm,
164
+ input: messages,
165
+ runId,
166
+ extraParams,
167
+ metadata,
168
+ name,
169
+ });
170
+ }
171
+ async handleLLMStart(llm, prompts, runId, _parentRunId, extraParams, _tags, metadata, name) {
172
+ this.startGenerationSpan({
173
+ llm,
174
+ input: prompts,
175
+ runId,
176
+ extraParams,
177
+ metadata,
178
+ name,
179
+ });
180
+ }
181
+ async handleLLMEnd(output, runId) {
182
+ const span = this.spans.get(runId);
183
+ if (!span) {
184
+ return;
185
+ }
186
+ span.setAttributes(createObservationAttributes('generation', {
187
+ output: getOutput(output),
188
+ usageDetails: getUsageDetails(output),
189
+ }));
190
+ span.end();
191
+ this.spans.delete(runId);
192
+ await this.flush();
193
+ }
194
+ async handleLLMError(err, runId) {
195
+ const span = this.spans.get(runId);
196
+ if (!span) {
197
+ return;
198
+ }
199
+ const message = err instanceof Error ? err.message : String(err);
200
+ span.setStatus({ code: SpanStatusCode.ERROR, message });
201
+ span.setAttributes(createObservationAttributes('generation', {
202
+ level: 'ERROR',
203
+ statusMessage: message,
204
+ }));
205
+ span.end();
206
+ this.spans.delete(runId);
207
+ await this.flush();
208
+ }
209
+ async flush() {
210
+ try {
211
+ await this.provider.forceFlush();
212
+ }
213
+ catch (error) {
214
+ process.emitWarning(`[LangfuseAgentCallbackHandler] Failed to flush Langfuse spans: ${error instanceof Error ? error.message : String(error)}`);
215
+ }
216
+ }
217
+ async dispose() {
218
+ for (const span of this.spans.values()) {
219
+ span.end();
220
+ }
221
+ this.spans.clear();
222
+ await this.flush();
223
+ try {
224
+ await this.provider.shutdown();
225
+ }
226
+ catch (error) {
227
+ process.emitWarning(`[LangfuseAgentCallbackHandler] Failed to shut down Langfuse provider: ${error instanceof Error ? error.message : String(error)}`);
228
+ }
229
+ }
230
+ }
231
+ function hasRequiredLangfuseConfig(langfuse) {
232
+ return (langfuse?.enabled === true &&
233
+ isPresent(langfuse.publicKey) &&
234
+ isPresent(langfuse.secretKey));
235
+ }
236
+ function createLegacyLangfuseHandler(params) {
237
+ return new CallbackHandler(params);
238
+ }
239
+ function createLangfuseHandler({ langfuse, userId, sessionId, traceMetadata, tags, }) {
240
+ if (!hasRequiredLangfuseConfig(langfuse)) {
241
+ return undefined;
242
+ }
243
+ return new LangfuseAgentCallbackHandler({
244
+ langfuse,
245
+ userId,
246
+ sessionId,
247
+ traceMetadata,
248
+ tags,
249
+ });
250
+ }
251
+ function hasExplicitLangfuseConfig(contexts) {
252
+ for (const context of contexts) {
253
+ if (context.langfuse != null) {
254
+ return true;
255
+ }
256
+ }
257
+ return false;
258
+ }
259
+ function hasLangfuseEnvConfig() {
260
+ return (isPresent(process.env.LANGFUSE_SECRET_KEY) &&
261
+ isPresent(process.env.LANGFUSE_PUBLIC_KEY) &&
262
+ isPresent(getEnvLangfuseBaseUrl()));
263
+ }
264
+ function isLangfuseCallbackHandler(value) {
265
+ return (value instanceof CallbackHandler ||
266
+ value instanceof LangfuseAgentCallbackHandler);
267
+ }
268
+ async function disposeLangfuseHandler(value) {
269
+ if (value instanceof LangfuseAgentCallbackHandler) {
270
+ await value.dispose();
271
+ }
272
+ }
273
+
274
+ export { LangfuseAgentCallbackHandler, createLangfuseHandler, createLangfuseTraceMetadata, createLegacyLangfuseHandler, disposeLangfuseHandler, getLangfuseTraceName, hasExplicitLangfuseConfig, hasLangfuseEnvConfig, isLangfuseCallbackHandler };
275
+ //# sourceMappingURL=langfuse.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"langfuse.mjs","sources":["../../src/langfuse.ts"],"sourcesContent":["import { CallbackHandler } from '@langfuse/langchain';\nimport { isDefaultExportSpan, LangfuseSpanProcessor } from '@langfuse/otel';\nimport {\n LangfuseOtelSpanAttributes,\n createObservationAttributes,\n} from '@langfuse/tracing';\nimport { BaseCallbackHandler } from '@langchain/core/callbacks/base';\nimport { BasicTracerProvider } from '@opentelemetry/sdk-trace-base';\nimport { SpanStatusCode } from '@opentelemetry/api';\nimport type { Serialized } from '@langchain/core/load/serializable';\nimport type { BaseMessage } from '@langchain/core/messages';\nimport type { LLMResult } from '@langchain/core/outputs';\nimport type { Attributes, Span } from '@opentelemetry/api';\nimport type * as t from '@/types';\nimport { isPresent } from '@/utils/misc';\n\nconst TRACE_METADATA_MAX_LENGTH = 200;\nconst LANGFUSE_TRACER_NAME = 'langfuse-sdk';\n\nexport type LangfuseTraceMetadata = Record<string, string>;\n\ntype LangfuseHandlerParams = {\n userId?: string;\n sessionId?: string;\n traceMetadata?: LangfuseTraceMetadata;\n tags?: string[];\n};\n\ntype AgentLangfuseHandlerParams = LangfuseHandlerParams & {\n langfuse?: t.LangfuseConfig;\n};\n\ntype ResolvedLangfuseConfig = t.LangfuseConfig & {\n enabled: true;\n publicKey: string;\n secretKey: string;\n};\n\nfunction getEnvLangfuseBaseUrl(): string | undefined {\n return process.env.LANGFUSE_BASE_URL ?? process.env.LANGFUSE_BASEURL;\n}\n\nfunction createTraceMetadata(\n metadata: Record<string, unknown>\n): LangfuseTraceMetadata {\n const traceMetadata: LangfuseTraceMetadata = {};\n for (const [key, value] of Object.entries(metadata)) {\n if (value == null) {\n continue;\n }\n const stringValue = typeof value === 'string' ? value : String(value);\n if (\n stringValue.trim() === '' ||\n stringValue.length > TRACE_METADATA_MAX_LENGTH\n ) {\n continue;\n }\n traceMetadata[key] = stringValue;\n }\n return traceMetadata;\n}\n\nexport function createLangfuseTraceMetadata({\n messageId,\n parentMessageId,\n agentId,\n agentName,\n}: {\n messageId?: unknown;\n parentMessageId?: unknown;\n agentId?: unknown;\n agentName?: unknown;\n}): LangfuseTraceMetadata {\n return createTraceMetadata({\n messageId,\n parentMessageId,\n agentId,\n agentName,\n });\n}\n\nfunction getModelName(serialized: Serialized): string {\n const serializedRecord = serialized as unknown as Record<string, unknown>;\n const kwargs = serializedRecord.kwargs as Record<string, unknown> | undefined;\n const modelName =\n kwargs?.model ??\n kwargs?.model_name ??\n kwargs?.modelName ??\n kwargs?.model_id ??\n kwargs?.modelId ??\n serializedRecord.name;\n\n if (typeof modelName === 'string' && modelName.trim() !== '') {\n return modelName;\n }\n\n if (Array.isArray(serializedRecord.id) && serializedRecord.id.length > 0) {\n return String(serializedRecord.id[serializedRecord.id.length - 1]);\n }\n\n return 'ChatModel';\n}\n\nfunction getModelParameters(\n extraParams?: Record<string, unknown>\n): Record<string, string | number> {\n const invocationParams = extraParams?.invocation_params;\n const params =\n invocationParams != null && typeof invocationParams === 'object'\n ? (invocationParams as Record<string, unknown>)\n : (extraParams ?? {});\n\n return Object.fromEntries(\n Object.entries(params).filter(([, value]) => {\n return typeof value === 'string' || typeof value === 'number';\n })\n ) as Record<string, string | number>;\n}\n\nfunction getOutput(output: LLMResult): unknown {\n return output.generations.map((generation) =>\n generation.map((item) => {\n if ('message' in item && item.message != null) {\n return (item.message as { content?: unknown }).content;\n }\n return item.text;\n })\n );\n}\n\nfunction getUsageDetails(\n output: LLMResult\n): Record<string, number> | undefined {\n const llmOutput = output.llmOutput as Record<string, unknown> | undefined;\n const usage = llmOutput?.tokenUsage ?? llmOutput?.usage;\n if (usage == null || typeof usage !== 'object') {\n return undefined;\n }\n\n const usageEntries = Object.entries(usage as Record<string, unknown>).filter(\n ([, value]) => typeof value === 'number'\n );\n\n return usageEntries.length > 0\n ? (Object.fromEntries(usageEntries) as Record<string, number>)\n : undefined;\n}\n\nexport function getLangfuseTraceName(\n traceMetadata?: LangfuseTraceMetadata,\n fallback: string = 'LibreChat Agent'\n): string {\n const agentName = traceMetadata?.agentName;\n return isPresent(agentName) ? `${fallback}: ${agentName}` : fallback;\n}\n\nfunction getTraceAttributes({\n userId,\n sessionId,\n traceMetadata,\n tags,\n}: LangfuseHandlerParams): Attributes {\n const attributes: Attributes = {\n [LangfuseOtelSpanAttributes.TRACE_NAME]:\n getLangfuseTraceName(traceMetadata),\n };\n\n if (isPresent(userId)) {\n attributes[LangfuseOtelSpanAttributes.TRACE_USER_ID] = userId;\n }\n if (isPresent(sessionId)) {\n attributes[LangfuseOtelSpanAttributes.TRACE_SESSION_ID] = sessionId;\n }\n if (tags != null && tags.length > 0) {\n attributes[LangfuseOtelSpanAttributes.TRACE_TAGS] = tags;\n }\n for (const [key, value] of Object.entries(traceMetadata ?? {})) {\n attributes[`${LangfuseOtelSpanAttributes.TRACE_METADATA}.${key}`] = value;\n }\n\n return attributes;\n}\n\nexport class LangfuseAgentCallbackHandler extends BaseCallbackHandler {\n name = 'librechat_langfuse_agent_handler';\n\n private readonly provider: BasicTracerProvider;\n private readonly processor: LangfuseSpanProcessor;\n private readonly userId?: string;\n private readonly sessionId?: string;\n private readonly traceMetadata?: LangfuseTraceMetadata;\n private readonly tags?: string[];\n private readonly spans = new Map<string, Span>();\n\n constructor({\n langfuse,\n userId,\n sessionId,\n traceMetadata,\n tags,\n }: LangfuseHandlerParams & { langfuse: ResolvedLangfuseConfig }) {\n super();\n this.userId = userId;\n this.sessionId = sessionId;\n this.traceMetadata = traceMetadata;\n this.tags = tags;\n this.processor = new LangfuseSpanProcessor({\n publicKey: langfuse.publicKey,\n secretKey: langfuse.secretKey,\n ...(isPresent(langfuse.baseUrl) ? { baseUrl: langfuse.baseUrl } : {}),\n environment:\n process.env.LANGFUSE_TRACING_ENVIRONMENT ??\n process.env.NODE_ENV ??\n 'development',\n exportMode: 'immediate',\n shouldExportSpan: ({ otelSpan }): boolean =>\n isDefaultExportSpan(otelSpan) ||\n otelSpan.instrumentationScope.name === LANGFUSE_TRACER_NAME,\n });\n this.provider = new BasicTracerProvider({\n spanProcessors: [this.processor],\n });\n }\n\n private startGenerationSpan({\n llm,\n input,\n runId,\n extraParams,\n metadata,\n name,\n }: {\n llm: Serialized;\n input: unknown;\n runId: string;\n extraParams?: Record<string, unknown>;\n metadata?: Record<string, unknown>;\n name?: string;\n }): void {\n if (this.spans.has(runId)) {\n return;\n }\n\n const tracer = this.provider.getTracer(LANGFUSE_TRACER_NAME);\n const spanName =\n typeof name === 'string' && name.trim() !== '' ? name : getModelName(llm);\n const span = tracer.startSpan(spanName, {\n attributes: {\n ...getTraceAttributes({\n userId: this.userId,\n sessionId: this.sessionId,\n traceMetadata: this.traceMetadata,\n tags: this.tags,\n }),\n ...createObservationAttributes('generation', {\n input,\n model: getModelName(llm),\n modelParameters: getModelParameters(extraParams),\n metadata: {\n ...metadata,\n ...this.traceMetadata,\n },\n }),\n },\n });\n this.spans.set(runId, span);\n }\n\n async handleChatModelStart(\n llm: Serialized,\n messages: BaseMessage[][],\n runId: string,\n _parentRunId?: string,\n extraParams?: Record<string, unknown>,\n _tags?: string[],\n metadata?: Record<string, unknown>,\n name?: string\n ): Promise<void> {\n this.startGenerationSpan({\n llm,\n input: messages,\n runId,\n extraParams,\n metadata,\n name,\n });\n }\n\n async handleLLMStart(\n llm: Serialized,\n prompts: string[],\n runId: string,\n _parentRunId?: string,\n extraParams?: Record<string, unknown>,\n _tags?: string[],\n metadata?: Record<string, unknown>,\n name?: string\n ): Promise<void> {\n this.startGenerationSpan({\n llm,\n input: prompts,\n runId,\n extraParams,\n metadata,\n name,\n });\n }\n\n async handleLLMEnd(output: LLMResult, runId: string): Promise<void> {\n const span = this.spans.get(runId);\n if (!span) {\n return;\n }\n\n span.setAttributes(\n createObservationAttributes('generation', {\n output: getOutput(output),\n usageDetails: getUsageDetails(output),\n })\n );\n span.end();\n this.spans.delete(runId);\n await this.flush();\n }\n\n async handleLLMError(err: unknown, runId: string): Promise<void> {\n const span = this.spans.get(runId);\n if (!span) {\n return;\n }\n\n const message = err instanceof Error ? err.message : String(err);\n span.setStatus({ code: SpanStatusCode.ERROR, message });\n span.setAttributes(\n createObservationAttributes('generation', {\n level: 'ERROR',\n statusMessage: message,\n })\n );\n span.end();\n this.spans.delete(runId);\n await this.flush();\n }\n\n private async flush(): Promise<void> {\n try {\n await this.provider.forceFlush();\n } catch (error) {\n process.emitWarning(\n `[LangfuseAgentCallbackHandler] Failed to flush Langfuse spans: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n async dispose(): Promise<void> {\n for (const span of this.spans.values()) {\n span.end();\n }\n this.spans.clear();\n await this.flush();\n try {\n await this.provider.shutdown();\n } catch (error) {\n process.emitWarning(\n `[LangfuseAgentCallbackHandler] Failed to shut down Langfuse provider: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n}\n\nfunction hasRequiredLangfuseConfig(\n langfuse?: t.LangfuseConfig\n): langfuse is ResolvedLangfuseConfig {\n return (\n langfuse?.enabled === true &&\n isPresent(langfuse.publicKey) &&\n isPresent(langfuse.secretKey)\n );\n}\n\nexport function createLegacyLangfuseHandler(\n params: LangfuseHandlerParams\n): CallbackHandler {\n return new CallbackHandler(params);\n}\n\nexport function createLangfuseHandler({\n langfuse,\n userId,\n sessionId,\n traceMetadata,\n tags,\n}: AgentLangfuseHandlerParams): LangfuseAgentCallbackHandler | undefined {\n if (!hasRequiredLangfuseConfig(langfuse)) {\n return undefined;\n }\n\n return new LangfuseAgentCallbackHandler({\n langfuse,\n userId,\n sessionId,\n traceMetadata,\n tags,\n });\n}\n\nexport function hasExplicitLangfuseConfig(\n contexts: Iterable<{ langfuse?: t.LangfuseConfig }>\n): boolean {\n for (const context of contexts) {\n if (context.langfuse != null) {\n return true;\n }\n }\n return false;\n}\n\nexport function hasLangfuseEnvConfig(): boolean {\n return (\n isPresent(process.env.LANGFUSE_SECRET_KEY) &&\n isPresent(process.env.LANGFUSE_PUBLIC_KEY) &&\n isPresent(getEnvLangfuseBaseUrl())\n );\n}\n\nexport function isLangfuseCallbackHandler(value: unknown): boolean {\n return (\n value instanceof CallbackHandler ||\n value instanceof LangfuseAgentCallbackHandler\n );\n}\n\nexport async function disposeLangfuseHandler(value: unknown): Promise<void> {\n if (value instanceof LangfuseAgentCallbackHandler) {\n await value.dispose();\n }\n}\n"],"names":[],"mappings":"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"}
package/dist/esm/main.mjs CHANGED
@@ -34,7 +34,7 @@ export { handleServerToolResult, handleToolCallChunks, handleToolCalls, toolResu
34
34
  export { CompileCheckToolName, createCompileCheckTool, createCompileCheckToolDefinition } from './tools/local/CompileCheckTool.mjs';
35
35
  export { LocalFileCheckpointerImpl, createLocalFileCheckpointer } from './tools/local/FileCheckpointer.mjs';
36
36
  export { LocalEditFileToolName, LocalEditFileToolSchema, LocalGlobSearchToolName, LocalGlobSearchToolSchema, LocalGrepSearchToolName, LocalGrepSearchToolSchema, LocalListDirectoryToolName, LocalListDirectoryToolSchema, LocalReadFileToolSchema, LocalWriteFileToolName, LocalWriteFileToolSchema, _resetRipgrepCacheForTests, createLocalCodingToolBundle, createLocalCodingToolDefinitions, createLocalCodingToolRegistry, createLocalCodingTools, createLocalEditFileTool, createLocalGlobSearchTool, createLocalGrepSearchTool, createLocalListDirectoryTool, createLocalReadFileTool, createLocalWriteFileTool } from './tools/local/LocalCodingTools.mjs';
37
- export { _resetLocalEngineWarningsForTests, buildSandboxRuntimeConfig, executeLocalBash, executeLocalBashWithArgs, executeLocalCode, getLocalCwd, getLocalSessionId, getReadRoots, getSpawn, getWorkspaceFS, getWorkspaceRoots, getWriteRoots, resolveLocalExecutionConfig, resolveWorkspacePath, resolveWorkspacePathSafe, shellQuote, spawnLocalProcess, truncateLocalOutput, validateBashCommand } from './tools/local/LocalExecutionEngine.mjs';
37
+ export { LOCAL_SPAWN_TIMEOUT_MS, _resetLocalEngineWarningsForTests, buildSandboxRuntimeConfig, executeLocalBash, executeLocalBashWithArgs, executeLocalCode, getLocalCwd, getLocalSessionId, getReadRoots, getSpawn, getWorkspaceFS, getWorkspaceRoots, getWriteRoots, resolveLocalExecutionConfig, resolveWorkspacePath, resolveWorkspacePathSafe, shellQuote, spawnLocalProcess, truncateLocalOutput, validateBashCommand } from './tools/local/LocalExecutionEngine.mjs';
38
38
  export { LocalBashExecutionToolDescription, LocalCodeExecutionToolDescription, createLocalBashExecutionTool, createLocalCodeExecutionTool } from './tools/local/LocalExecutionTools.mjs';
39
39
  export { _createBashProgramForTests, applyPreToolUseHooksForBridge, createLocalBashProgrammaticToolCallingTool, createLocalProgrammaticToolCallingTool } from './tools/local/LocalProgrammaticToolCalling.mjs';
40
40
  export { resolveLocalExecutionTools, resolveLocalToolRegistry, resolveLocalToolsForBinding } from './tools/local/resolveLocalExecutionTools.mjs';
@@ -43,6 +43,10 @@ export { bashAstFindingsToErrors, runBashAstChecks } from './tools/local/bashAst
43
43
  export { applyEdit, locateEdit } from './tools/local/editStrategies.mjs';
44
44
  export { _resetSyntaxCheckProbeCacheForTests, runPostEditSyntaxCheck } from './tools/local/syntaxCheck.mjs';
45
45
  export { decodeFile, encodeFile } from './tools/local/textEncoding.mjs';
46
+ export { createCloudflareBridgeRuntime } from './tools/cloudflare/CloudflareBridgeRuntime.mjs';
47
+ export { createCloudflareBashProgrammaticToolCallingTool, createCloudflareProgrammaticToolCallingTool } from './tools/cloudflare/CloudflareProgrammaticToolCalling.mjs';
48
+ export { createCloudflareLocalExecutionConfig, createCloudflareWorkspaceFS, executeCloudflareBash, executeCloudflareCode, formatCloudflareOutput, getCloudflareWorkspaceRoot, resolveCloudflareSandbox, validateCloudflareBashCommand } from './tools/cloudflare/CloudflareSandboxExecutionEngine.mjs';
49
+ export { CLOUDFLARE_BASH_CODING_TOOL_NAMES, CLOUDFLARE_CODING_TOOL_NAMES, CloudflareBashExecutionToolDescription, CloudflareCodeExecutionToolDescription, createCloudflareBashExecutionTool, createCloudflareCodeExecutionTool, createCloudflareCodingToolBundle, createCloudflareCodingTools, createCloudflareExecutionTool } from './tools/cloudflare/CloudflareSandboxTools.mjs';
46
50
  export { createSearchTool } from './tools/search/tool.mjs';
47
51
  export { DATE_RANGE, DEFAULT_COUNTRY_DESCRIPTION, DEFAULT_QUERY_DESCRIPTION, WebSearchToolDefinition, WebSearchToolDescription, WebSearchToolName, WebSearchToolSchema, countrySchema, dateSchema, imagesSchema, newsSchema, querySchema, videosSchema } from './tools/search/schema.mjs';
48
52
  export { ANTHROPIC_TOOL_TOKEN_MULTIPLIER, DEFAULT_TOOL_TOKEN_MULTIPLIER } from './common/constants.mjs';
@@ -1 +1 @@
1
- {"version":3,"file":"main.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"main.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/dist/esm/run.mjs CHANGED
@@ -1,5 +1,4 @@
1
1
  import './instrumentation.mjs';
2
- import { CallbackHandler } from '@langfuse/langchain';
3
2
  import { PromptTemplate } from '@langchain/core/prompts';
4
3
  import { RunnableLambda } from '@langchain/core/runnables';
5
4
  import { ChatOpenAI as ChatOpenAI$1, AzureChatOpenAI as AzureChatOpenAI$1 } from '@langchain/openai';
@@ -16,7 +15,8 @@ import { HandlerRegistry } from './events.mjs';
16
15
  import { executeHooks } from './hooks/executeHooks.mjs';
17
16
  import './hooks/createWorkspacePolicyHook.mjs';
18
17
  import { isOpenAILike } from './utils/llm.mjs';
19
- import { isPresent } from './utils/misc.mjs';
18
+ import { appendCallbacks, findCallback } from './utils/callbacks.mjs';
19
+ import { hasLangfuseEnvConfig, hasExplicitLangfuseConfig, createLangfuseTraceMetadata, createLegacyLangfuseHandler, getLangfuseTraceName, createLangfuseHandler, isLangfuseCallbackHandler, disposeLangfuseHandler } from './langfuse.mjs';
20
20
 
21
21
  // src/run.ts
22
22
  const defaultOmitOptions = new Set([
@@ -461,34 +461,36 @@ class Run {
461
461
  this.hookRegistry?.clearHaltSignal(this.id);
462
462
  /** Custom event callback to intercept and handle custom events */
463
463
  const customEventCallback = this.createCustomEventCallback();
464
- const baseCallbacks = config.callbacks ?? [];
465
464
  const streamCallbacks = streamOptions?.callbacks
466
465
  ? this.getCallbacks(streamOptions.callbacks)
467
- : [];
466
+ : undefined;
468
467
  const customHandler = BaseCallbackHandler.fromMethods({
469
468
  [Callback.CUSTOM_EVENT]: customEventCallback,
470
469
  });
471
470
  customHandler.awaitHandlers = true;
472
- config.callbacks = baseCallbacks
473
- .concat(streamCallbacks)
474
- .concat(customHandler);
475
- if (isPresent(process.env.LANGFUSE_SECRET_KEY) &&
476
- isPresent(process.env.LANGFUSE_PUBLIC_KEY) &&
477
- isPresent(process.env.LANGFUSE_BASE_URL)) {
478
- const userId = config.configurable?.user_id;
479
- const sessionId = config.configurable?.thread_id;
471
+ config.callbacks = appendCallbacks(config.callbacks, streamCallbacks ? [streamCallbacks, customHandler] : [customHandler]);
472
+ if (hasLangfuseEnvConfig() &&
473
+ !hasExplicitLangfuseConfig(this.Graph.agentContexts.values())) {
474
+ const userId = typeof config.configurable?.user_id === 'string'
475
+ ? config.configurable.user_id
476
+ : undefined;
477
+ const sessionId = typeof config.configurable?.thread_id === 'string'
478
+ ? config.configurable.thread_id
479
+ : undefined;
480
480
  const primaryContext = this.Graph.agentContexts.get(this.Graph.defaultAgentId);
481
- const traceMetadata = {
481
+ const traceMetadata = createLangfuseTraceMetadata({
482
482
  messageId: this.id,
483
483
  parentMessageId: config.configurable?.requestBody?.parentMessageId,
484
484
  agentName: primaryContext?.name,
485
- };
486
- const handler = new CallbackHandler({
485
+ });
486
+ const handler = createLegacyLangfuseHandler({
487
487
  userId,
488
488
  sessionId,
489
489
  traceMetadata,
490
+ tags: ['librechat', 'agent'],
490
491
  });
491
- config.callbacks = (config.callbacks ?? []).concat([handler]);
492
+ config.runName = config.runName ?? getLangfuseTraceName(traceMetadata);
493
+ config.callbacks = appendCallbacks(config.callbacks, [handler]);
492
494
  }
493
495
  if (!this.id) {
494
496
  throw new Error('Run ID not provided');
@@ -887,23 +889,46 @@ class Run {
887
889
  };
888
890
  }
889
891
  async generateTitle({ provider, inputText, contentParts, titlePrompt, clientOptions, chainOptions, skipLanguage, titleMethod = TitleMethod.COMPLETION, titlePromptTemplate, }) {
890
- if (chainOptions != null &&
891
- isPresent(process.env.LANGFUSE_SECRET_KEY) &&
892
- isPresent(process.env.LANGFUSE_PUBLIC_KEY) &&
893
- isPresent(process.env.LANGFUSE_BASE_URL)) {
894
- const userId = chainOptions.configurable?.user_id;
895
- const sessionId = chainOptions.configurable?.thread_id;
896
- const titleContext = this.Graph?.agentContexts.get(this.Graph.defaultAgentId);
897
- const traceMetadata = {
898
- messageId: 'title-' + this.id,
899
- agentName: titleContext?.name,
900
- };
901
- const handler = new CallbackHandler({
902
- userId,
903
- sessionId,
904
- traceMetadata,
905
- });
906
- chainOptions.callbacks = (chainOptions.callbacks ?? []).concat([handler]);
892
+ let titleLangfuseHandler;
893
+ const titleContext = this.Graph == null
894
+ ? undefined
895
+ : this.Graph.agentContexts.get(this.Graph.defaultAgentId);
896
+ const traceMetadata = createLangfuseTraceMetadata({
897
+ messageId: 'title-' + this.id,
898
+ agentName: titleContext?.name,
899
+ });
900
+ const titleRunName = getLangfuseTraceName(traceMetadata, 'LibreChat Title');
901
+ if (chainOptions != null) {
902
+ const userId = typeof chainOptions.configurable?.user_id === 'string'
903
+ ? chainOptions.configurable.user_id
904
+ : undefined;
905
+ const sessionId = typeof chainOptions.configurable?.thread_id === 'string'
906
+ ? chainOptions.configurable.thread_id
907
+ : undefined;
908
+ const hasExplicitLangfuse = this.Graph != null &&
909
+ hasExplicitLangfuseConfig(this.Graph.agentContexts.values());
910
+ if (titleContext?.langfuse != null) {
911
+ titleLangfuseHandler = createLangfuseHandler({
912
+ langfuse: titleContext.langfuse,
913
+ userId,
914
+ sessionId,
915
+ traceMetadata,
916
+ tags: ['librechat', 'title'],
917
+ });
918
+ }
919
+ else if (hasLangfuseEnvConfig() && !hasExplicitLangfuse) {
920
+ titleLangfuseHandler = createLegacyLangfuseHandler({
921
+ userId,
922
+ sessionId,
923
+ traceMetadata,
924
+ tags: ['librechat', 'title'],
925
+ });
926
+ }
927
+ if (titleLangfuseHandler != null) {
928
+ chainOptions.callbacks = appendCallbacks(chainOptions.callbacks, [
929
+ titleLangfuseHandler,
930
+ ]);
931
+ }
907
932
  }
908
933
  const convoTemplate = PromptTemplate.fromTemplate(titlePromptTemplate ?? 'User: {input}\nAI: {output}');
909
934
  const response = contentParts
@@ -947,19 +972,25 @@ class Run {
947
972
  const invokeConfig = Object.assign({}, chainOptions, {
948
973
  run_id: this.id,
949
974
  runId: this.id,
975
+ runName: chainOptions?.runName ?? titleRunName,
950
976
  });
951
977
  try {
952
- return await fullChain.invoke({ input: inputText, output: response }, invokeConfig);
953
- }
954
- catch (_e) {
955
- // Fallback: strip callbacks to avoid EventStream tracer errors in certain environments
956
- // But preserve langfuse handler if it exists
957
- const langfuseHandler = invokeConfig.callbacks?.find((cb) => cb instanceof CallbackHandler);
958
- const { callbacks: _cb, ...rest } = invokeConfig;
959
- const safeConfig = Object.assign({}, rest, {
960
- callbacks: langfuseHandler ? [langfuseHandler] : [],
961
- });
962
- return await fullChain.invoke({ input: inputText, output: response }, safeConfig);
978
+ try {
979
+ return await fullChain.invoke({ input: inputText, output: response }, invokeConfig);
980
+ }
981
+ catch (_e) {
982
+ // Fallback: strip callbacks to avoid EventStream tracer errors in certain environments
983
+ // but preserve Langfuse tracing if it exists.
984
+ const langfuseHandler = findCallback(invokeConfig.callbacks, isLangfuseCallbackHandler);
985
+ const { callbacks: _cb, ...rest } = invokeConfig;
986
+ const safeConfig = Object.assign({}, rest, {
987
+ callbacks: langfuseHandler ? [langfuseHandler] : [],
988
+ });
989
+ return await fullChain.invoke({ input: inputText, output: response }, safeConfig);
990
+ }
991
+ }
992
+ finally {
993
+ await disposeLangfuseHandler(titleLangfuseHandler);
963
994
  }
964
995
  }
965
996
  }