@vybestack/llxprt-code-agents 0.10.0-nightly.260613.1adad3b34

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.
Files changed (176) hide show
  1. package/dist/.last_build +0 -0
  2. package/dist/index.d.ts +10 -0
  3. package/dist/index.js +11 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/src/agents/executor-prompt-builder.d.ts +19 -0
  6. package/dist/src/agents/executor-prompt-builder.js +44 -0
  7. package/dist/src/agents/executor-prompt-builder.js.map +1 -0
  8. package/dist/src/agents/executor-termination.d.ts +22 -0
  9. package/dist/src/agents/executor-termination.js +44 -0
  10. package/dist/src/agents/executor-termination.js.map +1 -0
  11. package/dist/src/agents/executor-validation.d.ts +17 -0
  12. package/dist/src/agents/executor-validation.js +35 -0
  13. package/dist/src/agents/executor-validation.js.map +1 -0
  14. package/dist/src/agents/executor.d.ts +136 -0
  15. package/dist/src/agents/executor.js +874 -0
  16. package/dist/src/agents/executor.js.map +1 -0
  17. package/dist/src/agents/invocation.d.ts +45 -0
  18. package/dist/src/agents/invocation.js +118 -0
  19. package/dist/src/agents/invocation.js.map +1 -0
  20. package/dist/src/agents/recovery.d.ts +75 -0
  21. package/dist/src/agents/recovery.js +107 -0
  22. package/dist/src/agents/recovery.js.map +1 -0
  23. package/dist/src/agents/types.d.ts +149 -0
  24. package/dist/src/agents/types.js +18 -0
  25. package/dist/src/agents/types.js.map +1 -0
  26. package/dist/src/agents/utils.d.ts +15 -0
  27. package/dist/src/agents/utils.js +28 -0
  28. package/dist/src/agents/utils.js.map +1 -0
  29. package/dist/src/compression/CompressionHandler.d.ts +178 -0
  30. package/dist/src/compression/CompressionHandler.js +630 -0
  31. package/dist/src/compression/CompressionHandler.js.map +1 -0
  32. package/dist/src/compression/HighDensityStrategy.d.ts +113 -0
  33. package/dist/src/compression/HighDensityStrategy.js +769 -0
  34. package/dist/src/compression/HighDensityStrategy.js.map +1 -0
  35. package/dist/src/compression/MiddleOutStrategy.d.ts +27 -0
  36. package/dist/src/compression/MiddleOutStrategy.js +347 -0
  37. package/dist/src/compression/MiddleOutStrategy.js.map +1 -0
  38. package/dist/src/compression/OneShotStrategy.d.ts +22 -0
  39. package/dist/src/compression/OneShotStrategy.js +235 -0
  40. package/dist/src/compression/OneShotStrategy.js.map +1 -0
  41. package/dist/src/compression/TopDownTruncationStrategy.d.ts +13 -0
  42. package/dist/src/compression/TopDownTruncationStrategy.js +74 -0
  43. package/dist/src/compression/TopDownTruncationStrategy.js.map +1 -0
  44. package/dist/src/compression/compressionBudgeting.d.ts +34 -0
  45. package/dist/src/compression/compressionBudgeting.js +139 -0
  46. package/dist/src/compression/compressionBudgeting.js.map +1 -0
  47. package/dist/src/compression/compressionStrategyFactory.d.ts +23 -0
  48. package/dist/src/compression/compressionStrategyFactory.js +40 -0
  49. package/dist/src/compression/compressionStrategyFactory.js.map +1 -0
  50. package/dist/src/compression/index.d.ts +16 -0
  51. package/dist/src/compression/index.js +17 -0
  52. package/dist/src/compression/index.js.map +1 -0
  53. package/dist/src/compression/reasoningUtils.d.ts +18 -0
  54. package/dist/src/compression/reasoningUtils.js +22 -0
  55. package/dist/src/compression/reasoningUtils.js.map +1 -0
  56. package/dist/src/compression/utils.d.ts +114 -0
  57. package/dist/src/compression/utils.js +316 -0
  58. package/dist/src/compression/utils.js.map +1 -0
  59. package/dist/src/core/AgentHookManager.d.ts +41 -0
  60. package/dist/src/core/AgentHookManager.js +65 -0
  61. package/dist/src/core/AgentHookManager.js.map +1 -0
  62. package/dist/src/core/ChatSessionFactory.d.ts +50 -0
  63. package/dist/src/core/ChatSessionFactory.js +216 -0
  64. package/dist/src/core/ChatSessionFactory.js.map +1 -0
  65. package/dist/src/core/ConversationManager.d.ts +113 -0
  66. package/dist/src/core/ConversationManager.js +311 -0
  67. package/dist/src/core/ConversationManager.js.map +1 -0
  68. package/dist/src/core/DirectMessageProcessor.d.ts +79 -0
  69. package/dist/src/core/DirectMessageProcessor.js +478 -0
  70. package/dist/src/core/DirectMessageProcessor.js.map +1 -0
  71. package/dist/src/core/IdeContextTracker.d.ts +56 -0
  72. package/dist/src/core/IdeContextTracker.js +207 -0
  73. package/dist/src/core/IdeContextTracker.js.map +1 -0
  74. package/dist/src/core/MessageConverter.d.ts +78 -0
  75. package/dist/src/core/MessageConverter.js +492 -0
  76. package/dist/src/core/MessageConverter.js.map +1 -0
  77. package/dist/src/core/MessageStreamOrchestrator.d.ts +85 -0
  78. package/dist/src/core/MessageStreamOrchestrator.js +448 -0
  79. package/dist/src/core/MessageStreamOrchestrator.js.map +1 -0
  80. package/dist/src/core/MessageStreamTerminalHandler.d.ts +16 -0
  81. package/dist/src/core/MessageStreamTerminalHandler.js +170 -0
  82. package/dist/src/core/MessageStreamTerminalHandler.js.map +1 -0
  83. package/dist/src/core/StreamProcessor.d.ts +105 -0
  84. package/dist/src/core/StreamProcessor.js +660 -0
  85. package/dist/src/core/StreamProcessor.js.map +1 -0
  86. package/dist/src/core/TodoContinuationService.d.ts +74 -0
  87. package/dist/src/core/TodoContinuationService.js +312 -0
  88. package/dist/src/core/TodoContinuationService.js.map +1 -0
  89. package/dist/src/core/TurnProcessor.d.ts +91 -0
  90. package/dist/src/core/TurnProcessor.js +540 -0
  91. package/dist/src/core/TurnProcessor.js.map +1 -0
  92. package/dist/src/core/baseLlmClient.d.ts +115 -0
  93. package/dist/src/core/baseLlmClient.js +231 -0
  94. package/dist/src/core/baseLlmClient.js.map +1 -0
  95. package/dist/src/core/bucketFailoverIntegration.d.ts +62 -0
  96. package/dist/src/core/bucketFailoverIntegration.js +186 -0
  97. package/dist/src/core/bucketFailoverIntegration.js.map +1 -0
  98. package/dist/src/core/chatSession.d.ts +121 -0
  99. package/dist/src/core/chatSession.js +720 -0
  100. package/dist/src/core/chatSession.js.map +1 -0
  101. package/dist/src/core/client.d.ts +132 -0
  102. package/dist/src/core/client.js +524 -0
  103. package/dist/src/core/client.js.map +1 -0
  104. package/dist/src/core/clientHelpers.d.ts +15 -0
  105. package/dist/src/core/clientHelpers.js +122 -0
  106. package/dist/src/core/clientHelpers.js.map +1 -0
  107. package/dist/src/core/clientLlmUtilities.d.ts +30 -0
  108. package/dist/src/core/clientLlmUtilities.js +125 -0
  109. package/dist/src/core/clientLlmUtilities.js.map +1 -0
  110. package/dist/src/core/clientToolGovernance.d.ts +37 -0
  111. package/dist/src/core/clientToolGovernance.js +104 -0
  112. package/dist/src/core/clientToolGovernance.js.map +1 -0
  113. package/dist/src/core/compression-config.d.ts +12 -0
  114. package/dist/src/core/compression-config.js +21 -0
  115. package/dist/src/core/compression-config.js.map +1 -0
  116. package/dist/src/core/coreToolScheduler.d.ts +105 -0
  117. package/dist/src/core/coreToolScheduler.js +453 -0
  118. package/dist/src/core/coreToolScheduler.js.map +1 -0
  119. package/dist/src/core/hookToolRestrictions.d.ts +18 -0
  120. package/dist/src/core/hookToolRestrictions.js +187 -0
  121. package/dist/src/core/hookToolRestrictions.js.map +1 -0
  122. package/dist/src/core/nonInteractiveToolExecutor.d.ts +17 -0
  123. package/dist/src/core/nonInteractiveToolExecutor.js +102 -0
  124. package/dist/src/core/nonInteractiveToolExecutor.js.map +1 -0
  125. package/dist/src/core/subagent.d.ts +105 -0
  126. package/dist/src/core/subagent.js +650 -0
  127. package/dist/src/core/subagent.js.map +1 -0
  128. package/dist/src/core/subagentExecution.d.ts +104 -0
  129. package/dist/src/core/subagentExecution.js +275 -0
  130. package/dist/src/core/subagentExecution.js.map +1 -0
  131. package/dist/src/core/subagentOrchestrator.d.ts +84 -0
  132. package/dist/src/core/subagentOrchestrator.js +503 -0
  133. package/dist/src/core/subagentOrchestrator.js.map +1 -0
  134. package/dist/src/core/subagentRuntimeSetup.d.ts +75 -0
  135. package/dist/src/core/subagentRuntimeSetup.js +387 -0
  136. package/dist/src/core/subagentRuntimeSetup.js.map +1 -0
  137. package/dist/src/core/subagentScheduler.d.ts +17 -0
  138. package/dist/src/core/subagentScheduler.js +7 -0
  139. package/dist/src/core/subagentScheduler.js.map +1 -0
  140. package/dist/src/core/subagentToolProcessing.d.ts +51 -0
  141. package/dist/src/core/subagentToolProcessing.js +359 -0
  142. package/dist/src/core/subagentToolProcessing.js.map +1 -0
  143. package/dist/src/core/toolGovernance.d.ts +18 -0
  144. package/dist/src/core/toolGovernance.js +50 -0
  145. package/dist/src/core/toolGovernance.js.map +1 -0
  146. package/dist/src/core/turn.d.ts +47 -0
  147. package/dist/src/core/turn.js +455 -0
  148. package/dist/src/core/turn.js.map +1 -0
  149. package/dist/src/core/turnLogging.d.ts +35 -0
  150. package/dist/src/core/turnLogging.js +80 -0
  151. package/dist/src/core/turnLogging.js.map +1 -0
  152. package/dist/src/index.d.ts +32 -0
  153. package/dist/src/index.js +44 -0
  154. package/dist/src/index.js.map +1 -0
  155. package/dist/src/scheduler/confirmation-coordinator.d.ts +139 -0
  156. package/dist/src/scheduler/confirmation-coordinator.js +443 -0
  157. package/dist/src/scheduler/confirmation-coordinator.js.map +1 -0
  158. package/dist/src/scheduler/result-aggregator.d.ts +127 -0
  159. package/dist/src/scheduler/result-aggregator.js +302 -0
  160. package/dist/src/scheduler/result-aggregator.js.map +1 -0
  161. package/dist/src/scheduler/status-transitions.d.ts +39 -0
  162. package/dist/src/scheduler/status-transitions.js +184 -0
  163. package/dist/src/scheduler/status-transitions.js.map +1 -0
  164. package/dist/src/scheduler/tool-dispatcher.d.ts +40 -0
  165. package/dist/src/scheduler/tool-dispatcher.js +120 -0
  166. package/dist/src/scheduler/tool-dispatcher.js.map +1 -0
  167. package/dist/src/scheduler/tool-executor.d.ts +44 -0
  168. package/dist/src/scheduler/tool-executor.js +117 -0
  169. package/dist/src/scheduler/tool-executor.js.map +1 -0
  170. package/dist/src/scheduler/utils.d.ts +11 -0
  171. package/dist/src/scheduler/utils.js +19 -0
  172. package/dist/src/scheduler/utils.js.map +1 -0
  173. package/dist/src/tools/task.d.ts +128 -0
  174. package/dist/src/tools/task.js +932 -0
  175. package/dist/src/tools/task.js.map +1 -0
  176. package/package.json +54 -0
@@ -0,0 +1,660 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { FinishReason, } from '@google/genai';
7
+ import { isRetryableError, retryWithBackoff, } from '@vybestack/llxprt-code-core/utils/retry.js';
8
+ import { prependAsyncGenerator } from '@vybestack/llxprt-code-core/utils/asyncIterator.js';
9
+ // @plan:PLAN-20260608-ISSUE1586.P15 — auth types from auth package
10
+ import { flushRuntimeAuthScope } from '@vybestack/llxprt-code-auth';
11
+ import { isFunctionResponse } from '@vybestack/llxprt-code-core/utils/messageInspectors.js';
12
+ import { DebugLogger } from '@vybestack/llxprt-code-core/debug/index.js';
13
+ import { ContentConverters } from '@vybestack/llxprt-code-core/services/history/ContentConverters.js';
14
+ import { isValidResponse, isValidNonThoughtTextPart, convertIContentToResponse, } from './MessageConverter.js';
15
+ import { logApiRequest, logApiResponse, logApiError } from './turnLogging.js';
16
+ import { InvalidStreamError, EmptyStreamError, isSchemaDepthError, isThoughtPart, } from '@vybestack/llxprt-code-core/core/chatSessionTypes.js';
17
+ import { analyzeResponseOutcome } from '@vybestack/llxprt-code-core/utils/generateContentResponseUtilities.js';
18
+ import { hasCycleInSchema } from '@vybestack/llxprt-code-tools';
19
+ import { isStructuredError } from '@vybestack/llxprt-code-core/utils/quotaErrorDetection.js';
20
+ import { AgentExecutionStoppedError, AgentExecutionBlockedError, } from './chatSession.js';
21
+ import { attachHookRestrictedAllowedTools, filterHookRestrictedContent, filterHookRestrictedFunctionCalls, filterHookRestrictedParts, getHookRestrictedAllowedTools, getHookRestrictedFunctionCallsFromParts, mergeHookRestrictedFunctionCalls, } from './hookToolRestrictions.js';
22
+ import { canonicalizeToolName } from './toolGovernance.js';
23
+ function isMissingFinishReason(finishReason) {
24
+ return finishReason == null || finishReason === '';
25
+ }
26
+ export class StreamProcessor {
27
+ runtimeContext;
28
+ conversationManager;
29
+ compressionHandler;
30
+ providerResolver;
31
+ providerRuntimeBuilder;
32
+ historyService;
33
+ generationConfig;
34
+ logger = new DebugLogger('llxprt:gemini:stream-processor');
35
+ constructor(runtimeContext, conversationManager, compressionHandler, providerResolver, providerRuntimeBuilder, historyService, generationConfig) {
36
+ this.runtimeContext = runtimeContext;
37
+ this.conversationManager = conversationManager;
38
+ this.compressionHandler = compressionHandler;
39
+ this.providerResolver = providerResolver;
40
+ this.providerRuntimeBuilder = providerRuntimeBuilder;
41
+ this.historyService = historyService;
42
+ this.generationConfig = generationConfig;
43
+ }
44
+ /**
45
+ * Makes an API call with retry and returns a stream processor.
46
+ * This is the outer method that resolves the provider, enforces context window,
47
+ * makes the API call with retry, and returns processStreamResponse.
48
+ */
49
+ async makeApiCallAndProcessStream(params, promptId, pendingTokens, userContent) {
50
+ const provider = this.providerResolver('stream');
51
+ const providerBaseUrl = this.runtimeContext.state.baseUrl;
52
+ this.logger.debug(() => '[StreamProcessor] Active provider snapshot before stream request', {
53
+ providerName: provider.name,
54
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- Preserve defensive runtime boundary guard despite current static types.
55
+ providerDefaultModel: provider.getDefaultModel?.(),
56
+ configModel: this.runtimeContext.state.model,
57
+ baseUrl: providerBaseUrl,
58
+ });
59
+ // Enforce context window limits before proceeding
60
+ await this.compressionHandler.enforceContextWindow(pendingTokens, promptId, provider);
61
+ // Check if provider supports IContent interface
62
+ if (typeof provider.generateChatCompletion !== 'function') {
63
+ throw new Error(`Provider ${provider.name} does not support IContent interface`);
64
+ }
65
+ const streamResponse = await this._executeStreamApiCall(params, promptId, userContent, provider);
66
+ return this._createCancellableStream(streamResponse, userContent);
67
+ }
68
+ _createCancellableStream(streamResponse, userContent) {
69
+ let processedStream;
70
+ const ensureProcessedStream = () => {
71
+ processedStream ??= this.processStreamResponse(streamResponse, userContent);
72
+ return processedStream;
73
+ };
74
+ const cancellableStream = {
75
+ async next(value) {
76
+ return ensureProcessedStream().next(value);
77
+ },
78
+ async return(value) {
79
+ if (processedStream) {
80
+ return typeof processedStream.return === 'function'
81
+ ? processedStream.return(value)
82
+ : { done: true, value: undefined };
83
+ }
84
+ if (typeof streamResponse.return === 'function') {
85
+ await streamResponse.return(value);
86
+ }
87
+ return { done: true, value: undefined };
88
+ },
89
+ async throw(error) {
90
+ if (processedStream) {
91
+ if (typeof processedStream.throw === 'function') {
92
+ return processedStream.throw(error);
93
+ }
94
+ throw error;
95
+ }
96
+ if (typeof streamResponse.throw === 'function') {
97
+ return streamResponse.throw(error);
98
+ }
99
+ if (typeof streamResponse.return === 'function') {
100
+ await streamResponse.return(undefined);
101
+ }
102
+ throw error;
103
+ },
104
+ [Symbol.asyncIterator]() {
105
+ return this;
106
+ },
107
+ };
108
+ return cancellableStream;
109
+ }
110
+ /**
111
+ * Execute the stream API call with retry and bucket failover.
112
+ * Split from makeApiCallAndProcessStream to keep methods under 80 lines.
113
+ */
114
+ async _executeStreamApiCall(params, promptId, userContent, provider) {
115
+ const apiCall = () => this._buildAndSendStreamRequest(params, promptId, userContent, provider);
116
+ const retryFetchErrors = params.config?.retryFetchErrors;
117
+ return retryWithBackoff(apiCall, {
118
+ onPersistent429: () => this._handleBucketFailover(),
119
+ signal: params.config?.abortSignal,
120
+ retryFetchErrors,
121
+ shouldRetryOnError: (error, currentRetryFetchErrors) => error instanceof EmptyStreamError ||
122
+ isRetryableError(error, currentRetryFetchErrors),
123
+ });
124
+ }
125
+ async _buildAndSendStreamRequest(params, promptId, userContent, provider) {
126
+ const requestContents = this._buildRequestContents(userContent);
127
+ const configForHooks = this.runtimeContext.providerRuntime.config;
128
+ const requestTools = this._selectRequestTools(params);
129
+ const toolSelection = await this._applyToolSelectionHook(configForHooks, requestTools);
130
+ const tools = toolSelection.tools;
131
+ const { requestPayload, baseRuntimeContext, runtimeContext } = this._prepareRequestPayload(requestContents, tools, params);
132
+ const finalContents = await this._fireBeforeModelHook(configForHooks, requestPayload.contents, tools, toolSelection.allowedFunctionNames);
133
+ requestPayload.contents = finalContents;
134
+ logApiRequest(this.runtimeContext, this.runtimeContext.state, ContentConverters.toGeminiContents(requestPayload.contents), this.runtimeContext.state.model, promptId);
135
+ return this._sendProviderRequest(provider, requestPayload, runtimeContext, baseRuntimeContext, params, promptId, toolSelection.allowedFunctionNames);
136
+ }
137
+ /**
138
+ * Fire BeforeModel hook and return possibly-modified requestContents.
139
+ * Throws if the hook requests execution stop or blocking.
140
+ */
141
+ async _fireBeforeModelHook(configForHooks, requestContents, tools, hookRestrictedAllowedTools) {
142
+ if (configForHooks === undefined ||
143
+ typeof configForHooks.getEnableHooks !== 'function' ||
144
+ configForHooks.getEnableHooks() !== true) {
145
+ return requestContents;
146
+ }
147
+ const hookSystem = typeof configForHooks.getHookSystem === 'function'
148
+ ? configForHooks.getHookSystem()
149
+ : undefined;
150
+ if (hookSystem === undefined)
151
+ return requestContents;
152
+ await hookSystem.initialize();
153
+ const beforeModelResult = await hookSystem.fireBeforeModelEvent({
154
+ contents: requestContents,
155
+ tools,
156
+ });
157
+ if (beforeModelResult?.shouldStopExecution() === true) {
158
+ const reason = beforeModelResult.getEffectiveReason();
159
+ throw new AgentExecutionStoppedError(reason !== undefined && reason !== null && reason !== ''
160
+ ? reason
161
+ : 'Execution stopped by BeforeModel hook', beforeModelResult.systemMessage);
162
+ }
163
+ if (beforeModelResult?.isBlockingDecision() === true) {
164
+ let syntheticResponse = beforeModelResult.getSyntheticResponse();
165
+ // eslint-disable-next-line sonarjs/nested-control-flow -- Existing structure is intentionally preserved; refactoring this boundary is outside the lint slice.
166
+ if (syntheticResponse) {
167
+ const candidate = syntheticResponse.candidates?.[0];
168
+ const candidateFinishReason = candidate?.finishReason;
169
+ if (candidate && isMissingFinishReason(candidateFinishReason)) {
170
+ syntheticResponse = this._patchMissingFinishReason(syntheticResponse, candidate);
171
+ }
172
+ }
173
+ const reason = beforeModelResult.getEffectiveReason();
174
+ throw new AgentExecutionBlockedError(reason !== undefined && reason !== null && reason !== ''
175
+ ? reason
176
+ : 'Request blocked by BeforeModel hook', syntheticResponse === undefined
177
+ ? undefined
178
+ : attachHookRestrictedAllowedTools(syntheticResponse, hookRestrictedAllowedTools));
179
+ }
180
+ return this._applyRequestModifications(beforeModelResult, requestContents);
181
+ }
182
+ _patchMissingFinishReason(syntheticResponse, candidate) {
183
+ return {
184
+ ...syntheticResponse,
185
+ candidates: [{ ...candidate, finishReason: FinishReason.STOP }],
186
+ };
187
+ }
188
+ _applyRequestModifications(beforeModelResult, requestContents) {
189
+ if (!beforeModelResult)
190
+ return requestContents;
191
+ const modifiedRequest = beforeModelResult.applyLLMRequestModifications({
192
+ model: this.runtimeContext.state.model || '',
193
+ contents: ContentConverters.toGeminiContents(requestContents),
194
+ });
195
+ const modifiedContents = modifiedRequest.contents;
196
+ if (modifiedContents !== undefined && modifiedContents !== null) {
197
+ return ContentConverters.toIContents(modifiedContents);
198
+ }
199
+ return requestContents;
200
+ }
201
+ _prepareRequestPayload(requestContents, tools, params) {
202
+ this.logger.debug(() => '[StreamProcessor] Calling provider.generateChatCompletion', {
203
+ providerName: this.providerResolver('stream').name,
204
+ model: this.runtimeContext.state.model,
205
+ historyLength: requestContents.length,
206
+ toolCount: tools?.length ?? 0,
207
+ baseUrl: this.runtimeContext.state.baseUrl,
208
+ });
209
+ const baseRuntimeContext = this.providerRuntimeBuilder('StreamProcessor.generateRequest', { historyLength: requestContents.length });
210
+ const requestPayload = { contents: requestContents, tools };
211
+ const runtimeContext = this._buildRuntimeContext(baseRuntimeContext, params, tools);
212
+ return { requestPayload, baseRuntimeContext, runtimeContext };
213
+ }
214
+ _buildRuntimeContext(baseRuntimeContext, params, tools) {
215
+ if (!params.config)
216
+ return baseRuntimeContext;
217
+ return {
218
+ ...baseRuntimeContext,
219
+ config: { ...baseRuntimeContext.config, ...params.config, tools },
220
+ };
221
+ }
222
+ async _sendProviderRequest(provider, requestPayload, runtimeContext, baseRuntimeContext, params, promptId, hookRestrictedAllowedTools) {
223
+ const startTime = Date.now();
224
+ try {
225
+ const streamResponse = provider.generateChatCompletion({
226
+ contents: requestPayload.contents,
227
+ tools: requestPayload.tools,
228
+ config: runtimeContext.config,
229
+ runtime: runtimeContext,
230
+ settings: runtimeContext.settingsService,
231
+ metadata: {
232
+ ...runtimeContext.metadata,
233
+ abortSignal: params.config?.abortSignal,
234
+ },
235
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- Preserve defensive runtime boundary guard despite current static types.
236
+ userMemory: baseRuntimeContext.config?.getUserMemory?.(),
237
+ });
238
+ return await this._consumeFirstChunkAndReturn(streamResponse, requestPayload, promptId, startTime, hookRestrictedAllowedTools);
239
+ }
240
+ catch (error) {
241
+ const durationMs = Date.now() - startTime;
242
+ logApiError(this.runtimeContext, this.runtimeContext.state, this.runtimeContext.state.model, promptId, durationMs, error);
243
+ throw error;
244
+ }
245
+ }
246
+ /**
247
+ * Eagerly consume first chunk within retry boundary (#1750).
248
+ */
249
+ async _consumeFirstChunkAndReturn(streamResponse, requestPayload, promptId, startTime, hookRestrictedAllowedTools) {
250
+ const convertedStream = this._convertIContentStream(streamResponse, requestPayload, { promptId, startTime }, hookRestrictedAllowedTools);
251
+ const firstChunk = await convertedStream.next();
252
+ if (firstChunk.done === true) {
253
+ throw new EmptyStreamError('Model stream ended immediately with no content.');
254
+ }
255
+ return prependAsyncGenerator(firstChunk.value, convertedStream);
256
+ }
257
+ _selectRequestTools(params) {
258
+ return params.config?.tools ?? this.generationConfig.tools;
259
+ }
260
+ async _applyToolSelectionHook(configForHooks, tools) {
261
+ if (configForHooks === undefined) {
262
+ return { tools, allowedFunctionNames: undefined };
263
+ }
264
+ const getToolSelectionHooksEnabled = configForHooks.getEnableHooks;
265
+ if (typeof getToolSelectionHooksEnabled !== 'function' ||
266
+ getToolSelectionHooksEnabled.call(configForHooks) !== true) {
267
+ return { tools, allowedFunctionNames: undefined };
268
+ }
269
+ const getToolSelectionHookSystem = configForHooks.getHookSystem;
270
+ const hookSystem = typeof getToolSelectionHookSystem === 'function'
271
+ ? getToolSelectionHookSystem.call(configForHooks)
272
+ : undefined;
273
+ if (hookSystem === undefined) {
274
+ return { tools, allowedFunctionNames: undefined };
275
+ }
276
+ await hookSystem.initialize();
277
+ const toolsFromConfig = Array.isArray(tools)
278
+ ? tools
279
+ : [];
280
+ const toolSelectionResult = await hookSystem.fireBeforeToolSelectionEvent(toolsFromConfig);
281
+ const modifiedConfig = toolSelectionResult?.applyToolConfigModifications({
282
+ tools: toolsFromConfig,
283
+ });
284
+ const toolConfig = modifiedConfig?.toolConfig;
285
+ if (
286
+ // eslint-disable-next-line sonarjs/expression-complexity -- Existing structure is intentionally preserved; refactoring this boundary is outside the lint slice.
287
+ toolConfig !== undefined &&
288
+ toolConfig !== null &&
289
+ typeof toolConfig === 'object' &&
290
+ 'allowedFunctionNames' in toolConfig &&
291
+ Array.isArray(toolConfig.allowedFunctionNames)) {
292
+ const allowedFunctions = toolConfig.allowedFunctionNames;
293
+ const allowedNames = new Set(allowedFunctions.map(canonicalizeToolName));
294
+ const filteredTools = toolsFromConfig
295
+ .map((toolGroup) => ({
296
+ ...toolGroup,
297
+ functionDeclarations: Array.isArray(toolGroup.functionDeclarations)
298
+ ? toolGroup.functionDeclarations.filter((fn) => typeof fn.name === 'string' &&
299
+ allowedNames.has(canonicalizeToolName(fn.name)))
300
+ : [],
301
+ }))
302
+ .filter((g) => g.functionDeclarations.length > 0);
303
+ return { tools: filteredTools, allowedFunctionNames: allowedFunctions };
304
+ }
305
+ return { tools: toolsFromConfig, allowedFunctionNames: undefined };
306
+ }
307
+ _buildRequestContents(userContent) {
308
+ const matcher = this.conversationManager.makePositionMatcher();
309
+ if (Array.isArray(userContent)) {
310
+ const userIContents = userContent.map((content) => {
311
+ const turnKey = this.historyService.generateTurnKey();
312
+ const idGen = this.historyService.getIdGeneratorCallback(turnKey);
313
+ return ContentConverters.toIContent(content, idGen, matcher, turnKey);
314
+ });
315
+ return this.historyService.getCuratedForProvider(userIContents);
316
+ }
317
+ const turnKey = this.historyService.generateTurnKey();
318
+ const idGen = this.historyService.getIdGeneratorCallback(turnKey);
319
+ const userIContent = ContentConverters.toIContent(userContent, idGen, matcher, turnKey);
320
+ return this.historyService.getCuratedForProvider([userIContent]);
321
+ }
322
+ async _handleBucketFailover() {
323
+ const failoverHandler = this.runtimeContext.providerRuntime.config?.getBucketFailoverHandler();
324
+ if (!failoverHandler)
325
+ return null;
326
+ this.logger.debug(() => 'Attempting bucket failover on persistent 429');
327
+ const success = await failoverHandler.tryFailover();
328
+ if (success) {
329
+ const runtimeId = this.runtimeContext.providerRuntime.runtimeId ??
330
+ this.runtimeContext.state.runtimeId;
331
+ if (typeof runtimeId === 'string' && runtimeId.trim() !== '') {
332
+ flushRuntimeAuthScope(runtimeId);
333
+ }
334
+ this.logger.debug(() => `Bucket failover successful, new bucket: ${failoverHandler.getCurrentBucket()}`);
335
+ return true;
336
+ }
337
+ this.logger.debug(() => 'Bucket failover failed - no more buckets available');
338
+ return false;
339
+ }
340
+ /**
341
+ * Convert IContent stream to GenerateContentResponse stream.
342
+ * Tracks token usage metadata from IContent format.
343
+ * Triggers AfterModel hook per streamed chunk.
344
+ */
345
+ async *_convertIContentStream(streamResponse, llmRequest, telemetryContext, hookRestrictedAllowedTools) {
346
+ let lastConvertedChunk;
347
+ for await (const iContent of streamResponse) {
348
+ this._trackPromptTokens(iContent);
349
+ const convertedChunk = attachHookRestrictedAllowedTools(convertIContentToResponse(iContent), hookRestrictedAllowedTools);
350
+ lastConvertedChunk = convertedChunk;
351
+ const hookResult = await this._processAfterModelHook(iContent, llmRequest, convertedChunk, hookRestrictedAllowedTools);
352
+ if (hookResult.type === 'modified') {
353
+ const restrictedResponse = attachHookRestrictedAllowedTools(hookResult.response, hookRestrictedAllowedTools);
354
+ lastConvertedChunk = restrictedResponse;
355
+ yield restrictedResponse;
356
+ continue;
357
+ }
358
+ yield convertedChunk;
359
+ }
360
+ this._logTelemetry(telemetryContext, lastConvertedChunk);
361
+ }
362
+ _trackPromptTokens(iContent) {
363
+ const promptTokens = iContent.metadata?.usage?.promptTokens;
364
+ if (promptTokens === undefined)
365
+ return;
366
+ const cacheReads = iContent.metadata?.usage?.cache_read_input_tokens ?? 0;
367
+ const cacheWrites = iContent.metadata?.usage?.cache_creation_input_tokens ?? 0;
368
+ const combinedPromptTokens = promptTokens + cacheReads + cacheWrites;
369
+ this.logger.debug(() => `[StreamProcessor] Tracking promptTokens from IContent: ${combinedPromptTokens}`);
370
+ this.compressionHandler.lastPromptTokenCount = combinedPromptTokens;
371
+ }
372
+ async _processAfterModelHook(iContent, llmRequest, convertedChunk, hookRestrictedAllowedTools) {
373
+ const hookConfig = this.runtimeContext.providerRuntime.config;
374
+ if (hookConfig === undefined ||
375
+ typeof hookConfig.getEnableHooks !== 'function' ||
376
+ hookConfig.getEnableHooks() !== true) {
377
+ return { type: 'passthrough' };
378
+ }
379
+ const hookSystem = typeof hookConfig.getHookSystem === 'function'
380
+ ? hookConfig.getHookSystem()
381
+ : undefined;
382
+ if (hookSystem === undefined)
383
+ return { type: 'passthrough' };
384
+ // eslint-disable-next-line sonarjs/nested-control-flow -- Existing structure is intentionally preserved; refactoring this boundary is outside the lint slice.
385
+ if (!hookSystem.isInitialized()) {
386
+ await hookSystem.initialize();
387
+ }
388
+ const filteredContent = filterHookRestrictedContent(convertIContentToResponse(iContent).candidates?.[0]?.content ?? {
389
+ role: 'model',
390
+ parts: [],
391
+ }, hookRestrictedAllowedTools);
392
+ const afterModelResult = await hookSystem.fireAfterModelEvent(llmRequest ?? {}, ContentConverters.toIContent(filteredContent));
393
+ // eslint-disable-next-line sonarjs/nested-control-flow -- Existing structure is intentionally preserved; refactoring this boundary is outside the lint slice.
394
+ if (afterModelResult?.shouldStopExecution() === true) {
395
+ const effectiveReason = afterModelResult.getEffectiveReason();
396
+ throw new AgentExecutionStoppedError(effectiveReason ?? 'Execution stopped by AfterModel hook', afterModelResult.systemMessage);
397
+ }
398
+ // eslint-disable-next-line sonarjs/nested-control-flow -- Existing structure is intentionally preserved; refactoring this boundary is outside the lint slice.
399
+ if (afterModelResult?.isBlockingDecision() === true) {
400
+ const modifiedResponse = afterModelResult.getModifiedResponse();
401
+ const syntheticResponse = attachHookRestrictedAllowedTools(modifiedResponse ?? convertedChunk, hookRestrictedAllowedTools);
402
+ const effectiveReason = afterModelResult.getEffectiveReason();
403
+ throw new AgentExecutionBlockedError(effectiveReason ?? 'Execution blocked by AfterModel hook', syntheticResponse, afterModelResult.systemMessage);
404
+ }
405
+ const modifiedResponse = afterModelResult?.getModifiedResponse();
406
+ // eslint-disable-next-line sonarjs/nested-control-flow -- Existing structure is intentionally preserved; refactoring this boundary is outside the lint slice.
407
+ if (modifiedResponse) {
408
+ return { type: 'modified', response: modifiedResponse };
409
+ }
410
+ return { type: 'passthrough' };
411
+ }
412
+ _logTelemetry(telemetryContext, lastConvertedChunk) {
413
+ if (telemetryContext && lastConvertedChunk) {
414
+ const durationMs = Date.now() - telemetryContext.startTime;
415
+ logApiResponse(this.runtimeContext, this.runtimeContext.state, this.runtimeContext.state.model, telemetryContext.promptId, durationMs, lastConvertedChunk.usageMetadata, JSON.stringify(lastConvertedChunk));
416
+ }
417
+ }
418
+ /**
419
+ * Process streaming response chunks into a complete conversation turn.
420
+ * Yields each chunk immediately as it arrives from the provider stream,
421
+ * while simultaneously tracking metadata for validation and history.
422
+ *
423
+ * CRITICAL: This method must yield chunks inline during the for-await loop.
424
+ * Collecting all chunks first (as was done in a prior refactoring) blocks
425
+ * the entire pipeline — no output reaches the user, no abort signal checks
426
+ * run, and stalled provider streams hang indefinitely. See #1846.
427
+ */
428
+ async *processStreamResponse(streamResponse, userInput) {
429
+ const acc = this._createStreamAccumulator();
430
+ const includeThoughts = this.runtimeContext.ephemerals.reasoning.includeInContext();
431
+ for await (const chunk of streamResponse) {
432
+ const filteredChunk = attachHookRestrictedAllowedTools(chunk, getHookRestrictedAllowedTools(chunk));
433
+ this._accumulateChunkMetadata(filteredChunk, acc, includeThoughts);
434
+ yield filteredChunk;
435
+ }
436
+ await this._finalizeStreamProcessing(acc, userInput);
437
+ }
438
+ _createStreamAccumulator() {
439
+ return {
440
+ modelResponseParts: [],
441
+ outcome: {
442
+ hasVisibleText: false,
443
+ hasThinking: false,
444
+ hasToolCalls: false,
445
+ isActionable: false,
446
+ },
447
+ finishReason: undefined,
448
+ allChunks: [],
449
+ };
450
+ }
451
+ _accumulateChunkMetadata(chunk, acc, includeThoughts) {
452
+ const candidateWithReason = chunk.candidates?.find((c) => c.finishReason !== undefined);
453
+ if (candidateWithReason !== undefined)
454
+ acc.finishReason = candidateWithReason.finishReason;
455
+ const allowedTools = getHookRestrictedAllowedTools(chunk);
456
+ const parts = chunk.candidates?.[0]?.content?.parts ?? [];
457
+ const effectiveParts = isValidResponse(chunk)
458
+ ? filterHookRestrictedParts(parts, allowedTools)
459
+ : [];
460
+ const allowedPartCalls = getHookRestrictedFunctionCallsFromParts(effectiveParts, allowedTools);
461
+ const allowedMergedCalls = mergeHookRestrictedFunctionCalls(allowedPartCalls, filterHookRestrictedFunctionCalls(chunk.functionCalls ?? [], allowedTools));
462
+ const allowedTopLevelCallParts = allowedMergedCalls
463
+ .slice(allowedPartCalls.length)
464
+ .map((functionCall) => ({ functionCall }));
465
+ const outcomeParts = [...effectiveParts, ...allowedTopLevelCallParts];
466
+ if (outcomeParts.length > 0) {
467
+ const chunkOutcome = analyzeResponseOutcome(outcomeParts);
468
+ acc.outcome = {
469
+ hasVisibleText: acc.outcome.hasVisibleText || chunkOutcome.hasVisibleText,
470
+ hasThinking: acc.outcome.hasThinking || chunkOutcome.hasThinking,
471
+ hasToolCalls: acc.outcome.hasToolCalls || chunkOutcome.hasToolCalls,
472
+ isActionable: acc.outcome.isActionable || chunkOutcome.isActionable,
473
+ };
474
+ acc.modelResponseParts.push(...(includeThoughts
475
+ ? outcomeParts
476
+ : outcomeParts.filter((p) => !isThoughtPart(p))));
477
+ }
478
+ const chunkText = typeof chunk.text === 'string' ? chunk.text : '';
479
+ this.logger.debug(() => `[stream:terminal] observed converted chunk`, {
480
+ chunkFinishReason: candidateWithReason?.finishReason,
481
+ partCount: effectiveParts.length,
482
+ toolCallCount: allowedMergedCalls.length,
483
+ textLength: chunkText.length,
484
+ hasUsageMetadata: Boolean(chunk.usageMetadata),
485
+ });
486
+ if (chunk.usageMetadata?.promptTokenCount !== undefined) {
487
+ const chunkUsage = chunk.usageMetadata;
488
+ this.compressionHandler.lastPromptTokenCount =
489
+ chunk.usageMetadata.promptTokenCount +
490
+ (chunkUsage.cache_read_input_tokens ?? 0) +
491
+ (chunkUsage.cache_creation_input_tokens ?? 0);
492
+ }
493
+ acc.allChunks.push(chunk);
494
+ }
495
+ async _finalizeStreamProcessing(acc, userInput) {
496
+ const consolidatedParts = this._consolidateTextParts(acc.modelResponseParts);
497
+ const responseText = this._extractResponseText(consolidatedParts);
498
+ if (isMissingFinishReason(acc.finishReason)) {
499
+ this.logger.debug(() => `[stream:terminal] stream ended without finishReason (hasToolCall=${String(acc.outcome.hasToolCalls)}, hasTextResponse=${String(acc.outcome.hasVisibleText)}, hasThinkingResponse=${String(acc.outcome.hasThinking)}, responseTextLength=${responseText.length})`);
500
+ }
501
+ else {
502
+ this.logger.debug(() => `[stream:terminal] finalized stream with finishReason`, {
503
+ finishReason: acc.finishReason,
504
+ hasToolCall: acc.outcome.hasToolCalls,
505
+ hasTextResponse: acc.outcome.hasVisibleText,
506
+ hasThinkingResponse: acc.outcome.hasThinking,
507
+ responseTextLength: responseText.length,
508
+ chunkCount: acc.allChunks.length,
509
+ });
510
+ }
511
+ this._validateStreamCompletion(userInput, acc.outcome, acc.finishReason, responseText);
512
+ await this._recordHistoryWithUsage(userInput, consolidatedParts, acc.allChunks);
513
+ }
514
+ /**
515
+ * Consolidate adjacent text parts.
516
+ */
517
+ _consolidateTextParts(modelResponseParts) {
518
+ const consolidatedParts = [];
519
+ for (const part of modelResponseParts) {
520
+ const lastPart = consolidatedParts[consolidatedParts.length - 1];
521
+ if (
522
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- Preserve defensive runtime boundary guard despite current static types.
523
+ lastPart?.text &&
524
+ isValidNonThoughtTextPart(lastPart) &&
525
+ isValidNonThoughtTextPart(part)) {
526
+ lastPart.text += part.text;
527
+ }
528
+ else {
529
+ consolidatedParts.push(part);
530
+ }
531
+ }
532
+ return consolidatedParts;
533
+ }
534
+ /**
535
+ * Extract response text from consolidated parts.
536
+ */
537
+ _extractResponseText(consolidatedParts) {
538
+ return consolidatedParts
539
+ .filter((part) => isValidNonThoughtTextPart(part))
540
+ .map((part) => part.text)
541
+ .join('')
542
+ .trim();
543
+ }
544
+ /**
545
+ * Validate stream completion and throw appropriate errors.
546
+ */
547
+ _validateStreamCompletion(userInput, outcome, finishReason, responseText) {
548
+ const isToolContinuationInput = Array.isArray(userInput)
549
+ ? userInput.some(isFunctionResponse)
550
+ : isFunctionResponse(userInput);
551
+ const validationContext = {
552
+ hasToolCall: outcome.hasToolCalls,
553
+ hasTextResponse: outcome.hasVisibleText,
554
+ hasThinkingResponse: outcome.hasThinking,
555
+ finishReason,
556
+ responseTextLength: responseText.length,
557
+ isToolContinuationInput,
558
+ };
559
+ this.logger.debug(() => `[stream:terminal] validating converted stream completion`, validationContext);
560
+ const hasMissingFinishAndNoText = isMissingFinishReason(finishReason) && !outcome.hasVisibleText;
561
+ const isEmptyResponse = responseText === '';
562
+ const noRelevantContent = !outcome.hasToolCalls && !isToolContinuationInput && !outcome.hasThinking;
563
+ const isInvalidResponse = noRelevantContent && (hasMissingFinishAndNoText || isEmptyResponse);
564
+ if (isInvalidResponse) {
565
+ this._throwMissingResponseError(finishReason, outcome.hasVisibleText, validationContext);
566
+ }
567
+ if (finishReason === FinishReason.MALFORMED_FUNCTION_CALL) {
568
+ this.logger.warn(() => `[stream:terminal] validation failed: malformed function call finishReason`, validationContext);
569
+ throw new InvalidStreamError('Model stream ended with malformed function call.', 'MALFORMED_FUNCTION_CALL');
570
+ }
571
+ }
572
+ _throwMissingResponseError(finishReason, hasTextResponse, validationContext) {
573
+ if (isMissingFinishReason(finishReason) && !hasTextResponse) {
574
+ this.logger.warn(() => `[stream:terminal] validation failed: missing finishReason and text`, validationContext);
575
+ throw new InvalidStreamError('Model stream ended without a finish reason and no text response.', 'NO_FINISH_REASON_NO_TEXT');
576
+ }
577
+ this.logger.warn(() => `[stream:terminal] validation failed: empty response text`, validationContext);
578
+ throw new InvalidStreamError('Model stream ended with empty response text.', 'NO_RESPONSE_TEXT');
579
+ }
580
+ /**
581
+ * Record history with usage metadata and sync token counts.
582
+ */
583
+ async _recordHistoryWithUsage(userInput, consolidatedParts, allChunks) {
584
+ // Use recordHistory to correctly save the conversation turn.
585
+ const modelOutput = [
586
+ { role: 'model', parts: consolidatedParts },
587
+ ];
588
+ // Capture usage metadata from the stream
589
+ let streamingUsageMetadata = null;
590
+ let actualPromptTokens = null;
591
+ // Find the last chunk that has usage metadata (similar to getLastChunkWithMetadata logic)
592
+ const lastChunkWithMetadata = allChunks
593
+ .slice()
594
+ .reverse()
595
+ .find((chunk) => chunk.usageMetadata);
596
+ if (lastChunkWithMetadata?.usageMetadata) {
597
+ streamingUsageMetadata = {
598
+ promptTokens: lastChunkWithMetadata.usageMetadata.promptTokenCount ?? 0,
599
+ completionTokens: lastChunkWithMetadata.usageMetadata.candidatesTokenCount ?? 0,
600
+ totalTokens: lastChunkWithMetadata.usageMetadata.totalTokenCount ?? 0,
601
+ };
602
+ const usageMetadata = lastChunkWithMetadata.usageMetadata;
603
+ const cacheReads = usageMetadata.cache_read_input_tokens ?? 0;
604
+ const cacheWrites = usageMetadata.cache_creation_input_tokens ?? 0;
605
+ actualPromptTokens =
606
+ streamingUsageMetadata.promptTokens + cacheReads + cacheWrites;
607
+ }
608
+ // Record history first (adds estimated tokens)
609
+ this.conversationManager.recordHistory(userInput, modelOutput, undefined, streamingUsageMetadata);
610
+ // Ensure token estimation updates are complete before syncing to actual API prompt tokens.
611
+ await this.historyService.waitForTokenUpdates();
612
+ // Sync token counts AFTER recording history to replace estimated tokens with actual API prompt tokens
613
+ // Use explicit check for undefined to allow 0 values
614
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition, sonarjs/different-types-comparison -- preserve defensive runtime boundary guard despite current static types.
615
+ if (actualPromptTokens !== null && actualPromptTokens !== undefined) {
616
+ if (actualPromptTokens > 0) {
617
+ this.logger.debug(() => `[StreamProcessor] Syncing prompt token count to HistoryService: ${actualPromptTokens}`);
618
+ this.historyService.syncTotalTokens(actualPromptTokens);
619
+ await this.historyService.waitForTokenUpdates();
620
+ }
621
+ }
622
+ else if (this.compressionHandler.lastPromptTokenCount !== null) {
623
+ if (this.compressionHandler.lastPromptTokenCount > 0) {
624
+ this.logger.debug(() => `[StreamProcessor] Syncing prompt token count to HistoryService: ${this.compressionHandler.lastPromptTokenCount}`);
625
+ this.historyService.syncTotalTokens(this.compressionHandler.lastPromptTokenCount);
626
+ await this.historyService.waitForTokenUpdates();
627
+ }
628
+ }
629
+ else {
630
+ this.logger.debug(() => `[StreamProcessor] No token count to sync (lastPromptTokenCount: ${this.compressionHandler.lastPromptTokenCount})`);
631
+ }
632
+ }
633
+ /**
634
+ * Enrich schema depth errors with diagnostic information.
635
+ * Adapted from maybeIncludeSchemaDepthContext in chatSession.ts.
636
+ */
637
+ _enrichSchemaDepthError(error) {
638
+ // Check for potentially problematic cyclic tools with cyclic schemas
639
+ // and include a recommendation to remove potentially problematic tools.
640
+ if (isStructuredError(error) && isSchemaDepthError(error.message)) {
641
+ const toolNames = this.runtimeContext.tools.listToolNames();
642
+ const cyclicSchemaTools = [];
643
+ // Check each tool's metadata for cyclic schemas
644
+ for (const toolName of toolNames) {
645
+ const metadata = this.runtimeContext.tools.getToolMetadata(toolName);
646
+ if (metadata?.parameterSchema &&
647
+ hasCycleInSchema(metadata.parameterSchema)) {
648
+ cyclicSchemaTools.push(toolName);
649
+ }
650
+ }
651
+ if (cyclicSchemaTools.length > 0) {
652
+ const extraDetails = `\n\nThis error was probably caused by cyclic schema references in one of the following tools, try disabling them:\n\n - ` +
653
+ cyclicSchemaTools.join(`\n - `) +
654
+ `\n`;
655
+ error.message += extraDetails;
656
+ }
657
+ }
658
+ }
659
+ }
660
+ //# sourceMappingURL=StreamProcessor.js.map