@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
|
@@ -467,10 +467,11 @@ export type ToolOutputReferencesConfig = {
|
|
|
467
467
|
*/
|
|
468
468
|
maxTotalSize?: number;
|
|
469
469
|
};
|
|
470
|
-
export type ToolExecutionEngine = 'sandbox' | 'local';
|
|
470
|
+
export type ToolExecutionEngine = 'sandbox' | 'local' | 'cloudflare-sandbox';
|
|
471
471
|
/**
|
|
472
472
|
* Records pre-write file contents so callers can rewind edits/writes
|
|
473
|
-
* made by
|
|
473
|
+
* made by local-compatible coding-tool engines. Implementations live
|
|
474
|
+
* in `src/tools/local`.
|
|
474
475
|
*/
|
|
475
476
|
export interface LocalFileCheckpointer {
|
|
476
477
|
/**
|
|
@@ -586,6 +587,12 @@ export type LocalExecConfig = {
|
|
|
586
587
|
* overridden together for non-host engines.
|
|
587
588
|
*/
|
|
588
589
|
fs?: import('@/tools/local/workspaceFS').WorkspaceFS;
|
|
590
|
+
/**
|
|
591
|
+
* Set by custom execution backends that already provide their own
|
|
592
|
+
* sandbox boundary. Suppresses the local host-sandbox warning while
|
|
593
|
+
* preserving the warning for plain host `child_process` execution.
|
|
594
|
+
*/
|
|
595
|
+
sandboxed?: boolean;
|
|
589
596
|
};
|
|
590
597
|
export type LocalExecutionConfig = {
|
|
591
598
|
/**
|
|
@@ -740,11 +747,120 @@ export type LocalExecutionConfig = {
|
|
|
740
747
|
timeoutMs?: number;
|
|
741
748
|
};
|
|
742
749
|
};
|
|
750
|
+
export type CloudflareSandboxExecOptions = {
|
|
751
|
+
cwd?: string;
|
|
752
|
+
env?: Record<string, string | undefined>;
|
|
753
|
+
timeout?: number;
|
|
754
|
+
stream?: boolean;
|
|
755
|
+
onOutput?: (stream: 'stdout' | 'stderr', data: string) => void;
|
|
756
|
+
signal?: AbortSignal;
|
|
757
|
+
};
|
|
758
|
+
export type CloudflareSandboxExecResult = {
|
|
759
|
+
success?: boolean;
|
|
760
|
+
exitCode: number;
|
|
761
|
+
stdout: string;
|
|
762
|
+
stderr: string;
|
|
763
|
+
command?: string;
|
|
764
|
+
duration?: number;
|
|
765
|
+
timestamp?: string;
|
|
766
|
+
};
|
|
767
|
+
export type CloudflareSandboxReadFileResult = string | Buffer | Uint8Array | {
|
|
768
|
+
content: string | Buffer | Uint8Array | ReadableStream<Uint8Array>;
|
|
769
|
+
size?: number;
|
|
770
|
+
mimeType?: string;
|
|
771
|
+
encoding?: 'utf-8' | 'utf8' | 'base64';
|
|
772
|
+
isBinary?: boolean;
|
|
773
|
+
};
|
|
774
|
+
export type CloudflareSandboxListFilesOptions = {
|
|
775
|
+
recursive?: boolean;
|
|
776
|
+
includeHidden?: boolean;
|
|
777
|
+
};
|
|
778
|
+
export type CloudflareSandboxFileInfo = {
|
|
779
|
+
name: string;
|
|
780
|
+
absolutePath?: string;
|
|
781
|
+
relativePath?: string;
|
|
782
|
+
type?: 'file' | 'directory' | 'symlink' | 'other';
|
|
783
|
+
size?: number;
|
|
784
|
+
modifiedAt?: string;
|
|
785
|
+
mode?: string;
|
|
786
|
+
};
|
|
787
|
+
export type CloudflareSandboxListFilesResult = CloudflareSandboxFileInfo[] | {
|
|
788
|
+
files: CloudflareSandboxFileInfo[];
|
|
789
|
+
count?: number;
|
|
790
|
+
path?: string;
|
|
791
|
+
success?: boolean;
|
|
792
|
+
};
|
|
793
|
+
export interface CloudflareSandboxRuntime {
|
|
794
|
+
exec(command: string, options?: CloudflareSandboxExecOptions): Promise<CloudflareSandboxExecResult>;
|
|
795
|
+
readFile(path: string, options?: {
|
|
796
|
+
encoding?: string;
|
|
797
|
+
}): Promise<CloudflareSandboxReadFileResult>;
|
|
798
|
+
writeFile(path: string, content: string | ReadableStream<Uint8Array>, options?: {
|
|
799
|
+
encoding?: string;
|
|
800
|
+
}): Promise<unknown>;
|
|
801
|
+
mkdir(path: string, options?: {
|
|
802
|
+
recursive?: boolean;
|
|
803
|
+
}): Promise<unknown>;
|
|
804
|
+
listFiles(path: string, options?: CloudflareSandboxListFilesOptions): Promise<CloudflareSandboxListFilesResult>;
|
|
805
|
+
deleteFile(path: string): Promise<unknown>;
|
|
806
|
+
}
|
|
807
|
+
export type CloudflareSandboxExecutionConfig = {
|
|
808
|
+
sandbox: CloudflareSandboxRuntime | (() => CloudflareSandboxRuntime | Promise<CloudflareSandboxRuntime>);
|
|
809
|
+
/** Working directory inside the sandbox. Defaults to `/workspace`. */
|
|
810
|
+
workspaceRoot?: string;
|
|
811
|
+
/** Extra environment variables merged into sandbox command executions. */
|
|
812
|
+
env?: Record<string, string | undefined>;
|
|
813
|
+
/** Default timeout for sandbox commands, in milliseconds. */
|
|
814
|
+
timeoutMs?: number;
|
|
815
|
+
/** Maximum stdout/stderr characters surfaced to the model. */
|
|
816
|
+
maxOutputChars?: number;
|
|
817
|
+
/**
|
|
818
|
+
* Add the built-in coding suite when `engine` is `cloudflare-sandbox`.
|
|
819
|
+
* Defaults to true, matching the local execution backend.
|
|
820
|
+
*/
|
|
821
|
+
includeCodingTools?: boolean;
|
|
822
|
+
/**
|
|
823
|
+
* Optional exact coding-tool names to expose when `includeCodingTools`
|
|
824
|
+
* is on. Defaults to the full local-parity Cloudflare bundle. Use this
|
|
825
|
+
* to publish a bash-only sandbox surface, for example file/search tools
|
|
826
|
+
* plus `bash_tool` and `run_tools_with_bash`, without exposing
|
|
827
|
+
* `execute_code`.
|
|
828
|
+
*/
|
|
829
|
+
codingToolNames?: readonly string[];
|
|
830
|
+
/** Optional shell executable for bash-style tools. Defaults to `bash`. */
|
|
831
|
+
shell?: string;
|
|
832
|
+
/**
|
|
833
|
+
* Optional project-level compile check configuration. Mirrors the local
|
|
834
|
+
* execution backend.
|
|
835
|
+
*/
|
|
836
|
+
compileCheck?: LocalExecutionConfig['compileCheck'];
|
|
837
|
+
/** Optional read-only guard for mutating coding tools. */
|
|
838
|
+
readOnly?: boolean;
|
|
839
|
+
/** Permit dangerous commands that the validator otherwise blocks. */
|
|
840
|
+
allowDangerousCommands?: LocalExecutionConfig['allowDangerousCommands'];
|
|
841
|
+
/** Tree-sitter-bash AST validation pass for bash commands. */
|
|
842
|
+
bashAst?: LocalExecutionConfig['bashAst'];
|
|
843
|
+
/**
|
|
844
|
+
* Enable per-Run file checkpointing for `edit_file` / `write_file`
|
|
845
|
+
* against the Cloudflare Sandbox workspace.
|
|
846
|
+
*/
|
|
847
|
+
fileCheckpointing?: LocalExecutionConfig['fileCheckpointing'];
|
|
848
|
+
/** Maximum bytes to read in `read_file` before returning a stub. */
|
|
849
|
+
maxReadBytes?: LocalExecutionConfig['maxReadBytes'];
|
|
850
|
+
/** Controls whether `read_file` returns binary files as attachments. */
|
|
851
|
+
attachReadAttachments?: LocalExecutionConfig['attachReadAttachments'];
|
|
852
|
+
/** Maximum pre-encoding byte size to embed inline. */
|
|
853
|
+
maxAttachmentBytes?: LocalExecutionConfig['maxAttachmentBytes'];
|
|
854
|
+
/** Run a fast per-file syntax check after successful edits/writes. */
|
|
855
|
+
postEditSyntaxCheck?: LocalExecutionConfig['postEditSyntaxCheck'];
|
|
856
|
+
};
|
|
743
857
|
export type ToolExecutionConfig = {
|
|
744
858
|
/** `sandbox` preserves the remote Code API behavior and is the default. */
|
|
745
859
|
engine?: ToolExecutionEngine;
|
|
746
860
|
/** Local process execution settings used when `engine` is `local`. */
|
|
747
861
|
local?: LocalExecutionConfig;
|
|
862
|
+
/** Cloudflare Sandbox execution settings used when `engine` is `cloudflare-sandbox`. */
|
|
863
|
+
cloudflare?: CloudflareSandboxExecutionConfig;
|
|
748
864
|
};
|
|
749
865
|
export type ProgrammaticCache = {
|
|
750
866
|
toolMap: ToolMap;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { BaseCallbackHandler, CallbackHandlerMethods } from '@langchain/core/callbacks/base';
|
|
2
|
+
import type { Callbacks } from '@langchain/core/callbacks/manager';
|
|
3
|
+
export type CallbackEntry = BaseCallbackHandler | CallbackHandlerMethods;
|
|
4
|
+
export declare function appendCallbacks(callbacks: Callbacks | undefined, additions: readonly CallbackEntry[]): Callbacks;
|
|
5
|
+
export declare function findCallback(callbacks: Callbacks | undefined, predicate: (callback: CallbackEntry) => boolean): CallbackEntry | undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@librechat/agents",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.92",
|
|
4
4
|
"main": "./dist/cjs/main.cjs",
|
|
5
5
|
"module": "./dist/esm/main.mjs",
|
|
6
6
|
"types": "./dist/types/index.d.ts",
|
|
@@ -227,9 +227,9 @@
|
|
|
227
227
|
"@langchain/openai": "1.4.5",
|
|
228
228
|
"@langchain/textsplitters": "^1.0.1",
|
|
229
229
|
"@langchain/xai": "^1.3.17",
|
|
230
|
-
"@langfuse/langchain": "^
|
|
231
|
-
"@langfuse/otel": "^
|
|
232
|
-
"@langfuse/tracing": "^
|
|
230
|
+
"@langfuse/langchain": "^5.3.0",
|
|
231
|
+
"@langfuse/otel": "^5.3.0",
|
|
232
|
+
"@langfuse/tracing": "^5.3.0",
|
|
233
233
|
"@opentelemetry/sdk-node": "^0.218.0",
|
|
234
234
|
"@scarf/scarf": "^1.4.0",
|
|
235
235
|
"@types/diff": "^7.0.2",
|
|
@@ -2847,6 +2847,72 @@ describe('ChatModelStreamHandler eager event tool execution', () => {
|
|
|
2847
2847
|
expect(graph.eagerEventToolCallChunks.size).toBe(0);
|
|
2848
2848
|
});
|
|
2849
2849
|
|
|
2850
|
+
it('does not prestart streamed Cloudflare sandbox direct coding tools', async () => {
|
|
2851
|
+
const graph = createGraph({
|
|
2852
|
+
toolExecution: {
|
|
2853
|
+
engine: 'cloudflare-sandbox',
|
|
2854
|
+
cloudflare: { sandbox: {} },
|
|
2855
|
+
} as StandardGraph['toolExecution'],
|
|
2856
|
+
getAgentContext: jest.fn(
|
|
2857
|
+
(): Partial<AgentContext> => ({
|
|
2858
|
+
provider: Providers.OPENAI,
|
|
2859
|
+
reasoningKey: 'reasoning_content',
|
|
2860
|
+
toolDefinitions: [{ name: Constants.BASH_TOOL }, { name: 'weather' }],
|
|
2861
|
+
graphTools: [],
|
|
2862
|
+
agentId: 'agent_1',
|
|
2863
|
+
})
|
|
2864
|
+
) as unknown as StandardGraph['getAgentContext'],
|
|
2865
|
+
});
|
|
2866
|
+
const dispatchSpy = jest.spyOn(events, 'safeDispatchCustomEvent');
|
|
2867
|
+
const handler = new ChatModelStreamHandler();
|
|
2868
|
+
const metadata = { langgraph_node: 'agent' };
|
|
2869
|
+
|
|
2870
|
+
await handler.handle(
|
|
2871
|
+
GraphEvents.CHAT_MODEL_STREAM,
|
|
2872
|
+
{
|
|
2873
|
+
chunk: {
|
|
2874
|
+
content: '',
|
|
2875
|
+
tool_call_chunks: [
|
|
2876
|
+
{
|
|
2877
|
+
id: 'call_weather',
|
|
2878
|
+
name: 'weather',
|
|
2879
|
+
args: '{"city":"NYC"}',
|
|
2880
|
+
index: 0,
|
|
2881
|
+
},
|
|
2882
|
+
],
|
|
2883
|
+
} as unknown as t.StreamChunk,
|
|
2884
|
+
},
|
|
2885
|
+
metadata,
|
|
2886
|
+
graph
|
|
2887
|
+
);
|
|
2888
|
+
await handler.handle(
|
|
2889
|
+
GraphEvents.CHAT_MODEL_STREAM,
|
|
2890
|
+
{
|
|
2891
|
+
chunk: {
|
|
2892
|
+
content: '',
|
|
2893
|
+
tool_call_chunks: [
|
|
2894
|
+
{
|
|
2895
|
+
id: 'call_bash',
|
|
2896
|
+
name: Constants.BASH_TOOL,
|
|
2897
|
+
args: '{"command":"echo ok"}',
|
|
2898
|
+
index: 1,
|
|
2899
|
+
},
|
|
2900
|
+
],
|
|
2901
|
+
} as unknown as t.StreamChunk,
|
|
2902
|
+
},
|
|
2903
|
+
metadata,
|
|
2904
|
+
graph
|
|
2905
|
+
);
|
|
2906
|
+
|
|
2907
|
+
expect(dispatchSpy).not.toHaveBeenCalledWith(
|
|
2908
|
+
GraphEvents.ON_TOOL_EXECUTE,
|
|
2909
|
+
expect.anything(),
|
|
2910
|
+
expect.anything()
|
|
2911
|
+
);
|
|
2912
|
+
expect(graph.eagerEventToolExecutions.size).toBe(0);
|
|
2913
|
+
expect(graph.eagerEventToolCallChunks.size).toBe(0);
|
|
2914
|
+
});
|
|
2915
|
+
|
|
2850
2916
|
it('prestarts streamed remote bash tools when the next Anthropic tool call begins', async () => {
|
|
2851
2917
|
const graph = createGraph({
|
|
2852
2918
|
getAgentContext: jest.fn(
|
|
@@ -53,6 +53,7 @@ export class AgentContext {
|
|
|
53
53
|
name,
|
|
54
54
|
provider,
|
|
55
55
|
clientOptions,
|
|
56
|
+
langfuse,
|
|
56
57
|
tools,
|
|
57
58
|
toolMap,
|
|
58
59
|
toolEnd,
|
|
@@ -80,6 +81,7 @@ export class AgentContext {
|
|
|
80
81
|
name: name ?? agentId,
|
|
81
82
|
provider,
|
|
82
83
|
clientOptions,
|
|
84
|
+
langfuse,
|
|
83
85
|
maxContextTokens,
|
|
84
86
|
streamBuffer,
|
|
85
87
|
tools,
|
|
@@ -149,6 +151,8 @@ export class AgentContext {
|
|
|
149
151
|
provider: Providers;
|
|
150
152
|
/** Client options for this agent */
|
|
151
153
|
clientOptions?: t.ClientOptions;
|
|
154
|
+
/** Per-agent Langfuse tracing configuration. */
|
|
155
|
+
langfuse?: t.LangfuseConfig;
|
|
152
156
|
/** Token count map indexed by message position */
|
|
153
157
|
indexTokenCountMap: Record<string, number | undefined> = {};
|
|
154
158
|
/** Canonical pre-run token map used to restore token accounting on reset */
|
|
@@ -309,6 +313,7 @@ export class AgentContext {
|
|
|
309
313
|
name,
|
|
310
314
|
provider,
|
|
311
315
|
clientOptions,
|
|
316
|
+
langfuse,
|
|
312
317
|
maxContextTokens,
|
|
313
318
|
streamBuffer,
|
|
314
319
|
tokenCounter,
|
|
@@ -332,6 +337,7 @@ export class AgentContext {
|
|
|
332
337
|
name?: string;
|
|
333
338
|
provider: Providers;
|
|
334
339
|
clientOptions?: t.ClientOptions;
|
|
340
|
+
langfuse?: t.LangfuseConfig;
|
|
335
341
|
maxContextTokens?: number;
|
|
336
342
|
streamBuffer?: number;
|
|
337
343
|
tokenCounter?: t.TokenCounter;
|
|
@@ -355,6 +361,7 @@ export class AgentContext {
|
|
|
355
361
|
this.name = name;
|
|
356
362
|
this.provider = provider;
|
|
357
363
|
this.clientOptions = clientOptions;
|
|
364
|
+
this.langfuse = langfuse;
|
|
358
365
|
this.maxContextTokens = maxContextTokens;
|
|
359
366
|
this.streamBuffer = streamBuffer;
|
|
360
367
|
this.tokenCounter = tokenCounter;
|
|
@@ -458,11 +465,14 @@ export class AgentContext {
|
|
|
458
465
|
}
|
|
459
466
|
|
|
460
467
|
private hasAvailableTool(name: string): boolean {
|
|
461
|
-
if (this.toolDefinitions?.some((tool) => tool.name === name)
|
|
462
|
-
|
|
468
|
+
if (this.toolDefinitions?.some((tool) => tool.name === name) === true)
|
|
469
|
+
return true;
|
|
470
|
+
if (
|
|
471
|
+
this.tools?.some((tool) => 'name' in tool && tool.name === name) === true
|
|
472
|
+
) {
|
|
463
473
|
return true;
|
|
464
474
|
}
|
|
465
|
-
if (this.toolMap?.has(name)) return true;
|
|
475
|
+
if (this.toolMap?.has(name) === true) return true;
|
|
466
476
|
return this.toolRegistry?.has(name) === true;
|
|
467
477
|
}
|
|
468
478
|
|
package/src/graphs/Graph.ts
CHANGED
|
@@ -52,14 +52,21 @@ import { attemptInvoke, tryFallbackProviders } from '@/llm/invoke';
|
|
|
52
52
|
import { shouldTriggerSummarization } from '@/summarization';
|
|
53
53
|
import { createSummarizeNode } from '@/summarization/node';
|
|
54
54
|
import { messagesStateReducer } from '@/messages/reducer';
|
|
55
|
+
import { appendCallbacks } from '@/utils/callbacks';
|
|
55
56
|
import { createSchemaOnlyTools } from '@/tools/schema';
|
|
56
57
|
import { AgentContext } from '@/agents/AgentContext';
|
|
57
58
|
import { createFakeStreamingLLM } from '@/llm/fake';
|
|
58
59
|
import { handleToolCalls } from '@/tools/handlers';
|
|
59
60
|
import { resolveLocalToolsForBinding } from '@/tools/local';
|
|
60
61
|
import { createLocalCodingToolBundle } from '@/tools/local/LocalCodingTools';
|
|
62
|
+
import { createCloudflareCodingToolBundle } from '@/tools/cloudflare';
|
|
61
63
|
import { isThinkingEnabled } from '@/llm/request';
|
|
62
64
|
import { initializeModel } from '@/llm/init';
|
|
65
|
+
import {
|
|
66
|
+
createLangfuseHandler,
|
|
67
|
+
disposeLangfuseHandler,
|
|
68
|
+
createLangfuseTraceMetadata,
|
|
69
|
+
} from '@/langfuse';
|
|
63
70
|
import { HandlerRegistry } from '@/events';
|
|
64
71
|
import { ChatOpenAI } from '@/llm/openai';
|
|
65
72
|
import { partitionAndMarkOpenRouterToolCache } from '@/llm/openrouter/toolCache';
|
|
@@ -337,11 +344,12 @@ export abstract class Graph<
|
|
|
337
344
|
/**
|
|
338
345
|
* Single per-Run file checkpointer shared across every ToolNode the
|
|
339
346
|
* graph compiles. Lazily constructed when
|
|
340
|
-
* `toolExecution.local.fileCheckpointing === true`
|
|
341
|
-
*
|
|
342
|
-
*
|
|
343
|
-
*
|
|
344
|
-
*
|
|
347
|
+
* `toolExecution.local.fileCheckpointing === true` or
|
|
348
|
+
* `toolExecution.cloudflare.fileCheckpointing === true` so
|
|
349
|
+
* multi-agent graphs see ONE snapshot store, not one-per-agent.
|
|
350
|
+
* Returns undefined when checkpointing is disabled or a supported
|
|
351
|
+
* coding-tool engine isn't selected. Exposed via
|
|
352
|
+
* `Run.getFileCheckpointer()` / `Run.rewindFiles()`.
|
|
345
353
|
*/
|
|
346
354
|
private _fileCheckpointer?: t.LocalFileCheckpointer;
|
|
347
355
|
/**
|
|
@@ -364,20 +372,32 @@ export abstract class Graph<
|
|
|
364
372
|
if (this._fileCheckpointer != null) {
|
|
365
373
|
return this._fileCheckpointer;
|
|
366
374
|
}
|
|
367
|
-
if (
|
|
368
|
-
this.toolExecution?.engine !== 'local' ||
|
|
369
|
-
this.toolExecution.local?.fileCheckpointing !== true
|
|
370
|
-
) {
|
|
371
|
-
return undefined;
|
|
372
|
-
}
|
|
373
375
|
// Eagerly create via the bundle factory so the construction path
|
|
374
376
|
// matches the bundle-only callers (and future bundle-internal
|
|
375
377
|
// cleanup hooks fire). The bundle factory itself accepts a pre-
|
|
376
378
|
// supplied checkpointer when present, so re-injecting this one
|
|
377
379
|
// into every ToolNode is idempotent.
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
380
|
+
if (
|
|
381
|
+
this.toolExecution?.engine === 'local' &&
|
|
382
|
+
this.toolExecution.local?.fileCheckpointing === true
|
|
383
|
+
) {
|
|
384
|
+
const bundle = createLocalCodingToolBundle(
|
|
385
|
+
this.toolExecution.local ?? {}
|
|
386
|
+
);
|
|
387
|
+
this._fileCheckpointer = bundle.checkpointer;
|
|
388
|
+
return this._fileCheckpointer;
|
|
389
|
+
}
|
|
390
|
+
if (
|
|
391
|
+
this.toolExecution?.engine === 'cloudflare-sandbox' &&
|
|
392
|
+
this.toolExecution.cloudflare?.fileCheckpointing === true
|
|
393
|
+
) {
|
|
394
|
+
const bundle = createCloudflareCodingToolBundle(
|
|
395
|
+
this.toolExecution.cloudflare
|
|
396
|
+
);
|
|
397
|
+
this._fileCheckpointer = bundle.checkpointer;
|
|
398
|
+
return this._fileCheckpointer;
|
|
399
|
+
}
|
|
400
|
+
return undefined;
|
|
381
401
|
}
|
|
382
402
|
}
|
|
383
403
|
|
|
@@ -1318,6 +1338,25 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
1318
1338
|
{ force: true }
|
|
1319
1339
|
);
|
|
1320
1340
|
|
|
1341
|
+
const langfuseHandler = createLangfuseHandler({
|
|
1342
|
+
langfuse: agentContext.langfuse,
|
|
1343
|
+
userId: config.configurable?.user_id as string | undefined,
|
|
1344
|
+
sessionId: config.configurable?.thread_id as string | undefined,
|
|
1345
|
+
traceMetadata: createLangfuseTraceMetadata({
|
|
1346
|
+
messageId: this.runId,
|
|
1347
|
+
parentMessageId: config.configurable?.requestBody?.parentMessageId,
|
|
1348
|
+
agentId,
|
|
1349
|
+
agentName: agentContext.name,
|
|
1350
|
+
}),
|
|
1351
|
+
tags: ['librechat', 'agent'],
|
|
1352
|
+
});
|
|
1353
|
+
const invokeConfig = langfuseHandler
|
|
1354
|
+
? {
|
|
1355
|
+
...config,
|
|
1356
|
+
callbacks: appendCallbacks(config.callbacks, [langfuseHandler]),
|
|
1357
|
+
}
|
|
1358
|
+
: config;
|
|
1359
|
+
|
|
1321
1360
|
try {
|
|
1322
1361
|
result = await attemptInvoke(
|
|
1323
1362
|
{
|
|
@@ -1326,17 +1365,19 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
|
|
|
1326
1365
|
provider: agentContext.provider,
|
|
1327
1366
|
context: this,
|
|
1328
1367
|
},
|
|
1329
|
-
|
|
1368
|
+
invokeConfig
|
|
1330
1369
|
);
|
|
1331
1370
|
} catch (primaryError) {
|
|
1332
1371
|
result = await tryFallbackProviders({
|
|
1333
1372
|
fallbacks,
|
|
1334
1373
|
tools: agentContext.tools,
|
|
1335
1374
|
messages: finalMessages,
|
|
1336
|
-
config,
|
|
1375
|
+
config: invokeConfig,
|
|
1337
1376
|
primaryError,
|
|
1338
1377
|
context: this,
|
|
1339
1378
|
});
|
|
1379
|
+
} finally {
|
|
1380
|
+
await disposeLangfuseHandler(langfuseHandler);
|
|
1340
1381
|
}
|
|
1341
1382
|
|
|
1342
1383
|
if (!result) {
|
package/src/index.ts
CHANGED
package/src/instrumentation.ts
CHANGED
|
@@ -5,14 +5,9 @@ import { isPresent } from '@/utils/misc';
|
|
|
5
5
|
if (
|
|
6
6
|
isPresent(process.env.LANGFUSE_SECRET_KEY) &&
|
|
7
7
|
isPresent(process.env.LANGFUSE_PUBLIC_KEY) &&
|
|
8
|
-
isPresent(process.env.LANGFUSE_BASE_URL)
|
|
8
|
+
isPresent(process.env.LANGFUSE_BASE_URL ?? process.env.LANGFUSE_BASEURL)
|
|
9
9
|
) {
|
|
10
|
-
const langfuseSpanProcessor = new LangfuseSpanProcessor(
|
|
11
|
-
publicKey: process.env.LANGFUSE_PUBLIC_KEY,
|
|
12
|
-
secretKey: process.env.LANGFUSE_SECRET_KEY,
|
|
13
|
-
baseUrl: process.env.LANGFUSE_BASE_URL,
|
|
14
|
-
environment: process.env.LANGFUSE_TRACING_ENVIRONMENT ?? process.env.NODE_ENV ?? 'development',
|
|
15
|
-
});
|
|
10
|
+
const langfuseSpanProcessor = new LangfuseSpanProcessor();
|
|
16
11
|
|
|
17
12
|
const sdk = new NodeSDK({
|
|
18
13
|
spanProcessors: [langfuseSpanProcessor],
|