@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,127 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ /**
7
+ * @internal
8
+ * Owns result buffering, ordered publishing, and batch output-limit computation.
9
+ * Extracted from CoreToolScheduler as part of the Phase 2 decomposition
10
+ * (issue 1580).
11
+ *
12
+ * Ordering guarantee: results are published in `executionIndex` order
13
+ * regardless of which tool finishes first, using a reentrancy-guarded loop
14
+ * with a `setImmediate` recovery path for the race where a result arrives
15
+ * after the loop exits but before the flag is cleared.
16
+ */
17
+ import type { ToolCallResponseInfo } from '../core/turn.js';
18
+ import type { ToolResult } from '@vybestack/llxprt-code-tools';
19
+ import { type ToolOutputSettingsProvider } from '@vybestack/llxprt-code-core/utils/toolOutputLimiter.js';
20
+ import type { ScheduledToolCall } from '@vybestack/llxprt-code-core/scheduler/types.js';
21
+ /**
22
+ * Callbacks provided by CoreToolScheduler so ResultAggregator can publish
23
+ * without importing the scheduler class (prevents circular dependency).
24
+ */
25
+ export interface ResultPublishCallbacks {
26
+ /** Transition a call to the 'success' terminal state. */
27
+ setSuccess(callId: string, response: ToolCallResponseInfo): void;
28
+ /** Transition a call to the 'error' terminal state. */
29
+ setError(callId: string, response: ToolCallResponseInfo): void;
30
+ /**
31
+ * Returns the active Config (or equivalent provider) so ResultAggregator
32
+ * can compute per-tool token limits when no batch override is in effect.
33
+ */
34
+ getFallbackOutputConfig(): ToolOutputSettingsProvider;
35
+ }
36
+ /**
37
+ * @internal
38
+ */
39
+ export declare class ResultAggregator {
40
+ private readonly callbacks;
41
+ /** Pending tool results keyed by callId. */
42
+ private readonly pendingResults;
43
+ /** The executionIndex of the next result to publish. */
44
+ private nextPublishIndex;
45
+ /** Total tools in the current batch; set by {@link beginBatch}. */
46
+ private currentBatchSize;
47
+ /**
48
+ * Per-tool output config derived by dividing the batch token budget equally.
49
+ * Undefined when the batch has ≤ 1 tool.
50
+ */
51
+ private batchOutputConfig;
52
+ /** Reentrancy guard for {@link publishBufferedResults}. */
53
+ private isPublishingBufferedResults;
54
+ /** Set when a second publish is requested during an active publish pass. */
55
+ private pendingPublishRequest;
56
+ constructor(callbacks: ResultPublishCallbacks);
57
+ /** Store a successful tool result for ordered publishing. */
58
+ bufferResult(callId: string, toolName: string, scheduledCall: ScheduledToolCall, result: ToolResult, executionIndex: number): void;
59
+ /** Store an error result (ToolResult with `.error` set) for ordered publishing. */
60
+ bufferError(callId: string, toolName: string, scheduledCall: ScheduledToolCall, error: Error, executionIndex: number): void;
61
+ /**
62
+ * Store a placeholder for a cancelled call so the ordered-publish loop can
63
+ * advance past this index. The call is already in 'cancelled' terminal state
64
+ * so no callback is fired — the entry is simply discarded after its index is
65
+ * consumed.
66
+ */
67
+ bufferCancelled(callId: string, scheduledCall: ScheduledToolCall, executionIndex: number): void;
68
+ /**
69
+ * Called once at the start of each execution batch to record how many tools
70
+ * are participating and to apply proportional output-token limits when the
71
+ * batch has more than one tool.
72
+ */
73
+ beginBatch(size: number): void;
74
+ /**
75
+ * Publishes buffered results in `executionIndex` order.
76
+ *
77
+ * Reentrancy guard: if called while a publish pass is already running the
78
+ * call sets `pendingPublishRequest` and returns immediately. The running
79
+ * pass will loop once more before releasing the lock.
80
+ *
81
+ * Recovery path: after releasing the lock we check whether any buffered
82
+ * results are ready (i.e. the next expected index is present) and schedule
83
+ * a follow-up via `setImmediate` to avoid missing results that arrived while
84
+ * the lock was held.
85
+ */
86
+ publishBufferedResults(signal: AbortSignal): Promise<void>;
87
+ /**
88
+ * Clears all buffered state. Called by `CoreToolScheduler.cancelAll()` and
89
+ * indirectly by `dispose()`.
90
+ */
91
+ reset(): void;
92
+ /** Find a buffered entry by its executionIndex. */
93
+ private findByExecutionIndex;
94
+ /**
95
+ * Issue #987 fix: if tools complete before `beginBatch` is called,
96
+ * `currentBatchSize` may still be 0. Recover it from the actual pending
97
+ * entries so publishing can proceed.
98
+ */
99
+ private recoverBatchSizeIfNeeded;
100
+ /** When the entire batch has been published, reset counters for the next batch. */
101
+ private resetBatchIfComplete;
102
+ private publishBufferedResultsPass;
103
+ /**
104
+ * After releasing the reentrancy lock, schedule a follow-up publish via
105
+ * `setImmediate` when the next expected result is already buffered. This
106
+ * handles the race where:
107
+ * 1. We break the inner `while` loop waiting for result N.
108
+ * 2. Result N arrives and calls `publishBufferedResults`.
109
+ * 3. That call sees the lock held, sets `pendingPublishRequest`, and returns.
110
+ * 4. We exit the `do-while` without seeing the flag (it was set after the check).
111
+ */
112
+ private scheduleFollowUpIfNeeded;
113
+ /**
114
+ * Convert a buffered result to a `ToolCallResponseInfo` and invoke the
115
+ * appropriate status callback (`setSuccess` or `setError`).
116
+ */
117
+ private publishResult;
118
+ /**
119
+ * Apply batch-level output limits for parallel tool batches. (#1301)
120
+ *
121
+ * `tool-output-max-tokens` is treated as a budget for the entire batch.
122
+ * For batches of 2+ tools this method divides the budget equally and stores
123
+ * the reduced per-tool limit in {@link batchOutputConfig}, which
124
+ * {@link publishResult} picks up when building function-response parts.
125
+ */
126
+ private applyBatchOutputLimits;
127
+ }
@@ -0,0 +1,302 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { ToolErrorType } from '@vybestack/llxprt-code-tools';
7
+ import { DEFAULT_AGENT_ID } from '../core/turn.js';
8
+ import { convertToFunctionResponse, extractAgentIdFromMetadata, createErrorResponse, } from '@vybestack/llxprt-code-core/utils/generateContentResponseUtilities.js';
9
+ import { DEFAULT_MAX_TOKENS, } from '@vybestack/llxprt-code-core/utils/toolOutputLimiter.js';
10
+ import { DebugLogger } from '@vybestack/llxprt-code-core/debug/index.js';
11
+ const logger = new DebugLogger('llxprt:scheduler:result-aggregator');
12
+ // ---- ResultAggregator -------------------------------------------------------
13
+ /**
14
+ * @internal
15
+ */
16
+ export class ResultAggregator {
17
+ callbacks;
18
+ /** Pending tool results keyed by callId. */
19
+ pendingResults = new Map();
20
+ /** The executionIndex of the next result to publish. */
21
+ nextPublishIndex = 0;
22
+ /** Total tools in the current batch; set by {@link beginBatch}. */
23
+ currentBatchSize = 0;
24
+ /**
25
+ * Per-tool output config derived by dividing the batch token budget equally.
26
+ * Undefined when the batch has ≤ 1 tool.
27
+ */
28
+ batchOutputConfig = undefined;
29
+ /** Reentrancy guard for {@link publishBufferedResults}. */
30
+ isPublishingBufferedResults = false;
31
+ /** Set when a second publish is requested during an active publish pass. */
32
+ pendingPublishRequest = false;
33
+ constructor(callbacks) {
34
+ this.callbacks = callbacks;
35
+ }
36
+ // ---- public buffering API ------------------------------------------------
37
+ /** Store a successful tool result for ordered publishing. */
38
+ bufferResult(callId, toolName, scheduledCall, result, executionIndex) {
39
+ this.pendingResults.set(callId, {
40
+ result,
41
+ callId,
42
+ toolName,
43
+ scheduledCall,
44
+ executionIndex,
45
+ });
46
+ }
47
+ /** Store an error result (ToolResult with `.error` set) for ordered publishing. */
48
+ bufferError(callId, toolName, scheduledCall, error, executionIndex) {
49
+ const errorResult = {
50
+ error: {
51
+ message: error.message,
52
+ type: ToolErrorType.UNHANDLED_EXCEPTION,
53
+ },
54
+ llmContent: error.message,
55
+ returnDisplay: error.message,
56
+ };
57
+ this.pendingResults.set(callId, {
58
+ result: errorResult,
59
+ callId,
60
+ toolName,
61
+ scheduledCall,
62
+ executionIndex,
63
+ });
64
+ }
65
+ /**
66
+ * Store a placeholder for a cancelled call so the ordered-publish loop can
67
+ * advance past this index. The call is already in 'cancelled' terminal state
68
+ * so no callback is fired — the entry is simply discarded after its index is
69
+ * consumed.
70
+ */
71
+ bufferCancelled(callId, scheduledCall, executionIndex) {
72
+ const cancelledResult = {
73
+ error: {
74
+ message: 'Tool call cancelled by user.',
75
+ type: ToolErrorType.EXECUTION_FAILED,
76
+ },
77
+ llmContent: 'Tool call cancelled by user.',
78
+ returnDisplay: 'Cancelled',
79
+ };
80
+ this.pendingResults.set(callId, {
81
+ result: cancelledResult,
82
+ callId,
83
+ toolName: scheduledCall.request.name,
84
+ scheduledCall,
85
+ executionIndex,
86
+ isCancelled: true,
87
+ });
88
+ }
89
+ // ---- batch initialisation ------------------------------------------------
90
+ /**
91
+ * Called once at the start of each execution batch to record how many tools
92
+ * are participating and to apply proportional output-token limits when the
93
+ * batch has more than one tool.
94
+ */
95
+ beginBatch(size) {
96
+ this.currentBatchSize = size;
97
+ this.applyBatchOutputLimits(size);
98
+ }
99
+ // ---- publishing ----------------------------------------------------------
100
+ /**
101
+ * Publishes buffered results in `executionIndex` order.
102
+ *
103
+ * Reentrancy guard: if called while a publish pass is already running the
104
+ * call sets `pendingPublishRequest` and returns immediately. The running
105
+ * pass will loop once more before releasing the lock.
106
+ *
107
+ * Recovery path: after releasing the lock we check whether any buffered
108
+ * results are ready (i.e. the next expected index is present) and schedule
109
+ * a follow-up via `setImmediate` to avoid missing results that arrived while
110
+ * the lock was held.
111
+ */
112
+ async publishBufferedResults(signal) {
113
+ if (this.isPublishingBufferedResults) {
114
+ this.pendingPublishRequest = true;
115
+ return;
116
+ }
117
+ this.isPublishingBufferedResults = true;
118
+ this.pendingPublishRequest = false;
119
+ try {
120
+ await this.publishBufferedResultsPass(signal);
121
+ }
122
+ finally {
123
+ this.isPublishingBufferedResults = false;
124
+ this.scheduleFollowUpIfNeeded(signal);
125
+ }
126
+ }
127
+ // ---- state reset ---------------------------------------------------------
128
+ /**
129
+ * Clears all buffered state. Called by `CoreToolScheduler.cancelAll()` and
130
+ * indirectly by `dispose()`.
131
+ */
132
+ reset() {
133
+ this.pendingResults.clear();
134
+ this.nextPublishIndex = 0;
135
+ this.currentBatchSize = 0;
136
+ this.isPublishingBufferedResults = false;
137
+ this.pendingPublishRequest = false;
138
+ this.batchOutputConfig = undefined;
139
+ }
140
+ // ---- private helpers -----------------------------------------------------
141
+ /** Find a buffered entry by its executionIndex. */
142
+ findByExecutionIndex(index) {
143
+ for (const entry of this.pendingResults.values()) {
144
+ if (entry.executionIndex === index) {
145
+ return entry;
146
+ }
147
+ }
148
+ return undefined;
149
+ }
150
+ /**
151
+ * Issue #987 fix: if tools complete before `beginBatch` is called,
152
+ * `currentBatchSize` may still be 0. Recover it from the actual pending
153
+ * entries so publishing can proceed.
154
+ */
155
+ recoverBatchSizeIfNeeded() {
156
+ if (this.currentBatchSize !== 0 || this.pendingResults.size === 0) {
157
+ return;
158
+ }
159
+ let maxIndex = -1;
160
+ for (const entry of this.pendingResults.values()) {
161
+ if (entry.executionIndex > maxIndex) {
162
+ maxIndex = entry.executionIndex;
163
+ }
164
+ }
165
+ const recovered = Math.min(maxIndex + 1, this.pendingResults.size);
166
+ this.currentBatchSize = recovered > 0 ? recovered : 1;
167
+ if (logger.enabled) {
168
+ logger.debug(() => `Recovered batch size from pending results: currentBatchSize=${this.currentBatchSize}, ` +
169
+ `pendingResults.size=${this.pendingResults.size}, maxIndex=${maxIndex}`);
170
+ }
171
+ }
172
+ /** When the entire batch has been published, reset counters for the next batch. */
173
+ resetBatchIfComplete() {
174
+ if (this.nextPublishIndex === this.currentBatchSize &&
175
+ this.currentBatchSize > 0) {
176
+ this.nextPublishIndex = 0;
177
+ this.currentBatchSize = 0;
178
+ this.pendingResults.clear();
179
+ this.batchOutputConfig = undefined;
180
+ }
181
+ }
182
+ async publishBufferedResultsPass(signal) {
183
+ this.pendingPublishRequest = false;
184
+ this.recoverBatchSizeIfNeeded();
185
+ while (this.nextPublishIndex < this.currentBatchSize) {
186
+ const nextBuffered = this.findByExecutionIndex(this.nextPublishIndex);
187
+ if (!nextBuffered) {
188
+ break; // Gap — wait for the missing result to arrive
189
+ }
190
+ if (nextBuffered.isCancelled !== true) {
191
+ await this.publishResult(nextBuffered, signal);
192
+ }
193
+ this.pendingResults.delete(nextBuffered.callId);
194
+ this.nextPublishIndex++;
195
+ }
196
+ this.resetBatchIfComplete();
197
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- Async publish reentrancy can flip this flag while awaiting result publication.
198
+ if (this.pendingPublishRequest) {
199
+ await this.publishBufferedResultsPass(signal);
200
+ }
201
+ }
202
+ /**
203
+ * After releasing the reentrancy lock, schedule a follow-up publish via
204
+ * `setImmediate` when the next expected result is already buffered. This
205
+ * handles the race where:
206
+ * 1. We break the inner `while` loop waiting for result N.
207
+ * 2. Result N arrives and calls `publishBufferedResults`.
208
+ * 3. That call sees the lock held, sets `pendingPublishRequest`, and returns.
209
+ * 4. We exit the `do-while` without seeing the flag (it was set after the check).
210
+ */
211
+ scheduleFollowUpIfNeeded(signal) {
212
+ if (this.pendingResults.size === 0) {
213
+ return;
214
+ }
215
+ const hasNext = this.findByExecutionIndex(this.nextPublishIndex) !== undefined;
216
+ if (hasNext) {
217
+ setImmediate(() => {
218
+ void this.publishBufferedResults(signal);
219
+ });
220
+ }
221
+ }
222
+ /**
223
+ * Convert a buffered result to a `ToolCallResponseInfo` and invoke the
224
+ * appropriate status callback (`setSuccess` or `setError`).
225
+ */
226
+ async publishResult(buffered, _signal) {
227
+ const { result, callId, toolName, scheduledCall } = buffered;
228
+ if (result.error === undefined) {
229
+ const outputConfig = this.batchOutputConfig ?? this.callbacks.getFallbackOutputConfig();
230
+ const responseParts = convertToFunctionResponse(toolName, callId, result.llmContent, outputConfig);
231
+ const metadataAgentId = extractAgentIdFromMetadata(result.metadata);
232
+ const successResponse = {
233
+ callId,
234
+ responseParts,
235
+ resultDisplay: result.returnDisplay,
236
+ error: undefined,
237
+ errorType: undefined,
238
+ agentId: metadataAgentId ?? scheduledCall.request.agentId ?? DEFAULT_AGENT_ID,
239
+ ...(result.suppressDisplay !== undefined && {
240
+ suppressDisplay: result.suppressDisplay,
241
+ }),
242
+ };
243
+ logger.debug(`callId=${callId}, toolName=${toolName}, returnDisplay type=${typeof result.returnDisplay}, hasValue=${Boolean(result.returnDisplay)}`);
244
+ this.callbacks.setSuccess(callId, successResponse);
245
+ }
246
+ else {
247
+ const error = new Error(result.error.message);
248
+ const errorResponse = createErrorResponse(scheduledCall.request, error, result.error.type);
249
+ this.callbacks.setError(callId, errorResponse);
250
+ }
251
+ }
252
+ /**
253
+ * Apply batch-level output limits for parallel tool batches. (#1301)
254
+ *
255
+ * `tool-output-max-tokens` is treated as a budget for the entire batch.
256
+ * For batches of 2+ tools this method divides the budget equally and stores
257
+ * the reduced per-tool limit in {@link batchOutputConfig}, which
258
+ * {@link publishResult} picks up when building function-response parts.
259
+ */
260
+ applyBatchOutputLimits(batchSize) {
261
+ if (batchSize <= 1) {
262
+ this.batchOutputConfig = undefined;
263
+ return;
264
+ }
265
+ try {
266
+ const fallback = this.callbacks.getFallbackOutputConfig();
267
+ const ephemeral = typeof fallback.getEphemeralSettings === 'function'
268
+ ? fallback.getEphemeralSettings()
269
+ : {};
270
+ const maxBatchTokens = ephemeral['tool-output-max-tokens'] ??
271
+ DEFAULT_MAX_TOKENS;
272
+ const perToolBudget = Math.max(1000, Math.floor(maxBatchTokens / batchSize));
273
+ if (logger.enabled) {
274
+ logger.debug(() => `Batch of ${batchSize} tools: applying per-tool output limit ` +
275
+ `of ${perToolBudget} tokens (batch budget: ${maxBatchTokens}).`);
276
+ }
277
+ this.batchOutputConfig = {
278
+ getEphemeralSettings: () => ({
279
+ ...ephemeral,
280
+ 'tool-output-max-tokens': perToolBudget,
281
+ // eslint-disable-next-line sonarjs/expression-complexity -- Existing structure is intentionally preserved; refactoring this boundary is outside the lint slice.
282
+ ...(ephemeral['tool-output-truncate-mode'] !== undefined &&
283
+ ephemeral['tool-output-truncate-mode'] !== null &&
284
+ ephemeral['tool-output-truncate-mode'] !== false &&
285
+ ephemeral['tool-output-truncate-mode'] !== 0 &&
286
+ ephemeral['tool-output-truncate-mode'] !== '' &&
287
+ !(typeof ephemeral['tool-output-truncate-mode'] === 'number' &&
288
+ Number.isNaN(ephemeral['tool-output-truncate-mode']))
289
+ ? {}
290
+ : { 'tool-output-truncate-mode': 'truncate' }),
291
+ }),
292
+ };
293
+ }
294
+ catch (error) {
295
+ if (logger.enabled) {
296
+ logger.debug(() => `Failed to compute batch output limits; skipping budget guard: ${error}`);
297
+ }
298
+ this.batchOutputConfig = undefined;
299
+ }
300
+ }
301
+ }
302
+ //# sourceMappingURL=result-aggregator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result-aggregator.js","sourceRoot":"","sources":["../../../src/scheduler/result-aggregator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ /**
7
+ * Pure transition builder functions for ToolCall state machine.
8
+ * Extracted from CoreToolScheduler.setStatusInternal to keep functions under 80 lines.
9
+ */
10
+ import type { ToolCall, ValidatingToolCall, ScheduledToolCall, ExecutingToolCall, SuccessfulToolCall, ErroredToolCall, CancelledToolCall, WaitingToolCall, Status } from '@vybestack/llxprt-code-core/scheduler/types.js';
11
+ import type { ToolCallResponseInfo } from '@vybestack/llxprt-code-core/core/turn.js';
12
+ import type { ToolCallConfirmationDetails } from '@vybestack/llxprt-code-tools';
13
+ import type { SerializableConfirmationDetails } from '@vybestack/llxprt-code-core/confirmation-bus/types.js';
14
+ /**
15
+ * Common context extracted from a non-terminal tool call for building transitions.
16
+ */
17
+ interface TransitionContext {
18
+ request: ToolCall['request'];
19
+ tool: Exclude<ToolCall, ErroredToolCall>['tool'];
20
+ invocation: Exclude<ToolCall, ErroredToolCall | WaitingToolCall>['invocation'];
21
+ startTime?: number;
22
+ outcome?: ToolCall['outcome'];
23
+ }
24
+ export declare function buildSuccessTransition(ctx: TransitionContext, response: ToolCallResponseInfo): SuccessfulToolCall;
25
+ export declare function buildErrorTransition(ctx: TransitionContext, response: ToolCallResponseInfo): ErroredToolCall;
26
+ export declare function buildCancelledTransition(ctx: TransitionContext, reason: string, currentStatus: Status, currentCall: ToolCall): CancelledToolCall;
27
+ export declare function buildAwaitingApprovalTransition(ctx: TransitionContext, confirmationDetails: ToolCallConfirmationDetails | SerializableConfirmationDetails): WaitingToolCall;
28
+ export declare function buildSimpleTransition(ctx: TransitionContext, status: 'scheduled' | 'validating' | 'executing'): ScheduledToolCall | ValidatingToolCall | ExecutingToolCall;
29
+ /**
30
+ * Build a cancelled tool call from cancelAll() — simpler than the setStatusInternal
31
+ * path because we don't need to check for edit confirmations or use a reason string.
32
+ */
33
+ export declare function buildCancelAllEntry(call: ValidatingToolCall | ScheduledToolCall | ExecutingToolCall | WaitingToolCall): CancelledToolCall;
34
+ /**
35
+ * Apply a status transition to a single tool call.
36
+ * Returns the original call if it's in a terminal state or doesn't match the target callId.
37
+ */
38
+ export declare function applyTransition(currentCall: ToolCall, targetCallId: string, newStatus: Status, auxiliaryData?: unknown): ToolCall;
39
+ export {};
@@ -0,0 +1,184 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { DEFAULT_AGENT_ID } from '@vybestack/llxprt-code-core/core/turn.js';
7
+ import { ToolConfirmationOutcome } from '@vybestack/llxprt-code-tools';
8
+ function getTransitionContext(call) {
9
+ // Terminal states cannot transition further
10
+ if (call.status === 'success' ||
11
+ call.status === 'error' ||
12
+ call.status === 'cancelled') {
13
+ return undefined;
14
+ }
15
+ return {
16
+ request: call.request,
17
+ tool: call.tool,
18
+ invocation: call.invocation,
19
+ startTime: call.startTime,
20
+ outcome: call.outcome,
21
+ };
22
+ }
23
+ function computeDuration(startTime) {
24
+ return startTime != null ? Date.now() - startTime : undefined;
25
+ }
26
+ function ensureAgentId(response, request) {
27
+ const copy = { ...response };
28
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- intentional falsy coalescing: agentId is string | undefined, empty string should fall through
29
+ if (!copy.agentId) {
30
+ copy.agentId = request.agentId ?? DEFAULT_AGENT_ID;
31
+ }
32
+ return copy;
33
+ }
34
+ export function buildSuccessTransition(ctx, response) {
35
+ return {
36
+ request: ctx.request,
37
+ tool: ctx.tool,
38
+ invocation: ctx.invocation,
39
+ status: 'success',
40
+ response: ensureAgentId(response, ctx.request),
41
+ durationMs: computeDuration(ctx.startTime),
42
+ outcome: ctx.outcome,
43
+ };
44
+ }
45
+ export function buildErrorTransition(ctx, response) {
46
+ return {
47
+ request: ctx.request,
48
+ status: 'error',
49
+ tool: ctx.tool,
50
+ invocation: ctx.invocation,
51
+ response: ensureAgentId(response, ctx.request),
52
+ durationMs: computeDuration(ctx.startTime),
53
+ outcome: ctx.outcome,
54
+ };
55
+ }
56
+ export function buildCancelledTransition(ctx, reason, currentStatus, currentCall) {
57
+ // Preserve diff for cancelled edit operations
58
+ let resultDisplay = undefined;
59
+ if (currentStatus === 'awaiting_approval') {
60
+ const waitingCall = currentCall;
61
+ if (waitingCall.confirmationDetails.type === 'edit') {
62
+ resultDisplay = {
63
+ fileDiff: waitingCall.confirmationDetails.fileDiff,
64
+ fileName: waitingCall.confirmationDetails.fileName,
65
+ originalContent: waitingCall.confirmationDetails.originalContent,
66
+ newContent: waitingCall.confirmationDetails.newContent,
67
+ filePath: waitingCall.confirmationDetails.filePath,
68
+ };
69
+ }
70
+ }
71
+ return {
72
+ request: ctx.request,
73
+ tool: ctx.tool,
74
+ invocation: ctx.invocation,
75
+ status: 'cancelled',
76
+ response: {
77
+ callId: ctx.request.callId,
78
+ responseParts: [
79
+ {
80
+ functionResponse: {
81
+ id: ctx.request.callId,
82
+ name: ctx.request.name,
83
+ response: {
84
+ error: `[Operation Cancelled] Reason: ${reason}`,
85
+ },
86
+ },
87
+ },
88
+ ],
89
+ resultDisplay,
90
+ error: undefined,
91
+ errorType: undefined,
92
+ agentId: ctx.request.agentId ?? DEFAULT_AGENT_ID,
93
+ },
94
+ durationMs: computeDuration(ctx.startTime),
95
+ outcome: ctx.outcome,
96
+ };
97
+ }
98
+ export function buildAwaitingApprovalTransition(ctx, confirmationDetails) {
99
+ return {
100
+ request: ctx.request,
101
+ tool: ctx.tool,
102
+ status: 'awaiting_approval',
103
+ confirmationDetails,
104
+ startTime: ctx.startTime,
105
+ outcome: ctx.outcome,
106
+ invocation: ctx.invocation,
107
+ };
108
+ }
109
+ export function buildSimpleTransition(ctx, status) {
110
+ return {
111
+ request: ctx.request,
112
+ tool: ctx.tool,
113
+ status,
114
+ startTime: ctx.startTime,
115
+ outcome: ctx.outcome,
116
+ invocation: ctx.invocation,
117
+ };
118
+ }
119
+ /**
120
+ * Build a cancelled tool call from cancelAll() — simpler than the setStatusInternal
121
+ * path because we don't need to check for edit confirmations or use a reason string.
122
+ */
123
+ export function buildCancelAllEntry(call) {
124
+ return {
125
+ status: 'cancelled',
126
+ request: call.request,
127
+ response: {
128
+ callId: call.request.callId,
129
+ responseParts: [
130
+ {
131
+ functionResponse: {
132
+ id: call.request.callId,
133
+ name: call.request.name,
134
+ response: {
135
+ error: 'Tool call cancelled by user.',
136
+ },
137
+ },
138
+ },
139
+ ],
140
+ resultDisplay: undefined,
141
+ error: undefined,
142
+ errorType: undefined,
143
+ agentId: call.request.agentId ?? DEFAULT_AGENT_ID,
144
+ },
145
+ tool: call.tool,
146
+ invocation: call.invocation,
147
+ durationMs: call.startTime != null ? Date.now() - call.startTime : undefined,
148
+ outcome: ToolConfirmationOutcome.Cancel,
149
+ };
150
+ }
151
+ /**
152
+ * Apply a status transition to a single tool call.
153
+ * Returns the original call if it's in a terminal state or doesn't match the target callId.
154
+ */
155
+ export function applyTransition(currentCall, targetCallId, newStatus, auxiliaryData) {
156
+ if (currentCall.request.callId !== targetCallId ||
157
+ currentCall.status === 'success' ||
158
+ currentCall.status === 'error' ||
159
+ currentCall.status === 'cancelled') {
160
+ return currentCall;
161
+ }
162
+ const ctx = getTransitionContext(currentCall);
163
+ if (!ctx)
164
+ return currentCall;
165
+ switch (newStatus) {
166
+ case 'success':
167
+ return buildSuccessTransition(ctx, auxiliaryData);
168
+ case 'error':
169
+ return buildErrorTransition(ctx, auxiliaryData);
170
+ case 'cancelled':
171
+ return buildCancelledTransition(ctx, auxiliaryData, currentCall.status, currentCall);
172
+ case 'awaiting_approval':
173
+ return buildAwaitingApprovalTransition(ctx, auxiliaryData);
174
+ case 'scheduled':
175
+ case 'validating':
176
+ case 'executing':
177
+ return buildSimpleTransition(ctx, newStatus);
178
+ default: {
179
+ const exhaustiveCheck = newStatus;
180
+ return exhaustiveCheck;
181
+ }
182
+ }
183
+ }
184
+ //# sourceMappingURL=status-transitions.js.map