@librechat/agents 4.0.2 → 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/structuredChat.cjs +2 -8
- package/dist/cjs/decisions/structuredChat.cjs.map +1 -1
- package/dist/cjs/decisions/structuredOutput.cjs +18 -0
- package/dist/cjs/decisions/structuredOutput.cjs.map +1 -0
- package/dist/cjs/graphs/Graph.cjs +25 -9
- package/dist/cjs/graphs/Graph.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 +10 -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/run.cjs +7 -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/subagent/SubagentExecutionRegistry.cjs +2 -2
- package/dist/cjs/tools/subagent/SubagentExecutionRegistry.cjs.map +1 -1
- package/dist/cjs/tools/subagent/SubagentExecutor.cjs +66 -16
- 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 +48 -5
- 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 +1 -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/structuredChat.mjs +2 -8
- package/dist/esm/decisions/structuredChat.mjs.map +1 -1
- package/dist/esm/decisions/structuredOutput.mjs +18 -0
- package/dist/esm/decisions/structuredOutput.mjs.map +1 -0
- package/dist/esm/graphs/Graph.mjs +25 -9
- package/dist/esm/graphs/Graph.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 +5 -3
- 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/run.mjs +7 -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/subagent/SubagentExecutionRegistry.mjs +2 -2
- package/dist/esm/tools/subagent/SubagentExecutionRegistry.mjs.map +1 -1
- package/dist/esm/tools/subagent/SubagentExecutor.mjs +66 -16
- 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 +46 -6
- 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 +1 -0
- package/dist/esm/tools/toolErrorContent.mjs +1 -1
- package/dist/types/decisions/structuredChat.d.ts +3 -2
- package/dist/types/decisions/structuredOutput.d.ts +4 -0
- package/dist/types/graphs/Graph.d.ts +6 -3
- package/dist/types/index.d.ts +2 -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/run.d.ts +1 -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/subagent/SubagentExecutionRegistry.d.ts +2 -0
- package/dist/types/tools/subagent/SubagentExecutor.d.ts +10 -2
- package/dist/types/tools/subagent/SubagentReplay.d.ts +3 -1
- package/dist/types/tools/subagent/diagnostics.d.ts +27 -3
- package/dist/types/tools/subagent/hostArgs.d.ts +57 -0
- package/dist/types/tools/subagent/index.d.ts +3 -2
- package/dist/types/types/graph.d.ts +36 -0
- package/dist/types/types/run.d.ts +4 -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/structuredChat.ts +9 -15
- package/src/decisions/structuredOutput.ts +25 -0
- package/src/graphs/Graph.ts +53 -9
- package/src/index.ts +7 -0
- 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/run.ts +9 -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/subagent/SubagentExecutionRegistry.ts +6 -2
- package/src/tools/subagent/SubagentExecutor.ts +145 -18
- package/src/tools/subagent/SubagentReplay.ts +10 -3
- package/src/tools/subagent/childGraphConfig.ts +12 -1
- package/src/tools/subagent/diagnostics.ts +98 -6
- package/src/tools/subagent/hostArgs.ts +413 -0
- package/src/tools/subagent/index.ts +9 -0
- package/src/types/graph.ts +41 -0
- package/src/types/run.ts +4 -2
- package/src/types/tools.ts +6 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { SubagentHostArgs } from '@/types/graph';
|
|
1
2
|
import {
|
|
2
3
|
SubagentSettlementBindingError,
|
|
3
4
|
SubagentDefinitionBindingError,
|
|
@@ -5,11 +6,39 @@ import {
|
|
|
5
6
|
SubagentExecutionInvalidatedError,
|
|
6
7
|
} from './SubagentExecutionRegistry';
|
|
7
8
|
import { describeCodeApiError } from '@/tools/diagnostics';
|
|
9
|
+
import { isSubagentHostArgName } from './hostArgs';
|
|
8
10
|
|
|
9
11
|
/** Which step of child start-up failed: execution identity, then host config resolution. */
|
|
10
12
|
export type SubagentResolutionPhase = 'identity' | 'config';
|
|
11
13
|
|
|
14
|
+
/** Why a host resolver refused a declared host argument value. */
|
|
15
|
+
export type SubagentHostArgumentRejection = 'unavailable' | 'not_allowed';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Thrown by a lazy resolver to refuse one declared host argument value. The
|
|
19
|
+
* parent model receives a fixed message naming the argument; the value and
|
|
20
|
+
* any error text stay private.
|
|
21
|
+
*/
|
|
22
|
+
export class SubagentHostArgumentError extends Error {
|
|
23
|
+
readonly argument: string;
|
|
24
|
+
readonly rejection: SubagentHostArgumentRejection;
|
|
25
|
+
|
|
26
|
+
constructor(argument: string, rejection: SubagentHostArgumentRejection) {
|
|
27
|
+
super('Subagent host argument was rejected.');
|
|
28
|
+
this.name = 'SubagentHostArgumentError';
|
|
29
|
+
this.argument = argument;
|
|
30
|
+
this.rejection = rejection;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Safe host-argument refusal retained across the detached delivery boundary. */
|
|
35
|
+
export type SubagentHostArgumentFailure = {
|
|
36
|
+
argument: string;
|
|
37
|
+
rejection: SubagentHostArgumentRejection;
|
|
38
|
+
};
|
|
39
|
+
|
|
12
40
|
const SUBAGENT_ERROR_TYPES = [
|
|
41
|
+
['SubagentHostArgumentError', SubagentHostArgumentError],
|
|
13
42
|
['SubagentExecutionInvalidatedError', SubagentExecutionInvalidatedError],
|
|
14
43
|
['SubagentDefinitionBindingError', SubagentDefinitionBindingError],
|
|
15
44
|
['SubagentInvocationBindingError', SubagentInvocationBindingError],
|
|
@@ -27,6 +56,8 @@ const SUBAGENT_RESOLUTION_MESSAGES = {
|
|
|
27
56
|
model_unavailable: 'Subagent error: Model or provider unavailable.',
|
|
28
57
|
configuration_changed:
|
|
29
58
|
'Subagent error: Subagent configuration changed. Start a new execution.',
|
|
59
|
+
host_argument_rejected:
|
|
60
|
+
'Subagent error: A requested subagent argument is not available. Omit it to let the host choose, or pass a different value.',
|
|
30
61
|
unknown: 'Subagent error: Unable to initialize the selected subagent.',
|
|
31
62
|
} as const;
|
|
32
63
|
|
|
@@ -67,6 +98,7 @@ function normalizeResolutionCause(
|
|
|
67
98
|
case 'agent_unavailable':
|
|
68
99
|
case 'model_unavailable':
|
|
69
100
|
case 'configuration_changed':
|
|
101
|
+
case 'host_argument_rejected':
|
|
70
102
|
return cause;
|
|
71
103
|
default:
|
|
72
104
|
return 'unknown';
|
|
@@ -79,16 +111,68 @@ export function getSubagentResolutionFailureMessage(
|
|
|
79
111
|
return SUBAGENT_RESOLUTION_MESSAGES[normalizeResolutionCause(cause)];
|
|
80
112
|
}
|
|
81
113
|
|
|
114
|
+
/** Returns a resolver's typed host-argument refusal when its name is safe to show. */
|
|
115
|
+
export function getSubagentHostArgumentFailure(
|
|
116
|
+
error: unknown,
|
|
117
|
+
suppliedHostArgs: SubagentHostArgs | undefined
|
|
118
|
+
): SubagentHostArgumentFailure | undefined {
|
|
119
|
+
try {
|
|
120
|
+
if (
|
|
121
|
+
!(error instanceof SubagentHostArgumentError) ||
|
|
122
|
+
suppliedHostArgs == null
|
|
123
|
+
) {
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
const { argument, rejection } = error;
|
|
127
|
+
if (
|
|
128
|
+
typeof argument !== 'string' ||
|
|
129
|
+
!isSubagentHostArgName(argument) ||
|
|
130
|
+
!Object.prototype.hasOwnProperty.call(suppliedHostArgs, argument)
|
|
131
|
+
) {
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
argument,
|
|
136
|
+
rejection: rejection === 'unavailable' ? 'unavailable' : 'not_allowed',
|
|
137
|
+
};
|
|
138
|
+
} catch {
|
|
139
|
+
return undefined;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Model-facing message for a refused host argument. */
|
|
144
|
+
export function getSubagentHostArgumentFailureMessage(
|
|
145
|
+
failure: SubagentHostArgumentFailure
|
|
146
|
+
): string {
|
|
147
|
+
const { argument } = failure;
|
|
148
|
+
const omit = `Omit "${argument}" to let the host choose, or pass a different value.`;
|
|
149
|
+
return failure.rejection === 'unavailable'
|
|
150
|
+
? `Subagent error: The requested "${argument}" is unavailable right now. ${omit}`
|
|
151
|
+
: `Subagent error: The requested "${argument}" is not allowed for this subagent. ${omit}`;
|
|
152
|
+
}
|
|
153
|
+
|
|
82
154
|
/** Safe typed failure retained when detached execution crosses the host boundary. */
|
|
83
155
|
export class SubagentResolutionError extends Error {
|
|
84
156
|
readonly phase: SubagentResolutionPhase;
|
|
85
157
|
readonly resolutionCause: SubagentResolutionCause;
|
|
158
|
+
readonly hostArgument?: SubagentHostArgumentFailure;
|
|
86
159
|
|
|
87
|
-
constructor(
|
|
88
|
-
|
|
160
|
+
constructor(
|
|
161
|
+
phase: SubagentResolutionPhase,
|
|
162
|
+
cause: SubagentResolutionCause,
|
|
163
|
+
hostArgument?: SubagentHostArgumentFailure
|
|
164
|
+
) {
|
|
165
|
+
super(
|
|
166
|
+
hostArgument == null
|
|
167
|
+
? getSubagentResolutionFailureMessage(cause)
|
|
168
|
+
: getSubagentHostArgumentFailureMessage(hostArgument)
|
|
169
|
+
);
|
|
89
170
|
this.name = 'SubagentResolutionError';
|
|
90
171
|
this.phase = phase;
|
|
91
172
|
this.resolutionCause = normalizeResolutionCause(cause);
|
|
173
|
+
if (hostArgument != null) {
|
|
174
|
+
this.hostArgument = hostArgument;
|
|
175
|
+
}
|
|
92
176
|
}
|
|
93
177
|
}
|
|
94
178
|
|
|
@@ -111,7 +195,8 @@ export function logSubagentResolutionFailure(
|
|
|
111
195
|
signal: AbortSignal,
|
|
112
196
|
error: unknown,
|
|
113
197
|
context?: SubagentResolutionContext,
|
|
114
|
-
onResolutionFailure?: SubagentResolutionFailureHandler
|
|
198
|
+
onResolutionFailure?: SubagentResolutionFailureHandler,
|
|
199
|
+
suppliedHostArgs?: SubagentHostArgs
|
|
115
200
|
): SubagentResolutionDiagnostic {
|
|
116
201
|
const detail: SubagentResolutionDiagnostic = {
|
|
117
202
|
...context,
|
|
@@ -122,11 +207,18 @@ export function logSubagentResolutionFailure(
|
|
|
122
207
|
cause: 'unknown',
|
|
123
208
|
message: SUBAGENT_RESOLUTION_MESSAGES.unknown,
|
|
124
209
|
};
|
|
210
|
+
const hostArgumentRejected =
|
|
211
|
+
getSubagentHostArgumentFailure(error, suppliedHostArgs) != null;
|
|
212
|
+
if (hostArgumentRejected) {
|
|
213
|
+
detail.cause = 'host_argument_rejected';
|
|
214
|
+
detail.message = SUBAGENT_RESOLUTION_MESSAGES.host_argument_rejected;
|
|
215
|
+
}
|
|
125
216
|
if (onResolutionFailure != null) {
|
|
126
217
|
try {
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
218
|
+
const reported = onResolutionFailure(Object.freeze({ ...detail }), error);
|
|
219
|
+
const cause = hostArgumentRejected
|
|
220
|
+
? detail.cause
|
|
221
|
+
: normalizeResolutionCause(reported);
|
|
130
222
|
return {
|
|
131
223
|
...detail,
|
|
132
224
|
cause,
|
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
import { createHash } from 'crypto';
|
|
2
|
+
import type {
|
|
3
|
+
SubagentHostArgs,
|
|
4
|
+
SubagentHostArgSpec,
|
|
5
|
+
SubagentHostArgSpecs,
|
|
6
|
+
} from '@/types/graph';
|
|
7
|
+
import type { JsonSchemaType } from '@/types/tools';
|
|
8
|
+
|
|
9
|
+
/** Bounds on host-declared subagent call arguments and their values. */
|
|
10
|
+
export const SUBAGENT_HOST_ARG_LIMITS = Object.freeze({
|
|
11
|
+
argsPerSubagent: 8,
|
|
12
|
+
distinctArgs: 16,
|
|
13
|
+
enumValues: 64,
|
|
14
|
+
mergedEnumValues: 256,
|
|
15
|
+
valueLength: 256,
|
|
16
|
+
descriptionLength: 1024,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const HOST_ARG_NAME_PATTERN = /^[a-z][a-z0-9_]{0,63}$/;
|
|
20
|
+
/** Advertises the runtime's no-control-character rule; fixed and linear-time. */
|
|
21
|
+
const FREE_FORM_SCHEMA_PATTERN = '^[^\\u0000-\\u001f\\u007f]*$';
|
|
22
|
+
const RESERVED_HOST_ARG_NAMES: ReadonlySet<string> = new Set([
|
|
23
|
+
'intent',
|
|
24
|
+
'description',
|
|
25
|
+
'subagent_type',
|
|
26
|
+
'run_in_background',
|
|
27
|
+
'subagent_thread_id',
|
|
28
|
+
]);
|
|
29
|
+
|
|
30
|
+
/** Any subagent entry that may declare host arguments. */
|
|
31
|
+
export type SubagentHostArgDeclaration = {
|
|
32
|
+
type: string;
|
|
33
|
+
hostArgs?: SubagentHostArgSpecs;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export type SubagentHostArgsResult =
|
|
37
|
+
| { ok: true; hostArgs?: SubagentHostArgs }
|
|
38
|
+
| { ok: false; message: string };
|
|
39
|
+
|
|
40
|
+
type HostArgEntry = readonly [string, SubagentHostArgSpec];
|
|
41
|
+
|
|
42
|
+
type MergedHostArg = {
|
|
43
|
+
description: string;
|
|
44
|
+
values: string[];
|
|
45
|
+
seenValues: Set<string>;
|
|
46
|
+
freeForm: boolean;
|
|
47
|
+
maxLength: number;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/** A name a host may declare: lowercase snake case, not a built-in subagent argument. */
|
|
51
|
+
export function isSubagentHostArgName(name: string): boolean {
|
|
52
|
+
return HOST_ARG_NAME_PATTERN.test(name) && !RESERVED_HOST_ARG_NAMES.has(name);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Length in Unicode code points, the unit JSON Schema `maxLength` counts. */
|
|
56
|
+
function countCodePoints(value: string): number {
|
|
57
|
+
let count = 0;
|
|
58
|
+
for (const _ of value) {
|
|
59
|
+
count += 1;
|
|
60
|
+
}
|
|
61
|
+
return count;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function hasControlCharacter(value: string): boolean {
|
|
65
|
+
for (let i = 0; i < value.length; i++) {
|
|
66
|
+
const code = value.charCodeAt(i);
|
|
67
|
+
if (code < 0x20 || code === 0x7f) {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function isBoundedText(value: unknown, maxLength: number): value is string {
|
|
75
|
+
return (
|
|
76
|
+
typeof value === 'string' &&
|
|
77
|
+
value.trim().length > 0 &&
|
|
78
|
+
countCodePoints(value) <= maxLength &&
|
|
79
|
+
!hasControlCharacter(value)
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function getFreeFormMaxLength(spec: SubagentHostArgSpec): number {
|
|
84
|
+
return spec.maxLength ?? SUBAGENT_HOST_ARG_LIMITS.valueLength;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function validateEnum(label: string, values: readonly string[]): void {
|
|
88
|
+
if (
|
|
89
|
+
!Array.isArray(values) ||
|
|
90
|
+
values.length === 0 ||
|
|
91
|
+
values.length > SUBAGENT_HOST_ARG_LIMITS.enumValues
|
|
92
|
+
) {
|
|
93
|
+
throw new Error(
|
|
94
|
+
`${label} enum must list 1-${SUBAGENT_HOST_ARG_LIMITS.enumValues} values.`
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
const seen = new Set<string>();
|
|
98
|
+
for (const value of values) {
|
|
99
|
+
if (!isBoundedText(value, SUBAGENT_HOST_ARG_LIMITS.valueLength)) {
|
|
100
|
+
throw new Error(
|
|
101
|
+
`${label} enum values must be non-blank strings of at most ${SUBAGENT_HOST_ARG_LIMITS.valueLength} characters without control characters.`
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
if (seen.has(value)) {
|
|
105
|
+
throw new Error(`${label} enum values must be unique.`);
|
|
106
|
+
}
|
|
107
|
+
seen.add(value);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function validateFreeForm(label: string, spec: SubagentHostArgSpec): void {
|
|
112
|
+
const maxLength = getFreeFormMaxLength(spec);
|
|
113
|
+
if (
|
|
114
|
+
!Number.isSafeInteger(maxLength) ||
|
|
115
|
+
maxLength < 1 ||
|
|
116
|
+
maxLength > SUBAGENT_HOST_ARG_LIMITS.valueLength
|
|
117
|
+
) {
|
|
118
|
+
throw new Error(
|
|
119
|
+
`${label} maxLength must be an integer from 1 to ${SUBAGENT_HOST_ARG_LIMITS.valueLength}.`
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function validateSpec(
|
|
125
|
+
type: string,
|
|
126
|
+
name: string,
|
|
127
|
+
spec: SubagentHostArgSpec | undefined
|
|
128
|
+
): asserts spec is SubagentHostArgSpec {
|
|
129
|
+
const label = `Subagent "${type}" host argument "${name}"`;
|
|
130
|
+
if (!isSubagentHostArgName(name)) {
|
|
131
|
+
throw new Error(
|
|
132
|
+
`${label} must match ${HOST_ARG_NAME_PATTERN.source} and must not reuse a built-in subagent argument name.`
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
if (spec == null) {
|
|
136
|
+
throw new Error(`${label} must be an object.`);
|
|
137
|
+
}
|
|
138
|
+
if ((spec as { pattern?: unknown }).pattern !== undefined) {
|
|
139
|
+
throw new Error(
|
|
140
|
+
`${label} cannot declare a pattern; validate the format in the resolver.`
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
if (
|
|
144
|
+
typeof spec.description !== 'string' ||
|
|
145
|
+
spec.description.trim().length === 0 ||
|
|
146
|
+
spec.description.length > SUBAGENT_HOST_ARG_LIMITS.descriptionLength
|
|
147
|
+
) {
|
|
148
|
+
throw new Error(
|
|
149
|
+
`${label} needs a description of at most ${SUBAGENT_HOST_ARG_LIMITS.descriptionLength} characters.`
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
if (spec.enum == null) {
|
|
153
|
+
validateFreeForm(label, spec);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
if (spec.maxLength != null) {
|
|
157
|
+
throw new Error(`${label} cannot combine enum with maxLength.`);
|
|
158
|
+
}
|
|
159
|
+
validateEnum(label, spec.enum);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Returns a subagent's validated host argument declarations in declaration
|
|
164
|
+
* order. Throws on a malformed or oversized declaration.
|
|
165
|
+
*/
|
|
166
|
+
export function getSubagentHostArgSpecs(
|
|
167
|
+
config: SubagentHostArgDeclaration
|
|
168
|
+
): readonly HostArgEntry[] {
|
|
169
|
+
const { hostArgs } = config;
|
|
170
|
+
if (hostArgs == null) {
|
|
171
|
+
return [];
|
|
172
|
+
}
|
|
173
|
+
if (typeof hostArgs !== 'object' || Array.isArray(hostArgs)) {
|
|
174
|
+
throw new Error(`Subagent "${config.type}" hostArgs must be an object.`);
|
|
175
|
+
}
|
|
176
|
+
const entries = Object.entries(hostArgs);
|
|
177
|
+
if (entries.length > SUBAGENT_HOST_ARG_LIMITS.argsPerSubagent) {
|
|
178
|
+
throw new Error(
|
|
179
|
+
`Subagent "${config.type}" declares more than ${SUBAGENT_HOST_ARG_LIMITS.argsPerSubagent} host arguments.`
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
for (const [name, spec] of entries) {
|
|
183
|
+
validateSpec(config.type, name, spec);
|
|
184
|
+
}
|
|
185
|
+
return entries;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/** Every host argument name declared by at least one subagent. */
|
|
189
|
+
export function collectSubagentHostArgNames(
|
|
190
|
+
configs: readonly SubagentHostArgDeclaration[]
|
|
191
|
+
): ReadonlySet<string> {
|
|
192
|
+
const names = new Set<string>();
|
|
193
|
+
for (const config of configs) {
|
|
194
|
+
for (const [name] of getSubagentHostArgSpecs(config)) {
|
|
195
|
+
names.add(name);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
if (names.size > SUBAGENT_HOST_ARG_LIMITS.distinctArgs) {
|
|
199
|
+
throw new Error(
|
|
200
|
+
`Subagents declare more than ${SUBAGENT_HOST_ARG_LIMITS.distinctArgs} distinct host arguments.`
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
return names;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function mergeSpec(
|
|
207
|
+
merged: Map<string, MergedHostArg>,
|
|
208
|
+
name: string,
|
|
209
|
+
spec: SubagentHostArgSpec
|
|
210
|
+
): void {
|
|
211
|
+
let entry = merged.get(name);
|
|
212
|
+
if (entry == null) {
|
|
213
|
+
entry = {
|
|
214
|
+
description: spec.description,
|
|
215
|
+
values: [],
|
|
216
|
+
seenValues: new Set(),
|
|
217
|
+
freeForm: false,
|
|
218
|
+
maxLength: 0,
|
|
219
|
+
};
|
|
220
|
+
merged.set(name, entry);
|
|
221
|
+
}
|
|
222
|
+
if (spec.enum == null) {
|
|
223
|
+
entry.freeForm = true;
|
|
224
|
+
entry.maxLength = Math.max(entry.maxLength, getFreeFormMaxLength(spec));
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
for (const value of spec.enum) {
|
|
228
|
+
entry.maxLength = Math.max(entry.maxLength, countCodePoints(value));
|
|
229
|
+
if (!entry.seenValues.has(value)) {
|
|
230
|
+
entry.seenValues.add(value);
|
|
231
|
+
entry.values.push(value);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
if (entry.values.length > SUBAGENT_HOST_ARG_LIMITS.mergedEnumValues) {
|
|
235
|
+
throw new Error(
|
|
236
|
+
`Subagent host argument "${name}" lists more than ${SUBAGENT_HOST_ARG_LIMITS.mergedEnumValues} distinct values across subagents.`
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function toPropertySchema(entry: MergedHostArg): JsonSchemaType {
|
|
242
|
+
if (!entry.freeForm) {
|
|
243
|
+
return {
|
|
244
|
+
type: 'string',
|
|
245
|
+
description: entry.description,
|
|
246
|
+
enum: entry.values,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
return {
|
|
250
|
+
type: 'string',
|
|
251
|
+
description: entry.description,
|
|
252
|
+
maxLength: entry.maxLength,
|
|
253
|
+
pattern: FREE_FORM_SCHEMA_PATTERN,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function summarizeSpecs(entries: readonly HostArgEntry[]): string {
|
|
258
|
+
return entries
|
|
259
|
+
.map(
|
|
260
|
+
([name, spec]) =>
|
|
261
|
+
`${name}: ${
|
|
262
|
+
spec.enum == null
|
|
263
|
+
? `any text up to ${getFreeFormMaxLength(spec)} characters`
|
|
264
|
+
: spec.enum.join(' | ')
|
|
265
|
+
}`
|
|
266
|
+
)
|
|
267
|
+
.join('; ');
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Builds one optional tool property per declared host argument plus a
|
|
272
|
+
* per-type summary of the values each subagent accepts. The first
|
|
273
|
+
* declaration's description wins; enums are unioned across subagents.
|
|
274
|
+
*/
|
|
275
|
+
export function buildSubagentHostArgProperties(
|
|
276
|
+
configs: readonly SubagentHostArgDeclaration[]
|
|
277
|
+
): {
|
|
278
|
+
properties: Record<string, JsonSchemaType>;
|
|
279
|
+
summaries: ReadonlyMap<string, string>;
|
|
280
|
+
} {
|
|
281
|
+
const merged = new Map<string, MergedHostArg>();
|
|
282
|
+
const summaries = new Map<string, string>();
|
|
283
|
+
for (const config of configs) {
|
|
284
|
+
const entries = getSubagentHostArgSpecs(config);
|
|
285
|
+
if (entries.length === 0) {
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
for (const [name, spec] of entries) {
|
|
289
|
+
mergeSpec(merged, name, spec);
|
|
290
|
+
}
|
|
291
|
+
summaries.set(config.type, summarizeSpecs(entries));
|
|
292
|
+
}
|
|
293
|
+
if (merged.size > SUBAGENT_HOST_ARG_LIMITS.distinctArgs) {
|
|
294
|
+
throw new Error(
|
|
295
|
+
`Subagents declare more than ${SUBAGENT_HOST_ARG_LIMITS.distinctArgs} distinct host arguments.`
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
const properties: Record<string, JsonSchemaType> = {};
|
|
299
|
+
for (const [name, entry] of merged) {
|
|
300
|
+
properties[name] = toPropertySchema(entry);
|
|
301
|
+
}
|
|
302
|
+
return { properties, summaries };
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Reads the declared host argument properties from raw tool input. Missing,
|
|
307
|
+
* null, and blank values count as omitted; other non-string values are
|
|
308
|
+
* rejected rather than coerced.
|
|
309
|
+
*/
|
|
310
|
+
export function pickSubagentHostArgInput(
|
|
311
|
+
input: object,
|
|
312
|
+
names: ReadonlySet<string>
|
|
313
|
+
): SubagentHostArgsResult {
|
|
314
|
+
if (names.size === 0) {
|
|
315
|
+
return { ok: true };
|
|
316
|
+
}
|
|
317
|
+
const values = input as Readonly<Record<string, unknown>>;
|
|
318
|
+
const picked: Record<string, string> = {};
|
|
319
|
+
let count = 0;
|
|
320
|
+
for (const name of names) {
|
|
321
|
+
if (!Object.prototype.hasOwnProperty.call(values, name)) {
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
const value = values[name];
|
|
325
|
+
if (value == null) {
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
if (typeof value !== 'string') {
|
|
329
|
+
return { ok: false, message: `Error: "${name}" must be a string.` };
|
|
330
|
+
}
|
|
331
|
+
if (value.trim() === '') {
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
334
|
+
picked[name] = value;
|
|
335
|
+
count += 1;
|
|
336
|
+
}
|
|
337
|
+
return count === 0 ? { ok: true } : { ok: true, hostArgs: picked };
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function checkValue(
|
|
341
|
+
type: string,
|
|
342
|
+
name: string,
|
|
343
|
+
spec: SubagentHostArgSpec,
|
|
344
|
+
value: string
|
|
345
|
+
): string | undefined {
|
|
346
|
+
const omit = `Omit "${name}" to let the host choose.`;
|
|
347
|
+
if (spec.enum != null) {
|
|
348
|
+
return spec.enum.includes(value)
|
|
349
|
+
? undefined
|
|
350
|
+
: `Error: "${name}" for subagent "${type}" must be one of: ${spec.enum.join(', ')}. ${omit}`;
|
|
351
|
+
}
|
|
352
|
+
const maxLength = getFreeFormMaxLength(spec);
|
|
353
|
+
return isBoundedText(value, maxLength)
|
|
354
|
+
? undefined
|
|
355
|
+
: `Error: "${name}" for subagent "${type}" must be at most ${maxLength} characters without control characters. ${omit}`;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Checks call values against the selected subagent's declarations and
|
|
360
|
+
* returns them frozen in canonical key order. Rejects arguments the selected
|
|
361
|
+
* subagent does not declare, including ones declared by a sibling.
|
|
362
|
+
*/
|
|
363
|
+
export function resolveSubagentHostArgs(
|
|
364
|
+
config: SubagentHostArgDeclaration,
|
|
365
|
+
hostArgs: SubagentHostArgs | undefined
|
|
366
|
+
): SubagentHostArgsResult {
|
|
367
|
+
if (hostArgs == null) {
|
|
368
|
+
return { ok: true };
|
|
369
|
+
}
|
|
370
|
+
const names = Object.keys(hostArgs).sort();
|
|
371
|
+
if (names.length === 0) {
|
|
372
|
+
return { ok: true };
|
|
373
|
+
}
|
|
374
|
+
const specs = new Map(getSubagentHostArgSpecs(config));
|
|
375
|
+
const resolved: Record<string, string> = {};
|
|
376
|
+
for (const name of names) {
|
|
377
|
+
const spec = specs.get(name);
|
|
378
|
+
if (spec == null) {
|
|
379
|
+
return {
|
|
380
|
+
ok: false,
|
|
381
|
+
message: isSubagentHostArgName(name)
|
|
382
|
+
? `Error: Subagent "${config.type}" does not accept "${name}". Omit it for this subagent type.`
|
|
383
|
+
: `Error: Subagent "${config.type}" received an unsupported argument.`,
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
const value = hostArgs[name];
|
|
387
|
+
if (typeof value !== 'string') {
|
|
388
|
+
return { ok: false, message: `Error: "${name}" must be a string.` };
|
|
389
|
+
}
|
|
390
|
+
const error = checkValue(config.type, name, spec, value);
|
|
391
|
+
if (error != null) {
|
|
392
|
+
return { ok: false, message: error };
|
|
393
|
+
}
|
|
394
|
+
resolved[name] = value;
|
|
395
|
+
}
|
|
396
|
+
return { ok: true, hostArgs: Object.freeze(resolved) };
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/** Opaque, value-free identity of a call's host arguments for replay records. */
|
|
400
|
+
export function getSubagentHostArgsDigest(
|
|
401
|
+
hostArgs: SubagentHostArgs | undefined
|
|
402
|
+
): string | undefined {
|
|
403
|
+
if (hostArgs == null) {
|
|
404
|
+
return undefined;
|
|
405
|
+
}
|
|
406
|
+
const entries = Object.entries(hostArgs).sort(([left], [right]) =>
|
|
407
|
+
left < right ? -1 : 1
|
|
408
|
+
);
|
|
409
|
+
if (entries.length === 0) {
|
|
410
|
+
return undefined;
|
|
411
|
+
}
|
|
412
|
+
return createHash('sha256').update(JSON.stringify(entries)).digest('hex');
|
|
413
|
+
}
|
|
@@ -21,9 +21,18 @@ export { InMemorySubagentTaskStore } from './InMemorySubagentTaskStore';
|
|
|
21
21
|
export type { InMemorySubagentTaskStoreOptions } from './InMemorySubagentTaskStore';
|
|
22
22
|
export {
|
|
23
23
|
SubagentResolutionError,
|
|
24
|
+
SubagentHostArgumentError,
|
|
24
25
|
getSubagentResolutionFailureMessage,
|
|
26
|
+
getSubagentHostArgumentFailureMessage,
|
|
25
27
|
} from './diagnostics';
|
|
28
|
+
export {
|
|
29
|
+
SUBAGENT_HOST_ARG_LIMITS,
|
|
30
|
+
buildSubagentHostArgProperties,
|
|
31
|
+
resolveSubagentHostArgs,
|
|
32
|
+
} from './hostArgs';
|
|
26
33
|
export type {
|
|
34
|
+
SubagentHostArgumentFailure,
|
|
35
|
+
SubagentHostArgumentRejection,
|
|
27
36
|
SubagentResolutionPhase,
|
|
28
37
|
SubagentResolutionCause,
|
|
29
38
|
SubagentResolutionContext,
|
package/src/types/graph.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ProviderTextProtection } from '@/protection/providerText';
|
|
1
2
|
// src/types/graph.ts
|
|
2
3
|
import type {
|
|
3
4
|
BaseMessage,
|
|
@@ -408,6 +409,7 @@ export type ModelEndData =
|
|
|
408
409
|
| undefined;
|
|
409
410
|
export type GraphTools = GenericTool[] | BindToolsInput[] | GoogleAIToolType[];
|
|
410
411
|
export type StandardGraphInput = {
|
|
412
|
+
providerTextProtection?: ProviderTextProtection;
|
|
411
413
|
runId?: string;
|
|
412
414
|
signal?: AbortSignal;
|
|
413
415
|
agents: AgentInputs[];
|
|
@@ -574,6 +576,31 @@ export interface SubagentResolveConfigurable {
|
|
|
574
576
|
user_id?: string;
|
|
575
577
|
}
|
|
576
578
|
|
|
579
|
+
/**
|
|
580
|
+
* Optional string argument a host lets the parent model pass on a subagent
|
|
581
|
+
* call, such as where the child should run. The SDK checks the declared shape
|
|
582
|
+
* before resolution; the host still authorizes the value in its resolver.
|
|
583
|
+
*/
|
|
584
|
+
export interface SubagentHostArgSpec {
|
|
585
|
+
/** Model-facing explanation of the argument and when to pass it. */
|
|
586
|
+
description: string;
|
|
587
|
+
/**
|
|
588
|
+
* Values this subagent accepts. Omit to accept a bounded free-form string,
|
|
589
|
+
* whose format the resolver must check.
|
|
590
|
+
*/
|
|
591
|
+
enum?: readonly string[];
|
|
592
|
+
/** Maximum length of a free-form value (at most 256). */
|
|
593
|
+
maxLength?: number;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
/** Host argument declarations keyed by tool-call property name. */
|
|
597
|
+
export type SubagentHostArgSpecs = Readonly<
|
|
598
|
+
Record<string, SubagentHostArgSpec>
|
|
599
|
+
>;
|
|
600
|
+
|
|
601
|
+
/** Validated host argument values from one subagent call. */
|
|
602
|
+
export type SubagentHostArgs = Readonly<Record<string, string>>;
|
|
603
|
+
|
|
577
604
|
/** Runtime context supplied when a host lazily resolves a selected subagent. */
|
|
578
605
|
export interface SubagentResolveContext {
|
|
579
606
|
/** Stable subagent identity selected by the model. */
|
|
@@ -592,6 +619,13 @@ export interface SubagentResolveContext {
|
|
|
592
619
|
signal: AbortSignal;
|
|
593
620
|
/** Stable, sanitized host context from the parent tool invocation. */
|
|
594
621
|
configurable?: Readonly<SubagentResolveConfigurable>;
|
|
622
|
+
/**
|
|
623
|
+
* Values the parent passed for this subagent's declared `hostArgs`, already
|
|
624
|
+
* checked against the declaration. Omitted when the call passed none. Bound
|
|
625
|
+
* to the execution: a reconstruction with different values is rejected
|
|
626
|
+
* before the resolver runs.
|
|
627
|
+
*/
|
|
628
|
+
hostArgs?: SubagentHostArgs;
|
|
595
629
|
}
|
|
596
630
|
|
|
597
631
|
/** Host contract for resolving a selected subagent's full graph inputs. */
|
|
@@ -623,6 +657,12 @@ export interface SubagentConfig extends SubagentConfigBase {
|
|
|
623
657
|
* `(context.executionId, context.descriptor.configId)`.
|
|
624
658
|
*/
|
|
625
659
|
resolveAgentInputs?: SubagentAgentInputsResolver;
|
|
660
|
+
/**
|
|
661
|
+
* Optional per-call arguments the parent model may pass for this subagent,
|
|
662
|
+
* delivered to `resolveAgentInputs` as `context.hostArgs`. Only lazy
|
|
663
|
+
* configs accept them. Declaring none leaves the tool schema unchanged.
|
|
664
|
+
*/
|
|
665
|
+
hostArgs?: SubagentHostArgSpecs;
|
|
626
666
|
/** When true, reuse the parent's AgentInputs (context isolation without separate config). */
|
|
627
667
|
self?: boolean;
|
|
628
668
|
}
|
|
@@ -639,6 +679,7 @@ export interface GraphSubagentConfig extends SubagentConfigBase {
|
|
|
639
679
|
kind: 'graph';
|
|
640
680
|
configId?: never;
|
|
641
681
|
resolveAgentInputs?: never;
|
|
682
|
+
hostArgs?: never;
|
|
642
683
|
allowNested?: false;
|
|
643
684
|
agents: AgentInputs[];
|
|
644
685
|
/**
|
package/src/types/run.ts
CHANGED
|
@@ -33,8 +33,9 @@ export type LegacyGraphConfig = BaseGraphConfig & {
|
|
|
33
33
|
g.StandardGraphInput,
|
|
34
34
|
/** `streamLimits` is excluded because legacy graphs receive limits only
|
|
35
35
|
* via the top-level `RunConfig.streamLimits`; accepting the field here
|
|
36
|
-
* would type-check but be silently ignored by `createLegacyGraph`.
|
|
37
|
-
|
|
36
|
+
* would type-check but be silently ignored by `createLegacyGraph`.
|
|
37
|
+
* Required provider-text protection also belongs only to RunConfig. */
|
|
38
|
+
'provider' | 'clientOptions' | 'agents' | 'streamLimits' | 'providerTextProtection'
|
|
38
39
|
> &
|
|
39
40
|
Omit<g.AgentInputs, 'provider' | 'clientOptions' | 'agentId'>;
|
|
40
41
|
|
|
@@ -336,6 +337,7 @@ export type RunConfig = {
|
|
|
336
337
|
* tool-call argument byte cap is ON by default, the per-turn event cap is
|
|
337
338
|
* opt-in. See {@link StreamLimits}.
|
|
338
339
|
*/
|
|
340
|
+
providerTextProtection?: g.StandardGraphInput['providerTextProtection'];
|
|
339
341
|
streamLimits?: StreamLimits;
|
|
340
342
|
returnContent?: boolean;
|
|
341
343
|
tokenCounter?: TokenCounter;
|