@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.
- package/dist/cjs/agents/AgentContext.cjs +9 -5
- package/dist/cjs/agents/AgentContext.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +48 -14
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/instrumentation.cjs +2 -7
- package/dist/cjs/instrumentation.cjs.map +1 -1
- package/dist/cjs/langfuse.cjs +285 -0
- package/dist/cjs/langfuse.cjs.map +1 -0
- package/dist/cjs/main.cjs +25 -0
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/run.cjs +75 -44
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/stream.cjs +10 -3
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/tools/cloudflare/CloudflareBridgeRuntime.cjs +380 -0
- package/dist/cjs/tools/cloudflare/CloudflareBridgeRuntime.cjs.map +1 -0
- package/dist/cjs/tools/cloudflare/CloudflareProgrammaticToolCalling.cjs +997 -0
- package/dist/cjs/tools/cloudflare/CloudflareProgrammaticToolCalling.cjs.map +1 -0
- package/dist/cjs/tools/cloudflare/CloudflareSandboxExecutionEngine.cjs +575 -0
- package/dist/cjs/tools/cloudflare/CloudflareSandboxExecutionEngine.cjs.map +1 -0
- package/dist/cjs/tools/cloudflare/CloudflareSandboxTools.cjs +165 -0
- package/dist/cjs/tools/cloudflare/CloudflareSandboxTools.cjs.map +1 -0
- package/dist/cjs/tools/local/LocalExecutionEngine.cjs +17 -5
- package/dist/cjs/tools/local/LocalExecutionEngine.cjs.map +1 -1
- package/dist/cjs/tools/local/resolveLocalExecutionTools.cjs +110 -6
- package/dist/cjs/tools/local/resolveLocalExecutionTools.cjs.map +1 -1
- package/dist/cjs/utils/callbacks.cjs +27 -0
- package/dist/cjs/utils/callbacks.cjs.map +1 -0
- package/dist/esm/agents/AgentContext.mjs +9 -5
- package/dist/esm/agents/AgentContext.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +48 -14
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/instrumentation.mjs +2 -7
- package/dist/esm/instrumentation.mjs.map +1 -1
- package/dist/esm/langfuse.mjs +275 -0
- package/dist/esm/langfuse.mjs.map +1 -0
- package/dist/esm/main.mjs +5 -1
- package/dist/esm/main.mjs.map +1 -1
- package/dist/esm/run.mjs +75 -44
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/stream.mjs +10 -3
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/tools/cloudflare/CloudflareBridgeRuntime.mjs +378 -0
- package/dist/esm/tools/cloudflare/CloudflareBridgeRuntime.mjs.map +1 -0
- package/dist/esm/tools/cloudflare/CloudflareProgrammaticToolCalling.mjs +994 -0
- package/dist/esm/tools/cloudflare/CloudflareProgrammaticToolCalling.mjs.map +1 -0
- package/dist/esm/tools/cloudflare/CloudflareSandboxExecutionEngine.mjs +566 -0
- package/dist/esm/tools/cloudflare/CloudflareSandboxExecutionEngine.mjs.map +1 -0
- package/dist/esm/tools/cloudflare/CloudflareSandboxTools.mjs +155 -0
- package/dist/esm/tools/cloudflare/CloudflareSandboxTools.mjs.map +1 -0
- package/dist/esm/tools/local/LocalExecutionEngine.mjs +17 -6
- package/dist/esm/tools/local/LocalExecutionEngine.mjs.map +1 -1
- package/dist/esm/tools/local/resolveLocalExecutionTools.mjs +111 -7
- package/dist/esm/tools/local/resolveLocalExecutionTools.mjs.map +1 -1
- package/dist/esm/utils/callbacks.mjs +24 -0
- package/dist/esm/utils/callbacks.mjs.map +1 -0
- package/dist/types/agents/AgentContext.d.ts +4 -1
- package/dist/types/graphs/Graph.d.ts +6 -5
- package/dist/types/index.d.ts +1 -0
- package/dist/types/langfuse.d.ts +57 -0
- package/dist/types/tools/cloudflare/CloudflareBridgeRuntime.d.ts +23 -0
- package/dist/types/tools/cloudflare/CloudflareProgrammaticToolCalling.d.ts +4 -0
- package/dist/types/tools/cloudflare/CloudflareSandboxExecutionEngine.d.ts +21 -0
- package/dist/types/tools/cloudflare/CloudflareSandboxTools.d.ts +22 -0
- package/dist/types/tools/cloudflare/index.d.ts +4 -0
- package/dist/types/tools/local/LocalExecutionEngine.d.ts +1 -0
- package/dist/types/types/graph.d.ts +8 -0
- package/dist/types/types/run.d.ts +2 -2
- package/dist/types/types/tools.d.ts +118 -2
- package/dist/types/utils/callbacks.d.ts +5 -0
- package/package.json +4 -4
- package/src/__tests__/stream.eagerEventExecution.test.ts +66 -0
- package/src/agents/AgentContext.ts +13 -3
- package/src/graphs/Graph.ts +57 -16
- package/src/index.ts +1 -0
- package/src/instrumentation.ts +2 -7
- package/src/langfuse.ts +441 -0
- package/src/run.ts +105 -59
- package/src/specs/langfuse-callbacks.test.ts +75 -0
- package/src/specs/langfuse-config.test.ts +114 -0
- package/src/specs/langfuse-metadata.test.ts +19 -1
- package/src/stream.ts +13 -3
- package/src/tools/__tests__/CloudflareSandboxExecution.test.ts +537 -0
- package/src/tools/cloudflare/CloudflareBridgeRuntime.ts +480 -0
- package/src/tools/cloudflare/CloudflareProgrammaticToolCalling.ts +1162 -0
- package/src/tools/cloudflare/CloudflareSandboxExecutionEngine.ts +744 -0
- package/src/tools/cloudflare/CloudflareSandboxTools.ts +225 -0
- package/src/tools/cloudflare/index.ts +4 -0
- package/src/tools/local/LocalExecutionEngine.ts +20 -4
- package/src/tools/local/resolveLocalExecutionTools.ts +169 -7
- package/src/types/graph.ts +9 -0
- package/src/types/run.ts +2 -7
- package/src/types/tools.ts +141 -2
- package/src/utils/callbacks.ts +39 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { CallbackManager } from '@langchain/core/callbacks/manager';
|
|
2
|
+
import { HumanMessage } from '@langchain/core/messages';
|
|
3
|
+
import { Providers } from '@/common';
|
|
4
|
+
import { Run } from '@/run';
|
|
5
|
+
import type * as t from '@/types';
|
|
6
|
+
|
|
7
|
+
const mockSpan = {
|
|
8
|
+
end: jest.fn(),
|
|
9
|
+
setAttributes: jest.fn(),
|
|
10
|
+
setStatus: jest.fn(),
|
|
11
|
+
};
|
|
12
|
+
const mockStartSpan = jest.fn(() => mockSpan);
|
|
13
|
+
const mockForceFlush = jest.fn();
|
|
14
|
+
const mockShutdown = jest.fn();
|
|
15
|
+
|
|
16
|
+
jest.mock('@langfuse/otel', () => ({
|
|
17
|
+
LangfuseSpanProcessor: jest.fn().mockImplementation(() => ({})),
|
|
18
|
+
isDefaultExportSpan: jest.fn(() => false),
|
|
19
|
+
}));
|
|
20
|
+
|
|
21
|
+
jest.mock('@opentelemetry/sdk-trace-base', () => ({
|
|
22
|
+
BasicTracerProvider: jest.fn().mockImplementation(() => ({
|
|
23
|
+
forceFlush: mockForceFlush,
|
|
24
|
+
getTracer: jest.fn(() => ({
|
|
25
|
+
startSpan: mockStartSpan,
|
|
26
|
+
})),
|
|
27
|
+
shutdown: mockShutdown,
|
|
28
|
+
})),
|
|
29
|
+
}));
|
|
30
|
+
|
|
31
|
+
describe('Langfuse callback composition', () => {
|
|
32
|
+
beforeEach(() => {
|
|
33
|
+
jest.clearAllMocks();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('runs explicit per-agent tracing when callbacks is a CallbackManager', async () => {
|
|
37
|
+
const manager = CallbackManager.fromHandlers({
|
|
38
|
+
handleCustomEvent: async (): Promise<void> => undefined,
|
|
39
|
+
});
|
|
40
|
+
const run = await Run.create<t.IState>({
|
|
41
|
+
runId: 'test-langfuse-callback-manager',
|
|
42
|
+
graphConfig: {
|
|
43
|
+
type: 'standard',
|
|
44
|
+
agents: [
|
|
45
|
+
{
|
|
46
|
+
agentId: 'agent_abc123',
|
|
47
|
+
name: 'DWAINE',
|
|
48
|
+
provider: Providers.OPENAI,
|
|
49
|
+
clientOptions: { model: 'gpt-4' },
|
|
50
|
+
tools: [],
|
|
51
|
+
langfuse: {
|
|
52
|
+
enabled: true,
|
|
53
|
+
publicKey: 'pk-test',
|
|
54
|
+
secretKey: 'sk-test',
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
skipCleanup: true,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
run.Graph?.overrideTestModel(['hello']);
|
|
63
|
+
|
|
64
|
+
const config = {
|
|
65
|
+
callbacks: manager,
|
|
66
|
+
configurable: { thread_id: 'thread-1', user_id: 'user-1' },
|
|
67
|
+
streamMode: 'values' as const,
|
|
68
|
+
version: 'v2' as const,
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
await run.processStream({ messages: [new HumanMessage('hello')] }, config);
|
|
72
|
+
|
|
73
|
+
expect(mockStartSpan).toHaveBeenCalled();
|
|
74
|
+
});
|
|
75
|
+
});
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { LangfuseSpanProcessor } from '@langfuse/otel';
|
|
2
|
+
import { BasicTracerProvider } from '@opentelemetry/sdk-trace-base';
|
|
3
|
+
import { HumanMessage } from '@langchain/core/messages';
|
|
4
|
+
import type { Serialized } from '@langchain/core/load/serializable';
|
|
5
|
+
import { createLangfuseHandler } from '@/langfuse';
|
|
6
|
+
|
|
7
|
+
const mockSpan = {
|
|
8
|
+
end: jest.fn(),
|
|
9
|
+
setAttributes: jest.fn(),
|
|
10
|
+
setStatus: jest.fn(),
|
|
11
|
+
};
|
|
12
|
+
const mockStartSpan = jest.fn(() => mockSpan);
|
|
13
|
+
const mockGetTracer = jest.fn(() => ({
|
|
14
|
+
startSpan: mockStartSpan,
|
|
15
|
+
}));
|
|
16
|
+
|
|
17
|
+
jest.mock('@langfuse/otel', () => ({
|
|
18
|
+
LangfuseSpanProcessor: jest.fn().mockImplementation(() => ({})),
|
|
19
|
+
isDefaultExportSpan: jest.fn(() => false),
|
|
20
|
+
}));
|
|
21
|
+
|
|
22
|
+
jest.mock('@opentelemetry/sdk-trace-base', () => ({
|
|
23
|
+
BasicTracerProvider: jest.fn().mockImplementation(() => ({
|
|
24
|
+
forceFlush: jest.fn(),
|
|
25
|
+
getTracer: mockGetTracer,
|
|
26
|
+
shutdown: jest.fn(),
|
|
27
|
+
})),
|
|
28
|
+
}));
|
|
29
|
+
|
|
30
|
+
describe('createLangfuseHandler', () => {
|
|
31
|
+
beforeEach(() => {
|
|
32
|
+
jest.clearAllMocks();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('creates a handler when keys are provided and baseUrl is omitted', () => {
|
|
36
|
+
const handler = createLangfuseHandler({
|
|
37
|
+
langfuse: {
|
|
38
|
+
enabled: true,
|
|
39
|
+
publicKey: 'pk-test',
|
|
40
|
+
secretKey: 'sk-test',
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
expect(handler).toBeDefined();
|
|
45
|
+
expect(LangfuseSpanProcessor).toHaveBeenCalledWith(
|
|
46
|
+
expect.objectContaining({
|
|
47
|
+
publicKey: 'pk-test',
|
|
48
|
+
secretKey: 'sk-test',
|
|
49
|
+
exportMode: 'immediate',
|
|
50
|
+
})
|
|
51
|
+
);
|
|
52
|
+
expect(
|
|
53
|
+
(LangfuseSpanProcessor as jest.Mock).mock.calls[0][0].baseUrl
|
|
54
|
+
).toBeUndefined();
|
|
55
|
+
expect(BasicTracerProvider).toHaveBeenCalledTimes(1);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('starts per-agent spans with v5 trace attributes', async () => {
|
|
59
|
+
const handler = createLangfuseHandler({
|
|
60
|
+
langfuse: {
|
|
61
|
+
enabled: true,
|
|
62
|
+
publicKey: 'pk-test',
|
|
63
|
+
secretKey: 'sk-test',
|
|
64
|
+
},
|
|
65
|
+
userId: 'user-1',
|
|
66
|
+
sessionId: 'thread-1',
|
|
67
|
+
traceMetadata: {
|
|
68
|
+
messageId: 'message-1',
|
|
69
|
+
agentId: 'agent-1',
|
|
70
|
+
agentName: 'DWAINE',
|
|
71
|
+
},
|
|
72
|
+
tags: ['librechat', 'agent'],
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
await handler?.handleChatModelStart(
|
|
76
|
+
{
|
|
77
|
+
id: ['langchain', 'chat_models', 'ChatOpenAI'],
|
|
78
|
+
kwargs: { model: 'gpt-4o' },
|
|
79
|
+
} as unknown as Serialized,
|
|
80
|
+
[[new HumanMessage('hello')]],
|
|
81
|
+
'run-1'
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
expect(mockGetTracer).toHaveBeenCalledWith('langfuse-sdk');
|
|
85
|
+
expect(mockStartSpan).toHaveBeenCalledWith(
|
|
86
|
+
'gpt-4o',
|
|
87
|
+
expect.objectContaining({
|
|
88
|
+
attributes: expect.objectContaining({
|
|
89
|
+
'langfuse.trace.name': 'LibreChat Agent: DWAINE',
|
|
90
|
+
'langfuse.trace.metadata.agentId': 'agent-1',
|
|
91
|
+
'langfuse.trace.metadata.messageId': 'message-1',
|
|
92
|
+
'langfuse.observation.model.name': 'gpt-4o',
|
|
93
|
+
'langfuse.observation.type': 'generation',
|
|
94
|
+
'user.id': 'user-1',
|
|
95
|
+
'session.id': 'thread-1',
|
|
96
|
+
'langfuse.trace.tags': ['librechat', 'agent'],
|
|
97
|
+
}),
|
|
98
|
+
})
|
|
99
|
+
);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('does not create a handler when a required key is missing', () => {
|
|
103
|
+
const handler = createLangfuseHandler({
|
|
104
|
+
langfuse: {
|
|
105
|
+
enabled: true,
|
|
106
|
+
publicKey: 'pk-test',
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
expect(handler).toBeUndefined();
|
|
111
|
+
expect(LangfuseSpanProcessor).not.toHaveBeenCalled();
|
|
112
|
+
expect(BasicTracerProvider).not.toHaveBeenCalled();
|
|
113
|
+
});
|
|
114
|
+
});
|
|
@@ -10,7 +10,10 @@ const MockedCallbackHandler = CallbackHandler as jest.MockedClass<
|
|
|
10
10
|
typeof CallbackHandler
|
|
11
11
|
>;
|
|
12
12
|
|
|
13
|
-
async function createTestRun(
|
|
13
|
+
async function createTestRun(
|
|
14
|
+
agentName?: string,
|
|
15
|
+
agentOverrides: Record<string, unknown> = {}
|
|
16
|
+
): Promise<Run<never>> {
|
|
14
17
|
const run = await Run.create({
|
|
15
18
|
runId: 'test-run-id',
|
|
16
19
|
graphConfig: {
|
|
@@ -22,6 +25,7 @@ async function createTestRun(agentName?: string): Promise<Run<never>> {
|
|
|
22
25
|
provider: Providers.OPENAI,
|
|
23
26
|
clientOptions: { model: 'gpt-4' },
|
|
24
27
|
tools: [],
|
|
28
|
+
...agentOverrides,
|
|
25
29
|
},
|
|
26
30
|
],
|
|
27
31
|
},
|
|
@@ -88,4 +92,18 @@ describe('Langfuse trace metadata includes agentName', () => {
|
|
|
88
92
|
|
|
89
93
|
expect(MockedCallbackHandler).not.toHaveBeenCalled();
|
|
90
94
|
});
|
|
95
|
+
|
|
96
|
+
it('does not create the legacy CallbackHandler when explicit agent config is supplied', async () => {
|
|
97
|
+
const run = await createTestRun('DWAINE', {
|
|
98
|
+
langfuse: {
|
|
99
|
+
enabled: false,
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
await run.processStream(
|
|
103
|
+
{ messages: [] },
|
|
104
|
+
{ configurable: { thread_id: 't1', user_id: 'u1' }, version: 'v2' }
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
expect(MockedCallbackHandler).not.toHaveBeenCalled();
|
|
108
|
+
});
|
|
91
109
|
});
|
package/src/stream.ts
CHANGED
|
@@ -136,10 +136,19 @@ function isDirectGraphTool(
|
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
function isDirectLocalTool(name: string, graph: StandardGraph): boolean {
|
|
139
|
-
|
|
139
|
+
const toolExecution = graph.toolExecution;
|
|
140
|
+
const engine = toolExecution?.engine;
|
|
141
|
+
if (
|
|
142
|
+
toolExecution == null ||
|
|
143
|
+
(engine !== 'local' && engine !== 'cloudflare-sandbox')
|
|
144
|
+
) {
|
|
140
145
|
return false;
|
|
141
146
|
}
|
|
142
|
-
|
|
147
|
+
const includeCodingTools =
|
|
148
|
+
engine === 'cloudflare-sandbox'
|
|
149
|
+
? toolExecution.cloudflare?.includeCodingTools
|
|
150
|
+
: toolExecution.local?.includeCodingTools;
|
|
151
|
+
if (includeCodingTools === false) {
|
|
143
152
|
return CODE_EXECUTION_TOOLS.has(name);
|
|
144
153
|
}
|
|
145
154
|
return LOCAL_CODING_BUNDLE_NAME_SET.has(name);
|
|
@@ -270,7 +279,8 @@ function hasPotentialDirectToolInStreamContext(args: {
|
|
|
270
279
|
agentContext?: AgentContext;
|
|
271
280
|
}): boolean {
|
|
272
281
|
const { graph, agentContext } = args;
|
|
273
|
-
|
|
282
|
+
const engine = graph.toolExecution?.engine;
|
|
283
|
+
if (engine === 'local' || engine === 'cloudflare-sandbox') {
|
|
274
284
|
return true;
|
|
275
285
|
}
|
|
276
286
|
if ((agentContext?.graphTools?.length ?? 0) > 0) {
|