@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
package/src/run.ts
CHANGED
|
@@ -16,8 +16,11 @@ import {
|
|
|
16
16
|
HumanMessage,
|
|
17
17
|
SystemMessage,
|
|
18
18
|
} from '@langchain/core/messages';
|
|
19
|
+
import type {
|
|
20
|
+
MessageContentComplex,
|
|
21
|
+
UsageMetadata,
|
|
22
|
+
} from '@langchain/core/messages';
|
|
19
23
|
import type { StringPromptValue } from '@langchain/core/prompt_values';
|
|
20
|
-
import type { MessageContentComplex } from '@langchain/core/messages';
|
|
21
24
|
import type { RunnableConfig } from '@langchain/core/runnables';
|
|
22
25
|
import type { MultiAgentGraph } from '@/graphs/MultiAgentGraph';
|
|
23
26
|
import type { StandardGraph } from '@/graphs/Graph';
|
|
@@ -44,6 +47,12 @@ import {
|
|
|
44
47
|
isLangfuseCallbackHandler,
|
|
45
48
|
withLangfuseAttributes,
|
|
46
49
|
} from '@/langfuse';
|
|
50
|
+
import {
|
|
51
|
+
REASONING_LABEL_PROMPT,
|
|
52
|
+
buildReasoningLabelTraceSeed,
|
|
53
|
+
buildReasoningLabelPrompt,
|
|
54
|
+
normalizeReasoningLabel,
|
|
55
|
+
} from '@/prompts/reasoningLabel';
|
|
47
56
|
import {
|
|
48
57
|
hasToolOutputTracingConfig,
|
|
49
58
|
resolveLangfuseConfig,
|
|
@@ -59,6 +68,10 @@ import {
|
|
|
59
68
|
resolveLangfuseRuntimeScope,
|
|
60
69
|
withLangfuseRuntimeScope,
|
|
61
70
|
} from '@/langfuseRuntimeScope';
|
|
71
|
+
import {
|
|
72
|
+
getRunStepResumeState,
|
|
73
|
+
stripRunStepResumeState,
|
|
74
|
+
} from '@/tools/runStepResume';
|
|
62
75
|
import {
|
|
63
76
|
Callback,
|
|
64
77
|
GraphEvents,
|
|
@@ -72,6 +85,7 @@ import {
|
|
|
72
85
|
import { applyGraphRuntimeConfig } from '@/graphs/applyGraphRuntimeConfig';
|
|
73
86
|
import { createTokenCounter, encodingForModel } from '@/utils/tokens';
|
|
74
87
|
import { initializeLangfuseTracing } from './instrumentation';
|
|
88
|
+
import { seedRunInitialSessions } from '@/utils/toolSessions';
|
|
75
89
|
import { getTraceIdSeed } from '@/langfuseRuntimeContext';
|
|
76
90
|
import { createGraph } from '@/graphs/createGraph';
|
|
77
91
|
import { resolveMaxSeals } from '@/llm/preempt';
|
|
@@ -95,6 +109,7 @@ export const defaultOmitOptions = new Set([
|
|
|
95
109
|
|
|
96
110
|
const ACTIVITY_LABEL_TRACE_NAME = 'LibreChat Activity Label';
|
|
97
111
|
const ACTIVITY_PHASE_TRACE_NAME = 'LibreChat Activity Phase';
|
|
112
|
+
const REASONING_LABEL_TRACE_NAME = 'LibreChat Reasoning Label';
|
|
98
113
|
|
|
99
114
|
const CUSTOM_GRAPH_EVENTS = new Set<string>([
|
|
100
115
|
GraphEvents.ON_AGENT_UPDATE,
|
|
@@ -173,7 +188,9 @@ function isLangGraphResumeMapForInterrupt(
|
|
|
173
188
|
}
|
|
174
189
|
|
|
175
190
|
function getInterruptHookSessionId(payload: unknown): string | undefined {
|
|
176
|
-
const publicPayload = stripSubagentResumeManifest(
|
|
191
|
+
const publicPayload = stripSubagentResumeManifest(
|
|
192
|
+
stripRunStepResumeState(payload)
|
|
193
|
+
);
|
|
177
194
|
if (
|
|
178
195
|
publicPayload == null ||
|
|
179
196
|
typeof publicPayload !== 'object' ||
|
|
@@ -193,11 +210,15 @@ type InterruptStateSnapshot = {
|
|
|
193
210
|
values?: { messages?: BaseMessage[] };
|
|
194
211
|
tasks?: Array<{
|
|
195
212
|
interrupts?: Array<{ id?: string; value?: unknown }>;
|
|
213
|
+
state?: RunnableConfig | InterruptStateSnapshot;
|
|
196
214
|
}>;
|
|
197
215
|
};
|
|
198
216
|
|
|
199
217
|
type WorkflowWithStateHistory = {
|
|
200
|
-
getState?(
|
|
218
|
+
getState?(
|
|
219
|
+
config: RunnableConfig,
|
|
220
|
+
options?: { subgraphs?: boolean }
|
|
221
|
+
): Promise<InterruptStateSnapshot>;
|
|
201
222
|
getStateHistory?(
|
|
202
223
|
config: RunnableConfig
|
|
203
224
|
): AsyncIterableIterator<InterruptStateSnapshot>;
|
|
@@ -215,6 +236,17 @@ function getFirstPersistedInterrupt(
|
|
|
215
236
|
return { id: pendingInterrupt.id, value: pendingInterrupt.value };
|
|
216
237
|
}
|
|
217
238
|
}
|
|
239
|
+
const nestedState = task.state;
|
|
240
|
+
if (
|
|
241
|
+
nestedState != null &&
|
|
242
|
+
'tasks' in nestedState &&
|
|
243
|
+
Array.isArray(nestedState.tasks)
|
|
244
|
+
) {
|
|
245
|
+
const nestedInterrupt = getFirstPersistedInterrupt(nestedState);
|
|
246
|
+
if (nestedInterrupt != null) {
|
|
247
|
+
return nestedInterrupt;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
218
250
|
}
|
|
219
251
|
return undefined;
|
|
220
252
|
}
|
|
@@ -290,6 +322,8 @@ export class Run<_T extends t.BaseGraphState> {
|
|
|
290
322
|
private activityLabelSeq = 0;
|
|
291
323
|
/** Per-run sequence for parent activity-phase trace and invocation ids. */
|
|
292
324
|
private activityPhaseLabelSeq = 0;
|
|
325
|
+
/** Per-run sequence for reasoning-label trace and invocation ids. */
|
|
326
|
+
private reasoningLabelSeq = 0;
|
|
293
327
|
/** Latest user turn used to keep detached phase roots conversation-shaped. */
|
|
294
328
|
private activityPhaseTraceInput?: string;
|
|
295
329
|
/** Distinguishes sibling forks started from the same explicit checkpoint. */
|
|
@@ -351,9 +385,25 @@ export class Run<_T extends t.BaseGraphState> {
|
|
|
351
385
|
}
|
|
352
386
|
|
|
353
387
|
if (config.initialSessions && this.Graph) {
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
388
|
+
const configuredAgents =
|
|
389
|
+
'agents' in config.graphConfig &&
|
|
390
|
+
Array.isArray(config.graphConfig.agents)
|
|
391
|
+
? config.graphConfig.agents
|
|
392
|
+
: undefined;
|
|
393
|
+
const agents: Array<Pick<t.AgentInputs, 'codeSessionKey'>> =
|
|
394
|
+
configuredAgents ?? [
|
|
395
|
+
{
|
|
396
|
+
codeSessionKey:
|
|
397
|
+
'codeSessionKey' in config.graphConfig
|
|
398
|
+
? config.graphConfig.codeSessionKey
|
|
399
|
+
: undefined,
|
|
400
|
+
},
|
|
401
|
+
];
|
|
402
|
+
seedRunInitialSessions({
|
|
403
|
+
sessions: this.Graph.sessions,
|
|
404
|
+
initialSessions: config.initialSessions,
|
|
405
|
+
agents,
|
|
406
|
+
});
|
|
357
407
|
}
|
|
358
408
|
|
|
359
409
|
this.returnContent = config.returnContent ?? false;
|
|
@@ -949,6 +999,12 @@ export class Run<_T extends t.BaseGraphState> {
|
|
|
949
999
|
delete config.configurable?.[SUBAGENT_RESUME_ATTEMPT_CONFIG_KEY];
|
|
950
1000
|
delete config.configurable?.[SUBAGENT_RESUME_MANIFEST_CONFIG_KEY];
|
|
951
1001
|
}
|
|
1002
|
+
if (isResume) {
|
|
1003
|
+
await this.restoreInterruptFromCheckpoint(
|
|
1004
|
+
config,
|
|
1005
|
+
(inputs as Command).update
|
|
1006
|
+
);
|
|
1007
|
+
}
|
|
952
1008
|
|
|
953
1009
|
/**
|
|
954
1010
|
* Cancellation can arrive either at graph construction or per-call through
|
|
@@ -1503,7 +1559,9 @@ export class Run<_T extends t.BaseGraphState> {
|
|
|
1503
1559
|
}
|
|
1504
1560
|
return {
|
|
1505
1561
|
...this._interrupt,
|
|
1506
|
-
payload: stripSubagentResumeManifest(
|
|
1562
|
+
payload: stripSubagentResumeManifest(
|
|
1563
|
+
stripRunStepResumeState(this._interrupt.payload)
|
|
1564
|
+
),
|
|
1507
1565
|
} as t.RunInterruptResult<TPayload>;
|
|
1508
1566
|
}
|
|
1509
1567
|
|
|
@@ -1622,7 +1680,7 @@ export class Run<_T extends t.BaseGraphState> {
|
|
|
1622
1680
|
await this.restoreInterruptFromCheckpoint(callerConfig, resumeUpdate);
|
|
1623
1681
|
const interrupt = this._interrupt;
|
|
1624
1682
|
const resumeManifest = requireValidSubagentResumeManifest(
|
|
1625
|
-
interrupt?.payload
|
|
1683
|
+
stripRunStepResumeState(interrupt?.payload)
|
|
1626
1684
|
);
|
|
1627
1685
|
const resumeConfigurable = { ...callerConfig.configurable };
|
|
1628
1686
|
delete resumeConfigurable[SUBAGENT_RESUME_ATTEMPT_CONFIG_KEY];
|
|
@@ -1709,7 +1767,7 @@ export class Run<_T extends t.BaseGraphState> {
|
|
|
1709
1767
|
callerConfig: t.RunStreamConfig,
|
|
1710
1768
|
resumeUpdate?: ResumeCommandUpdate
|
|
1711
1769
|
): Promise<void> {
|
|
1712
|
-
if (this._interrupt != null || this.
|
|
1770
|
+
if (this._interrupt != null || !this.hasCheckpointer) {
|
|
1713
1771
|
return;
|
|
1714
1772
|
}
|
|
1715
1773
|
const workflow = this.graphRunnable as
|
|
@@ -1719,11 +1777,16 @@ export class Run<_T extends t.BaseGraphState> {
|
|
|
1719
1777
|
return;
|
|
1720
1778
|
}
|
|
1721
1779
|
|
|
1722
|
-
const snapshot = await workflow.getState(callerConfig as RunnableConfig
|
|
1780
|
+
const snapshot = await workflow.getState(callerConfig as RunnableConfig, {
|
|
1781
|
+
subgraphs: true,
|
|
1782
|
+
});
|
|
1723
1783
|
const persistedInterrupt = getFirstPersistedInterrupt(snapshot);
|
|
1724
1784
|
if (persistedInterrupt == null) {
|
|
1725
1785
|
return;
|
|
1726
1786
|
}
|
|
1787
|
+
this.Graph?.restoreRunStepResumeState(
|
|
1788
|
+
getRunStepResumeState(persistedInterrupt.value)
|
|
1789
|
+
);
|
|
1727
1790
|
const persistedMessages = getPersistedMessages(snapshot);
|
|
1728
1791
|
if (persistedMessages != null) {
|
|
1729
1792
|
const resumeMessages = getResumeUpdateMessages(resumeUpdate);
|
|
@@ -2303,6 +2366,261 @@ export class Run<_T extends t.BaseGraphState> {
|
|
|
2303
2366
|
}
|
|
2304
2367
|
}
|
|
2305
2368
|
|
|
2369
|
+
/**
|
|
2370
|
+
* Generates one replacement title for a user-visible reasoning step. Hosts
|
|
2371
|
+
* own accumulation, scheduling, revision ordering, durable delivery, and
|
|
2372
|
+
* billing; the SDK only performs one bounded, redaction-aware generation.
|
|
2373
|
+
*/
|
|
2374
|
+
async generateReasoningLabel({
|
|
2375
|
+
provider,
|
|
2376
|
+
clientOptions,
|
|
2377
|
+
visibleReasoning,
|
|
2378
|
+
reasoningStepId,
|
|
2379
|
+
revision,
|
|
2380
|
+
status = 'streaming',
|
|
2381
|
+
previousLabel,
|
|
2382
|
+
agentId,
|
|
2383
|
+
prompt,
|
|
2384
|
+
charLimit = 6_000,
|
|
2385
|
+
chainOptions,
|
|
2386
|
+
traceSeed,
|
|
2387
|
+
sourceRunId,
|
|
2388
|
+
sourceTraceId,
|
|
2389
|
+
responseId,
|
|
2390
|
+
}: t.RunReasoningLabelOptions): Promise<t.ReasoningLabelResult> {
|
|
2391
|
+
const normalizedStepId = reasoningStepId.trim();
|
|
2392
|
+
const snapshotChars = visibleReasoning.trim().length;
|
|
2393
|
+
if (
|
|
2394
|
+
normalizedStepId === '' ||
|
|
2395
|
+
snapshotChars === 0 ||
|
|
2396
|
+
!Number.isInteger(revision) ||
|
|
2397
|
+
revision < 0
|
|
2398
|
+
) {
|
|
2399
|
+
return {};
|
|
2400
|
+
}
|
|
2401
|
+
|
|
2402
|
+
const reasoningSeq = ++this.reasoningLabelSeq;
|
|
2403
|
+
const requestedContext =
|
|
2404
|
+
this.Graph == null || agentId == null
|
|
2405
|
+
? undefined
|
|
2406
|
+
: this.Graph.agentContexts.get(agentId);
|
|
2407
|
+
if (agentId != null && requestedContext == null) {
|
|
2408
|
+
return {};
|
|
2409
|
+
}
|
|
2410
|
+
if (agentId == null && (this.Graph?.agentContexts.size ?? 0) > 1) {
|
|
2411
|
+
return {};
|
|
2412
|
+
}
|
|
2413
|
+
const reasoningContext =
|
|
2414
|
+
this.Graph == null
|
|
2415
|
+
? undefined
|
|
2416
|
+
: (requestedContext ??
|
|
2417
|
+
this.Graph.agentContexts.get(this.Graph.defaultAgentId));
|
|
2418
|
+
const reasoningChainOptions = {
|
|
2419
|
+
...(chainOptions ?? {}),
|
|
2420
|
+
} as Partial<RunnableConfig> & {
|
|
2421
|
+
configurable?: Record<string, unknown> & {
|
|
2422
|
+
requestBody?: { parentMessageId?: unknown };
|
|
2423
|
+
};
|
|
2424
|
+
};
|
|
2425
|
+
const reasoningUserId =
|
|
2426
|
+
typeof reasoningChainOptions.configurable?.user_id === 'string'
|
|
2427
|
+
? reasoningChainOptions.configurable.user_id
|
|
2428
|
+
: undefined;
|
|
2429
|
+
const reasoningSessionId =
|
|
2430
|
+
typeof reasoningChainOptions.configurable?.thread_id === 'string'
|
|
2431
|
+
? reasoningChainOptions.configurable.thread_id
|
|
2432
|
+
: undefined;
|
|
2433
|
+
const reasoningParentMessageId =
|
|
2434
|
+
reasoningChainOptions.configurable?.requestBody?.parentMessageId;
|
|
2435
|
+
const reasoningAgentId =
|
|
2436
|
+
agentId ??
|
|
2437
|
+
(this.Graph?.agentContexts.size === 1
|
|
2438
|
+
? this.Graph.defaultAgentId
|
|
2439
|
+
: undefined);
|
|
2440
|
+
const reasoningAgentName =
|
|
2441
|
+
reasoningAgentId == null ? undefined : reasoningContext?.name;
|
|
2442
|
+
const resolvedSourceRunId = sourceRunId ?? this.id;
|
|
2443
|
+
const reasoningResponseId = responseId ?? this.id;
|
|
2444
|
+
const reasoningMetadata: Record<string, unknown> = {
|
|
2445
|
+
sourceRunId: resolvedSourceRunId,
|
|
2446
|
+
...(sourceTraceId == null ? {} : { sourceTraceId }),
|
|
2447
|
+
responseId: reasoningResponseId,
|
|
2448
|
+
reasoningStepId: normalizedStepId,
|
|
2449
|
+
revision,
|
|
2450
|
+
status,
|
|
2451
|
+
snapshotChars,
|
|
2452
|
+
...(typeof reasoningParentMessageId === 'string'
|
|
2453
|
+
? { parentMessageId: reasoningParentMessageId }
|
|
2454
|
+
: {}),
|
|
2455
|
+
...(reasoningAgentId == null ? {} : { agentId: reasoningAgentId }),
|
|
2456
|
+
...(reasoningAgentName == null ? {} : { agentName: reasoningAgentName }),
|
|
2457
|
+
};
|
|
2458
|
+
const traceMetadata = {
|
|
2459
|
+
...createLangfuseTraceMetadata({
|
|
2460
|
+
messageId: `reasoning-label-${reasoningResponseId}`,
|
|
2461
|
+
parentMessageId: reasoningParentMessageId,
|
|
2462
|
+
agentId: reasoningAgentId,
|
|
2463
|
+
agentName: reasoningAgentName,
|
|
2464
|
+
}),
|
|
2465
|
+
sourceRunId: resolvedSourceRunId,
|
|
2466
|
+
...(sourceTraceId == null ? {} : { sourceTraceId }),
|
|
2467
|
+
responseId: reasoningResponseId,
|
|
2468
|
+
reasoningStepId: normalizedStepId,
|
|
2469
|
+
revision: String(revision),
|
|
2470
|
+
status,
|
|
2471
|
+
snapshotChars: String(snapshotChars),
|
|
2472
|
+
};
|
|
2473
|
+
const reasoningRunName =
|
|
2474
|
+
reasoningChainOptions.runName ?? REASONING_LABEL_TRACE_NAME;
|
|
2475
|
+
const reasoningTags = ['librechat', 'reasoning-label', 'reasoning-step'];
|
|
2476
|
+
const reasoningLangfuseConfig = resolveLangfuseConfig(
|
|
2477
|
+
this.langfuse,
|
|
2478
|
+
reasoningContext?.langfuse
|
|
2479
|
+
);
|
|
2480
|
+
initializeLangfuseTracing(reasoningLangfuseConfig);
|
|
2481
|
+
|
|
2482
|
+
const inheritedTraceSeed = getTraceIdSeed();
|
|
2483
|
+
const reasoningTraceSeed =
|
|
2484
|
+
reasoningLangfuseConfig?.deterministicTraceId === true ||
|
|
2485
|
+
inheritedTraceSeed != null
|
|
2486
|
+
? (traceSeed ??
|
|
2487
|
+
buildReasoningLabelTraceSeed(
|
|
2488
|
+
resolvedSourceRunId,
|
|
2489
|
+
normalizedStepId,
|
|
2490
|
+
revision
|
|
2491
|
+
))
|
|
2492
|
+
: undefined;
|
|
2493
|
+
const reasoningScopeRunId = `reasoning-label:${this.id}:${reasoningSeq}:${nanoid()}`;
|
|
2494
|
+
const reasoningRuntimeScope = resolveLangfuseRuntimeScope({
|
|
2495
|
+
runLangfuse: this.langfuse,
|
|
2496
|
+
langfuseOverlay: reasoningContext?.langfuse,
|
|
2497
|
+
traceIdSeed: reasoningTraceSeed,
|
|
2498
|
+
runId: reasoningScopeRunId,
|
|
2499
|
+
});
|
|
2500
|
+
let reasoningLangfuseHandler: CallbackEntry | undefined;
|
|
2501
|
+
if (reasoningSessionId != null) {
|
|
2502
|
+
reasoningLangfuseHandler = createLangfuseHandler({
|
|
2503
|
+
langfuse: reasoningLangfuseConfig,
|
|
2504
|
+
userId: reasoningUserId,
|
|
2505
|
+
sessionId: reasoningSessionId,
|
|
2506
|
+
traceMetadata,
|
|
2507
|
+
tags: reasoningTags,
|
|
2508
|
+
traceIdSeed:
|
|
2509
|
+
reasoningLangfuseConfig?.deterministicTraceId === true
|
|
2510
|
+
? reasoningTraceSeed
|
|
2511
|
+
: undefined,
|
|
2512
|
+
runId: reasoningScopeRunId,
|
|
2513
|
+
toolOutputTracing: reasoningRuntimeScope.toolOutputTracing,
|
|
2514
|
+
traceName: reasoningRunName,
|
|
2515
|
+
});
|
|
2516
|
+
}
|
|
2517
|
+
if (reasoningLangfuseHandler != null) {
|
|
2518
|
+
reasoningChainOptions.callbacks = appendCallbacks(
|
|
2519
|
+
reasoningChainOptions.callbacks,
|
|
2520
|
+
[reasoningLangfuseHandler]
|
|
2521
|
+
);
|
|
2522
|
+
}
|
|
2523
|
+
|
|
2524
|
+
const redaction = hasToolOutputTracingConfig(
|
|
2525
|
+
this.langfuse,
|
|
2526
|
+
reasoningContext?.langfuse
|
|
2527
|
+
)
|
|
2528
|
+
? resolveToolOutputTracingConfig(
|
|
2529
|
+
this.langfuse,
|
|
2530
|
+
reasoningContext?.langfuse
|
|
2531
|
+
)
|
|
2532
|
+
: undefined;
|
|
2533
|
+
const userPrompt = buildReasoningLabelPrompt({
|
|
2534
|
+
visibleReasoning,
|
|
2535
|
+
status,
|
|
2536
|
+
charLimit,
|
|
2537
|
+
previousLabel,
|
|
2538
|
+
redaction,
|
|
2539
|
+
});
|
|
2540
|
+
if (userPrompt === '') {
|
|
2541
|
+
await disposeLangfuseHandler(reasoningLangfuseHandler);
|
|
2542
|
+
return {};
|
|
2543
|
+
}
|
|
2544
|
+
|
|
2545
|
+
const model = initializeModel({
|
|
2546
|
+
provider,
|
|
2547
|
+
clientOptions: {
|
|
2548
|
+
...(clientOptions ?? {}),
|
|
2549
|
+
streaming: false,
|
|
2550
|
+
} as t.ClientOptions,
|
|
2551
|
+
}) as t.ChatModelInstance;
|
|
2552
|
+
const reasoningRunId = `${this.id}-reasoning-${reasoningSeq}`;
|
|
2553
|
+
const invokeConfig = Object.assign({}, reasoningChainOptions, {
|
|
2554
|
+
run_id: reasoningRunId,
|
|
2555
|
+
runId: reasoningRunId,
|
|
2556
|
+
runName: reasoningRunName,
|
|
2557
|
+
tags: [
|
|
2558
|
+
...new Set([...(reasoningChainOptions.tags ?? []), ...reasoningTags]),
|
|
2559
|
+
],
|
|
2560
|
+
metadata: {
|
|
2561
|
+
...(reasoningChainOptions.metadata ?? {}),
|
|
2562
|
+
...reasoningMetadata,
|
|
2563
|
+
},
|
|
2564
|
+
}) as Partial<RunnableConfig>;
|
|
2565
|
+
const invokeLabel = (
|
|
2566
|
+
runtimeConfig: Partial<RunnableConfig>
|
|
2567
|
+
): Promise<unknown> =>
|
|
2568
|
+
withLangfuseAttributes(
|
|
2569
|
+
{
|
|
2570
|
+
langfuse: reasoningLangfuseConfig,
|
|
2571
|
+
userId: reasoningUserId,
|
|
2572
|
+
sessionId: reasoningSessionId,
|
|
2573
|
+
traceName: reasoningRunName,
|
|
2574
|
+
traceMetadata,
|
|
2575
|
+
tags: reasoningTags,
|
|
2576
|
+
},
|
|
2577
|
+
() =>
|
|
2578
|
+
model.invoke(
|
|
2579
|
+
[
|
|
2580
|
+
new SystemMessage(prompt ?? REASONING_LABEL_PROMPT),
|
|
2581
|
+
new HumanMessage(userPrompt),
|
|
2582
|
+
],
|
|
2583
|
+
runtimeConfig
|
|
2584
|
+
)
|
|
2585
|
+
);
|
|
2586
|
+
const extractResult = (response: unknown): t.ReasoningLabelResult => {
|
|
2587
|
+
const result = response as {
|
|
2588
|
+
content?: unknown;
|
|
2589
|
+
usage_metadata?: UsageMetadata;
|
|
2590
|
+
} | null;
|
|
2591
|
+
const content = result?.content;
|
|
2592
|
+
let text = '';
|
|
2593
|
+
if (typeof content === 'string') {
|
|
2594
|
+
text = content;
|
|
2595
|
+
} else if (Array.isArray(content)) {
|
|
2596
|
+
text = content
|
|
2597
|
+
.map((block) =>
|
|
2598
|
+
typeof block === 'string'
|
|
2599
|
+
? block
|
|
2600
|
+
: ((block as { text?: string }).text ?? '')
|
|
2601
|
+
)
|
|
2602
|
+
.join('');
|
|
2603
|
+
}
|
|
2604
|
+
const label = normalizeReasoningLabel(text);
|
|
2605
|
+
return {
|
|
2606
|
+
...(label === '' ? {} : { label }),
|
|
2607
|
+
...(result?.usage_metadata == null
|
|
2608
|
+
? {}
|
|
2609
|
+
: { usage: result.usage_metadata }),
|
|
2610
|
+
};
|
|
2611
|
+
};
|
|
2612
|
+
|
|
2613
|
+
try {
|
|
2614
|
+
const response = await withLangfuseRuntimeScope(
|
|
2615
|
+
reasoningRuntimeScope,
|
|
2616
|
+
() => invokeLabel(invokeConfig)
|
|
2617
|
+
);
|
|
2618
|
+
return extractResult(response);
|
|
2619
|
+
} finally {
|
|
2620
|
+
await disposeLangfuseHandler(reasoningLangfuseHandler);
|
|
2621
|
+
}
|
|
2622
|
+
}
|
|
2623
|
+
|
|
2306
2624
|
/**
|
|
2307
2625
|
* Generates one parent summary for two or more logical activities. The
|
|
2308
2626
|
* summary model is traced as a dedicated activity-phase chain root in the
|
|
@@ -2661,8 +2979,8 @@ function findActivityPhaseTraceInput(
|
|
|
2661
2979
|
const message = messages[i];
|
|
2662
2980
|
if (
|
|
2663
2981
|
message.getType() !== 'human' ||
|
|
2664
|
-
message.additional_kwargs
|
|
2665
|
-
message.additional_kwargs
|
|
2982
|
+
message.additional_kwargs.role === 'system' ||
|
|
2983
|
+
message.additional_kwargs.isMeta === true
|
|
2666
2984
|
) {
|
|
2667
2985
|
continue;
|
|
2668
2986
|
}
|
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
|
|