@librechat/agents 3.5.0 → 3.6.0
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/run.cjs +29 -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/run.mjs +29 -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 +7 -4
- package/dist/types/agents/projection.d.ts +1 -1
- package/dist/types/events.d.ts +2 -2
- package/dist/types/graphs/Graph.d.ts +22 -14
- package/dist/types/graphs/MultiAgentGraph.d.ts +2 -2
- package/dist/types/graphs/createGraph.d.ts +4 -4
- package/dist/types/graphs/graphFactory.d.ts +1 -1
- package/dist/types/hitl/askUserQuestion.d.ts +1 -1
- package/dist/types/hitl/askUserQuestions.d.ts +1 -1
- package/dist/types/hitl/askUserQuestionsInterrupt.d.ts +1 -1
- package/dist/types/hooks/types.d.ts +1 -1
- package/dist/types/instrumentation.d.ts +1 -1
- package/dist/types/langfuse.d.ts +3 -3
- package/dist/types/langfuseConfig.d.ts +2 -2
- package/dist/types/langfuseRuntimeContext.d.ts +1 -1
- package/dist/types/langfuseRuntimeScope.d.ts +2 -2
- package/dist/types/langfuseSpanRegistry.d.ts +1 -1
- package/dist/types/langfuseToolOutputTracing.d.ts +3 -3
- package/dist/types/llm/anthropic/index.d.ts +1 -1
- package/dist/types/llm/bedrock/index.d.ts +1 -1
- package/dist/types/llm/bedrock/toolCache.d.ts +2 -2
- package/dist/types/llm/contextOverflowRecovery.d.ts +2 -2
- package/dist/types/llm/google/index.d.ts +1 -1
- package/dist/types/llm/init.d.ts +2 -2
- package/dist/types/llm/invoke.d.ts +6 -6
- package/dist/types/llm/mistral/index.d.ts +1 -1
- package/dist/types/llm/openai/index.d.ts +2 -2
- package/dist/types/llm/openrouter/index.d.ts +2 -2
- package/dist/types/llm/openrouter/toolCache.d.ts +2 -2
- package/dist/types/llm/providers.d.ts +2 -2
- package/dist/types/llm/request.d.ts +2 -2
- package/dist/types/llm/stream/chunkAdapters.d.ts +1 -1
- package/dist/types/llm/streamLimits.d.ts +1 -1
- package/dist/types/llm/truncation.d.ts +1 -1
- package/dist/types/llm/vertexai/index.d.ts +1 -1
- package/dist/types/messages/alternation.d.ts +1 -1
- package/dist/types/messages/anthropicToolCache.d.ts +2 -2
- package/dist/types/messages/assistantPhase.d.ts +3 -3
- package/dist/types/messages/budget.d.ts +1 -1
- package/dist/types/messages/cache.d.ts +1 -1
- package/dist/types/messages/contextPruning.d.ts +2 -2
- package/dist/types/messages/core.d.ts +2 -2
- package/dist/types/messages/format.d.ts +2 -2
- package/dist/types/messages/ids.d.ts +2 -2
- package/dist/types/messages/injected.d.ts +1 -1
- package/dist/types/messages/langchain.d.ts +1 -1
- package/dist/types/messages/prune.d.ts +3 -3
- package/dist/types/openai/index.d.ts +1 -1
- package/dist/types/prompts/activityLabel.d.ts +2 -2
- package/dist/types/responses/index.d.ts +1 -1
- package/dist/types/run.d.ts +3 -3
- package/dist/types/session/handlers.d.ts +1 -1
- package/dist/types/session/types.d.ts +1 -1
- package/dist/types/stream.d.ts +4 -4
- package/dist/types/summarization/index.d.ts +1 -1
- package/dist/types/summarization/node.d.ts +6 -6
- package/dist/types/tools/BashExecutor.d.ts +2 -2
- package/dist/types/tools/BashProgrammaticToolCalling.d.ts +2 -2
- package/dist/types/tools/CodeExecutor.d.ts +7 -3
- package/dist/types/tools/CodeSessionFileSummary.d.ts +1 -1
- package/dist/types/tools/ProgrammaticToolCalling.d.ts +3 -3
- package/dist/types/tools/ReadFile.d.ts +1 -1
- package/dist/types/tools/SkillTool.d.ts +1 -1
- package/dist/types/tools/SubagentTool.d.ts +3 -3
- package/dist/types/tools/ToolNode.d.ts +8 -6
- package/dist/types/tools/ToolSearch.d.ts +2 -2
- package/dist/types/tools/cloudflare/CloudflareBridgeRuntime.d.ts +1 -1
- package/dist/types/tools/cloudflare/CloudflareProgrammaticToolCalling.d.ts +1 -1
- package/dist/types/tools/cloudflare/CloudflareSandboxExecutionEngine.d.ts +2 -2
- package/dist/types/tools/cloudflare/CloudflareSandboxTools.d.ts +1 -1
- package/dist/types/tools/eagerEventExecution.d.ts +1 -1
- package/dist/types/tools/handlers.d.ts +3 -3
- package/dist/types/tools/intentArg.d.ts +1 -1
- package/dist/types/tools/local/CompileCheckTool.d.ts +2 -2
- package/dist/types/tools/local/FileCheckpointer.d.ts +1 -1
- package/dist/types/tools/local/LocalCodingTools.d.ts +2 -2
- package/dist/types/tools/local/LocalExecutionEngine.d.ts +1 -1
- package/dist/types/tools/local/LocalExecutionTools.d.ts +1 -1
- package/dist/types/tools/local/LocalProgrammaticToolCalling.d.ts +1 -1
- package/dist/types/tools/local/bashAst.d.ts +1 -1
- package/dist/types/tools/local/resolveLocalExecutionTools.d.ts +1 -1
- package/dist/types/tools/local/syntaxCheck.d.ts +1 -1
- package/dist/types/tools/ptcTimeout.d.ts +1 -1
- package/dist/types/tools/runStepResume.d.ts +5 -0
- package/dist/types/tools/schema.d.ts +1 -1
- package/dist/types/tools/search/anthropic.d.ts +1 -1
- package/dist/types/tools/skillCatalog.d.ts +1 -1
- package/dist/types/tools/subagent/SubagentExecutor.d.ts +30 -5
- package/dist/types/tools/subagent/SubagentReplay.d.ts +4 -3
- package/dist/types/tools/subagent/childGraphConfig.d.ts +2 -2
- package/dist/types/types/activityLabel.d.ts +3 -3
- package/dist/types/types/graph.d.ts +16 -7
- package/dist/types/types/llm.d.ts +9 -9
- package/dist/types/types/run.d.ts +7 -7
- package/dist/types/types/stream.d.ts +23 -5
- package/dist/types/types/summarize.d.ts +2 -2
- package/dist/types/types/tools.d.ts +41 -21
- package/dist/types/utils/errors.d.ts +1 -1
- package/dist/types/utils/events.d.ts +1 -1
- package/dist/types/utils/handlers.d.ts +3 -3
- package/dist/types/utils/llm.d.ts +1 -1
- package/dist/types/utils/llmConfig.d.ts +1 -1
- package/dist/types/utils/title.d.ts +1 -1
- package/dist/types/utils/toolSessions.d.ts +18 -0
- package/package.json +28 -32
- package/src/agents/AgentContext.ts +7 -0
- package/src/graphs/Graph.ts +192 -13
- package/src/graphs/MultiAgentGraph.ts +1 -0
- package/src/run.ts +62 -11
- 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/stream.ts +17 -0
- package/src/types/tools.ts +50 -21
- package/src/utils/toolSessions.ts +113 -0
- package/dist/types/agents/__tests__/promptCacheLiveHelpers.d.ts +0 -52
- package/dist/types/test/mockTools.d.ts +0 -28
- package/dist/types/utils/__tests__/fixtures/contextOverflowSignatures.d.ts +0 -40
package/src/run.ts
CHANGED
|
@@ -29,6 +29,10 @@ import {
|
|
|
29
29
|
SUBAGENT_RESUME_ATTEMPT_CONFIG_KEY,
|
|
30
30
|
SUBAGENT_RESUME_MANIFEST_CONFIG_KEY,
|
|
31
31
|
} from '@/tools/subagent/SubagentReplay';
|
|
32
|
+
import {
|
|
33
|
+
getRunStepResumeState,
|
|
34
|
+
stripRunStepResumeState,
|
|
35
|
+
} from '@/tools/runStepResume';
|
|
32
36
|
import {
|
|
33
37
|
ACTIVITY_PHASE_LABEL_PROMPT,
|
|
34
38
|
ACTIVITY_LABEL_PROMPT,
|
|
@@ -72,6 +76,7 @@ import {
|
|
|
72
76
|
import { applyGraphRuntimeConfig } from '@/graphs/applyGraphRuntimeConfig';
|
|
73
77
|
import { createTokenCounter, encodingForModel } from '@/utils/tokens';
|
|
74
78
|
import { initializeLangfuseTracing } from './instrumentation';
|
|
79
|
+
import { seedRunInitialSessions } from '@/utils/toolSessions';
|
|
75
80
|
import { getTraceIdSeed } from '@/langfuseRuntimeContext';
|
|
76
81
|
import { createGraph } from '@/graphs/createGraph';
|
|
77
82
|
import { resolveMaxSeals } from '@/llm/preempt';
|
|
@@ -173,7 +178,9 @@ function isLangGraphResumeMapForInterrupt(
|
|
|
173
178
|
}
|
|
174
179
|
|
|
175
180
|
function getInterruptHookSessionId(payload: unknown): string | undefined {
|
|
176
|
-
const publicPayload = stripSubagentResumeManifest(
|
|
181
|
+
const publicPayload = stripSubagentResumeManifest(
|
|
182
|
+
stripRunStepResumeState(payload)
|
|
183
|
+
);
|
|
177
184
|
if (
|
|
178
185
|
publicPayload == null ||
|
|
179
186
|
typeof publicPayload !== 'object' ||
|
|
@@ -193,11 +200,15 @@ type InterruptStateSnapshot = {
|
|
|
193
200
|
values?: { messages?: BaseMessage[] };
|
|
194
201
|
tasks?: Array<{
|
|
195
202
|
interrupts?: Array<{ id?: string; value?: unknown }>;
|
|
203
|
+
state?: RunnableConfig | InterruptStateSnapshot;
|
|
196
204
|
}>;
|
|
197
205
|
};
|
|
198
206
|
|
|
199
207
|
type WorkflowWithStateHistory = {
|
|
200
|
-
getState?(
|
|
208
|
+
getState?(
|
|
209
|
+
config: RunnableConfig,
|
|
210
|
+
options?: { subgraphs?: boolean }
|
|
211
|
+
): Promise<InterruptStateSnapshot>;
|
|
201
212
|
getStateHistory?(
|
|
202
213
|
config: RunnableConfig
|
|
203
214
|
): AsyncIterableIterator<InterruptStateSnapshot>;
|
|
@@ -215,6 +226,17 @@ function getFirstPersistedInterrupt(
|
|
|
215
226
|
return { id: pendingInterrupt.id, value: pendingInterrupt.value };
|
|
216
227
|
}
|
|
217
228
|
}
|
|
229
|
+
const nestedState = task.state;
|
|
230
|
+
if (
|
|
231
|
+
nestedState != null &&
|
|
232
|
+
'tasks' in nestedState &&
|
|
233
|
+
Array.isArray(nestedState.tasks)
|
|
234
|
+
) {
|
|
235
|
+
const nestedInterrupt = getFirstPersistedInterrupt(nestedState);
|
|
236
|
+
if (nestedInterrupt != null) {
|
|
237
|
+
return nestedInterrupt;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
218
240
|
}
|
|
219
241
|
return undefined;
|
|
220
242
|
}
|
|
@@ -351,9 +373,25 @@ export class Run<_T extends t.BaseGraphState> {
|
|
|
351
373
|
}
|
|
352
374
|
|
|
353
375
|
if (config.initialSessions && this.Graph) {
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
376
|
+
const configuredAgents =
|
|
377
|
+
'agents' in config.graphConfig &&
|
|
378
|
+
Array.isArray(config.graphConfig.agents)
|
|
379
|
+
? config.graphConfig.agents
|
|
380
|
+
: undefined;
|
|
381
|
+
const agents: Array<Pick<t.AgentInputs, 'codeSessionKey'>> =
|
|
382
|
+
configuredAgents ?? [
|
|
383
|
+
{
|
|
384
|
+
codeSessionKey:
|
|
385
|
+
'codeSessionKey' in config.graphConfig
|
|
386
|
+
? config.graphConfig.codeSessionKey
|
|
387
|
+
: undefined,
|
|
388
|
+
},
|
|
389
|
+
];
|
|
390
|
+
seedRunInitialSessions({
|
|
391
|
+
sessions: this.Graph.sessions,
|
|
392
|
+
initialSessions: config.initialSessions,
|
|
393
|
+
agents,
|
|
394
|
+
});
|
|
357
395
|
}
|
|
358
396
|
|
|
359
397
|
this.returnContent = config.returnContent ?? false;
|
|
@@ -949,6 +987,12 @@ export class Run<_T extends t.BaseGraphState> {
|
|
|
949
987
|
delete config.configurable?.[SUBAGENT_RESUME_ATTEMPT_CONFIG_KEY];
|
|
950
988
|
delete config.configurable?.[SUBAGENT_RESUME_MANIFEST_CONFIG_KEY];
|
|
951
989
|
}
|
|
990
|
+
if (isResume) {
|
|
991
|
+
await this.restoreInterruptFromCheckpoint(
|
|
992
|
+
config,
|
|
993
|
+
(inputs as Command).update
|
|
994
|
+
);
|
|
995
|
+
}
|
|
952
996
|
|
|
953
997
|
/**
|
|
954
998
|
* Cancellation can arrive either at graph construction or per-call through
|
|
@@ -1503,7 +1547,9 @@ export class Run<_T extends t.BaseGraphState> {
|
|
|
1503
1547
|
}
|
|
1504
1548
|
return {
|
|
1505
1549
|
...this._interrupt,
|
|
1506
|
-
payload: stripSubagentResumeManifest(
|
|
1550
|
+
payload: stripSubagentResumeManifest(
|
|
1551
|
+
stripRunStepResumeState(this._interrupt.payload)
|
|
1552
|
+
),
|
|
1507
1553
|
} as t.RunInterruptResult<TPayload>;
|
|
1508
1554
|
}
|
|
1509
1555
|
|
|
@@ -1622,7 +1668,7 @@ export class Run<_T extends t.BaseGraphState> {
|
|
|
1622
1668
|
await this.restoreInterruptFromCheckpoint(callerConfig, resumeUpdate);
|
|
1623
1669
|
const interrupt = this._interrupt;
|
|
1624
1670
|
const resumeManifest = requireValidSubagentResumeManifest(
|
|
1625
|
-
interrupt?.payload
|
|
1671
|
+
stripRunStepResumeState(interrupt?.payload)
|
|
1626
1672
|
);
|
|
1627
1673
|
const resumeConfigurable = { ...callerConfig.configurable };
|
|
1628
1674
|
delete resumeConfigurable[SUBAGENT_RESUME_ATTEMPT_CONFIG_KEY];
|
|
@@ -1709,7 +1755,7 @@ export class Run<_T extends t.BaseGraphState> {
|
|
|
1709
1755
|
callerConfig: t.RunStreamConfig,
|
|
1710
1756
|
resumeUpdate?: ResumeCommandUpdate
|
|
1711
1757
|
): Promise<void> {
|
|
1712
|
-
if (this._interrupt != null || this.
|
|
1758
|
+
if (this._interrupt != null || !this.hasCheckpointer) {
|
|
1713
1759
|
return;
|
|
1714
1760
|
}
|
|
1715
1761
|
const workflow = this.graphRunnable as
|
|
@@ -1719,11 +1765,16 @@ export class Run<_T extends t.BaseGraphState> {
|
|
|
1719
1765
|
return;
|
|
1720
1766
|
}
|
|
1721
1767
|
|
|
1722
|
-
const snapshot = await workflow.getState(callerConfig as RunnableConfig
|
|
1768
|
+
const snapshot = await workflow.getState(callerConfig as RunnableConfig, {
|
|
1769
|
+
subgraphs: true,
|
|
1770
|
+
});
|
|
1723
1771
|
const persistedInterrupt = getFirstPersistedInterrupt(snapshot);
|
|
1724
1772
|
if (persistedInterrupt == null) {
|
|
1725
1773
|
return;
|
|
1726
1774
|
}
|
|
1775
|
+
this.Graph?.restoreRunStepResumeState(
|
|
1776
|
+
getRunStepResumeState(persistedInterrupt.value)
|
|
1777
|
+
);
|
|
1727
1778
|
const persistedMessages = getPersistedMessages(snapshot);
|
|
1728
1779
|
if (persistedMessages != null) {
|
|
1729
1780
|
const resumeMessages = getResumeUpdateMessages(resumeUpdate);
|
|
@@ -2661,8 +2712,8 @@ function findActivityPhaseTraceInput(
|
|
|
2661
2712
|
const message = messages[i];
|
|
2662
2713
|
if (
|
|
2663
2714
|
message.getType() !== 'human' ||
|
|
2664
|
-
message.additional_kwargs
|
|
2665
|
-
message.additional_kwargs
|
|
2715
|
+
message.additional_kwargs.role === 'system' ||
|
|
2716
|
+
message.additional_kwargs.isMeta === true
|
|
2666
2717
|
) {
|
|
2667
2718
|
continue;
|
|
2668
2719
|
}
|
package/src/stream.ts
CHANGED
|
@@ -169,7 +169,8 @@ function hasToolOutputReference(value: unknown): boolean {
|
|
|
169
169
|
|
|
170
170
|
function isEagerExecutionExcludedTool(
|
|
171
171
|
name: string,
|
|
172
|
-
graph: StandardGraph
|
|
172
|
+
graph: StandardGraph,
|
|
173
|
+
agentContext?: AgentContext
|
|
173
174
|
): boolean {
|
|
174
175
|
if (name === '') {
|
|
175
176
|
return false;
|
|
@@ -200,9 +201,21 @@ function isEagerExecutionExcludedTool(
|
|
|
200
201
|
// args, ToolNode discards the eager result but the mutation has already
|
|
201
202
|
// landed in the session workspace, corrupting later runs. Stateless mode
|
|
202
203
|
// uses a throwaway VM per call, so eager prestart stays safe there.
|
|
204
|
+
if (!CODE_EXECUTION_TOOLS.has(name)) {
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
if (graph.toolExecution?.sandbox?.statefulSessions === true) {
|
|
208
|
+
return true;
|
|
209
|
+
}
|
|
210
|
+
// A non-default code-session partition is the trusted per-agent signal that
|
|
211
|
+
// this call must remain isolated from the graph-wide stateless session. The
|
|
212
|
+
// actual tool factory may route it to a durable backend, which the stream
|
|
213
|
+
// layer cannot inspect in event-driven mode. Conservatively avoid speculative
|
|
214
|
+
// execution for these calls so discarded eager results cannot mutate that
|
|
215
|
+
// agent's workspace.
|
|
203
216
|
return (
|
|
204
|
-
|
|
205
|
-
|
|
217
|
+
agentContext?.codeSessionKey != null &&
|
|
218
|
+
agentContext.codeSessionKey !== Constants.EXECUTE_CODE
|
|
206
219
|
);
|
|
207
220
|
}
|
|
208
221
|
|
|
@@ -258,7 +271,8 @@ function toCodeEnvFile(file: t.FileRef, execSessionId: string): t.CodeEnvFile {
|
|
|
258
271
|
|
|
259
272
|
function getCodeSessionContext(
|
|
260
273
|
graph: StandardGraph,
|
|
261
|
-
name: string
|
|
274
|
+
name: string,
|
|
275
|
+
agentContext?: AgentContext
|
|
262
276
|
): t.ToolCallRequest['codeSessionContext'] | undefined {
|
|
263
277
|
if (
|
|
264
278
|
!CODE_EXECUTION_TOOLS.has(name) &&
|
|
@@ -269,9 +283,9 @@ function getCodeSessionContext(
|
|
|
269
283
|
return undefined;
|
|
270
284
|
}
|
|
271
285
|
|
|
272
|
-
const codeSession = graph.sessions.get(
|
|
273
|
-
|
|
274
|
-
|
|
286
|
+
const codeSession = graph.sessions.get(
|
|
287
|
+
agentContext?.codeSessionKey ?? Constants.EXECUTE_CODE
|
|
288
|
+
) as t.CodeSessionContext | undefined;
|
|
275
289
|
if (codeSession?.session_id == null || codeSession.session_id === '') {
|
|
276
290
|
return undefined;
|
|
277
291
|
}
|
|
@@ -716,7 +730,8 @@ function createEagerToolExecutionPlan(args: {
|
|
|
716
730
|
// tool from `hasDirectToolCallInBatch`. Excluded calls fall through to normal
|
|
717
731
|
// ToolNode execution; siblings may still eager-execute.
|
|
718
732
|
const candidateToolCalls = unstartedToolCalls.filter(
|
|
719
|
-
(toolCall) =>
|
|
733
|
+
(toolCall) =>
|
|
734
|
+
!isEagerExecutionExcludedTool(toolCall.name, graph, agentContext)
|
|
720
735
|
);
|
|
721
736
|
if (candidateToolCalls.length === 0) {
|
|
722
737
|
return [];
|
|
@@ -748,7 +763,11 @@ function createEagerToolExecutionPlan(args: {
|
|
|
748
763
|
name: toolCall.name,
|
|
749
764
|
args: toolCall.args,
|
|
750
765
|
stepId: graph.toolCallStepIds.get(toolCall.id!) ?? '',
|
|
751
|
-
codeSessionContext: getCodeSessionContext(
|
|
766
|
+
codeSessionContext: getCodeSessionContext(
|
|
767
|
+
graph,
|
|
768
|
+
toolCall.name,
|
|
769
|
+
agentContext
|
|
770
|
+
),
|
|
752
771
|
})),
|
|
753
772
|
usageCount: graph.getEagerEventToolUsageCount(agentContext?.agentId),
|
|
754
773
|
});
|
|
@@ -8,12 +8,15 @@ import {
|
|
|
8
8
|
appendFailedExecutionFileReminder,
|
|
9
9
|
appendTmpScratchReminder,
|
|
10
10
|
appendCodeSessionFileSummary,
|
|
11
|
+
addCodeApiExecutionProfileHeader,
|
|
11
12
|
emptyOutputMessage,
|
|
12
13
|
buildCodeApiHttpErrorMessage,
|
|
13
14
|
CodeApiRequestError,
|
|
15
|
+
buildCodeApiEndpoint,
|
|
14
16
|
getCodeBaseURL,
|
|
15
17
|
normalizeCodeApiRequestError,
|
|
16
18
|
resolveCodeApiAuthHeaders,
|
|
19
|
+
selectRuntimeSessionHint,
|
|
17
20
|
} from './CodeExecutor';
|
|
18
21
|
import { resolveFetchProxyAgent } from '@/utils/proxy';
|
|
19
22
|
import { INTENT_PROPERTY } from '@/tools/intentArg';
|
|
@@ -21,9 +24,6 @@ import { Constants } from '@/common';
|
|
|
21
24
|
|
|
22
25
|
config();
|
|
23
26
|
|
|
24
|
-
const baseEndpoint = getCodeBaseURL();
|
|
25
|
-
const EXEC_ENDPOINT = `${baseEndpoint}/exec`;
|
|
26
|
-
|
|
27
27
|
export const BashExecutionToolSchema = {
|
|
28
28
|
type: 'object',
|
|
29
29
|
properties: {
|
|
@@ -177,15 +177,24 @@ export const BashExecutionToolDefinition = {
|
|
|
177
177
|
function createBashExecutionTool(
|
|
178
178
|
params: t.BashExecutionToolParams | null = {}
|
|
179
179
|
): DynamicStructuredTool {
|
|
180
|
+
const execEndpoint = buildCodeApiEndpoint(
|
|
181
|
+
params?.baseUrl ?? getCodeBaseURL(),
|
|
182
|
+
'exec'
|
|
183
|
+
);
|
|
184
|
+
|
|
180
185
|
return tool(
|
|
181
186
|
async (rawInput, config) => {
|
|
182
|
-
/* `statefulSessions`
|
|
187
|
+
/* `statefulSessions` drives the prompt and gates runtime affinity hints;
|
|
188
|
+
* keep the flag itself out of the wire body. */
|
|
183
189
|
const {
|
|
184
190
|
authHeaders,
|
|
185
|
-
|
|
191
|
+
baseUrl: _baseUrl,
|
|
192
|
+
executionProfile,
|
|
193
|
+
runtimeSessionHint,
|
|
194
|
+
statefulSessions,
|
|
186
195
|
...executionParams
|
|
187
196
|
} = params ?? {};
|
|
188
|
-
void
|
|
197
|
+
void _baseUrl;
|
|
189
198
|
/* Drop any model-supplied `runtime_session_hint` from the raw args: the
|
|
190
199
|
* hint must only come from ToolNode's injected `_runtime_session_hint`
|
|
191
200
|
* (below), never from the tool call itself. */
|
|
@@ -217,11 +226,17 @@ function createBashExecutionTool(
|
|
|
217
226
|
...executionParams,
|
|
218
227
|
};
|
|
219
228
|
|
|
229
|
+
const effectiveRuntimeSessionHint = selectRuntimeSessionHint(
|
|
230
|
+
runtimeSessionHint,
|
|
231
|
+
_runtime_session_hint
|
|
232
|
+
);
|
|
220
233
|
if (
|
|
221
|
-
|
|
222
|
-
|
|
234
|
+
statefulSessions === true &&
|
|
235
|
+
executionProfile !== 'default' &&
|
|
236
|
+
typeof effectiveRuntimeSessionHint === 'string' &&
|
|
237
|
+
effectiveRuntimeSessionHint !== ''
|
|
223
238
|
) {
|
|
224
|
-
postData.runtime_session_hint =
|
|
239
|
+
postData.runtime_session_hint = effectiveRuntimeSessionHint;
|
|
225
240
|
}
|
|
226
241
|
|
|
227
242
|
/* See `CodeExecutor.ts` for the rationale — `/files/<session_id>`
|
|
@@ -248,19 +263,22 @@ function createBashExecutionTool(
|
|
|
248
263
|
headers: {
|
|
249
264
|
'Content-Type': 'application/json',
|
|
250
265
|
'User-Agent': 'LibreChat/1.0',
|
|
251
|
-
...
|
|
266
|
+
...addCodeApiExecutionProfileHeader(
|
|
267
|
+
resolvedAuthHeaders,
|
|
268
|
+
executionProfile
|
|
269
|
+
),
|
|
252
270
|
},
|
|
253
271
|
body: JSON.stringify(postData),
|
|
254
272
|
};
|
|
255
273
|
|
|
256
|
-
const proxyAgent = resolveFetchProxyAgent(
|
|
274
|
+
const proxyAgent = resolveFetchProxyAgent(execEndpoint);
|
|
257
275
|
if (proxyAgent) {
|
|
258
276
|
fetchOptions.agent = proxyAgent;
|
|
259
277
|
}
|
|
260
|
-
const response = await fetch(
|
|
278
|
+
const response = await fetch(execEndpoint, fetchOptions);
|
|
261
279
|
if (!response.ok) {
|
|
262
280
|
throw new CodeApiRequestError(
|
|
263
|
-
await buildCodeApiHttpErrorMessage('POST',
|
|
281
|
+
await buildCodeApiHttpErrorMessage('POST', execEndpoint, response)
|
|
264
282
|
);
|
|
265
283
|
}
|
|
266
284
|
|
|
@@ -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
|
|