@librechat/agents 3.2.68 → 3.3.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 +117 -3
- package/dist/cjs/agents/AgentContext.cjs.map +1 -1
- package/dist/cjs/common/enum.cjs +4 -0
- package/dist/cjs/common/enum.cjs.map +1 -1
- package/dist/cjs/graphs/Graph.cjs +243 -49
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/graphs/MultiAgentGraph.cjs +103 -28
- package/dist/cjs/graphs/MultiAgentGraph.cjs.map +1 -1
- package/dist/cjs/langfuseToolOutputTracing.cjs +4 -0
- package/dist/cjs/langfuseToolOutputTracing.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/index.cjs +11 -2
- package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
- package/dist/cjs/llm/contextOverflowRecovery.cjs +132 -0
- package/dist/cjs/llm/contextOverflowRecovery.cjs.map +1 -0
- package/dist/cjs/llm/google/index.cjs +1 -1
- package/dist/cjs/llm/invoke.cjs +60 -3
- package/dist/cjs/llm/invoke.cjs.map +1 -1
- package/dist/cjs/llm/openai/index.cjs +1 -1
- package/dist/cjs/main.cjs +21 -7
- package/dist/cjs/messages/format.cjs +136 -4
- package/dist/cjs/messages/format.cjs.map +1 -1
- package/dist/cjs/messages/prune.cjs +16 -5
- package/dist/cjs/messages/prune.cjs.map +1 -1
- package/dist/cjs/messages/recency.cjs +2 -0
- package/dist/cjs/messages/recency.cjs.map +1 -1
- package/dist/cjs/prompts/activityLabel.cjs +101 -0
- package/dist/cjs/prompts/activityLabel.cjs.map +1 -0
- package/dist/cjs/run.cjs +177 -3
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/stream.cjs +205 -49
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/summarization/node.cjs +55 -7
- package/dist/cjs/summarization/node.cjs.map +1 -1
- package/dist/cjs/tools/BashExecutor.cjs +2 -2
- package/dist/cjs/tools/BashExecutor.cjs.map +1 -1
- package/dist/cjs/tools/BashProgrammaticToolCalling.cjs +2 -2
- package/dist/cjs/tools/BashProgrammaticToolCalling.cjs.map +1 -1
- package/dist/cjs/tools/CodeExecutor.cjs +69 -8
- package/dist/cjs/tools/CodeExecutor.cjs.map +1 -1
- package/dist/cjs/tools/ProgrammaticToolCalling.cjs +19 -15
- package/dist/cjs/tools/ProgrammaticToolCalling.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +32 -3
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs +1 -1
- package/dist/cjs/utils/errors.cjs +317 -52
- package/dist/cjs/utils/errors.cjs.map +1 -1
- package/dist/esm/agents/AgentContext.mjs +118 -4
- package/dist/esm/agents/AgentContext.mjs.map +1 -1
- package/dist/esm/common/enum.mjs +4 -0
- package/dist/esm/common/enum.mjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +242 -48
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/graphs/MultiAgentGraph.mjs +103 -28
- package/dist/esm/graphs/MultiAgentGraph.mjs.map +1 -1
- package/dist/esm/langfuseToolOutputTracing.mjs +4 -1
- package/dist/esm/langfuseToolOutputTracing.mjs.map +1 -1
- package/dist/esm/llm/bedrock/index.mjs +11 -2
- package/dist/esm/llm/bedrock/index.mjs.map +1 -1
- package/dist/esm/llm/contextOverflowRecovery.mjs +130 -0
- package/dist/esm/llm/contextOverflowRecovery.mjs.map +1 -0
- package/dist/esm/llm/google/index.mjs +1 -1
- package/dist/esm/llm/invoke.mjs +59 -4
- package/dist/esm/llm/invoke.mjs.map +1 -1
- package/dist/esm/llm/openai/index.mjs +1 -1
- package/dist/esm/main.mjs +10 -10
- package/dist/esm/messages/format.mjs +136 -5
- package/dist/esm/messages/format.mjs.map +1 -1
- package/dist/esm/messages/prune.mjs +14 -6
- package/dist/esm/messages/prune.mjs.map +1 -1
- package/dist/esm/messages/recency.mjs +2 -1
- package/dist/esm/messages/recency.mjs.map +1 -1
- package/dist/esm/prompts/activityLabel.mjs +100 -0
- package/dist/esm/prompts/activityLabel.mjs.map +1 -0
- package/dist/esm/run.mjs +178 -4
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/stream.mjs +205 -49
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/summarization/node.mjs +55 -7
- package/dist/esm/summarization/node.mjs.map +1 -1
- package/dist/esm/tools/BashExecutor.mjs +3 -3
- package/dist/esm/tools/BashExecutor.mjs.map +1 -1
- package/dist/esm/tools/BashProgrammaticToolCalling.mjs +3 -3
- package/dist/esm/tools/BashProgrammaticToolCalling.mjs.map +1 -1
- package/dist/esm/tools/CodeExecutor.mjs +62 -9
- package/dist/esm/tools/CodeExecutor.mjs.map +1 -1
- package/dist/esm/tools/ProgrammaticToolCalling.mjs +20 -16
- package/dist/esm/tools/ProgrammaticToolCalling.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +32 -3
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/subagent/SubagentExecutor.mjs +1 -1
- package/dist/esm/utils/errors.mjs +317 -53
- package/dist/esm/utils/errors.mjs.map +1 -1
- package/dist/types/agents/AgentContext.d.ts +62 -3
- package/dist/types/common/enum.d.ts +5 -1
- package/dist/types/graphs/Graph.d.ts +16 -2
- package/dist/types/graphs/MultiAgentGraph.d.ts +1 -0
- package/dist/types/langfuseToolOutputTracing.d.ts +4 -0
- package/dist/types/llm/contextOverflowRecovery.d.ts +85 -0
- package/dist/types/llm/invoke.d.ts +35 -6
- package/dist/types/messages/format.d.ts +22 -0
- package/dist/types/messages/prune.d.ts +10 -2
- package/dist/types/messages/recency.d.ts +1 -0
- package/dist/types/prompts/activityLabel.d.ts +31 -0
- package/dist/types/run.d.ts +16 -0
- package/dist/types/tools/CodeExecutor.d.ts +14 -1
- package/dist/types/types/activityLabel.d.ts +53 -0
- package/dist/types/types/index.d.ts +1 -0
- package/dist/types/types/llm.d.ts +7 -4
- package/dist/types/types/stream.d.ts +7 -4
- package/dist/types/types/summarize.d.ts +22 -0
- package/dist/types/utils/__tests__/fixtures/contextOverflowSignatures.d.ts +40 -0
- package/dist/types/utils/errors.d.ts +65 -16
- package/dist/types/utils/redactSecrets.d.ts +3 -0
- package/package.json +7 -8
- package/src/agents/AgentContext.ts +188 -7
- package/src/agents/__tests__/AgentContext.overflow.test.ts +205 -0
- package/src/common/enum.ts +4 -0
- package/src/graphs/Graph.ts +409 -58
- package/src/graphs/MultiAgentGraph.ts +184 -46
- package/src/graphs/__tests__/Graph.contextOverflow.test.ts +631 -0
- package/src/langfuseToolOutputTracing.ts +4 -1
- package/src/llm/__tests__/contextOverflowRecovery.test.ts +401 -0
- package/src/llm/__tests__/fallbackOverflow.test.ts +287 -0
- package/src/llm/bedrock/index.ts +25 -12
- package/src/llm/contextOverflowRecovery.ts +292 -0
- package/src/llm/invoke.ts +119 -4
- package/src/messages/foldToollessToolBlocks.test.ts +438 -0
- package/src/messages/format.ts +233 -5
- package/src/messages/prune.ts +24 -11
- package/src/messages/recency.ts +3 -1
- package/src/prompts/activityLabel.ts +177 -0
- package/src/run.ts +322 -3
- package/src/scripts/context-overflow-probe.ts +997 -0
- package/src/specs/activity-label-prompt.test.ts +128 -0
- package/src/specs/activity-label-trace-seed.test.ts +47 -0
- package/src/specs/agent-handoffs.test.ts +903 -1
- package/src/specs/bedrock-toolless.live.test.ts +123 -0
- package/src/specs/context-overflow-recovery.live.test.ts +213 -0
- package/src/splitStream.test.ts +882 -0
- package/src/stream.ts +315 -51
- package/src/summarization/__tests__/aggregator.test.ts +83 -0
- package/src/summarization/__tests__/node.test.ts +139 -0
- package/src/summarization/node.ts +99 -14
- package/src/tools/BashExecutor.ts +4 -2
- package/src/tools/BashProgrammaticToolCalling.ts +4 -7
- package/src/tools/CodeExecutor.ts +119 -8
- package/src/tools/ProgrammaticToolCalling.ts +29 -27
- package/src/tools/ToolNode.ts +50 -8
- package/src/tools/__tests__/CodeApiAuthHeaders.test.ts +297 -3
- package/src/types/activityLabel.ts +55 -0
- package/src/types/index.ts +1 -0
- package/src/types/llm.ts +8 -1
- package/src/types/stream.ts +7 -4
- package/src/types/summarize.ts +22 -0
- package/src/utils/__tests__/errors.test.ts +270 -0
- package/src/utils/__tests__/fixtures/contextOverflowSignatures.ts +336 -0
- package/src/utils/__tests__/redactSecrets.test.ts +56 -0
- package/src/utils/errors.ts +484 -66
- package/src/utils/redactSecrets.ts +61 -0
package/src/run.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// src/run.ts
|
|
2
|
-
import { HumanMessage } from '@langchain/core/messages';
|
|
3
2
|
import { PromptTemplate } from '@langchain/core/prompts';
|
|
4
3
|
import { RunnableLambda } from '@langchain/core/runnables';
|
|
5
4
|
import { AzureChatOpenAI, ChatOpenAI } from '@langchain/openai';
|
|
6
5
|
import { BaseCallbackHandler } from '@langchain/core/callbacks/base';
|
|
6
|
+
import { HumanMessage, SystemMessage } from '@langchain/core/messages';
|
|
7
7
|
import {
|
|
8
8
|
Command,
|
|
9
9
|
INTERRUPT,
|
|
@@ -26,10 +26,19 @@ import {
|
|
|
26
26
|
isLangfuseCallbackHandler,
|
|
27
27
|
withLangfuseAttributes,
|
|
28
28
|
} from '@/langfuse';
|
|
29
|
+
import {
|
|
30
|
+
hasToolOutputTracingConfig,
|
|
31
|
+
resolveLangfuseConfig,
|
|
32
|
+
resolveToolOutputTracingConfig,
|
|
33
|
+
} from '@/langfuseConfig';
|
|
29
34
|
import {
|
|
30
35
|
resolveLangfuseRuntimeScope,
|
|
31
36
|
withLangfuseRuntimeScope,
|
|
32
37
|
} from '@/langfuseRuntimeScope';
|
|
38
|
+
import {
|
|
39
|
+
ACTIVITY_LABEL_PROMPT,
|
|
40
|
+
buildActivityLabelPrompt,
|
|
41
|
+
} from '@/prompts/activityLabel';
|
|
33
42
|
import {
|
|
34
43
|
appendCallbacks,
|
|
35
44
|
findCallback,
|
|
@@ -43,7 +52,7 @@ import { createTokenCounter, encodingForModel } from '@/utils/tokens';
|
|
|
43
52
|
import { initializeLangfuseTracing } from './instrumentation';
|
|
44
53
|
import { GraphEvents, Callback, TitleMethod } from '@/common';
|
|
45
54
|
import { MultiAgentGraph } from '@/graphs/MultiAgentGraph';
|
|
46
|
-
import {
|
|
55
|
+
import { getTraceIdSeed } from '@/langfuseRuntimeContext';
|
|
47
56
|
import { StandardGraph } from '@/graphs/Graph';
|
|
48
57
|
import { initializeModel } from '@/llm/init';
|
|
49
58
|
import { HandlerRegistry } from '@/events';
|
|
@@ -153,6 +162,10 @@ export class Run<_T extends t.BaseGraphState> {
|
|
|
153
162
|
* lets callers assert the type they expect.
|
|
154
163
|
*/
|
|
155
164
|
private _interrupt: t.RunInterruptResult<unknown> | undefined;
|
|
165
|
+
/** Per-run sequence for batch-unique activity-label trace-seed fallbacks. */
|
|
166
|
+
private activityLabelSeq = 0;
|
|
167
|
+
/** Distinguishes sibling forks started from the same explicit checkpoint. */
|
|
168
|
+
private checkpointForkSeq = 0;
|
|
156
169
|
private _haltedReason: string | undefined;
|
|
157
170
|
|
|
158
171
|
private constructor(config: Partial<t.RunConfig>) {
|
|
@@ -708,7 +721,28 @@ export class Run<_T extends t.BaseGraphState> {
|
|
|
708
721
|
* boundary.
|
|
709
722
|
*/
|
|
710
723
|
if (!isResume) {
|
|
711
|
-
|
|
724
|
+
const checkpointThreadId =
|
|
725
|
+
typeof config.configurable?.thread_id === 'string'
|
|
726
|
+
? config.configurable.thread_id
|
|
727
|
+
: undefined;
|
|
728
|
+
const checkpointNamespace =
|
|
729
|
+
typeof config.configurable?.checkpoint_ns === 'string'
|
|
730
|
+
? config.configurable.checkpoint_ns
|
|
731
|
+
: '';
|
|
732
|
+
const checkpointId =
|
|
733
|
+
typeof config.configurable?.checkpoint_id === 'string'
|
|
734
|
+
? config.configurable.checkpoint_id
|
|
735
|
+
: '';
|
|
736
|
+
const checkpointScope =
|
|
737
|
+
checkpointThreadId == null
|
|
738
|
+
? undefined
|
|
739
|
+
: JSON.stringify([
|
|
740
|
+
checkpointThreadId,
|
|
741
|
+
checkpointNamespace,
|
|
742
|
+
checkpointId,
|
|
743
|
+
checkpointId === '' ? 0 : ++this.checkpointForkSeq,
|
|
744
|
+
]);
|
|
745
|
+
graph.resetValues(streamOptions?.keepContent, checkpointScope);
|
|
712
746
|
}
|
|
713
747
|
this._interrupt = undefined;
|
|
714
748
|
this._haltedReason = undefined;
|
|
@@ -1478,6 +1512,291 @@ export class Run<_T extends t.BaseGraphState> {
|
|
|
1478
1512
|
await disposeLangfuseHandler(titleLangfuseHandler);
|
|
1479
1513
|
}
|
|
1480
1514
|
}
|
|
1515
|
+
|
|
1516
|
+
/**
|
|
1517
|
+
* Generates a short activity label for a completed tool/reasoning block
|
|
1518
|
+
* using a fast model. Mirrors `generateTitle`'s Langfuse wiring so the
|
|
1519
|
+
* call is traced under the conversation's session (sessionId from
|
|
1520
|
+
* `chainOptions.configurable.thread_id`) with its own tags — never as an
|
|
1521
|
+
* orphan trace. The payload contains no human messages by design: intent
|
|
1522
|
+
* comes from `lastAssistantText`, content from reasoning excerpts and
|
|
1523
|
+
* tool entries.
|
|
1524
|
+
*/
|
|
1525
|
+
async generateActivityLabel({
|
|
1526
|
+
provider,
|
|
1527
|
+
clientOptions,
|
|
1528
|
+
entries,
|
|
1529
|
+
thinkingExcerpts,
|
|
1530
|
+
lastAssistantText,
|
|
1531
|
+
prompt,
|
|
1532
|
+
charLimit = 600,
|
|
1533
|
+
chainOptions,
|
|
1534
|
+
traceSeed,
|
|
1535
|
+
agentId,
|
|
1536
|
+
}: t.RunActivityLabelOptions): Promise<{ label?: string }> {
|
|
1537
|
+
if (
|
|
1538
|
+
entries.length === 0 &&
|
|
1539
|
+
!(thinkingExcerpts && thinkingExcerpts.length > 0)
|
|
1540
|
+
) {
|
|
1541
|
+
return {};
|
|
1542
|
+
}
|
|
1543
|
+
const labelSeq = ++this.activityLabelSeq;
|
|
1544
|
+
|
|
1545
|
+
/** Resolve the LABELED agent's context: its Langfuse overlay carries the
|
|
1546
|
+
* trace metadata and the tool-output redaction policy that must govern
|
|
1547
|
+
* this label. */
|
|
1548
|
+
const requestedContext =
|
|
1549
|
+
this.Graph == null || agentId == null
|
|
1550
|
+
? undefined
|
|
1551
|
+
: this.Graph.agentContexts.get(agentId);
|
|
1552
|
+
/** Fail closed: an explicit but unknown/stale `agentId` must NOT silently
|
|
1553
|
+
* fall back to the default agent, whose redaction policy may be weaker
|
|
1554
|
+
* than the labeled agent's. Skip generation entirely instead. */
|
|
1555
|
+
if (agentId != null && requestedContext == null) {
|
|
1556
|
+
return {};
|
|
1557
|
+
}
|
|
1558
|
+
const labelContext =
|
|
1559
|
+
this.Graph == null
|
|
1560
|
+
? undefined
|
|
1561
|
+
: (requestedContext ??
|
|
1562
|
+
this.Graph.agentContexts.get(this.Graph.defaultAgentId));
|
|
1563
|
+
const traceMetadata = createLangfuseTraceMetadata({
|
|
1564
|
+
messageId: 'activity-label-' + this.id,
|
|
1565
|
+
agentName: labelContext?.name,
|
|
1566
|
+
});
|
|
1567
|
+
const labelRunName = getLangfuseTraceName(
|
|
1568
|
+
traceMetadata,
|
|
1569
|
+
'LibreChat Activity Label'
|
|
1570
|
+
);
|
|
1571
|
+
|
|
1572
|
+
/** Shallow-cloned: activity labels run once per tool batch, and writing
|
|
1573
|
+
* the Langfuse handler back onto a host-reused `chainOptions` would
|
|
1574
|
+
* accumulate duplicate callbacks across batches. */
|
|
1575
|
+
const labelChainOptions = {
|
|
1576
|
+
...(chainOptions ?? {}),
|
|
1577
|
+
} as Partial<RunnableConfig> & {
|
|
1578
|
+
configurable?: Record<string, unknown>;
|
|
1579
|
+
};
|
|
1580
|
+
const labelUserId =
|
|
1581
|
+
typeof labelChainOptions.configurable?.user_id === 'string'
|
|
1582
|
+
? (labelChainOptions.configurable.user_id as string)
|
|
1583
|
+
: undefined;
|
|
1584
|
+
const labelSessionId =
|
|
1585
|
+
typeof labelChainOptions.configurable?.thread_id === 'string'
|
|
1586
|
+
? (labelChainOptions.configurable.thread_id as string)
|
|
1587
|
+
: undefined;
|
|
1588
|
+
const labelLangfuseConfig = resolveLangfuseConfig(
|
|
1589
|
+
this.langfuse,
|
|
1590
|
+
labelContext?.langfuse
|
|
1591
|
+
);
|
|
1592
|
+
initializeLangfuseTracing(labelLangfuseConfig);
|
|
1593
|
+
/** Seed policy, threading two constraints:
|
|
1594
|
+
* 1. `runWithLangfuseRuntimeContext` SPREADS the surrounding context, so
|
|
1595
|
+
* an absent seed INHERITS the parent run's and collapses every label
|
|
1596
|
+
* into that trace. When a parent seed is active we must override it
|
|
1597
|
+
* with a per-label one.
|
|
1598
|
+
* 2. Without deterministic tracing there is no parent seed, and forcing
|
|
1599
|
+
* one here would make label trace ids deterministic when neither
|
|
1600
|
+
* `processStream` nor `generateTitle` are — so leave it unset.
|
|
1601
|
+
* Seeded when determinism is opted into OR a parent seed is live;
|
|
1602
|
+
* otherwise unseeded, matching the other generation paths. */
|
|
1603
|
+
const inheritedTraceSeed = getTraceIdSeed();
|
|
1604
|
+
const labelTraceSeed =
|
|
1605
|
+
labelLangfuseConfig?.deterministicTraceId === true ||
|
|
1606
|
+
inheritedTraceSeed != null
|
|
1607
|
+
? (traceSeed ?? `activity-label-${this.id}-${labelSeq}`)
|
|
1608
|
+
: undefined;
|
|
1609
|
+
const labelRuntimeScope = resolveLangfuseRuntimeScope({
|
|
1610
|
+
runLangfuse: this.langfuse,
|
|
1611
|
+
langfuseOverlay: labelContext?.langfuse,
|
|
1612
|
+
traceIdSeed: labelTraceSeed,
|
|
1613
|
+
});
|
|
1614
|
+
/** Handler only when a session id resolved from
|
|
1615
|
+
* `chainOptions.configurable.thread_id`: without it the label call has
|
|
1616
|
+
* no conversation identity, and tracing it would create an orphan
|
|
1617
|
+
* trace outside any session — worse than not tracing at all. */
|
|
1618
|
+
/** Declared then conditionally assigned (title precedent): a ternary
|
|
1619
|
+
* around the object literal makes eslint's indent rule and prettier
|
|
1620
|
+
* disagree, and both gate CI. */
|
|
1621
|
+
let labelLangfuseHandler: CallbackEntry | undefined;
|
|
1622
|
+
if (labelSessionId != null) {
|
|
1623
|
+
labelLangfuseHandler = createLangfuseHandler({
|
|
1624
|
+
langfuse: labelLangfuseConfig,
|
|
1625
|
+
userId: labelUserId,
|
|
1626
|
+
sessionId: labelSessionId,
|
|
1627
|
+
traceMetadata,
|
|
1628
|
+
tags: ['librechat', 'activity-label'],
|
|
1629
|
+
traceIdSeed:
|
|
1630
|
+
labelLangfuseConfig?.deterministicTraceId === true
|
|
1631
|
+
? labelTraceSeed
|
|
1632
|
+
: undefined,
|
|
1633
|
+
});
|
|
1634
|
+
}
|
|
1635
|
+
if (labelLangfuseHandler != null) {
|
|
1636
|
+
labelChainOptions.callbacks = appendCallbacks(
|
|
1637
|
+
labelChainOptions.callbacks,
|
|
1638
|
+
[labelLangfuseHandler]
|
|
1639
|
+
);
|
|
1640
|
+
}
|
|
1641
|
+
|
|
1642
|
+
/** The label prompt becomes Langfuse generation input, so the resolved
|
|
1643
|
+
* tool-output redaction policy (global disable / redactedToolNames)
|
|
1644
|
+
* applies to it exactly as to structured tool observations. */
|
|
1645
|
+
let redaction = hasToolOutputTracingConfig(
|
|
1646
|
+
this.langfuse,
|
|
1647
|
+
labelContext?.langfuse
|
|
1648
|
+
)
|
|
1649
|
+
? resolveToolOutputTracingConfig(this.langfuse, labelContext?.langfuse)
|
|
1650
|
+
: undefined;
|
|
1651
|
+
/** Multi-agent graph with no `agentId`: the caller did not say WHICH
|
|
1652
|
+
* agent ran this batch, so resolving from the default agent could trace
|
|
1653
|
+
* raw output that a stricter sibling's policy forbids. Fold every
|
|
1654
|
+
* agent's policy into the strictest one instead of guessing. */
|
|
1655
|
+
const agentContexts = this.Graph?.agentContexts;
|
|
1656
|
+
if (agentId == null && agentContexts != null && agentContexts.size > 1) {
|
|
1657
|
+
for (const context of agentContexts.values()) {
|
|
1658
|
+
if (!hasToolOutputTracingConfig(this.langfuse, context.langfuse)) {
|
|
1659
|
+
continue;
|
|
1660
|
+
}
|
|
1661
|
+
const candidate = resolveToolOutputTracingConfig(
|
|
1662
|
+
this.langfuse,
|
|
1663
|
+
context.langfuse
|
|
1664
|
+
);
|
|
1665
|
+
if (redaction == null) {
|
|
1666
|
+
redaction = candidate;
|
|
1667
|
+
continue;
|
|
1668
|
+
}
|
|
1669
|
+
redaction = {
|
|
1670
|
+
enabled: redaction.enabled === false ? false : candidate.enabled,
|
|
1671
|
+
redactedToolNames: new Set([
|
|
1672
|
+
...redaction.redactedToolNames,
|
|
1673
|
+
...candidate.redactedToolNames,
|
|
1674
|
+
]),
|
|
1675
|
+
redactedToolNameMatchMode:
|
|
1676
|
+
redaction.redactedToolNameMatchMode === 'partial' ||
|
|
1677
|
+
candidate.redactedToolNameMatchMode === 'partial'
|
|
1678
|
+
? 'partial'
|
|
1679
|
+
: 'exact',
|
|
1680
|
+
redactionText: redaction.redactionText,
|
|
1681
|
+
};
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
/** An active redaction policy suppresses free-form reasoning/intent, so
|
|
1685
|
+
* a reasoning-only block has nothing describable left — skip the model
|
|
1686
|
+
* call rather than paying for a label built from the prompt alone. */
|
|
1687
|
+
const freeFormSuppressed =
|
|
1688
|
+
redaction != null &&
|
|
1689
|
+
(redaction.enabled === false || redaction.redactedToolNames.size > 0);
|
|
1690
|
+
if (entries.length === 0 && freeFormSuppressed) {
|
|
1691
|
+
return {};
|
|
1692
|
+
}
|
|
1693
|
+
const userPrompt = buildActivityLabelPrompt({
|
|
1694
|
+
entries,
|
|
1695
|
+
charLimit,
|
|
1696
|
+
thinkingExcerpts,
|
|
1697
|
+
lastAssistantText,
|
|
1698
|
+
redaction,
|
|
1699
|
+
});
|
|
1700
|
+
|
|
1701
|
+
const model = initializeModel({
|
|
1702
|
+
provider,
|
|
1703
|
+
clientOptions: {
|
|
1704
|
+
...(clientOptions ?? {}),
|
|
1705
|
+
streaming: false,
|
|
1706
|
+
} as t.ClientOptions,
|
|
1707
|
+
}) as t.ChatModelInstance;
|
|
1708
|
+
|
|
1709
|
+
/** Distinct run id per label call: callback/tracing integrations key
|
|
1710
|
+
* in-flight runs by it, so reusing the parent run's id would collide
|
|
1711
|
+
* across successive (or concurrent) label batches. */
|
|
1712
|
+
const labelRunId = `${this.id}-activity-${labelSeq}`;
|
|
1713
|
+
const invokeConfig = Object.assign({}, labelChainOptions, {
|
|
1714
|
+
run_id: labelRunId,
|
|
1715
|
+
runId: labelRunId,
|
|
1716
|
+
runName: labelChainOptions.runName ?? labelRunName,
|
|
1717
|
+
}) as Partial<RunnableConfig>;
|
|
1718
|
+
|
|
1719
|
+
const invokeLabel = (
|
|
1720
|
+
runtimeConfig: Partial<RunnableConfig>
|
|
1721
|
+
): Promise<unknown> =>
|
|
1722
|
+
withLangfuseAttributes(
|
|
1723
|
+
{
|
|
1724
|
+
langfuse: labelLangfuseConfig,
|
|
1725
|
+
userId: labelUserId,
|
|
1726
|
+
sessionId: labelSessionId,
|
|
1727
|
+
traceName: runtimeConfig.runName ?? labelRunName,
|
|
1728
|
+
traceMetadata,
|
|
1729
|
+
tags: ['librechat', 'activity-label'],
|
|
1730
|
+
},
|
|
1731
|
+
() =>
|
|
1732
|
+
model.invoke(
|
|
1733
|
+
[
|
|
1734
|
+
new SystemMessage(prompt ?? ACTIVITY_LABEL_PROMPT),
|
|
1735
|
+
new HumanMessage(userPrompt),
|
|
1736
|
+
],
|
|
1737
|
+
runtimeConfig
|
|
1738
|
+
)
|
|
1739
|
+
);
|
|
1740
|
+
|
|
1741
|
+
const extractLabel = (response: unknown): string => {
|
|
1742
|
+
const content = (response as { content?: unknown } | null)?.content;
|
|
1743
|
+
let text = '';
|
|
1744
|
+
if (typeof content === 'string') {
|
|
1745
|
+
text = content;
|
|
1746
|
+
} else if (Array.isArray(content)) {
|
|
1747
|
+
text = content
|
|
1748
|
+
.map((block) =>
|
|
1749
|
+
typeof block === 'string'
|
|
1750
|
+
? block
|
|
1751
|
+
: ((block as { text?: string }).text ?? '')
|
|
1752
|
+
)
|
|
1753
|
+
.join('');
|
|
1754
|
+
}
|
|
1755
|
+
return text.trim().replace(/^["']|["']$/g, '');
|
|
1756
|
+
};
|
|
1757
|
+
|
|
1758
|
+
try {
|
|
1759
|
+
let response: unknown;
|
|
1760
|
+
try {
|
|
1761
|
+
response = await withLangfuseRuntimeScope(labelRuntimeScope, () =>
|
|
1762
|
+
invokeLabel(invokeConfig)
|
|
1763
|
+
);
|
|
1764
|
+
} catch (error) {
|
|
1765
|
+
/** Retry ONLY recognized callback/tracer failures (the EventStream
|
|
1766
|
+
* tracer class of errors the stripped-callbacks fallback exists
|
|
1767
|
+
* for). Aborts and provider failures rethrow — retrying those
|
|
1768
|
+
* doubles traffic/cost and can restart cancelled requests. */
|
|
1769
|
+
const aborted =
|
|
1770
|
+
(labelChainOptions as { signal?: AbortSignal }).signal?.aborted ===
|
|
1771
|
+
true || (error as Error | null)?.name === 'AbortError';
|
|
1772
|
+
const callbackFailure = /callback|tracer|event.?stream/i.test(
|
|
1773
|
+
String(
|
|
1774
|
+
(error as Error | null)?.stack ??
|
|
1775
|
+
(error as Error | null)?.message ??
|
|
1776
|
+
''
|
|
1777
|
+
)
|
|
1778
|
+
);
|
|
1779
|
+
if (aborted || !callbackFailure) {
|
|
1780
|
+
throw error;
|
|
1781
|
+
}
|
|
1782
|
+
const langfuseHandler = findCallback(
|
|
1783
|
+
invokeConfig.callbacks,
|
|
1784
|
+
isLangfuseCallbackHandler
|
|
1785
|
+
);
|
|
1786
|
+
const { callbacks: _cb, ...rest } = invokeConfig;
|
|
1787
|
+
const safeConfig = Object.assign({}, rest, {
|
|
1788
|
+
callbacks: langfuseHandler ? [langfuseHandler] : [],
|
|
1789
|
+
});
|
|
1790
|
+
response = await withLangfuseRuntimeScope(labelRuntimeScope, () =>
|
|
1791
|
+
invokeLabel(safeConfig as Partial<RunnableConfig>)
|
|
1792
|
+
);
|
|
1793
|
+
}
|
|
1794
|
+
const label = extractLabel(response);
|
|
1795
|
+
return label.length > 0 ? { label } : {};
|
|
1796
|
+
} finally {
|
|
1797
|
+
await disposeLangfuseHandler(labelLangfuseHandler);
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1481
1800
|
}
|
|
1482
1801
|
|
|
1483
1802
|
function findLastMessageOfType(
|