@librechat/agents 4.0.1 → 4.0.3
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 +3 -2
- package/dist/cjs/agents/AgentContext.cjs.map +1 -1
- package/dist/cjs/decisions/deadline.cjs +52 -0
- package/dist/cjs/decisions/deadline.cjs.map +1 -0
- package/dist/cjs/decisions/dialect.cjs +88 -0
- package/dist/cjs/decisions/dialect.cjs.map +1 -0
- package/dist/cjs/decisions/http.cjs +77 -0
- package/dist/cjs/decisions/http.cjs.map +1 -0
- package/dist/cjs/decisions/index.cjs +7 -0
- package/dist/cjs/decisions/presets.cjs +82 -0
- package/dist/cjs/decisions/presets.cjs.map +1 -0
- package/dist/cjs/decisions/questions.cjs +70 -0
- package/dist/cjs/decisions/questions.cjs.map +1 -0
- package/dist/cjs/decisions/structuredChat.cjs +172 -0
- package/dist/cjs/decisions/structuredChat.cjs.map +1 -0
- package/dist/cjs/decisions/structuredOutput.cjs +18 -0
- package/dist/cjs/decisions/structuredOutput.cjs.map +1 -0
- package/dist/cjs/decisions/traceMarker.cjs +6 -0
- package/dist/cjs/decisions/traceMarker.cjs.map +1 -0
- package/dist/cjs/decisions/transport.cjs +166 -0
- package/dist/cjs/decisions/transport.cjs.map +1 -0
- package/dist/cjs/decisions/types.cjs +44 -0
- package/dist/cjs/decisions/types.cjs.map +1 -0
- package/dist/cjs/graphs/Graph.cjs +28 -9
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/langfuseToolOutputTracing.cjs +6 -1
- package/dist/cjs/langfuseToolOutputTracing.cjs.map +1 -1
- package/dist/cjs/llm/google/index.cjs +1 -1
- package/dist/cjs/llm/invoke.cjs +34 -12
- package/dist/cjs/llm/invoke.cjs.map +1 -1
- package/dist/cjs/llm/openai/index.cjs +7 -0
- package/dist/cjs/llm/openai/index.cjs.map +1 -1
- package/dist/cjs/llm/providerTextBoundary.cjs +355 -0
- package/dist/cjs/llm/providerTextBoundary.cjs.map +1 -0
- package/dist/cjs/llm/providerTextChunk.cjs +14 -0
- package/dist/cjs/llm/providerTextChunk.cjs.map +1 -0
- package/dist/cjs/llm/providerTextControls.cjs +236 -0
- package/dist/cjs/llm/providerTextControls.cjs.map +1 -0
- package/dist/cjs/llm/stream/smoother.cjs +2 -1
- package/dist/cjs/llm/stream/smoother.cjs.map +1 -1
- package/dist/cjs/main.cjs +49 -1
- package/dist/cjs/protection/providerText.cjs +224 -0
- package/dist/cjs/protection/providerText.cjs.map +1 -0
- package/dist/cjs/protection/providerTextInput.cjs +25 -0
- package/dist/cjs/protection/providerTextInput.cjs.map +1 -0
- package/dist/cjs/rerank/index.cjs +2 -0
- package/dist/cjs/rerank/search.cjs +45 -0
- package/dist/cjs/rerank/search.cjs.map +1 -0
- package/dist/cjs/rerank/systemone.cjs +70 -0
- package/dist/cjs/rerank/systemone.cjs.map +1 -0
- package/dist/cjs/run.cjs +11 -1
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/stream.cjs +42 -14
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/summarization/node.cjs +26 -8
- package/dist/cjs/summarization/node.cjs.map +1 -1
- package/dist/cjs/tools/SubagentTool.cjs +11 -3
- package/dist/cjs/tools/SubagentTool.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +6 -5
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/search/rerankers.cjs +1 -0
- package/dist/cjs/tools/search/search.cjs +3 -3
- package/dist/cjs/tools/search/search.cjs.map +1 -1
- package/dist/cjs/tools/search/tool.cjs +4 -3
- package/dist/cjs/tools/search/tool.cjs.map +1 -1
- package/dist/cjs/tools/subagent/SubagentExecutionRegistry.cjs +13 -2
- package/dist/cjs/tools/subagent/SubagentExecutionRegistry.cjs.map +1 -1
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs +149 -26
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
- package/dist/cjs/tools/subagent/SubagentReplay.cjs +4 -2
- package/dist/cjs/tools/subagent/SubagentReplay.cjs.map +1 -1
- package/dist/cjs/tools/subagent/childGraphConfig.cjs +3 -1
- package/dist/cjs/tools/subagent/childGraphConfig.cjs.map +1 -1
- package/dist/cjs/tools/subagent/diagnostics.cjs +88 -2
- package/dist/cjs/tools/subagent/diagnostics.cjs.map +1 -1
- package/dist/cjs/tools/subagent/hostArgs.cjs +214 -0
- package/dist/cjs/tools/subagent/hostArgs.cjs.map +1 -0
- package/dist/cjs/tools/subagent/index.cjs +2 -0
- package/dist/cjs/tools/toolErrorContent.cjs +1 -1
- package/dist/esm/agents/AgentContext.mjs +3 -2
- package/dist/esm/agents/AgentContext.mjs.map +1 -1
- package/dist/esm/decisions/deadline.mjs +52 -0
- package/dist/esm/decisions/deadline.mjs.map +1 -0
- package/dist/esm/decisions/dialect.mjs +87 -0
- package/dist/esm/decisions/dialect.mjs.map +1 -0
- package/dist/esm/decisions/http.mjs +75 -0
- package/dist/esm/decisions/http.mjs.map +1 -0
- package/dist/esm/decisions/index.mjs +8 -0
- package/dist/esm/decisions/presets.mjs +77 -0
- package/dist/esm/decisions/presets.mjs.map +1 -0
- package/dist/esm/decisions/questions.mjs +67 -0
- package/dist/esm/decisions/questions.mjs.map +1 -0
- package/dist/esm/decisions/structuredChat.mjs +172 -0
- package/dist/esm/decisions/structuredChat.mjs.map +1 -0
- package/dist/esm/decisions/structuredOutput.mjs +18 -0
- package/dist/esm/decisions/structuredOutput.mjs.map +1 -0
- package/dist/esm/decisions/traceMarker.mjs +6 -0
- package/dist/esm/decisions/traceMarker.mjs.map +1 -0
- package/dist/esm/decisions/transport.mjs +164 -0
- package/dist/esm/decisions/transport.mjs.map +1 -0
- package/dist/esm/decisions/types.mjs +39 -0
- package/dist/esm/decisions/types.mjs.map +1 -0
- package/dist/esm/graphs/Graph.mjs +28 -9
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/langfuseToolOutputTracing.mjs +6 -1
- package/dist/esm/langfuseToolOutputTracing.mjs.map +1 -1
- package/dist/esm/llm/google/index.mjs +1 -1
- package/dist/esm/llm/invoke.mjs +34 -12
- package/dist/esm/llm/invoke.mjs.map +1 -1
- package/dist/esm/llm/openai/index.mjs +7 -0
- package/dist/esm/llm/openai/index.mjs.map +1 -1
- package/dist/esm/llm/providerTextBoundary.mjs +355 -0
- package/dist/esm/llm/providerTextBoundary.mjs.map +1 -0
- package/dist/esm/llm/providerTextChunk.mjs +13 -0
- package/dist/esm/llm/providerTextChunk.mjs.map +1 -0
- package/dist/esm/llm/providerTextControls.mjs +230 -0
- package/dist/esm/llm/providerTextControls.mjs.map +1 -0
- package/dist/esm/llm/stream/smoother.mjs +2 -1
- package/dist/esm/llm/stream/smoother.mjs.map +1 -1
- package/dist/esm/main.mjs +16 -2
- package/dist/esm/protection/providerText.mjs +218 -0
- package/dist/esm/protection/providerText.mjs.map +1 -0
- package/dist/esm/protection/providerTextInput.mjs +24 -0
- package/dist/esm/protection/providerTextInput.mjs.map +1 -0
- package/dist/esm/rerank/index.mjs +3 -0
- package/dist/esm/rerank/search.mjs +45 -0
- package/dist/esm/rerank/search.mjs.map +1 -0
- package/dist/esm/rerank/systemone.mjs +70 -0
- package/dist/esm/rerank/systemone.mjs.map +1 -0
- package/dist/esm/run.mjs +11 -1
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/stream.mjs +42 -14
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/summarization/node.mjs +26 -8
- package/dist/esm/summarization/node.mjs.map +1 -1
- package/dist/esm/tools/SubagentTool.mjs +11 -3
- package/dist/esm/tools/SubagentTool.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +6 -5
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/search/rerankers.mjs +1 -1
- package/dist/esm/tools/search/search.mjs +3 -3
- package/dist/esm/tools/search/search.mjs.map +1 -1
- package/dist/esm/tools/search/tool.mjs +4 -3
- package/dist/esm/tools/search/tool.mjs.map +1 -1
- package/dist/esm/tools/subagent/SubagentExecutionRegistry.mjs +13 -2
- package/dist/esm/tools/subagent/SubagentExecutionRegistry.mjs.map +1 -1
- package/dist/esm/tools/subagent/SubagentExecutor.mjs +149 -26
- package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
- package/dist/esm/tools/subagent/SubagentReplay.mjs +4 -2
- package/dist/esm/tools/subagent/SubagentReplay.mjs.map +1 -1
- package/dist/esm/tools/subagent/childGraphConfig.mjs +3 -1
- package/dist/esm/tools/subagent/childGraphConfig.mjs.map +1 -1
- package/dist/esm/tools/subagent/diagnostics.mjs +84 -3
- package/dist/esm/tools/subagent/diagnostics.mjs.map +1 -1
- package/dist/esm/tools/subagent/hostArgs.mjs +207 -0
- package/dist/esm/tools/subagent/hostArgs.mjs.map +1 -0
- package/dist/esm/tools/subagent/index.mjs +2 -0
- package/dist/esm/tools/toolErrorContent.mjs +1 -1
- package/dist/types/decisions/deadline.d.ts +3 -0
- package/dist/types/decisions/dialect.d.ts +11 -0
- package/dist/types/decisions/http.d.ts +22 -0
- package/dist/types/decisions/index.d.ts +10 -0
- package/dist/types/decisions/presets.d.ts +17 -0
- package/dist/types/decisions/questions.d.ts +8 -0
- package/dist/types/decisions/structuredChat.d.ts +17 -0
- package/dist/types/decisions/structuredOutput.d.ts +4 -0
- package/dist/types/decisions/traceMarker.d.ts +2 -0
- package/dist/types/decisions/transport.d.ts +29 -0
- package/dist/types/decisions/types.d.ts +119 -0
- package/dist/types/graphs/Graph.d.ts +7 -3
- package/dist/types/index.d.ts +4 -0
- package/dist/types/llm/invoke.d.ts +4 -1
- package/dist/types/llm/providerTextBoundary.d.ts +4 -0
- package/dist/types/llm/providerTextChunk.d.ts +7 -0
- package/dist/types/llm/providerTextControls.d.ts +18 -0
- package/dist/types/protection/providerText.d.ts +77 -0
- package/dist/types/protection/providerTextInput.d.ts +3 -0
- package/dist/types/rerank/index.d.ts +4 -0
- package/dist/types/rerank/search.d.ts +7 -0
- package/dist/types/rerank/systemone.d.ts +13 -0
- package/dist/types/rerank/types.d.ts +24 -0
- package/dist/types/run.d.ts +2 -0
- package/dist/types/tools/BashExecutor.d.ts +4 -0
- package/dist/types/tools/CodeExecutor.d.ts +4 -0
- package/dist/types/tools/ReadFile.d.ts +4 -0
- package/dist/types/tools/SkillTool.d.ts +4 -0
- package/dist/types/tools/SubagentTool.d.ts +2 -0
- package/dist/types/tools/ToolSearch.d.ts +4 -0
- package/dist/types/tools/search/schema.d.ts +4 -0
- package/dist/types/tools/search/types.d.ts +3 -1
- package/dist/types/tools/subagent/SubagentExecutionRegistry.d.ts +6 -0
- package/dist/types/tools/subagent/SubagentExecutor.d.ts +22 -1
- package/dist/types/tools/subagent/SubagentReplay.d.ts +3 -1
- package/dist/types/tools/subagent/diagnostics.d.ts +56 -8
- package/dist/types/tools/subagent/hostArgs.d.ts +57 -0
- package/dist/types/tools/subagent/index.d.ts +3 -0
- package/dist/types/types/graph.d.ts +39 -0
- package/dist/types/types/run.d.ts +6 -2
- package/dist/types/types/tools.d.ts +2 -0
- package/package.json +4 -4
- package/src/agents/AgentContext.ts +3 -2
- package/src/decisions/deadline.ts +92 -0
- package/src/decisions/dialect.ts +200 -0
- package/src/decisions/http.ts +175 -0
- package/src/decisions/index.ts +14 -0
- package/src/decisions/presets.ts +111 -0
- package/src/decisions/questions.ts +128 -0
- package/src/decisions/structuredChat.ts +358 -0
- package/src/decisions/structuredOutput.ts +25 -0
- package/src/decisions/traceMarker.ts +2 -0
- package/src/decisions/transport.ts +335 -0
- package/src/decisions/types.ts +193 -0
- package/src/graphs/Graph.ts +57 -9
- package/src/index.ts +9 -0
- package/src/langfuseToolOutputTracing.ts +8 -1
- package/src/llm/invoke.ts +48 -7
- package/src/llm/openai/index.ts +8 -0
- package/src/llm/providerTextBoundary.ts +446 -0
- package/src/llm/providerTextChunk.ts +15 -0
- package/src/llm/providerTextControls.ts +173 -0
- package/src/llm/stream/smoother.ts +4 -2
- package/src/protection/providerText.ts +325 -0
- package/src/protection/providerTextInput.ts +21 -0
- package/src/rerank/index.ts +4 -0
- package/src/rerank/search.ts +85 -0
- package/src/rerank/systemone.ts +140 -0
- package/src/rerank/types.ts +28 -0
- package/src/run.ts +13 -0
- package/src/stream.ts +33 -7
- package/src/summarization/node.ts +32 -14
- package/src/tools/SubagentTool.ts +14 -3
- package/src/tools/ToolNode.ts +7 -3
- package/src/tools/search/search.ts +4 -4
- package/src/tools/search/tool.ts +27 -25
- package/src/tools/search/types.ts +4 -1
- package/src/tools/subagent/SubagentExecutionRegistry.ts +27 -2
- package/src/tools/subagent/SubagentExecutor.ts +323 -28
- package/src/tools/subagent/SubagentReplay.ts +10 -3
- package/src/tools/subagent/childGraphConfig.ts +12 -1
- package/src/tools/subagent/diagnostics.ts +180 -9
- package/src/tools/subagent/hostArgs.ts +413 -0
- package/src/tools/subagent/index.ts +20 -0
- package/src/types/graph.ts +44 -0
- package/src/types/run.ts +6 -2
- package/src/types/tools.ts +6 -1
package/src/stream.ts
CHANGED
|
@@ -58,6 +58,7 @@ import {
|
|
|
58
58
|
import { createToolCallsDispatchedEvent, safeDispatchCustomEvent } from '@/utils/events';
|
|
59
59
|
import { resolveToolOutcome, outcomeFieldsFromResult } from '@/tools/intentArg';
|
|
60
60
|
import { snapshotValidatedModelChunk } from '@/graphs/acceptedModelResponse';
|
|
61
|
+
import { ProviderTextProtectionError } from '@/protection/providerText';
|
|
61
62
|
import { TOOL_OUTPUT_REF_PATTERN } from '@/tools/toolOutputReferences';
|
|
62
63
|
import { formatToolErrorContent } from '@/tools/toolErrorContent';
|
|
63
64
|
import { PreparedSubagentError } from '@/tools/preparedSubagents';
|
|
@@ -1687,6 +1688,7 @@ export class ChatModelStreamHandler implements t.EventHandler {
|
|
|
1687
1688
|
graph.breakerAbort instanceof AbortController
|
|
1688
1689
|
? graph.breakerAbort
|
|
1689
1690
|
: undefined;
|
|
1691
|
+
const entrySignals = [eventBreaker?.signal, graph.signal, graph.config.signal];
|
|
1690
1692
|
/** Immutable scope captured at handler entry. A reset while this
|
|
1691
1693
|
* handler is suspended in an await replaces the object, so ONE
|
|
1692
1694
|
* reference comparison proves the event still belongs to the live run
|
|
@@ -1695,13 +1697,16 @@ export class ChatModelStreamHandler implements t.EventHandler {
|
|
|
1695
1697
|
const runScopeInvalidated = (): boolean =>
|
|
1696
1698
|
entryRunScope != null && graph.runScope !== entryRunScope;
|
|
1697
1699
|
const throwIfRunBreakerTripped = (): void => {
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1700
|
+
for (const signal of entrySignals) {
|
|
1701
|
+
if (signal?.aborted === true &&
|
|
1702
|
+
(signal.reason instanceof StreamLimitExceededError ||
|
|
1703
|
+
signal.reason instanceof PreparedSubagentError ||
|
|
1704
|
+
signal.reason instanceof ProviderTextProtectionError)) {
|
|
1705
|
+
throw signal.reason;
|
|
1706
|
+
}
|
|
1707
|
+
if (signal?.aborted === true && graph.providerTextProtection != null) {
|
|
1708
|
+
throw new ProviderTextProtectionError('cancelled');
|
|
1709
|
+
}
|
|
1705
1710
|
}
|
|
1706
1711
|
};
|
|
1707
1712
|
|
|
@@ -1797,6 +1802,8 @@ export class ChatModelStreamHandler implements t.EventHandler {
|
|
|
1797
1802
|
metadata,
|
|
1798
1803
|
agentContext,
|
|
1799
1804
|
});
|
|
1805
|
+
if (runScopeInvalidated()) return;
|
|
1806
|
+
throwIfRunBreakerTripped();
|
|
1800
1807
|
if (skipHandling) {
|
|
1801
1808
|
return;
|
|
1802
1809
|
}
|
|
@@ -1831,6 +1838,8 @@ export class ChatModelStreamHandler implements t.EventHandler {
|
|
|
1831
1838
|
content,
|
|
1832
1839
|
metadata,
|
|
1833
1840
|
});
|
|
1841
|
+
if (runScopeInvalidated()) return;
|
|
1842
|
+
throwIfRunBreakerTripped();
|
|
1834
1843
|
}
|
|
1835
1844
|
|
|
1836
1845
|
if (
|
|
@@ -2033,6 +2042,23 @@ export class ChatModelStreamHandler implements t.EventHandler {
|
|
|
2033
2042
|
});
|
|
2034
2043
|
runStep = graph.getRunStep(stepId);
|
|
2035
2044
|
}
|
|
2045
|
+
if (
|
|
2046
|
+
graph.providerTextProtection != null &&
|
|
2047
|
+
runStep?.type === StepTypes.TOOL_CALLS &&
|
|
2048
|
+
agentContext.currentTokenType === ContentTypes.TEXT &&
|
|
2049
|
+
(typeof content === 'string' || content.every(isTextContentPart))
|
|
2050
|
+
) {
|
|
2051
|
+
stepId = await dispatchMessageCreationStep({
|
|
2052
|
+
graph,
|
|
2053
|
+
stepKey,
|
|
2054
|
+
content,
|
|
2055
|
+
contentType: ContentTypes.TEXT,
|
|
2056
|
+
metadata,
|
|
2057
|
+
});
|
|
2058
|
+
if (runScopeInvalidated()) return;
|
|
2059
|
+
throwIfRunBreakerTripped();
|
|
2060
|
+
runStep = graph.getRunStep(stepId);
|
|
2061
|
+
}
|
|
2036
2062
|
if (!runStep) {
|
|
2037
2063
|
console.warn(`\n
|
|
2038
2064
|
==============================================================
|
|
@@ -56,6 +56,7 @@ import {
|
|
|
56
56
|
resolveClientOptionsModel,
|
|
57
57
|
} from '@/llm/request';
|
|
58
58
|
import { renderCompactionSemanticIndex } from '@/summarization/semanticIndex';
|
|
59
|
+
import { ProviderTextProtectionError } from '@/protection/providerText';
|
|
59
60
|
import { safeDispatchCustomEvent, emitAgentLog } from '@/utils/events';
|
|
60
61
|
import { prepareToolsForPromptCache } from '@/llm/promptCacheTools';
|
|
61
62
|
import { attemptInvoke, tryFallbackProviders } from '@/llm/invoke';
|
|
@@ -739,16 +740,6 @@ async function executeSummarizationWithFallback(params: {
|
|
|
739
740
|
summaryText = result.text;
|
|
740
741
|
summaryUsage = result.usage;
|
|
741
742
|
} catch (primaryError) {
|
|
742
|
-
const primaryDescribed = describeProviderError(
|
|
743
|
-
primaryError,
|
|
744
|
-
clientConfig.provider,
|
|
745
|
-
clientConfig.modelName
|
|
746
|
-
);
|
|
747
|
-
log('error', `Summarization LLM call failed ${primaryDescribed.suffix}`, {
|
|
748
|
-
...primaryDescribed.data,
|
|
749
|
-
messagesToRefineCount: messages.length,
|
|
750
|
-
});
|
|
751
|
-
|
|
752
743
|
/**
|
|
753
744
|
* A tripped stream circuit breaker is a safety abort, not a
|
|
754
745
|
* summarization failure to recover from: retrying on fallback providers
|
|
@@ -758,7 +749,7 @@ async function executeSummarizationWithFallback(params: {
|
|
|
758
749
|
* rejects the run. Rethrown so the summarize node fails the run with
|
|
759
750
|
* the actionable limit error, consistent with agent turns and subagents.
|
|
760
751
|
*/
|
|
761
|
-
if (primaryError instanceof StreamLimitExceededError) {
|
|
752
|
+
if (primaryError instanceof StreamLimitExceededError || primaryError instanceof ProviderTextProtectionError) {
|
|
762
753
|
throw primaryError;
|
|
763
754
|
}
|
|
764
755
|
/** A parallel branch's trip aborts the composed summarization signal,
|
|
@@ -777,6 +768,16 @@ async function executeSummarizationWithFallback(params: {
|
|
|
777
768
|
}
|
|
778
769
|
}
|
|
779
770
|
|
|
771
|
+
const primaryDescribed = describeProviderError(
|
|
772
|
+
primaryError,
|
|
773
|
+
clientConfig.provider,
|
|
774
|
+
clientConfig.modelName
|
|
775
|
+
);
|
|
776
|
+
log('error', `Summarization LLM call failed ${primaryDescribed.suffix}`, {
|
|
777
|
+
...primaryDescribed.data,
|
|
778
|
+
messagesToRefineCount: messages.length,
|
|
779
|
+
});
|
|
780
|
+
|
|
780
781
|
const rawFallbacks = (
|
|
781
782
|
clientConfig.clientOptions as unknown as t.LLMConfig | undefined
|
|
782
783
|
)?.fallbacks;
|
|
@@ -819,7 +820,9 @@ async function executeSummarizationWithFallback(params: {
|
|
|
819
820
|
);
|
|
820
821
|
}
|
|
821
822
|
} catch (fbErr) {
|
|
822
|
-
|
|
823
|
+
const trip = findStreamLimitAbortReason(graph?.getBreakerSignal?.(), summarizeConfig?.signal);
|
|
824
|
+
if (trip != null) throw trip;
|
|
825
|
+
if (fbErr instanceof StreamLimitExceededError || fbErr instanceof ProviderTextProtectionError) {
|
|
823
826
|
throw fbErr;
|
|
824
827
|
}
|
|
825
828
|
const fbDescribed = describeFallbackError(fbErr, fallbacks);
|
|
@@ -842,6 +845,8 @@ async function executeSummarizationWithFallback(params: {
|
|
|
842
845
|
}
|
|
843
846
|
}
|
|
844
847
|
|
|
848
|
+
const trip = findStreamLimitAbortReason(graph?.getBreakerSignal?.(), summarizeConfig?.signal);
|
|
849
|
+
if (trip != null) throw trip;
|
|
845
850
|
return { text: summaryText, usage: summaryUsage, usedMetadataStub };
|
|
846
851
|
}
|
|
847
852
|
|
|
@@ -875,6 +880,11 @@ async function dispatchCompletionEvents(params: {
|
|
|
875
880
|
messagesAfterCount,
|
|
876
881
|
} = params;
|
|
877
882
|
|
|
883
|
+
const assertNotTripped = (): void => {
|
|
884
|
+
const trip = findStreamLimitAbortReason(graph.getBreakerSignal?.(), runnableConfig?.signal);
|
|
885
|
+
if (trip != null) throw trip;
|
|
886
|
+
};
|
|
887
|
+
assertNotTripped();
|
|
878
888
|
runStep.summary = summaryBlock;
|
|
879
889
|
if (summaryUsage) {
|
|
880
890
|
runStep.usage = {
|
|
@@ -892,6 +902,7 @@ async function dispatchCompletionEvents(params: {
|
|
|
892
902
|
runnableConfig
|
|
893
903
|
);
|
|
894
904
|
|
|
905
|
+
assertNotTripped();
|
|
895
906
|
if (runnableConfig) {
|
|
896
907
|
await safeDispatchCustomEvent(
|
|
897
908
|
GraphEvents.ON_SUMMARIZE_COMPLETE,
|
|
@@ -904,6 +915,7 @@ async function dispatchCompletionEvents(params: {
|
|
|
904
915
|
);
|
|
905
916
|
}
|
|
906
917
|
|
|
918
|
+
assertNotTripped();
|
|
907
919
|
const sessionId = graph.runId ?? '';
|
|
908
920
|
if (graph.hookRegistry?.hasHookFor('PostCompact', sessionId) === true) {
|
|
909
921
|
const threadId = (
|
|
@@ -1017,11 +1029,11 @@ function withBreakerSignal<T extends { signal?: AbortSignal }>(
|
|
|
1017
1029
|
* child's private breaker never fires for it. */
|
|
1018
1030
|
function findStreamLimitAbortReason(
|
|
1019
1031
|
...signals: Array<AbortSignal | undefined>
|
|
1020
|
-
): StreamLimitExceededError | undefined {
|
|
1032
|
+
): StreamLimitExceededError | ProviderTextProtectionError | undefined {
|
|
1021
1033
|
for (const signal of signals) {
|
|
1022
1034
|
if (
|
|
1023
1035
|
signal?.aborted === true &&
|
|
1024
|
-
signal.reason instanceof StreamLimitExceededError
|
|
1036
|
+
(signal.reason instanceof StreamLimitExceededError || signal.reason instanceof ProviderTextProtectionError)
|
|
1025
1037
|
) {
|
|
1026
1038
|
return signal.reason;
|
|
1027
1039
|
}
|
|
@@ -1526,6 +1538,8 @@ export function createSummarizeNode({
|
|
|
1526
1538
|
return { summarizationRequest: undefined };
|
|
1527
1539
|
}
|
|
1528
1540
|
|
|
1541
|
+
const postCallTrip = findStreamLimitAbortReason(entryBreakerSignal, config?.signal);
|
|
1542
|
+
if (postCallTrip != null) throw postCallTrip;
|
|
1529
1543
|
const summaryText = enrichSummary(rawText, messagesToRefine);
|
|
1530
1544
|
|
|
1531
1545
|
const tokenCount = await computeSummaryTokenCount(
|
|
@@ -1533,6 +1547,8 @@ export function createSummarizeNode({
|
|
|
1533
1547
|
agentContext
|
|
1534
1548
|
);
|
|
1535
1549
|
|
|
1550
|
+
const commitTrip = findStreamLimitAbortReason(entryBreakerSignal, config?.signal);
|
|
1551
|
+
if (commitTrip != null) throw commitTrip;
|
|
1536
1552
|
if (usedIntraTurnFallback) {
|
|
1537
1553
|
agentContext.setSummary(summaryText, tokenCount, {
|
|
1538
1554
|
precedesMessages: true,
|
|
@@ -1712,6 +1728,8 @@ export function createSummarizationChunkHandler({
|
|
|
1712
1728
|
throw error;
|
|
1713
1729
|
}
|
|
1714
1730
|
}
|
|
1731
|
+
const protectionTrip = findStreamLimitAbortReason(graph?.getBreakerController?.().signal, config.signal);
|
|
1732
|
+
if (protectionTrip != null) throw protectionTrip;
|
|
1715
1733
|
const chunkAny = chunk as Parameters<typeof getChunkContent>[0]['chunk'];
|
|
1716
1734
|
const raw = getChunkContent({ chunk: chunkAny, provider, reasoningKey });
|
|
1717
1735
|
if (raw == null || (typeof raw === 'string' && !raw)) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { JsonSchemaType, LCTool } from '@/types/tools';
|
|
2
2
|
import type { SubagentConfig } from '@/types';
|
|
3
|
+
import { buildSubagentHostArgProperties } from '@/tools/subagent/hostArgs';
|
|
3
4
|
import { INTENT_PROPERTY } from '@/tools/intentArg';
|
|
4
5
|
import { Constants } from '@/common';
|
|
5
6
|
|
|
@@ -33,6 +34,9 @@ const RUN_IN_BACKGROUND_PROP_DESCRIPTION =
|
|
|
33
34
|
const SUBAGENT_THREAD_PROP_DESCRIPTION =
|
|
34
35
|
'Continue a host-owned child thread using a fresh execution lease. The saved thread must belong to this scope and subagent type. Only available with run_in_background.';
|
|
35
36
|
|
|
37
|
+
const HOST_ARGS_DESCRIPTION =
|
|
38
|
+
'\n\nOPTIONAL ARGUMENTS:\n- Some types accept extra arguments, listed in brackets after the type. Each is optional: omit it to let the host choose. Where values are listed, pass one listed for the selected type; where it says any text, pass a short value of your own.';
|
|
39
|
+
|
|
36
40
|
export const SubagentToolSchema = {
|
|
37
41
|
type: 'object',
|
|
38
42
|
properties: {
|
|
@@ -69,8 +73,13 @@ export function buildSubagentToolParams(
|
|
|
69
73
|
description: string;
|
|
70
74
|
} {
|
|
71
75
|
const types = configs.map((c) => c.type);
|
|
76
|
+
const hostArgs = buildSubagentHostArgProperties(configs);
|
|
72
77
|
const typeDescriptions = configs
|
|
73
|
-
.map((c) =>
|
|
78
|
+
.map((c) => {
|
|
79
|
+
const summary = hostArgs.summaries.get(c.type);
|
|
80
|
+
const line = `- "${c.type}" (${c.name}): ${c.description}`;
|
|
81
|
+
return summary == null ? line : `${line} [optional ${summary}]`;
|
|
82
|
+
})
|
|
74
83
|
.join('\n');
|
|
75
84
|
|
|
76
85
|
return {
|
|
@@ -96,8 +105,7 @@ export function buildSubagentToolParams(
|
|
|
96
105
|
},
|
|
97
106
|
}
|
|
98
107
|
: {}),
|
|
99
|
-
...(options.background === true &&
|
|
100
|
-
options.threadContinuation === true
|
|
108
|
+
...(options.background === true && options.threadContinuation === true
|
|
101
109
|
? {
|
|
102
110
|
subagent_thread_id: {
|
|
103
111
|
type: 'string',
|
|
@@ -105,10 +113,13 @@ export function buildSubagentToolParams(
|
|
|
105
113
|
},
|
|
106
114
|
}
|
|
107
115
|
: {}),
|
|
116
|
+
...hostArgs.properties,
|
|
108
117
|
},
|
|
109
118
|
required: ['description', 'subagent_type'],
|
|
110
119
|
},
|
|
111
120
|
description: `${SubagentToolDescription}${
|
|
121
|
+
hostArgs.summaries.size > 0 ? HOST_ARGS_DESCRIPTION : ''
|
|
122
|
+
}${
|
|
112
123
|
options.background === true
|
|
113
124
|
? '\n\nBACKGROUND EXECUTION:\n- Set run_in_background to true when you do not need the result immediately. The call returns a background_task_id; use the host background-task tools to poll, steer, queue, interrupt, or cancel it.'
|
|
114
125
|
: ''
|
package/src/tools/ToolNode.ts
CHANGED
|
@@ -130,6 +130,7 @@ import {
|
|
|
130
130
|
} from '@/tools/local';
|
|
131
131
|
import { stripCodeSessionFileSummary } from '@/tools/CodeSessionFileSummary';
|
|
132
132
|
import { Constants, GraphEvents, CODE_EXECUTION_TOOLS } from '@/common';
|
|
133
|
+
import { ProviderTextProtectionError } from '@/protection/providerText';
|
|
133
134
|
import { formatToolErrorContent } from '@/tools/toolErrorContent';
|
|
134
135
|
import { PreparedSubagentError } from '@/tools/preparedSubagents';
|
|
135
136
|
import { attachRunStepResumeState } from '@/tools/runStepResume';
|
|
@@ -2146,7 +2147,8 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
2146
2147
|
*/
|
|
2147
2148
|
if (
|
|
2148
2149
|
e instanceof StreamLimitExceededError ||
|
|
2149
|
-
e instanceof PreparedSubagentError
|
|
2150
|
+
e instanceof PreparedSubagentError ||
|
|
2151
|
+
e instanceof ProviderTextProtectionError
|
|
2150
2152
|
) {
|
|
2151
2153
|
throw e;
|
|
2152
2154
|
}
|
|
@@ -3486,7 +3488,8 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
3486
3488
|
if (
|
|
3487
3489
|
signal?.aborted === true &&
|
|
3488
3490
|
(signal.reason instanceof StreamLimitExceededError ||
|
|
3489
|
-
signal.reason instanceof PreparedSubagentError
|
|
3491
|
+
signal.reason instanceof PreparedSubagentError ||
|
|
3492
|
+
signal.reason instanceof ProviderTextProtectionError)
|
|
3490
3493
|
) {
|
|
3491
3494
|
throw signal.reason;
|
|
3492
3495
|
}
|
|
@@ -5467,7 +5470,8 @@ export class ToolNode<T = any> extends RunnableCallable<T, T> {
|
|
|
5467
5470
|
if (
|
|
5468
5471
|
composedSignal?.aborted === true &&
|
|
5469
5472
|
(composedSignal.reason instanceof StreamLimitExceededError ||
|
|
5470
|
-
composedSignal.reason instanceof PreparedSubagentError
|
|
5473
|
+
composedSignal.reason instanceof PreparedSubagentError ||
|
|
5474
|
+
composedSignal.reason instanceof ProviderTextProtectionError)
|
|
5471
5475
|
) {
|
|
5472
5476
|
throw composedSignal.reason;
|
|
5473
5477
|
}
|
|
@@ -9,8 +9,8 @@ import {
|
|
|
9
9
|
import { createKeenableAPI } from './keenable-search';
|
|
10
10
|
import { createTavilyAPI } from './tavily-search';
|
|
11
11
|
import { createSearchMetrics } from './metrics';
|
|
12
|
+
import { getDefaultRanking } from './rerankers';
|
|
12
13
|
import { createCrwAPI } from './crw-search';
|
|
13
|
-
import { BaseReranker, getDefaultRanking } from './rerankers';
|
|
14
14
|
|
|
15
15
|
/** Engines queried when `searxngSearchOptions.engines` is not configured. */
|
|
16
16
|
const DEFAULT_SEARXNG_ENGINES = 'google,bing,duckduckgo';
|
|
@@ -169,7 +169,7 @@ const getHighlights = async ({
|
|
|
169
169
|
}: {
|
|
170
170
|
content: string;
|
|
171
171
|
query: string;
|
|
172
|
-
reranker?:
|
|
172
|
+
reranker?: t.SearchReranker;
|
|
173
173
|
metrics: t.SearchMetrics;
|
|
174
174
|
topResults?: number;
|
|
175
175
|
maxContentLength?: number;
|
|
@@ -453,7 +453,7 @@ const createSearXNGAPI = (
|
|
|
453
453
|
const organicResults = (data.results ?? [])
|
|
454
454
|
.slice(0, numResults)
|
|
455
455
|
.map((result: t.SearXNGResult, index: number) => {
|
|
456
|
-
let attribution
|
|
456
|
+
let attribution: string;
|
|
457
457
|
try {
|
|
458
458
|
attribution = new URL(result.url ?? '').hostname;
|
|
459
459
|
} catch {
|
|
@@ -486,7 +486,7 @@ const createSearXNGAPI = (
|
|
|
486
486
|
const newsResults = (data.results ?? [])
|
|
487
487
|
.filter(isNewsResult)
|
|
488
488
|
.map((result: t.SearXNGResult, index: number) => {
|
|
489
|
-
let attribution
|
|
489
|
+
let attribution: string;
|
|
490
490
|
try {
|
|
491
491
|
attribution = new URL(result.url ?? '').hostname;
|
|
492
492
|
} catch {
|
package/src/tools/search/tool.ts
CHANGED
|
@@ -12,6 +12,10 @@ import {
|
|
|
12
12
|
newsSchema,
|
|
13
13
|
DATE_RANGE,
|
|
14
14
|
} from './schema';
|
|
15
|
+
import {
|
|
16
|
+
formatResultsForLLM,
|
|
17
|
+
MISSING_SEARCH_RESULT_DATA_ERROR,
|
|
18
|
+
} from './format';
|
|
15
19
|
import { createSearchAPI, createSourceProcessor } from './search';
|
|
16
20
|
import { createKeenableScraper } from './keenable-scraper';
|
|
17
21
|
import { createSerperScraper } from './serper-scraper';
|
|
@@ -21,10 +25,6 @@ import { INTENT_PROPERTY } from '@/tools/intentArg';
|
|
|
21
25
|
import { createCrwScraper } from './crw-scraper';
|
|
22
26
|
import { expandHighlights } from './highlights';
|
|
23
27
|
import { createSearchMetrics } from './metrics';
|
|
24
|
-
import {
|
|
25
|
-
formatResultsForLLM,
|
|
26
|
-
MISSING_SEARCH_RESULT_DATA_ERROR,
|
|
27
|
-
} from './format';
|
|
28
28
|
import { createDefaultLogger } from './utils';
|
|
29
29
|
import { createReranker } from './rerankers';
|
|
30
30
|
import { Constants } from '@/common';
|
|
@@ -535,13 +535,13 @@ export const createSearchTool = (
|
|
|
535
535
|
} = config;
|
|
536
536
|
|
|
537
537
|
const logger = config.logger || createDefaultLogger();
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
538
|
+
let effectiveTavilySearchOptions = tavilySearchOptions;
|
|
539
|
+
if (searchProvider === 'tavily' && config.safeSearch != null) {
|
|
540
|
+
effectiveTavilySearchOptions = {
|
|
541
|
+
...tavilySearchOptions,
|
|
542
|
+
safeSearch: config.safeSearch !== 0,
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
545
|
|
|
546
546
|
const schemaProperties: Record<string, unknown> = {
|
|
547
547
|
intent: { ...INTENT_PROPERTY },
|
|
@@ -643,20 +643,22 @@ export const createSearchTool = (
|
|
|
643
643
|
});
|
|
644
644
|
}
|
|
645
645
|
|
|
646
|
-
const selectedReranker =
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
646
|
+
const selectedReranker =
|
|
647
|
+
config.reranker ??
|
|
648
|
+
createReranker({
|
|
649
|
+
rerankerType,
|
|
650
|
+
jinaApiKey,
|
|
651
|
+
jinaApiUrl,
|
|
652
|
+
cohereApiKey,
|
|
653
|
+
cohereApiUrl,
|
|
654
|
+
ragApiUrl,
|
|
655
|
+
ragApiTokenSupplier,
|
|
656
|
+
ragApiProfile,
|
|
657
|
+
rerankerTimeout,
|
|
658
|
+
httpAgent,
|
|
659
|
+
httpsAgent,
|
|
660
|
+
logger,
|
|
661
|
+
});
|
|
660
662
|
|
|
661
663
|
/** `none` is a deliberate opt-out that `createReranker` already reports;
|
|
662
664
|
* only an unusable configuration warrants a warning here. */
|
|
@@ -287,6 +287,9 @@ export interface ScrapeResult {
|
|
|
287
287
|
highlights?: Highlight[];
|
|
288
288
|
}
|
|
289
289
|
|
|
290
|
+
/** Host implementations need only the public ranking seam, not BaseReranker's private state. */
|
|
291
|
+
export type SearchReranker = Pick<BaseReranker, 'provider' | 'rerank'>;
|
|
292
|
+
|
|
290
293
|
export interface ProcessSourcesConfig {
|
|
291
294
|
topResults?: number;
|
|
292
295
|
/** Max chars of scraped content stored per source and passed to the
|
|
@@ -306,7 +309,7 @@ export interface ProcessSourcesConfig {
|
|
|
306
309
|
separatorExpandBy?: number;
|
|
307
310
|
strategies?: string[];
|
|
308
311
|
filterContent?: boolean;
|
|
309
|
-
reranker?:
|
|
312
|
+
reranker?: SearchReranker;
|
|
310
313
|
logger?: Logger;
|
|
311
314
|
}
|
|
312
315
|
|
|
@@ -63,6 +63,8 @@ export type SubagentInvocationBinding = Readonly<{
|
|
|
63
63
|
description: string;
|
|
64
64
|
subagentType: string;
|
|
65
65
|
configId?: string;
|
|
66
|
+
/** Value-free identity of the call's validated host arguments. */
|
|
67
|
+
hostArgsDigest?: string;
|
|
66
68
|
}>;
|
|
67
69
|
|
|
68
70
|
export type SubagentSettlementBinding = Readonly<{
|
|
@@ -340,7 +342,8 @@ function assertCompatibleResumeExecution(
|
|
|
340
342
|
current.parentToolCallId === next.parentToolCallId &&
|
|
341
343
|
current.childRunId === next.childRunId &&
|
|
342
344
|
current.subagentType === next.subagentType &&
|
|
343
|
-
current.configId === next.configId
|
|
345
|
+
current.configId === next.configId &&
|
|
346
|
+
current.hostArgsDigest === next.hostArgsDigest
|
|
344
347
|
) {
|
|
345
348
|
return;
|
|
346
349
|
}
|
|
@@ -354,7 +357,8 @@ function assertSameInvocation(
|
|
|
354
357
|
if (
|
|
355
358
|
current.description === next.description &&
|
|
356
359
|
current.subagentType === next.subagentType &&
|
|
357
|
-
current.configId === next.configId
|
|
360
|
+
current.configId === next.configId &&
|
|
361
|
+
current.hostArgsDigest === next.hostArgsDigest
|
|
358
362
|
) {
|
|
359
363
|
return;
|
|
360
364
|
}
|
|
@@ -425,6 +429,7 @@ export class SubagentExecutionRecord<
|
|
|
425
429
|
TSettledOutput = never,
|
|
426
430
|
> {
|
|
427
431
|
private identityValue?: SubagentExecutionIdentity;
|
|
432
|
+
private attemptedIdentityValue?: SubagentExecutionIdentity;
|
|
428
433
|
private bindingValue?: SubagentDefinitionBinding;
|
|
429
434
|
private bindingAuthority?: 'provisional' | 'effective';
|
|
430
435
|
private invocationValue?: SubagentInvocationBinding;
|
|
@@ -488,6 +493,24 @@ export class SubagentExecutionRecord<
|
|
|
488
493
|
return this.identityValue;
|
|
489
494
|
}
|
|
490
495
|
|
|
496
|
+
/** Correlation only; never committed identity or resume authority. */
|
|
497
|
+
get attemptedIdentity(): SubagentExecutionIdentity | undefined {
|
|
498
|
+
return this.attemptedIdentityValue;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
recordIdentityAttempt(identity: SubagentExecutionIdentity): void {
|
|
502
|
+
const current = this.attemptedIdentityValue;
|
|
503
|
+
if (
|
|
504
|
+
current != null &&
|
|
505
|
+
current.childRunId === identity.childRunId &&
|
|
506
|
+
current.childThreadId === identity.childThreadId &&
|
|
507
|
+
current.approvalExecutionScope === identity.approvalExecutionScope
|
|
508
|
+
) {
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
511
|
+
this.attemptedIdentityValue = Object.freeze({ ...identity });
|
|
512
|
+
}
|
|
513
|
+
|
|
491
514
|
get binding(): SubagentDefinitionBinding | undefined {
|
|
492
515
|
return this.bindingValue;
|
|
493
516
|
}
|
|
@@ -570,6 +593,7 @@ export class SubagentExecutionRecord<
|
|
|
570
593
|
if (this.pendingIdentityResolution != null) {
|
|
571
594
|
return this.pendingIdentityResolution;
|
|
572
595
|
}
|
|
596
|
+
this.attemptedIdentityValue = undefined;
|
|
573
597
|
const pending = Promise.resolve()
|
|
574
598
|
.then(() => {
|
|
575
599
|
this.assertCurrentIdentityResolution(pending);
|
|
@@ -929,6 +953,7 @@ export class SubagentExecutionRegistry<
|
|
|
929
953
|
if (this.recordsByAddress.get(record.address.key) !== record) {
|
|
930
954
|
throw new SubagentExecutionInvalidatedError();
|
|
931
955
|
}
|
|
956
|
+
record.recordIdentityAttempt(identity);
|
|
932
957
|
const checkpointKey = getPreparationResourceKey(
|
|
933
958
|
'checkpoint',
|
|
934
959
|
identity.childThreadId
|