@librechat/agents 3.5.1 → 3.6.1
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 +5 -2
- package/dist/cjs/agents/AgentContext.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +148 -22
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/graphs/MultiAgentGraph.cjs +2 -1
- package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
- package/dist/cjs/main.cjs +4 -0
- package/dist/cjs/prompts/activityLabel.cjs +1 -0
- package/dist/cjs/prompts/reasoningLabel.cjs +60 -0
- package/dist/cjs/prompts/reasoningLabel.cjs.map +1 -0
- package/dist/cjs/run.cjs +161 -11
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/stream.cjs +8 -6
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/tools/BashExecutor.cjs +8 -7
- package/dist/cjs/tools/BashExecutor.cjs.map +1 -1
- package/dist/cjs/tools/BashProgrammaticToolCalling.cjs +5 -4
- package/dist/cjs/tools/BashProgrammaticToolCalling.cjs.map +1 -1
- package/dist/cjs/tools/CodeExecutor.cjs +26 -7
- package/dist/cjs/tools/CodeExecutor.cjs.map +1 -1
- package/dist/cjs/tools/ProgrammaticToolCalling.cjs +7 -6
- package/dist/cjs/tools/ProgrammaticToolCalling.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +33 -10
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/ToolSearch.cjs +1 -1
- package/dist/cjs/tools/ToolSearch.cjs.map +1 -1
- package/dist/cjs/tools/runStepResume.cjs +51 -0
- package/dist/cjs/tools/runStepResume.cjs.map +1 -0
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs +15 -43
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
- package/dist/cjs/tools/subagent/SubagentReplay.cjs +6 -1
- package/dist/cjs/tools/subagent/SubagentReplay.cjs.map +1 -1
- package/dist/cjs/utils/toolSessions.cjs +63 -0
- package/dist/cjs/utils/toolSessions.cjs.map +1 -0
- package/dist/esm/agents/AgentContext.mjs +5 -2
- package/dist/esm/agents/AgentContext.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +148 -22
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/graphs/MultiAgentGraph.mjs +2 -1
- package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
- package/dist/esm/main.mjs +2 -2
- package/dist/esm/prompts/activityLabel.mjs +1 -1
- package/dist/esm/prompts/reasoningLabel.mjs +57 -0
- package/dist/esm/prompts/reasoningLabel.mjs.map +1 -0
- package/dist/esm/run.mjs +161 -11
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/stream.mjs +8 -6
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/tools/BashExecutor.mjs +9 -8
- package/dist/esm/tools/BashExecutor.mjs.map +1 -1
- package/dist/esm/tools/BashProgrammaticToolCalling.mjs +6 -5
- package/dist/esm/tools/BashProgrammaticToolCalling.mjs.map +1 -1
- package/dist/esm/tools/CodeExecutor.mjs +23 -8
- package/dist/esm/tools/CodeExecutor.mjs.map +1 -1
- package/dist/esm/tools/ProgrammaticToolCalling.mjs +8 -7
- package/dist/esm/tools/ProgrammaticToolCalling.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +33 -10
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/ToolSearch.mjs +2 -2
- package/dist/esm/tools/ToolSearch.mjs.map +1 -1
- package/dist/esm/tools/runStepResume.mjs +48 -0
- package/dist/esm/tools/runStepResume.mjs.map +1 -0
- package/dist/esm/tools/subagent/SubagentExecutor.mjs +15 -43
- package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
- package/dist/esm/tools/subagent/SubagentReplay.mjs +6 -1
- package/dist/esm/tools/subagent/SubagentReplay.mjs.map +1 -1
- package/dist/esm/utils/toolSessions.mjs +62 -0
- package/dist/esm/utils/toolSessions.mjs.map +1 -0
- package/dist/types/agents/AgentContext.d.ts +4 -1
- package/dist/types/graphs/Graph.d.ts +11 -3
- package/dist/types/prompts/reasoningLabel.d.ts +17 -0
- package/dist/types/run.d.ts +8 -0
- package/dist/types/tools/CodeExecutor.d.ts +4 -0
- package/dist/types/tools/ProgrammaticToolCalling.d.ts +1 -1
- package/dist/types/tools/ToolNode.d.ts +3 -1
- package/dist/types/tools/runStepResume.d.ts +5 -0
- package/dist/types/tools/subagent/SubagentExecutor.d.ts +25 -0
- package/dist/types/tools/subagent/SubagentReplay.d.ts +2 -1
- package/dist/types/types/graph.d.ts +10 -1
- package/dist/types/types/index.d.ts +1 -0
- package/dist/types/types/reasoningLabel.d.ts +56 -0
- package/dist/types/types/stream.d.ts +18 -0
- package/dist/types/types/tools.d.ts +36 -16
- package/dist/types/utils/toolSessions.d.ts +18 -0
- package/package.json +1 -1
- package/src/agents/AgentContext.ts +7 -0
- package/src/graphs/Graph.ts +192 -13
- package/src/graphs/MultiAgentGraph.ts +1 -0
- package/src/prompts/reasoningLabel.ts +118 -0
- package/src/run.ts +330 -12
- package/src/stream.ts +28 -9
- package/src/tools/BashExecutor.ts +31 -13
- package/src/tools/BashProgrammaticToolCalling.ts +19 -9
- package/src/tools/CodeExecutor.ts +57 -16
- package/src/tools/ProgrammaticToolCalling.ts +26 -12
- package/src/tools/ToolNode.ts +58 -8
- package/src/tools/ToolSearch.ts +2 -2
- package/src/tools/runStepResume.ts +121 -0
- package/src/tools/subagent/SubagentExecutor.ts +67 -65
- package/src/tools/subagent/SubagentReplay.ts +22 -1
- package/src/types/graph.ts +10 -0
- package/src/types/index.ts +1 -0
- package/src/types/reasoningLabel.ts +59 -0
- package/src/types/stream.ts +17 -0
- package/src/types/tools.ts +50 -21
- package/src/utils/toolSessions.ts +113 -0
|
@@ -8,8 +8,10 @@ import {
|
|
|
8
8
|
CODE_ARTIFACT_PATH_GUIDANCE,
|
|
9
9
|
appendFailedExecutionFileReminder,
|
|
10
10
|
buildCodeApiExecutionErrorMessage,
|
|
11
|
+
buildCodeApiEndpoint,
|
|
11
12
|
CodeApiRequestError,
|
|
12
13
|
getCodeBaseURL,
|
|
14
|
+
selectRuntimeSessionHint,
|
|
13
15
|
} from './CodeExecutor';
|
|
14
16
|
import {
|
|
15
17
|
clampCodeApiRunTimeoutMs,
|
|
@@ -296,7 +298,7 @@ export function createBashProgrammaticToolCallingTool(
|
|
|
296
298
|
const maxRunTimeoutMs = resolveCodeApiRunTimeoutMs(initParams.runTimeoutMs);
|
|
297
299
|
const proxy = initParams.proxy ?? process.env.PROXY;
|
|
298
300
|
const debug = initParams.debug ?? process.env.BASH_PTC_DEBUG === 'true';
|
|
299
|
-
const EXEC_ENDPOINT =
|
|
301
|
+
const EXEC_ENDPOINT = buildCodeApiEndpoint(baseUrl, 'exec/programmatic');
|
|
300
302
|
|
|
301
303
|
return tool(
|
|
302
304
|
async (rawParams, config) => {
|
|
@@ -362,13 +364,19 @@ export function createBashProgrammaticToolCallingTool(
|
|
|
362
364
|
);
|
|
363
365
|
}
|
|
364
366
|
|
|
365
|
-
/*
|
|
366
|
-
*
|
|
367
|
-
*
|
|
367
|
+
/* The hint rides the INITIAL request only; continuation_token binds
|
|
368
|
+
* later round-trips. Prefer trusted per-agent factory context over
|
|
369
|
+
* legacy ToolNode injection. Explicit default profiles always drop it.
|
|
370
|
+
* BashPTC keeps its stateless runtime prompt in v1. */
|
|
371
|
+
const selectedRuntimeSessionHint = selectRuntimeSessionHint(
|
|
372
|
+
initParams.runtimeSessionHint,
|
|
373
|
+
_runtime_session_hint
|
|
374
|
+
);
|
|
368
375
|
const runtimeSessionHint =
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
376
|
+
initParams.executionProfile !== 'default' &&
|
|
377
|
+
typeof selectedRuntimeSessionHint === 'string' &&
|
|
378
|
+
selectedRuntimeSessionHint !== ''
|
|
379
|
+
? selectedRuntimeSessionHint
|
|
372
380
|
: undefined;
|
|
373
381
|
|
|
374
382
|
let response = await makeRequest(
|
|
@@ -385,7 +393,8 @@ export function createBashProgrammaticToolCallingTool(
|
|
|
385
393
|
: {}),
|
|
386
394
|
},
|
|
387
395
|
proxy,
|
|
388
|
-
initParams.authHeaders
|
|
396
|
+
initParams.authHeaders,
|
|
397
|
+
initParams.executionProfile
|
|
389
398
|
);
|
|
390
399
|
|
|
391
400
|
// ====================================================================
|
|
@@ -425,7 +434,8 @@ export function createBashProgrammaticToolCallingTool(
|
|
|
425
434
|
tool_results: toolResults,
|
|
426
435
|
},
|
|
427
436
|
proxy,
|
|
428
|
-
initParams.authHeaders
|
|
437
|
+
initParams.authHeaders,
|
|
438
|
+
initParams.executionProfile
|
|
429
439
|
);
|
|
430
440
|
}
|
|
431
441
|
|
|
@@ -19,6 +19,17 @@ export const getCodeBaseURL = (): string =>
|
|
|
19
19
|
getEnvironmentVariable(EnvVar.CODE_BASEURL) ??
|
|
20
20
|
Constants.OFFICIAL_CODE_BASEURL;
|
|
21
21
|
|
|
22
|
+
export function buildCodeApiEndpoint(baseUrl: string, route: string): string {
|
|
23
|
+
return `${baseUrl.replace(/\/+$/, '')}/${route.replace(/^\/+/, '')}`;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function selectRuntimeSessionHint(
|
|
27
|
+
factoryHint?: string,
|
|
28
|
+
injectedHint?: string
|
|
29
|
+
): string | undefined {
|
|
30
|
+
return factoryHint != null && factoryHint !== '' ? factoryHint : injectedHint;
|
|
31
|
+
}
|
|
32
|
+
|
|
22
33
|
export const emptyOutputMessage =
|
|
23
34
|
'stdout: Empty. Ensure you\'re writing output explicitly.\n';
|
|
24
35
|
|
|
@@ -108,8 +119,8 @@ export const CodeExecutionToolSchema = {
|
|
|
108
119
|
required: ['lang', 'code'],
|
|
109
120
|
} as const;
|
|
110
121
|
|
|
111
|
-
const
|
|
112
|
-
|
|
122
|
+
export const CODE_API_EXPECTED_PROFILE_HEADER =
|
|
123
|
+
'X-CodeAPI-Expected-Profile';
|
|
113
124
|
|
|
114
125
|
type SupportedLanguage = (typeof SUPPORTED_LANGUAGES)[number];
|
|
115
126
|
|
|
@@ -226,6 +237,19 @@ export async function resolveCodeApiAuthHeaders(
|
|
|
226
237
|
return authHeaders;
|
|
227
238
|
}
|
|
228
239
|
|
|
240
|
+
export function addCodeApiExecutionProfileHeader(
|
|
241
|
+
headers: t.CodeApiAuthHeaderMap,
|
|
242
|
+
executionProfile?: t.CodeApiExecutionProfile
|
|
243
|
+
): t.CodeApiAuthHeaderMap {
|
|
244
|
+
if (executionProfile == null) {
|
|
245
|
+
return headers;
|
|
246
|
+
}
|
|
247
|
+
return {
|
|
248
|
+
...headers,
|
|
249
|
+
[CODE_API_EXPECTED_PROFILE_HEADER]: executionProfile,
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
|
|
229
253
|
export async function buildCodeApiHttpErrorMessage(
|
|
230
254
|
_method: string,
|
|
231
255
|
_endpoint: string,
|
|
@@ -333,16 +357,24 @@ export const CodeExecutionToolDefinition = {
|
|
|
333
357
|
function createCodeExecutionTool(
|
|
334
358
|
params: t.CodeExecutionToolParams | null = {}
|
|
335
359
|
): DynamicStructuredTool {
|
|
360
|
+
const execEndpoint = buildCodeApiEndpoint(
|
|
361
|
+
params?.baseUrl ?? getCodeBaseURL(),
|
|
362
|
+
'exec'
|
|
363
|
+
);
|
|
364
|
+
|
|
336
365
|
return tool(
|
|
337
366
|
async (rawInput, config) => {
|
|
338
|
-
/* `statefulSessions`
|
|
339
|
-
*
|
|
367
|
+
/* `statefulSessions` drives the description and gates trusted runtime
|
|
368
|
+
* affinity hints. Keep the flag itself out of the wire body. */
|
|
340
369
|
const {
|
|
341
370
|
authHeaders,
|
|
342
|
-
|
|
371
|
+
baseUrl: _baseUrl,
|
|
372
|
+
executionProfile,
|
|
373
|
+
runtimeSessionHint,
|
|
374
|
+
statefulSessions,
|
|
343
375
|
...executionParams
|
|
344
376
|
} = params ?? {};
|
|
345
|
-
void
|
|
377
|
+
void _baseUrl;
|
|
346
378
|
/* Drop any model-supplied `runtime_session_hint` from the raw args: the
|
|
347
379
|
* hint is host-controlled and must only ever come from ToolNode's
|
|
348
380
|
* injected `_runtime_session_hint` (below). Spreading `...rest` into
|
|
@@ -383,14 +415,20 @@ function createCodeExecutionTool(
|
|
|
383
415
|
...executionParams,
|
|
384
416
|
};
|
|
385
417
|
|
|
386
|
-
/* Stateful sessions:
|
|
387
|
-
*
|
|
388
|
-
*
|
|
418
|
+
/* Stateful sessions: prefer the per-agent factory hint, falling back to
|
|
419
|
+
* legacy ToolNode injection. Explicit default-profile tools always drop
|
|
420
|
+
* the hint so a mixed graph cannot promote them to the stateful path. */
|
|
421
|
+
const effectiveRuntimeSessionHint = selectRuntimeSessionHint(
|
|
422
|
+
runtimeSessionHint,
|
|
423
|
+
_runtime_session_hint
|
|
424
|
+
);
|
|
389
425
|
if (
|
|
390
|
-
|
|
391
|
-
|
|
426
|
+
statefulSessions === true &&
|
|
427
|
+
executionProfile !== 'default' &&
|
|
428
|
+
typeof effectiveRuntimeSessionHint === 'string' &&
|
|
429
|
+
effectiveRuntimeSessionHint !== ''
|
|
392
430
|
) {
|
|
393
|
-
postData.runtime_session_hint =
|
|
431
|
+
postData.runtime_session_hint = effectiveRuntimeSessionHint;
|
|
394
432
|
}
|
|
395
433
|
|
|
396
434
|
/* File injection: `_injected_files` from ToolNode (set when host
|
|
@@ -421,19 +459,22 @@ function createCodeExecutionTool(
|
|
|
421
459
|
headers: {
|
|
422
460
|
'Content-Type': 'application/json',
|
|
423
461
|
'User-Agent': 'LibreChat/1.0',
|
|
424
|
-
...
|
|
462
|
+
...addCodeApiExecutionProfileHeader(
|
|
463
|
+
resolvedAuthHeaders,
|
|
464
|
+
executionProfile
|
|
465
|
+
),
|
|
425
466
|
},
|
|
426
467
|
body: JSON.stringify(postData),
|
|
427
468
|
};
|
|
428
469
|
|
|
429
|
-
const proxyAgent = resolveFetchProxyAgent(
|
|
470
|
+
const proxyAgent = resolveFetchProxyAgent(execEndpoint);
|
|
430
471
|
if (proxyAgent) {
|
|
431
472
|
fetchOptions.agent = proxyAgent;
|
|
432
473
|
}
|
|
433
|
-
const response = await fetch(
|
|
474
|
+
const response = await fetch(execEndpoint, fetchOptions);
|
|
434
475
|
if (!response.ok) {
|
|
435
476
|
throw new CodeApiRequestError(
|
|
436
|
-
await buildCodeApiHttpErrorMessage('POST',
|
|
477
|
+
await buildCodeApiHttpErrorMessage('POST', execEndpoint, response)
|
|
437
478
|
);
|
|
438
479
|
}
|
|
439
480
|
|
|
@@ -7,16 +7,19 @@ import type { ProgrammaticToolCallingJsonSchema } from './ptcTimeout';
|
|
|
7
7
|
import type * as t from '@/types';
|
|
8
8
|
import {
|
|
9
9
|
CODE_ARTIFACT_PATH_GUIDANCE,
|
|
10
|
+
addCodeApiExecutionProfileHeader,
|
|
10
11
|
appendCodeSessionFileSummary,
|
|
11
12
|
appendFailedExecutionFileReminder,
|
|
12
13
|
buildCodeApiExecutionErrorMessage,
|
|
13
14
|
buildCodeApiHttpErrorMessage,
|
|
14
15
|
CodeApiRequestError,
|
|
16
|
+
buildCodeApiEndpoint,
|
|
15
17
|
emptyOutputMessage,
|
|
16
18
|
getCodeBaseURL,
|
|
17
19
|
appendTmpScratchReminder,
|
|
18
20
|
normalizeCodeApiRequestError,
|
|
19
21
|
resolveCodeApiAuthHeaders,
|
|
22
|
+
selectRuntimeSessionHint,
|
|
20
23
|
} from './CodeExecutor';
|
|
21
24
|
import {
|
|
22
25
|
clampCodeApiRunTimeoutMs,
|
|
@@ -478,7 +481,8 @@ export async function makeRequest(
|
|
|
478
481
|
endpoint: string,
|
|
479
482
|
body: Record<string, unknown>,
|
|
480
483
|
proxy?: string,
|
|
481
|
-
authHeaders?: t.CodeApiAuthHeaders
|
|
484
|
+
authHeaders?: t.CodeApiAuthHeaders,
|
|
485
|
+
executionProfile?: t.CodeApiExecutionProfile
|
|
482
486
|
): Promise<t.ProgrammaticExecutionResponse> {
|
|
483
487
|
try {
|
|
484
488
|
const resolvedAuthHeaders = await resolveCodeApiAuthHeaders(authHeaders);
|
|
@@ -487,7 +491,10 @@ export async function makeRequest(
|
|
|
487
491
|
headers: {
|
|
488
492
|
'Content-Type': 'application/json',
|
|
489
493
|
'User-Agent': 'LibreChat/1.0',
|
|
490
|
-
...
|
|
494
|
+
...addCodeApiExecutionProfileHeader(
|
|
495
|
+
resolvedAuthHeaders,
|
|
496
|
+
executionProfile
|
|
497
|
+
),
|
|
491
498
|
},
|
|
492
499
|
body: JSON.stringify(body),
|
|
493
500
|
};
|
|
@@ -882,7 +889,7 @@ export function createProgrammaticToolCallingTool(
|
|
|
882
889
|
const maxRunTimeoutMs = resolveCodeApiRunTimeoutMs(initParams.runTimeoutMs);
|
|
883
890
|
const proxy = initParams.proxy ?? process.env.PROXY;
|
|
884
891
|
const debug = initParams.debug ?? process.env.PTC_DEBUG === 'true';
|
|
885
|
-
const EXEC_ENDPOINT =
|
|
892
|
+
const EXEC_ENDPOINT = buildCodeApiEndpoint(baseUrl, 'exec/programmatic');
|
|
886
893
|
|
|
887
894
|
return tool(
|
|
888
895
|
async (rawParams, config) => {
|
|
@@ -952,14 +959,19 @@ export function createProgrammaticToolCallingTool(
|
|
|
952
959
|
);
|
|
953
960
|
}
|
|
954
961
|
|
|
955
|
-
/*
|
|
956
|
-
*
|
|
957
|
-
*
|
|
958
|
-
* keeps its stateless prompt in v1
|
|
962
|
+
/* The hint rides the INITIAL request only; continuation_token binds
|
|
963
|
+
* later round-trips. Prefer trusted per-agent factory context over
|
|
964
|
+
* legacy ToolNode injection. Explicit default profiles always drop it.
|
|
965
|
+
* PTC keeps its stateless runtime prompt in v1. */
|
|
966
|
+
const selectedRuntimeSessionHint = selectRuntimeSessionHint(
|
|
967
|
+
initParams.runtimeSessionHint,
|
|
968
|
+
_runtime_session_hint
|
|
969
|
+
);
|
|
959
970
|
const runtimeSessionHint =
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
971
|
+
initParams.executionProfile !== 'default' &&
|
|
972
|
+
typeof selectedRuntimeSessionHint === 'string' &&
|
|
973
|
+
selectedRuntimeSessionHint !== ''
|
|
974
|
+
? selectedRuntimeSessionHint
|
|
963
975
|
: undefined;
|
|
964
976
|
|
|
965
977
|
let response = await makeRequest(
|
|
@@ -975,7 +987,8 @@ export function createProgrammaticToolCallingTool(
|
|
|
975
987
|
: {}),
|
|
976
988
|
},
|
|
977
989
|
proxy,
|
|
978
|
-
initParams.authHeaders
|
|
990
|
+
initParams.authHeaders,
|
|
991
|
+
initParams.executionProfile
|
|
979
992
|
);
|
|
980
993
|
|
|
981
994
|
// ====================================================================
|
|
@@ -1012,7 +1025,8 @@ export function createProgrammaticToolCallingTool(
|
|
|
1012
1025
|
tool_results: toolResults,
|
|
1013
1026
|
},
|
|
1014
1027
|
proxy,
|
|
1015
|
-
initParams.authHeaders
|
|
1028
|
+
initParams.authHeaders,
|
|
1029
|
+
initParams.executionProfile
|
|
1016
1030
|
);
|
|
1017
1031
|
}
|
|
1018
1032
|
|
package/src/tools/ToolNode.ts
CHANGED
|
@@ -62,6 +62,7 @@ import {
|
|
|
62
62
|
SUBAGENT_PARENT_BATCH_CONFIG_KEY,
|
|
63
63
|
SUBAGENT_REPLAY_CONTROLLER,
|
|
64
64
|
} from '@/tools/subagent/SubagentReplay';
|
|
65
|
+
import { attachRunStepResumeState } from '@/tools/runStepResume';
|
|
65
66
|
import {
|
|
66
67
|
INTENT_ARG,
|
|
67
68
|
readOutcomeFields,
|
|
@@ -595,17 +596,18 @@ function fileIdentityKey(file: {
|
|
|
595
596
|
|
|
596
597
|
function updateCodeSession(
|
|
597
598
|
sessions: t.ToolSessionMap,
|
|
599
|
+
sessionKey: string,
|
|
598
600
|
execSessionId: string,
|
|
599
601
|
files: t.FileRefs | undefined
|
|
600
602
|
): void {
|
|
601
603
|
const newFiles = files ?? [];
|
|
602
|
-
const existingSession = sessions.get(
|
|
604
|
+
const existingSession = sessions.get(sessionKey) as
|
|
603
605
|
| t.CodeSessionContext
|
|
604
606
|
| undefined;
|
|
605
607
|
const existingFiles = existingSession?.files ?? [];
|
|
606
608
|
|
|
607
609
|
if (newFiles.length === 0) {
|
|
608
|
-
sessions.set(
|
|
610
|
+
sessions.set(sessionKey, {
|
|
609
611
|
session_id: execSessionId,
|
|
610
612
|
files: existingFiles,
|
|
611
613
|
lastUpdated: Date.now(),
|
|
@@ -643,7 +645,7 @@ function updateCodeSession(
|
|
|
643
645
|
}
|
|
644
646
|
}
|
|
645
647
|
|
|
646
|
-
sessions.set(
|
|
648
|
+
sessions.set(sessionKey, {
|
|
647
649
|
session_id: execSessionId,
|
|
648
650
|
files: [...filteredExisting, ...filesWithSession],
|
|
649
651
|
lastUpdated: Date.now(),
|
|
@@ -694,6 +696,8 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
694
696
|
private programmaticCache?: t.ProgrammaticCache;
|
|
695
697
|
/** Reference to Graph's sessions map for automatic session injection */
|
|
696
698
|
private sessions?: t.ToolSessionMap;
|
|
699
|
+
/** Partition within `sessions` owned by this agent's execution profile. */
|
|
700
|
+
private codeSessionKey: string;
|
|
697
701
|
/** When true, dispatches ON_TOOL_EXECUTE events instead of invoking tools directly */
|
|
698
702
|
private eventDrivenMode: boolean = false;
|
|
699
703
|
/** Opt-in stream-layer prestart config for event-driven tools. */
|
|
@@ -794,6 +798,7 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
794
798
|
loadRuntimeTools,
|
|
795
799
|
toolRegistry,
|
|
796
800
|
sessions,
|
|
801
|
+
codeSessionKey,
|
|
797
802
|
eventDrivenMode,
|
|
798
803
|
eagerEventToolExecution,
|
|
799
804
|
eagerEventToolExecutions,
|
|
@@ -814,11 +819,45 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
814
819
|
fileCheckpointer,
|
|
815
820
|
getBreakerSignal,
|
|
816
821
|
getRunScope,
|
|
822
|
+
restoreRunStepResumeState,
|
|
823
|
+
createRunStepResumeState,
|
|
817
824
|
}: t.ToolNodeConstructorParams) {
|
|
818
825
|
super({
|
|
819
826
|
name: name ?? TOOL_NODE_RUN_NAME,
|
|
820
827
|
tags,
|
|
821
|
-
func: (input, config) =>
|
|
828
|
+
func: async (input, config) => {
|
|
829
|
+
const state = input as T & Pick<t.BaseGraphState, 'runStepState'>;
|
|
830
|
+
restoreRunStepResumeState?.(state.runStepState, config);
|
|
831
|
+
let result: T;
|
|
832
|
+
try {
|
|
833
|
+
result = await this.run(input, config);
|
|
834
|
+
} catch (error) {
|
|
835
|
+
if (!isGraphInterrupt(error) || createRunStepResumeState == null) {
|
|
836
|
+
throw error;
|
|
837
|
+
}
|
|
838
|
+
const resumeState = createRunStepResumeState();
|
|
839
|
+
throw new GraphInterrupt(
|
|
840
|
+
error.interrupts.map((pendingInterrupt) => ({
|
|
841
|
+
...pendingInterrupt,
|
|
842
|
+
value: attachRunStepResumeState(
|
|
843
|
+
pendingInterrupt.value,
|
|
844
|
+
resumeState
|
|
845
|
+
),
|
|
846
|
+
}))
|
|
847
|
+
);
|
|
848
|
+
}
|
|
849
|
+
if (createRunStepResumeState == null) {
|
|
850
|
+
return result;
|
|
851
|
+
}
|
|
852
|
+
const runStepState = createRunStepResumeState();
|
|
853
|
+
if (Array.isArray(result)) {
|
|
854
|
+
return [...result, { runStepState }] as T;
|
|
855
|
+
}
|
|
856
|
+
return {
|
|
857
|
+
...result,
|
|
858
|
+
runStepState,
|
|
859
|
+
};
|
|
860
|
+
},
|
|
822
861
|
});
|
|
823
862
|
this.trace = trace ?? this.trace;
|
|
824
863
|
this.runLangfuse = runLangfuse;
|
|
@@ -834,6 +873,7 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
834
873
|
toolExecution,
|
|
835
874
|
});
|
|
836
875
|
this.sessions = sessions;
|
|
876
|
+
this.codeSessionKey = codeSessionKey ?? Constants.EXECUTE_CODE;
|
|
837
877
|
this.eventDrivenMode = eventDrivenMode ?? false;
|
|
838
878
|
this.eagerEventToolExecution = eagerEventToolExecution;
|
|
839
879
|
this.eagerEventToolExecutions = eagerEventToolExecutions;
|
|
@@ -1328,7 +1368,7 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
1328
1368
|
* `/files/<session_id>` fallback was removed from the executors.
|
|
1329
1369
|
*/
|
|
1330
1370
|
if (this.participatesInCodeSession(call.name)) {
|
|
1331
|
-
const codeSession = this.sessions?.get(
|
|
1371
|
+
const codeSession = this.sessions?.get(this.codeSessionKey) as
|
|
1332
1372
|
| t.CodeSessionContext
|
|
1333
1373
|
| undefined;
|
|
1334
1374
|
const execSessionId = codeSession?.session_id;
|
|
@@ -2356,7 +2396,7 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
2356
2396
|
return undefined;
|
|
2357
2397
|
}
|
|
2358
2398
|
|
|
2359
|
-
const codeSession = this.sessions.get(
|
|
2399
|
+
const codeSession = this.sessions.get(this.codeSessionKey) as
|
|
2360
2400
|
| t.CodeSessionContext
|
|
2361
2401
|
| undefined;
|
|
2362
2402
|
if (!codeSession) {
|
|
@@ -2439,7 +2479,12 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
2439
2479
|
continue;
|
|
2440
2480
|
}
|
|
2441
2481
|
|
|
2442
|
-
updateCodeSession(
|
|
2482
|
+
updateCodeSession(
|
|
2483
|
+
this.sessions,
|
|
2484
|
+
this.codeSessionKey,
|
|
2485
|
+
execSessionId,
|
|
2486
|
+
artifact?.files
|
|
2487
|
+
);
|
|
2443
2488
|
}
|
|
2444
2489
|
}
|
|
2445
2490
|
|
|
@@ -2502,7 +2547,12 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
2502
2547
|
| undefined;
|
|
2503
2548
|
const execSessionId = artifact?.session_id;
|
|
2504
2549
|
if (execSessionId != null && execSessionId !== '') {
|
|
2505
|
-
updateCodeSession(
|
|
2550
|
+
updateCodeSession(
|
|
2551
|
+
this.sessions,
|
|
2552
|
+
this.codeSessionKey,
|
|
2553
|
+
execSessionId,
|
|
2554
|
+
artifact?.files
|
|
2555
|
+
);
|
|
2506
2556
|
}
|
|
2507
2557
|
}
|
|
2508
2558
|
|
package/src/tools/ToolSearch.ts
CHANGED
|
@@ -25,7 +25,7 @@ import { resolveFetchProxyAgent } from '@/utils/proxy';
|
|
|
25
25
|
import { tool, DynamicStructuredTool } from '@langchain/core/tools';
|
|
26
26
|
import type * as t from '@/types';
|
|
27
27
|
import { INTENT_PROPERTY } from '@/tools/intentArg';
|
|
28
|
-
import { getCodeBaseURL } from './CodeExecutor';
|
|
28
|
+
import { buildCodeApiEndpoint, getCodeBaseURL } from './CodeExecutor';
|
|
29
29
|
import { Constants } from '@/common';
|
|
30
30
|
|
|
31
31
|
config();
|
|
@@ -914,7 +914,7 @@ function createToolSearch(
|
|
|
914
914
|
const schema = createToolSearchSchema(mode);
|
|
915
915
|
|
|
916
916
|
const baseEndpoint = initParams.baseUrl ?? getCodeBaseURL();
|
|
917
|
-
const EXEC_ENDPOINT =
|
|
917
|
+
const EXEC_ENDPOINT = buildCodeApiEndpoint(baseEndpoint, 'exec');
|
|
918
918
|
|
|
919
919
|
const deferredToolsListing = getDeferredToolsListing(
|
|
920
920
|
initParams.toolRegistry,
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type { RunStepResumeEntry, RunStepResumeState } from '@/types';
|
|
2
|
+
|
|
3
|
+
const RUN_STEP_RESUME_STATE_KEY = '__librechat_run_step_resume_state';
|
|
4
|
+
const RUN_STEP_RESUME_PAYLOAD_KEY = '__librechat_run_step_resume_payload';
|
|
5
|
+
const RUN_STEP_RESUME_WRAPPER_KEY = '__librechat_run_step_resume_wrapper';
|
|
6
|
+
|
|
7
|
+
type RunStepResumePayload = {
|
|
8
|
+
[RUN_STEP_RESUME_STATE_KEY]: RunStepResumeState;
|
|
9
|
+
[RUN_STEP_RESUME_PAYLOAD_KEY]: unknown;
|
|
10
|
+
[RUN_STEP_RESUME_WRAPPER_KEY]: 1;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export function isRunStepResumeState(
|
|
14
|
+
value: unknown
|
|
15
|
+
): value is RunStepResumeState {
|
|
16
|
+
if (value == null || typeof value !== 'object') {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
const state = value as Partial<RunStepResumeState>;
|
|
20
|
+
if (
|
|
21
|
+
state.version !== 1 ||
|
|
22
|
+
!Number.isSafeInteger(state.revision) ||
|
|
23
|
+
(state.revision ?? -1) < 0 ||
|
|
24
|
+
!Number.isSafeInteger(state.nextIndex) ||
|
|
25
|
+
(state.nextIndex ?? -1) < 0 ||
|
|
26
|
+
!Array.isArray(state.toolCallSteps) ||
|
|
27
|
+
!Array.isArray(state.steps)
|
|
28
|
+
) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
const toolCallSteps = new Map<string, string>();
|
|
32
|
+
for (const reference of state.toolCallSteps as unknown[]) {
|
|
33
|
+
if (reference == null || typeof reference !== 'object') {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
const { toolCallId, stepId } = reference as {
|
|
37
|
+
toolCallId?: unknown;
|
|
38
|
+
stepId?: unknown;
|
|
39
|
+
};
|
|
40
|
+
if (
|
|
41
|
+
typeof toolCallId !== 'string' ||
|
|
42
|
+
toolCallId === '' ||
|
|
43
|
+
typeof stepId !== 'string' ||
|
|
44
|
+
stepId === '' ||
|
|
45
|
+
toolCallSteps.has(toolCallId)
|
|
46
|
+
) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
toolCallSteps.set(toolCallId, stepId);
|
|
50
|
+
}
|
|
51
|
+
const stepIds = new Set<string>();
|
|
52
|
+
for (const value of state.steps as unknown[]) {
|
|
53
|
+
if (value == null || typeof value !== 'object') {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
const entry = value as Partial<RunStepResumeEntry>;
|
|
57
|
+
const step = entry.step;
|
|
58
|
+
if (
|
|
59
|
+
step == null ||
|
|
60
|
+
typeof step.id !== 'string' ||
|
|
61
|
+
step.id === '' ||
|
|
62
|
+
!Number.isSafeInteger(step.index) ||
|
|
63
|
+
step.index < 0 ||
|
|
64
|
+
!Array.isArray(entry.pendingToolCallIds) ||
|
|
65
|
+
entry.pendingToolCallIds.some(
|
|
66
|
+
(toolCallId) => typeof toolCallId !== 'string' || toolCallId === ''
|
|
67
|
+
) ||
|
|
68
|
+
(entry.latestCompletionAt != null &&
|
|
69
|
+
!Number.isFinite(entry.latestCompletionAt)) ||
|
|
70
|
+
typeof entry.openMessageStep !== 'boolean' ||
|
|
71
|
+
entry.pendingToolCallIds.some(
|
|
72
|
+
(toolCallId) => toolCallSteps.get(toolCallId) !== step.id
|
|
73
|
+
) ||
|
|
74
|
+
stepIds.has(step.id)
|
|
75
|
+
) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
stepIds.add(step.id);
|
|
79
|
+
}
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function isRunStepResumePayload(value: unknown): value is RunStepResumePayload {
|
|
84
|
+
if (value == null || typeof value !== 'object') {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
const payload = value as Partial<RunStepResumePayload>;
|
|
88
|
+
return (
|
|
89
|
+
payload[RUN_STEP_RESUME_WRAPPER_KEY] === 1 &&
|
|
90
|
+
Object.prototype.hasOwnProperty.call(value, RUN_STEP_RESUME_PAYLOAD_KEY) &&
|
|
91
|
+
isRunStepResumeState(payload[RUN_STEP_RESUME_STATE_KEY])
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function attachRunStepResumeState(
|
|
96
|
+
payload: unknown,
|
|
97
|
+
state: RunStepResumeState
|
|
98
|
+
): object {
|
|
99
|
+
const publicPayload = isRunStepResumePayload(payload)
|
|
100
|
+
? payload[RUN_STEP_RESUME_PAYLOAD_KEY]
|
|
101
|
+
: payload;
|
|
102
|
+
return {
|
|
103
|
+
[RUN_STEP_RESUME_WRAPPER_KEY]: 1,
|
|
104
|
+
[RUN_STEP_RESUME_PAYLOAD_KEY]: publicPayload,
|
|
105
|
+
[RUN_STEP_RESUME_STATE_KEY]: state,
|
|
106
|
+
} satisfies RunStepResumePayload;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function getRunStepResumeState(
|
|
110
|
+
payload: unknown
|
|
111
|
+
): RunStepResumeState | undefined {
|
|
112
|
+
return isRunStepResumePayload(payload)
|
|
113
|
+
? payload[RUN_STEP_RESUME_STATE_KEY]
|
|
114
|
+
: undefined;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function stripRunStepResumeState(payload: unknown): unknown {
|
|
118
|
+
return isRunStepResumePayload(payload)
|
|
119
|
+
? payload[RUN_STEP_RESUME_PAYLOAD_KEY]
|
|
120
|
+
: payload;
|
|
121
|
+
}
|