@google/gemini-cli-core 0.23.0-preview.4 → 0.24.0-nightly.20251231.05049b5ab

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 (230) hide show
  1. package/dist/docs/cli/settings.md +7 -6
  2. package/dist/docs/get-started/configuration.md +79 -8
  3. package/dist/google-gemini-cli-core-0.24.0-nightly.20251227.37be16243.tgz +0 -0
  4. package/dist/src/agents/a2a-client-manager.d.ts +73 -0
  5. package/dist/src/agents/a2a-client-manager.js +165 -0
  6. package/dist/src/agents/a2a-client-manager.js.map +1 -0
  7. package/dist/src/agents/a2a-client-manager.test.d.ts +6 -0
  8. package/dist/src/agents/a2a-client-manager.test.js +211 -0
  9. package/dist/src/agents/a2a-client-manager.test.js.map +1 -0
  10. package/dist/src/agents/local-executor.js +1 -0
  11. package/dist/src/agents/local-executor.js.map +1 -1
  12. package/dist/src/agents/registry.d.ts +9 -1
  13. package/dist/src/agents/registry.js +74 -34
  14. package/dist/src/agents/registry.js.map +1 -1
  15. package/dist/src/agents/registry.test.js +79 -30
  16. package/dist/src/agents/registry.test.js.map +1 -1
  17. package/dist/src/agents/toml-loader.d.ts +14 -5
  18. package/dist/src/agents/toml-loader.js +98 -26
  19. package/dist/src/agents/toml-loader.js.map +1 -1
  20. package/dist/src/agents/toml-loader.test.js +121 -2
  21. package/dist/src/agents/toml-loader.test.js.map +1 -1
  22. package/dist/src/availability/policyHelpers.js +0 -2
  23. package/dist/src/availability/policyHelpers.js.map +1 -1
  24. package/dist/src/code_assist/server.js +7 -2
  25. package/dist/src/code_assist/server.js.map +1 -1
  26. package/dist/src/code_assist/server.test.js +3 -0
  27. package/dist/src/code_assist/server.test.js.map +1 -1
  28. package/dist/src/config/config.d.ts +47 -7
  29. package/dist/src/config/config.js +59 -28
  30. package/dist/src/config/config.js.map +1 -1
  31. package/dist/src/config/config.test.js +20 -1
  32. package/dist/src/config/config.test.js.map +1 -1
  33. package/dist/src/config/models.d.ts +1 -9
  34. package/dist/src/config/models.js +1 -11
  35. package/dist/src/config/models.js.map +1 -1
  36. package/dist/src/config/models.test.js +16 -16
  37. package/dist/src/config/models.test.js.map +1 -1
  38. package/dist/src/config/storage.d.ts +2 -0
  39. package/dist/src/config/storage.js +6 -0
  40. package/dist/src/config/storage.js.map +1 -1
  41. package/dist/src/config/storage.test.js +8 -0
  42. package/dist/src/config/storage.test.js.map +1 -1
  43. package/dist/src/confirmation-bus/message-bus.js +2 -1
  44. package/dist/src/confirmation-bus/message-bus.js.map +1 -1
  45. package/dist/src/core/client.d.ts +5 -1
  46. package/dist/src/core/client.js +159 -73
  47. package/dist/src/core/client.js.map +1 -1
  48. package/dist/src/core/client.test.js +110 -5
  49. package/dist/src/core/client.test.js.map +1 -1
  50. package/dist/src/core/contentGenerator.js +2 -2
  51. package/dist/src/core/contentGenerator.js.map +1 -1
  52. package/dist/src/core/coreToolHookTriggers.d.ts +2 -2
  53. package/dist/src/core/coreToolHookTriggers.js +74 -14
  54. package/dist/src/core/coreToolHookTriggers.js.map +1 -1
  55. package/dist/src/core/coreToolHookTriggers.test.d.ts +6 -0
  56. package/dist/src/core/coreToolHookTriggers.test.js +189 -0
  57. package/dist/src/core/coreToolHookTriggers.test.js.map +1 -0
  58. package/dist/src/core/coreToolScheduler.d.ts +5 -85
  59. package/dist/src/core/coreToolScheduler.js +33 -206
  60. package/dist/src/core/coreToolScheduler.js.map +1 -1
  61. package/dist/src/core/coreToolScheduler.test.js +19 -367
  62. package/dist/src/core/coreToolScheduler.test.js.map +1 -1
  63. package/dist/src/core/nonInteractiveToolExecutor.test.js +0 -1
  64. package/dist/src/core/nonInteractiveToolExecutor.test.js.map +1 -1
  65. package/dist/src/core/turn.d.ts +3 -21
  66. package/dist/src/core/turn.js +1 -0
  67. package/dist/src/core/turn.js.map +1 -1
  68. package/dist/src/fallback/handler.js +0 -6
  69. package/dist/src/fallback/handler.js.map +1 -1
  70. package/dist/src/generated/git-commit.d.ts +2 -2
  71. package/dist/src/generated/git-commit.js +2 -2
  72. package/dist/src/generated/git-commit.js.map +1 -1
  73. package/dist/src/hooks/hookAggregator.js +7 -0
  74. package/dist/src/hooks/hookAggregator.js.map +1 -1
  75. package/dist/src/hooks/hookPlanner.d.ts +1 -5
  76. package/dist/src/hooks/hookPlanner.js +2 -9
  77. package/dist/src/hooks/hookPlanner.js.map +1 -1
  78. package/dist/src/hooks/hookPlanner.test.js +1 -2
  79. package/dist/src/hooks/hookPlanner.test.js.map +1 -1
  80. package/dist/src/hooks/hookRegistry.d.ts +5 -10
  81. package/dist/src/hooks/hookRegistry.js +39 -12
  82. package/dist/src/hooks/hookRegistry.js.map +1 -1
  83. package/dist/src/hooks/hookRegistry.test.js +93 -2
  84. package/dist/src/hooks/hookRegistry.test.js.map +1 -1
  85. package/dist/src/hooks/hookRunner.d.ts +3 -1
  86. package/dist/src/hooks/hookRunner.js +31 -3
  87. package/dist/src/hooks/hookRunner.js.map +1 -1
  88. package/dist/src/hooks/hookRunner.test.js +58 -2
  89. package/dist/src/hooks/hookRunner.test.js.map +1 -1
  90. package/dist/src/hooks/hookSystem.js +1 -1
  91. package/dist/src/hooks/hookSystem.js.map +1 -1
  92. package/dist/src/hooks/index.d.ts +1 -1
  93. package/dist/src/hooks/index.js +1 -1
  94. package/dist/src/hooks/index.js.map +1 -1
  95. package/dist/src/hooks/trustedHooks.d.ts +28 -0
  96. package/dist/src/hooks/trustedHooks.js +90 -0
  97. package/dist/src/hooks/trustedHooks.js.map +1 -0
  98. package/dist/src/hooks/trustedHooks.test.d.ts +6 -0
  99. package/dist/src/hooks/trustedHooks.test.js +154 -0
  100. package/dist/src/hooks/trustedHooks.test.js.map +1 -0
  101. package/dist/src/hooks/types.d.ts +18 -9
  102. package/dist/src/hooks/types.js +31 -26
  103. package/dist/src/hooks/types.js.map +1 -1
  104. package/dist/src/hooks/types.test.js +5 -24
  105. package/dist/src/hooks/types.test.js.map +1 -1
  106. package/dist/src/ide/ide-client.js +4 -1
  107. package/dist/src/ide/ide-client.js.map +1 -1
  108. package/dist/src/index.d.ts +1 -0
  109. package/dist/src/index.js +1 -0
  110. package/dist/src/index.js.map +1 -1
  111. package/dist/src/mcp/oauth-utils.js +1 -1
  112. package/dist/src/mcp/oauth-utils.js.map +1 -1
  113. package/dist/src/mcp/token-storage/keychain-token-storage.js +1 -1
  114. package/dist/src/mcp/token-storage/keychain-token-storage.js.map +1 -1
  115. package/dist/src/policy/config.js +4 -2
  116. package/dist/src/policy/config.js.map +1 -1
  117. package/dist/src/policy/persistence.test.js +6 -1
  118. package/dist/src/policy/persistence.test.js.map +1 -1
  119. package/dist/src/policy/policy-engine.d.ts +10 -1
  120. package/dist/src/policy/policy-engine.js +24 -4
  121. package/dist/src/policy/policy-engine.js.map +1 -1
  122. package/dist/src/policy/policy-engine.test.js +26 -2
  123. package/dist/src/policy/policy-engine.test.js.map +1 -1
  124. package/dist/src/policy/shell-safety.test.js +2 -1
  125. package/dist/src/policy/shell-safety.test.js.map +1 -1
  126. package/dist/src/policy/toml-loader.d.ts +3 -5
  127. package/dist/src/policy/toml-loader.js +35 -20
  128. package/dist/src/policy/toml-loader.js.map +1 -1
  129. package/dist/src/policy/toml-loader.test.js +28 -7
  130. package/dist/src/policy/toml-loader.test.js.map +1 -1
  131. package/dist/src/policy/types.d.ts +15 -0
  132. package/dist/src/routing/strategies/compositeStrategy.js +4 -2
  133. package/dist/src/routing/strategies/compositeStrategy.js.map +1 -1
  134. package/dist/src/routing/strategies/compositeStrategy.test.js +11 -10
  135. package/dist/src/routing/strategies/compositeStrategy.test.js.map +1 -1
  136. package/dist/src/routing/strategies/overrideStrategy.js +2 -2
  137. package/dist/src/routing/strategies/overrideStrategy.js.map +1 -1
  138. package/dist/src/scheduler/types.d.ts +95 -0
  139. package/dist/src/scheduler/types.js +7 -0
  140. package/dist/src/scheduler/types.js.map +1 -0
  141. package/dist/src/services/environmentSanitization.d.ts +15 -0
  142. package/dist/src/services/environmentSanitization.js +141 -0
  143. package/dist/src/services/environmentSanitization.js.map +1 -0
  144. package/dist/src/services/environmentSanitization.test.d.ts +6 -0
  145. package/dist/src/services/environmentSanitization.test.js +284 -0
  146. package/dist/src/services/environmentSanitization.test.js.map +1 -0
  147. package/dist/src/services/gitService.js +10 -1
  148. package/dist/src/services/gitService.js.map +1 -1
  149. package/dist/src/services/gitService.test.js +18 -0
  150. package/dist/src/services/gitService.test.js.map +1 -1
  151. package/dist/src/services/shellExecutionService.d.ts +2 -0
  152. package/dist/src/services/shellExecutionService.js +5 -65
  153. package/dist/src/services/shellExecutionService.js.map +1 -1
  154. package/dist/src/services/shellExecutionService.test.js +26 -3
  155. package/dist/src/services/shellExecutionService.test.js.map +1 -1
  156. package/dist/src/services/skillManager.d.ts +61 -0
  157. package/dist/src/services/skillManager.js +157 -0
  158. package/dist/src/services/skillManager.js.map +1 -0
  159. package/dist/src/services/skillManager.test.d.ts +6 -0
  160. package/dist/src/services/skillManager.test.js +169 -0
  161. package/dist/src/services/skillManager.test.js.map +1 -0
  162. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +4 -6
  163. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
  164. package/dist/src/telemetry/loggers.test.circular.js +1 -0
  165. package/dist/src/telemetry/loggers.test.circular.js.map +1 -1
  166. package/dist/src/telemetry/sdk.js +3 -4
  167. package/dist/src/telemetry/sdk.js.map +1 -1
  168. package/dist/src/tools/edit.test.js +1 -1
  169. package/dist/src/tools/edit.test.js.map +1 -1
  170. package/dist/src/tools/mcp-client.d.ts +3 -2
  171. package/dist/src/tools/mcp-client.js +7 -6
  172. package/dist/src/tools/mcp-client.js.map +1 -1
  173. package/dist/src/tools/mcp-client.test.js +47 -42
  174. package/dist/src/tools/mcp-client.test.js.map +1 -1
  175. package/dist/src/tools/memoryTool.js +0 -2
  176. package/dist/src/tools/memoryTool.js.map +1 -1
  177. package/dist/src/tools/shell.js +6 -1
  178. package/dist/src/tools/shell.js.map +1 -1
  179. package/dist/src/tools/smart-edit.test.js +1 -1
  180. package/dist/src/tools/smart-edit.test.js.map +1 -1
  181. package/dist/src/tools/tool-error.d.ts +2 -1
  182. package/dist/src/tools/tool-error.js +2 -0
  183. package/dist/src/tools/tool-error.js.map +1 -1
  184. package/dist/src/tools/tool-registry.js +1 -1
  185. package/dist/src/tools/tool-registry.js.map +1 -1
  186. package/dist/src/tools/tools.d.ts +1 -1
  187. package/dist/src/tools/tools.js +1 -1
  188. package/dist/src/tools/web-search.js +2 -1
  189. package/dist/src/tools/web-search.js.map +1 -1
  190. package/dist/src/tools/write-file.js +2 -1
  191. package/dist/src/tools/write-file.js.map +1 -1
  192. package/dist/src/utils/checkpointUtils.d.ts +1 -1
  193. package/dist/src/utils/debugLogger.js +1 -0
  194. package/dist/src/utils/debugLogger.js.map +1 -1
  195. package/dist/src/utils/editCorrector.js +5 -4
  196. package/dist/src/utils/editCorrector.js.map +1 -1
  197. package/dist/src/utils/errorReporting.d.ts +1 -1
  198. package/dist/src/utils/errorReporting.js +13 -12
  199. package/dist/src/utils/errorReporting.js.map +1 -1
  200. package/dist/src/utils/errorReporting.test.js +17 -14
  201. package/dist/src/utils/errorReporting.test.js.map +1 -1
  202. package/dist/src/utils/fileUtils.d.ts +4 -0
  203. package/dist/src/utils/fileUtils.js +53 -0
  204. package/dist/src/utils/fileUtils.js.map +1 -1
  205. package/dist/src/utils/fileUtils.test.js +112 -1
  206. package/dist/src/utils/fileUtils.test.js.map +1 -1
  207. package/dist/src/utils/generateContentResponseUtilities.d.ts +2 -1
  208. package/dist/src/utils/generateContentResponseUtilities.js +96 -0
  209. package/dist/src/utils/generateContentResponseUtilities.js.map +1 -1
  210. package/dist/src/utils/generateContentResponseUtilities.test.js +221 -1
  211. package/dist/src/utils/generateContentResponseUtilities.test.js.map +1 -1
  212. package/dist/src/utils/getFolderStructure.js +1 -1
  213. package/dist/src/utils/getFolderStructure.js.map +1 -1
  214. package/dist/src/utils/memoryDiscovery.js +1 -1
  215. package/dist/src/utils/memoryDiscovery.js.map +1 -1
  216. package/dist/src/utils/retry.js +3 -3
  217. package/dist/src/utils/retry.js.map +1 -1
  218. package/dist/src/utils/summarizer.test.js +3 -2
  219. package/dist/src/utils/summarizer.test.js.map +1 -1
  220. package/dist/src/utils/terminal.d.ts +2 -0
  221. package/dist/src/utils/terminal.js +6 -0
  222. package/dist/src/utils/terminal.js.map +1 -1
  223. package/dist/src/utils/tool-utils.d.ts +9 -0
  224. package/dist/src/utils/tool-utils.js +29 -0
  225. package/dist/src/utils/tool-utils.js.map +1 -1
  226. package/dist/src/utils/tool-utils.test.js +15 -1
  227. package/dist/src/utils/tool-utils.test.js.map +1 -1
  228. package/dist/tsconfig.tsbuildinfo +1 -1
  229. package/package.json +5 -1
  230. package/dist/google-gemini-cli-core-0.23.0-preview.3.tgz +0 -0
@@ -0,0 +1,189 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
7
+ import { executeToolWithHooks } from './coreToolHookTriggers.js';
8
+ import { ToolErrorType } from '../tools/tool-error.js';
9
+ import { BaseToolInvocation, } from '../tools/tools.js';
10
+ import { MessageBusType, } from '../confirmation-bus/types.js';
11
+ class MockInvocation extends BaseToolInvocation {
12
+ constructor(params) {
13
+ super(params);
14
+ }
15
+ getDescription() {
16
+ return 'mock';
17
+ }
18
+ async execute() {
19
+ return {
20
+ llmContent: this.params.key ? `key: ${this.params.key}` : 'success',
21
+ returnDisplay: this.params.key
22
+ ? `key: ${this.params.key}`
23
+ : 'success display',
24
+ };
25
+ }
26
+ }
27
+ describe('executeToolWithHooks', () => {
28
+ let messageBus;
29
+ let mockTool;
30
+ beforeEach(() => {
31
+ messageBus = {
32
+ request: vi.fn(),
33
+ publish: vi.fn(),
34
+ subscribe: vi.fn(),
35
+ unsubscribe: vi.fn(),
36
+ };
37
+ mockTool = {
38
+ build: vi.fn().mockImplementation((params) => new MockInvocation(params)),
39
+ };
40
+ });
41
+ it('should prioritize continue: false over decision: block in BeforeTool', async () => {
42
+ const invocation = new MockInvocation({});
43
+ const abortSignal = new AbortController().signal;
44
+ vi.mocked(messageBus.request).mockResolvedValue({
45
+ type: MessageBusType.HOOK_EXECUTION_RESPONSE,
46
+ correlationId: 'test-id',
47
+ success: true,
48
+ output: {
49
+ continue: false,
50
+ stopReason: 'Stop immediately',
51
+ decision: 'block',
52
+ reason: 'Should be ignored because continue is false',
53
+ },
54
+ });
55
+ const result = await executeToolWithHooks(invocation, 'test_tool', abortSignal, messageBus, true, mockTool);
56
+ expect(result.error?.type).toBe(ToolErrorType.STOP_EXECUTION);
57
+ expect(result.error?.message).toBe('Stop immediately');
58
+ });
59
+ it('should block execution in BeforeTool if decision is block', async () => {
60
+ const invocation = new MockInvocation({});
61
+ const abortSignal = new AbortController().signal;
62
+ vi.mocked(messageBus.request).mockResolvedValue({
63
+ type: MessageBusType.HOOK_EXECUTION_RESPONSE,
64
+ correlationId: 'test-id',
65
+ success: true,
66
+ output: {
67
+ decision: 'block',
68
+ reason: 'Execution blocked',
69
+ },
70
+ });
71
+ const result = await executeToolWithHooks(invocation, 'test_tool', abortSignal, messageBus, true, mockTool);
72
+ expect(result.error?.type).toBe(ToolErrorType.EXECUTION_FAILED);
73
+ expect(result.error?.message).toBe('Execution blocked');
74
+ });
75
+ it('should handle continue: false in AfterTool', async () => {
76
+ const invocation = new MockInvocation({});
77
+ const abortSignal = new AbortController().signal;
78
+ const spy = vi.spyOn(invocation, 'execute');
79
+ // BeforeTool allow
80
+ vi.mocked(messageBus.request)
81
+ .mockResolvedValueOnce({
82
+ type: MessageBusType.HOOK_EXECUTION_RESPONSE,
83
+ correlationId: 'test-id',
84
+ success: true,
85
+ output: { decision: 'allow' },
86
+ })
87
+ // AfterTool stop
88
+ .mockResolvedValueOnce({
89
+ type: MessageBusType.HOOK_EXECUTION_RESPONSE,
90
+ correlationId: 'test-id',
91
+ success: true,
92
+ output: {
93
+ continue: false,
94
+ stopReason: 'Stop after execution',
95
+ },
96
+ });
97
+ const result = await executeToolWithHooks(invocation, 'test_tool', abortSignal, messageBus, true, mockTool);
98
+ expect(result.error?.type).toBe(ToolErrorType.STOP_EXECUTION);
99
+ expect(result.error?.message).toBe('Stop after execution');
100
+ expect(spy).toHaveBeenCalled();
101
+ });
102
+ it('should block result in AfterTool if decision is deny', async () => {
103
+ const invocation = new MockInvocation({});
104
+ const abortSignal = new AbortController().signal;
105
+ // BeforeTool allow
106
+ vi.mocked(messageBus.request)
107
+ .mockResolvedValueOnce({
108
+ type: MessageBusType.HOOK_EXECUTION_RESPONSE,
109
+ correlationId: 'test-id',
110
+ success: true,
111
+ output: { decision: 'allow' },
112
+ })
113
+ // AfterTool deny
114
+ .mockResolvedValueOnce({
115
+ type: MessageBusType.HOOK_EXECUTION_RESPONSE,
116
+ correlationId: 'test-id',
117
+ success: true,
118
+ output: {
119
+ decision: 'deny',
120
+ reason: 'Result denied',
121
+ },
122
+ });
123
+ const result = await executeToolWithHooks(invocation, 'test_tool', abortSignal, messageBus, true, mockTool);
124
+ expect(result.error?.type).toBe(ToolErrorType.EXECUTION_FAILED);
125
+ expect(result.error?.message).toBe('Result denied');
126
+ });
127
+ it('should apply modified tool input from BeforeTool hook', async () => {
128
+ const params = { key: 'original' };
129
+ const invocation = new MockInvocation(params);
130
+ const toolName = 'test-tool';
131
+ const abortSignal = new AbortController().signal;
132
+ // Capture arguments to verify what was passed before modification
133
+ const requestSpy = vi.fn().mockImplementation(async (request) => {
134
+ if (request.eventName === 'BeforeTool') {
135
+ // Verify input is original before we return modification instruction
136
+ expect(request.input.tool_input.key).toBe('original');
137
+ return {
138
+ type: MessageBusType.HOOK_EXECUTION_RESPONSE,
139
+ correlationId: 'test-id',
140
+ success: true,
141
+ output: {
142
+ hookSpecificOutput: {
143
+ hookEventName: 'BeforeTool',
144
+ tool_input: { key: 'modified' },
145
+ },
146
+ },
147
+ };
148
+ }
149
+ return {
150
+ type: MessageBusType.HOOK_EXECUTION_RESPONSE,
151
+ correlationId: 'test-id',
152
+ success: true,
153
+ output: {},
154
+ };
155
+ });
156
+ messageBus.request = requestSpy;
157
+ const result = await executeToolWithHooks(invocation, toolName, abortSignal, messageBus, true, // hooksEnabled
158
+ mockTool);
159
+ // Verify result reflects modified input
160
+ expect(result.llmContent).toBe('key: modified\n\n[System] Tool input parameters (key) were modified by a hook before execution.');
161
+ // Verify params object was modified in place
162
+ expect(invocation.params.key).toBe('modified');
163
+ expect(requestSpy).toHaveBeenCalled();
164
+ expect(mockTool.build).toHaveBeenCalledWith({ key: 'modified' });
165
+ });
166
+ it('should not modify input if hook does not provide tool_input', async () => {
167
+ const params = { key: 'original' };
168
+ const invocation = new MockInvocation(params);
169
+ const toolName = 'test-tool';
170
+ const abortSignal = new AbortController().signal;
171
+ vi.mocked(messageBus.request).mockResolvedValue({
172
+ type: MessageBusType.HOOK_EXECUTION_RESPONSE,
173
+ correlationId: 'test-id',
174
+ success: true,
175
+ output: {
176
+ hookSpecificOutput: {
177
+ hookEventName: 'BeforeTool',
178
+ // No tool_input
179
+ },
180
+ },
181
+ });
182
+ const result = await executeToolWithHooks(invocation, toolName, abortSignal, messageBus, true, // hooksEnabled
183
+ mockTool);
184
+ expect(result.llmContent).toBe('key: original');
185
+ expect(invocation.params.key).toBe('original');
186
+ expect(mockTool.build).not.toHaveBeenCalled();
187
+ });
188
+ });
189
+ //# sourceMappingURL=coreToolHookTriggers.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coreToolHookTriggers.test.js","sourceRoot":"","sources":["../../../src/core/coreToolHookTriggers.test.ts"],"names":[],"mappings":"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"}
@@ -3,82 +3,11 @@
3
3
  * Copyright 2025 Google LLC
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
- import type { ToolCallRequestInfo, ToolCallResponseInfo, ToolCallConfirmationDetails, EditorType, Config, ToolConfirmationPayload, AnyDeclarativeTool, AnyToolInvocation, AnsiOutput } from '../index.js';
7
- import { ToolConfirmationOutcome } from '../index.js';
8
- import type { Part, PartListUnion } from '@google/genai';
9
- export type ValidatingToolCall = {
10
- status: 'validating';
11
- request: ToolCallRequestInfo;
12
- tool: AnyDeclarativeTool;
13
- invocation: AnyToolInvocation;
14
- startTime?: number;
15
- outcome?: ToolConfirmationOutcome;
16
- };
17
- export type ScheduledToolCall = {
18
- status: 'scheduled';
19
- request: ToolCallRequestInfo;
20
- tool: AnyDeclarativeTool;
21
- invocation: AnyToolInvocation;
22
- startTime?: number;
23
- outcome?: ToolConfirmationOutcome;
24
- };
25
- export type ErroredToolCall = {
26
- status: 'error';
27
- request: ToolCallRequestInfo;
28
- response: ToolCallResponseInfo;
29
- tool?: AnyDeclarativeTool;
30
- durationMs?: number;
31
- outcome?: ToolConfirmationOutcome;
32
- };
33
- export type SuccessfulToolCall = {
34
- status: 'success';
35
- request: ToolCallRequestInfo;
36
- tool: AnyDeclarativeTool;
37
- response: ToolCallResponseInfo;
38
- invocation: AnyToolInvocation;
39
- durationMs?: number;
40
- outcome?: ToolConfirmationOutcome;
41
- };
42
- export type ExecutingToolCall = {
43
- status: 'executing';
44
- request: ToolCallRequestInfo;
45
- tool: AnyDeclarativeTool;
46
- invocation: AnyToolInvocation;
47
- liveOutput?: string | AnsiOutput;
48
- startTime?: number;
49
- outcome?: ToolConfirmationOutcome;
50
- pid?: number;
51
- };
52
- export type CancelledToolCall = {
53
- status: 'cancelled';
54
- request: ToolCallRequestInfo;
55
- response: ToolCallResponseInfo;
56
- tool: AnyDeclarativeTool;
57
- invocation: AnyToolInvocation;
58
- durationMs?: number;
59
- outcome?: ToolConfirmationOutcome;
60
- };
61
- export type WaitingToolCall = {
62
- status: 'awaiting_approval';
63
- request: ToolCallRequestInfo;
64
- tool: AnyDeclarativeTool;
65
- invocation: AnyToolInvocation;
66
- confirmationDetails: ToolCallConfirmationDetails;
67
- startTime?: number;
68
- outcome?: ToolConfirmationOutcome;
69
- };
70
- export type Status = ToolCall['status'];
71
- export type ToolCall = ValidatingToolCall | ScheduledToolCall | ErroredToolCall | SuccessfulToolCall | ExecutingToolCall | CancelledToolCall | WaitingToolCall;
72
- export type CompletedToolCall = SuccessfulToolCall | CancelledToolCall | ErroredToolCall;
73
- export type ConfirmHandler = (toolCall: WaitingToolCall) => Promise<ToolConfirmationOutcome>;
74
- export type OutputUpdateHandler = (toolCallId: string, outputChunk: string | AnsiOutput) => void;
75
- export type AllToolCallsCompleteHandler = (completedToolCalls: CompletedToolCall[]) => Promise<void>;
76
- export type ToolCallsUpdateHandler = (toolCalls: ToolCall[]) => void;
77
- export declare function convertToFunctionResponse(toolName: string, callId: string, llmContent: PartListUnion, model: string): Part[];
78
- export declare function truncateAndSaveToFile(content: string, callId: string, projectTempDir: string, threshold: number, truncateLines: number): Promise<{
79
- content: string;
80
- outputFile?: string;
81
- }>;
6
+ import { type ToolConfirmationPayload, ToolConfirmationOutcome } from '../tools/tools.js';
7
+ import type { EditorType } from '../utils/editor.js';
8
+ import type { Config } from '../config/config.js';
9
+ import { type ToolCall, type ValidatingToolCall, type ScheduledToolCall, type ErroredToolCall, type SuccessfulToolCall, type ExecutingToolCall, type CancelledToolCall, type WaitingToolCall, type Status, type CompletedToolCall, type ConfirmHandler, type OutputUpdateHandler, type AllToolCallsCompleteHandler, type ToolCallsUpdateHandler, type ToolCallRequestInfo, type ToolCallResponseInfo } from '../scheduler/types.js';
10
+ export type { ToolCall, ValidatingToolCall, ScheduledToolCall, ErroredToolCall, SuccessfulToolCall, ExecutingToolCall, CancelledToolCall, WaitingToolCall, Status, CompletedToolCall, ConfirmHandler, OutputUpdateHandler, AllToolCallsCompleteHandler, ToolCallsUpdateHandler, ToolCallRequestInfo, ToolCallResponseInfo, };
82
11
  interface CoreToolSchedulerOptions {
83
12
  config: Config;
84
13
  outputUpdateHandler?: OutputUpdateHandler;
@@ -105,14 +34,6 @@ export declare class CoreToolScheduler {
105
34
  private setArgsInternal;
106
35
  private isRunning;
107
36
  private buildInvocation;
108
- /**
109
- * Generates a suggestion string for a tool name that was not found in the registry.
110
- * It finds the closest matches based on Levenshtein distance.
111
- * @param unknownToolName The tool name that was not found.
112
- * @param topN The number of suggestions to return. Defaults to 3.
113
- * @returns A suggestion string like " Did you mean 'tool'?" or " Did you mean one of: 'tool1', 'tool2'?", or an empty string if no suggestions are found.
114
- */
115
- private getToolSuggestion;
116
37
  schedule(request: ToolCallRequestInfo | ToolCallRequestInfo[], signal: AbortSignal): Promise<void>;
117
38
  cancelAll(signal: AbortSignal): void;
118
39
  private _schedule;
@@ -132,4 +53,3 @@ export declare class CoreToolScheduler {
132
53
  private setToolCallOutcome;
133
54
  private isAutoApproved;
134
55
  }
135
- export {};
@@ -3,115 +3,24 @@
3
3
  * Copyright 2025 Google LLC
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
- import { ToolConfirmationOutcome, ApprovalMode, logToolCall, ToolErrorType, ToolCallEvent, logToolOutputTruncated, ToolOutputTruncatedEvent, runInDevTraceSpan, } from '../index.js';
7
- import { READ_FILE_TOOL_NAME, SHELL_TOOL_NAME } from '../tools/tool-names.js';
8
- import { supportsMultimodalFunctionResponse } from '../config/models.js';
6
+ import { ToolConfirmationOutcome, } from '../tools/tools.js';
7
+ import { ApprovalMode } from '../policy/types.js';
8
+ import { logToolCall, logToolOutputTruncated } from '../telemetry/loggers.js';
9
+ import { ToolErrorType } from '../tools/tool-error.js';
10
+ import { ToolCallEvent, ToolOutputTruncatedEvent } from '../telemetry/types.js';
11
+ import { runInDevTraceSpan } from '../telemetry/trace.js';
12
+ import { SHELL_TOOL_NAME } from '../tools/tool-names.js';
9
13
  import { isModifiableDeclarativeTool, modifyWithEditor, } from '../tools/modifiable-tool.js';
10
14
  import * as Diff from 'diff';
11
- import * as fs from 'node:fs/promises';
12
- import * as path from 'node:path';
13
15
  import { SHELL_TOOL_NAMES } from '../utils/shell-utils.js';
14
- import { doesToolInvocationMatch } from '../utils/tool-utils.js';
16
+ import { doesToolInvocationMatch, getToolSuggestion, } from '../utils/tool-utils.js';
15
17
  import { isShellInvocationAllowlisted } from '../utils/shell-permissions.js';
16
- import levenshtein from 'fast-levenshtein';
17
18
  import { ShellToolInvocation } from '../tools/shell.js';
18
19
  import { MessageBusType } from '../confirmation-bus/types.js';
19
20
  import { fireToolNotificationHook, executeToolWithHooks, } from './coreToolHookTriggers.js';
20
- import { debugLogger } from '../utils/debugLogger.js';
21
- /**
22
- * Formats tool output for a Gemini FunctionResponse.
23
- */
24
- function createFunctionResponsePart(callId, toolName, output) {
25
- return {
26
- functionResponse: {
27
- id: callId,
28
- name: toolName,
29
- response: { output },
30
- },
31
- };
32
- }
33
- export function convertToFunctionResponse(toolName, callId, llmContent, model) {
34
- if (typeof llmContent === 'string') {
35
- return [createFunctionResponsePart(callId, toolName, llmContent)];
36
- }
37
- const parts = toParts(llmContent);
38
- // Separate text from binary types
39
- const textParts = [];
40
- const inlineDataParts = [];
41
- const fileDataParts = [];
42
- for (const part of parts) {
43
- if (part.text !== undefined) {
44
- textParts.push(part.text);
45
- }
46
- else if (part.inlineData) {
47
- inlineDataParts.push(part);
48
- }
49
- else if (part.fileData) {
50
- fileDataParts.push(part);
51
- }
52
- else if (part.functionResponse) {
53
- if (parts.length > 1) {
54
- debugLogger.warn('convertToFunctionResponse received multiple parts with a functionResponse. Only the functionResponse will be used, other parts will be ignored');
55
- }
56
- // Handle passthrough case
57
- return [
58
- {
59
- functionResponse: {
60
- id: callId,
61
- name: toolName,
62
- response: part.functionResponse.response,
63
- },
64
- },
65
- ];
66
- }
67
- // Ignore other part types
68
- }
69
- // Build the primary response part
70
- const part = {
71
- functionResponse: {
72
- id: callId,
73
- name: toolName,
74
- response: textParts.length > 0 ? { output: textParts.join('\n') } : {},
75
- },
76
- };
77
- const isMultimodalFRSupported = supportsMultimodalFunctionResponse(model);
78
- const siblingParts = [...fileDataParts];
79
- if (inlineDataParts.length > 0) {
80
- if (isMultimodalFRSupported) {
81
- // Nest inlineData if supported by the model
82
- part.functionResponse.parts =
83
- inlineDataParts;
84
- }
85
- else {
86
- // Otherwise treat as siblings
87
- siblingParts.push(...inlineDataParts);
88
- }
89
- }
90
- // Add descriptive text if the response object is empty but we have binary content
91
- if (textParts.length === 0 &&
92
- (inlineDataParts.length > 0 || fileDataParts.length > 0)) {
93
- const totalBinaryItems = inlineDataParts.length + fileDataParts.length;
94
- part.functionResponse.response = {
95
- output: `Binary content provided (${totalBinaryItems} item(s)).`,
96
- };
97
- }
98
- if (siblingParts.length > 0) {
99
- return [part, ...siblingParts];
100
- }
101
- return [part];
102
- }
103
- function toParts(input) {
104
- const parts = [];
105
- for (const part of Array.isArray(input) ? input : [input]) {
106
- if (typeof part === 'string') {
107
- parts.push({ text: part });
108
- }
109
- else if (part) {
110
- parts.push(part);
111
- }
112
- }
113
- return parts;
114
- }
21
+ import {} from '../scheduler/types.js';
22
+ import { saveTruncatedContent } from '../utils/fileUtils.js';
23
+ import { convertToFunctionResponse } from '../utils/generateContentResponseUtilities.js';
115
24
  const createErrorResponse = (request, error, errorType) => ({
116
25
  callId: request.callId,
117
26
  error,
@@ -128,58 +37,6 @@ const createErrorResponse = (request, error, errorType) => ({
128
37
  errorType,
129
38
  contentLength: error.message.length,
130
39
  });
131
- export async function truncateAndSaveToFile(content, callId, projectTempDir, threshold, truncateLines) {
132
- if (content.length <= threshold) {
133
- return { content };
134
- }
135
- let lines = content.split('\n');
136
- let fileContent = content;
137
- // If the content is long but has few lines, wrap it to enable line-based truncation.
138
- if (lines.length <= truncateLines) {
139
- const wrapWidth = 120; // A reasonable width for wrapping.
140
- const wrappedLines = [];
141
- for (const line of lines) {
142
- if (line.length > wrapWidth) {
143
- for (let i = 0; i < line.length; i += wrapWidth) {
144
- wrappedLines.push(line.substring(i, i + wrapWidth));
145
- }
146
- }
147
- else {
148
- wrappedLines.push(line);
149
- }
150
- }
151
- lines = wrappedLines;
152
- fileContent = lines.join('\n');
153
- }
154
- const head = Math.floor(truncateLines / 5);
155
- const beginning = lines.slice(0, head);
156
- const end = lines.slice(-(truncateLines - head));
157
- const truncatedContent = beginning.join('\n') + '\n... [CONTENT TRUNCATED] ...\n' + end.join('\n');
158
- // Sanitize callId to prevent path traversal.
159
- const safeFileName = `${path.basename(callId)}.output`;
160
- const outputFile = path.join(projectTempDir, safeFileName);
161
- try {
162
- await fs.writeFile(outputFile, fileContent);
163
- return {
164
- content: `Tool output was too large and has been truncated.
165
- The full output has been saved to: ${outputFile}
166
- To read the complete output, use the ${READ_FILE_TOOL_NAME} tool with the absolute file path above. For large files, you can use the offset and limit parameters to read specific sections:
167
- - ${READ_FILE_TOOL_NAME} tool with offset=0, limit=100 to see the first 100 lines
168
- - ${READ_FILE_TOOL_NAME} tool with offset=N to skip N lines from the beginning
169
- - ${READ_FILE_TOOL_NAME} tool with limit=M to read only M lines at a time
170
- The truncated output below shows the beginning and end of the content. The marker '... [CONTENT TRUNCATED] ...' indicates where content was removed.
171
- This allows you to efficiently examine different parts of the output without loading the entire file.
172
- Truncated part of the output:
173
- ${truncatedContent}`,
174
- outputFile,
175
- };
176
- }
177
- catch (_error) {
178
- return {
179
- content: truncatedContent + `\n[Note: Could not save full output to file]`,
180
- };
181
- }
182
- }
183
40
  export class CoreToolScheduler {
184
41
  // Static WeakMap to track which MessageBus instances already have a handler subscribed
185
42
  // This prevents duplicate subscriptions when multiple CoreToolScheduler instances are created
@@ -206,26 +63,24 @@ export class CoreToolScheduler {
206
63
  // Use a static WeakMap to ensure we only subscribe ONCE per MessageBus instance
207
64
  // This prevents memory leaks when multiple CoreToolScheduler instances are created
208
65
  // (e.g., on every React render, or for each non-interactive tool call)
209
- if (this.config.getEnableMessageBusIntegration()) {
210
- const messageBus = this.config.getMessageBus();
211
- // Check if we've already subscribed a handler to this message bus
212
- if (!CoreToolScheduler.subscribedMessageBuses.has(messageBus)) {
213
- // Create a shared handler that will be used for this message bus
214
- const sharedHandler = (request) => {
215
- // When ASK_USER policy decision is made, respond with requiresUserConfirmation=true
216
- // to tell tools to use their legacy confirmation flow
217
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
218
- messageBus.publish({
219
- type: MessageBusType.TOOL_CONFIRMATION_RESPONSE,
220
- correlationId: request.correlationId,
221
- confirmed: false,
222
- requiresUserConfirmation: true,
223
- });
224
- };
225
- messageBus.subscribe(MessageBusType.TOOL_CONFIRMATION_REQUEST, sharedHandler);
226
- // Store the handler in the WeakMap so we don't subscribe again
227
- CoreToolScheduler.subscribedMessageBuses.set(messageBus, sharedHandler);
228
- }
66
+ const messageBus = this.config.getMessageBus();
67
+ // Check if we've already subscribed a handler to this message bus
68
+ if (!CoreToolScheduler.subscribedMessageBuses.has(messageBus)) {
69
+ // Create a shared handler that will be used for this message bus
70
+ const sharedHandler = (request) => {
71
+ // When ASK_USER policy decision is made, respond with requiresUserConfirmation=true
72
+ // to tell tools to use their legacy confirmation flow
73
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
74
+ messageBus.publish({
75
+ type: MessageBusType.TOOL_CONFIRMATION_RESPONSE,
76
+ correlationId: request.correlationId,
77
+ confirmed: false,
78
+ requiresUserConfirmation: true,
79
+ });
80
+ };
81
+ messageBus.subscribe(MessageBusType.TOOL_CONFIRMATION_REQUEST, sharedHandler);
82
+ // Store the handler in the WeakMap so we don't subscribe again
83
+ CoreToolScheduler.subscribedMessageBuses.set(messageBus, sharedHandler);
229
84
  }
230
85
  }
231
86
  setStatusInternal(targetCallId, newStatus, signal, auxiliaryData) {
@@ -398,34 +253,6 @@ export class CoreToolScheduler {
398
253
  return new Error(String(e));
399
254
  }
400
255
  }
401
- /**
402
- * Generates a suggestion string for a tool name that was not found in the registry.
403
- * It finds the closest matches based on Levenshtein distance.
404
- * @param unknownToolName The tool name that was not found.
405
- * @param topN The number of suggestions to return. Defaults to 3.
406
- * @returns A suggestion string like " Did you mean 'tool'?" or " Did you mean one of: 'tool1', 'tool2'?", or an empty string if no suggestions are found.
407
- */
408
- getToolSuggestion(unknownToolName, topN = 3) {
409
- const allToolNames = this.config.getToolRegistry().getAllToolNames();
410
- const matches = allToolNames.map((toolName) => ({
411
- name: toolName,
412
- distance: levenshtein.get(unknownToolName, toolName),
413
- }));
414
- matches.sort((a, b) => a.distance - b.distance);
415
- const topNResults = matches.slice(0, topN);
416
- if (topNResults.length === 0) {
417
- return '';
418
- }
419
- const suggestedNames = topNResults
420
- .map((match) => `"${match.name}"`)
421
- .join(', ');
422
- if (topNResults.length > 1) {
423
- return ` Did you mean one of: ${suggestedNames}?`;
424
- }
425
- else {
426
- return ` Did you mean ${suggestedNames}?`;
427
- }
428
- }
429
256
  schedule(request, signal) {
430
257
  return runInDevTraceSpan({ name: 'schedule' }, async ({ metadata: spanMetadata }) => {
431
258
  spanMetadata.input = request;
@@ -492,7 +319,7 @@ export class CoreToolScheduler {
492
319
  .getToolRegistry()
493
320
  .getTool(reqInfo.name);
494
321
  if (!toolInstance) {
495
- const suggestion = this.getToolSuggestion(reqInfo.name);
322
+ const suggestion = getToolSuggestion(reqInfo.name, this.config.getToolRegistry().getAllToolNames());
496
323
  const errorMessage = `Tool "${reqInfo.name}" not found in registry. Tools must use the exact names that are registered.${suggestion}`;
497
324
  return {
498
325
  status: 'error',
@@ -731,10 +558,10 @@ export class CoreToolScheduler {
731
558
  : tc);
732
559
  this.notifyToolCallsUpdate();
733
560
  };
734
- promise = executeToolWithHooks(invocation, toolName, signal, messageBus, hooksEnabled, liveOutputCallback, shellExecutionConfig, setPidCallback);
561
+ promise = executeToolWithHooks(invocation, toolName, signal, messageBus, hooksEnabled, toolCall.tool, liveOutputCallback, shellExecutionConfig, setPidCallback);
735
562
  }
736
563
  else {
737
- promise = executeToolWithHooks(invocation, toolName, signal, messageBus, hooksEnabled, liveOutputCallback, shellExecutionConfig);
564
+ promise = executeToolWithHooks(invocation, toolName, signal, messageBus, hooksEnabled, toolCall.tool, liveOutputCallback, shellExecutionConfig);
738
565
  }
739
566
  try {
740
567
  const toolResult = await promise;
@@ -754,7 +581,7 @@ export class CoreToolScheduler {
754
581
  const originalContentLength = content.length;
755
582
  const threshold = this.config.getTruncateToolOutputThreshold();
756
583
  const lines = this.config.getTruncateToolOutputLines();
757
- const truncatedResult = await truncateAndSaveToFile(content, callId, this.config.storage.getProjectTempDir(), threshold, lines);
584
+ const truncatedResult = await saveTruncatedContent(content, callId, this.config.storage.getProjectTempDir(), threshold, lines);
758
585
  content = truncatedResult.content;
759
586
  outputFile = truncatedResult.outputFile;
760
587
  if (outputFile) {