@google/gemini-cli-core 0.24.0-nightly.20260103.30f5c4af4 → 0.24.0-preview.1

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 (298) hide show
  1. package/dist/docs/cli/settings.md +1 -0
  2. package/dist/docs/cli/skills.md +156 -0
  3. package/dist/docs/cli/telemetry.md +3 -3
  4. package/dist/docs/cli/tutorials/skills-getting-started.md +124 -0
  5. package/dist/docs/cli/tutorials.md +4 -0
  6. package/dist/docs/get-started/configuration.md +32 -5
  7. package/dist/docs/sidebar.json +4 -0
  8. package/dist/google-gemini-cli-core-0.24.0-preview.0.tgz +0 -0
  9. package/dist/src/agents/a2a-client-manager.d.ts +5 -0
  10. package/dist/src/agents/a2a-client-manager.js +130 -0
  11. package/dist/src/agents/a2a-client-manager.js.map +1 -1
  12. package/dist/src/agents/a2a-client-manager.test.js +27 -1
  13. package/dist/src/agents/a2a-client-manager.test.js.map +1 -1
  14. package/dist/src/agents/a2aUtils.d.ts +28 -0
  15. package/dist/src/agents/a2aUtils.js +111 -0
  16. package/dist/src/agents/a2aUtils.js.map +1 -0
  17. package/dist/src/agents/a2aUtils.test.js +147 -0
  18. package/dist/src/agents/a2aUtils.test.js.map +1 -0
  19. package/dist/src/agents/delegate-to-agent-tool.d.ts +2 -2
  20. package/dist/src/agents/delegate-to-agent-tool.js +6 -6
  21. package/dist/src/agents/delegate-to-agent-tool.js.map +1 -1
  22. package/dist/src/agents/delegate-to-agent-tool.test.js +37 -7
  23. package/dist/src/agents/delegate-to-agent-tool.test.js.map +1 -1
  24. package/dist/src/agents/introspection-agent.js +2 -2
  25. package/dist/src/agents/introspection-agent.js.map +1 -1
  26. package/dist/src/agents/introspection-agent.test.js +2 -2
  27. package/dist/src/agents/introspection-agent.test.js.map +1 -1
  28. package/dist/src/agents/local-executor.js +1 -1
  29. package/dist/src/agents/local-executor.js.map +1 -1
  30. package/dist/src/agents/local-executor.test.js +2 -2
  31. package/dist/src/agents/local-executor.test.js.map +1 -1
  32. package/dist/src/agents/local-invocation.d.ts +2 -2
  33. package/dist/src/agents/local-invocation.js +3 -3
  34. package/dist/src/agents/local-invocation.js.map +1 -1
  35. package/dist/src/agents/local-invocation.test.js +7 -5
  36. package/dist/src/agents/local-invocation.test.js.map +1 -1
  37. package/dist/src/agents/remote-invocation.d.ts +17 -3
  38. package/dist/src/agents/remote-invocation.js +104 -6
  39. package/dist/src/agents/remote-invocation.js.map +1 -1
  40. package/dist/src/agents/remote-invocation.test.js +184 -18
  41. package/dist/src/agents/remote-invocation.test.js.map +1 -1
  42. package/dist/src/agents/subagent-tool-wrapper.d.ts +2 -2
  43. package/dist/src/agents/subagent-tool-wrapper.js +6 -5
  44. package/dist/src/agents/subagent-tool-wrapper.js.map +1 -1
  45. package/dist/src/agents/subagent-tool-wrapper.test.js +17 -10
  46. package/dist/src/agents/subagent-tool-wrapper.test.js.map +1 -1
  47. package/dist/src/agents/types.d.ts +6 -0
  48. package/dist/src/code_assist/oauth2.js +31 -1
  49. package/dist/src/code_assist/oauth2.js.map +1 -1
  50. package/dist/src/code_assist/oauth2.test.js +75 -3
  51. package/dist/src/code_assist/oauth2.test.js.map +1 -1
  52. package/dist/src/code_assist/server.d.ts +5 -0
  53. package/dist/src/code_assist/server.js +19 -4
  54. package/dist/src/code_assist/server.js.map +1 -1
  55. package/dist/src/code_assist/server.test.js +19 -0
  56. package/dist/src/code_assist/server.test.js.map +1 -1
  57. package/dist/src/code_assist/setup.js +6 -4
  58. package/dist/src/code_assist/setup.js.map +1 -1
  59. package/dist/src/code_assist/setup.test.js +63 -0
  60. package/dist/src/code_assist/setup.test.js.map +1 -1
  61. package/dist/src/code_assist/types.d.ts +18 -0
  62. package/dist/src/config/config.d.ts +19 -3
  63. package/dist/src/config/config.js +49 -25
  64. package/dist/src/config/config.js.map +1 -1
  65. package/dist/src/config/config.test.js +81 -4
  66. package/dist/src/config/config.test.js.map +1 -1
  67. package/dist/src/config/models.js +6 -4
  68. package/dist/src/config/models.js.map +1 -1
  69. package/dist/src/config/models.test.js +21 -1
  70. package/dist/src/config/models.test.js.map +1 -1
  71. package/dist/src/core/client.js +39 -7
  72. package/dist/src/core/client.js.map +1 -1
  73. package/dist/src/core/client.test.js +93 -0
  74. package/dist/src/core/client.test.js.map +1 -1
  75. package/dist/src/core/contentGenerator.js +1 -1
  76. package/dist/src/core/contentGenerator.js.map +1 -1
  77. package/dist/src/core/contentGenerator.test.js +1 -1
  78. package/dist/src/core/contentGenerator.test.js.map +1 -1
  79. package/dist/src/core/coreToolHookTriggers.test.js +11 -9
  80. package/dist/src/core/coreToolHookTriggers.test.js.map +1 -1
  81. package/dist/src/core/coreToolScheduler.d.ts +1 -0
  82. package/dist/src/core/coreToolScheduler.js +30 -106
  83. package/dist/src/core/coreToolScheduler.js.map +1 -1
  84. package/dist/src/core/coreToolScheduler.test.js +21 -21
  85. package/dist/src/core/coreToolScheduler.test.js.map +1 -1
  86. package/dist/src/core/loggingContentGenerator.js +14 -2
  87. package/dist/src/core/loggingContentGenerator.js.map +1 -1
  88. package/dist/src/core/prompts.js +1 -1
  89. package/dist/src/core/prompts.js.map +1 -1
  90. package/dist/src/core/sessionHookTriggers.d.ts +3 -2
  91. package/dist/src/core/sessionHookTriggers.js +8 -1
  92. package/dist/src/core/sessionHookTriggers.js.map +1 -1
  93. package/dist/src/core/turn.d.ts +16 -2
  94. package/dist/src/core/turn.js +2 -0
  95. package/dist/src/core/turn.js.map +1 -1
  96. package/dist/src/generated/git-commit.d.ts +2 -2
  97. package/dist/src/generated/git-commit.js +2 -2
  98. package/dist/src/generated/git-commit.js.map +1 -1
  99. package/dist/src/hooks/hookEventHandler.d.ts +6 -2
  100. package/dist/src/hooks/hookEventHandler.js +24 -3
  101. package/dist/src/hooks/hookEventHandler.js.map +1 -1
  102. package/dist/src/hooks/hookEventHandler.test.js +31 -8
  103. package/dist/src/hooks/hookEventHandler.test.js.map +1 -1
  104. package/dist/src/hooks/hookRunner.d.ts +2 -2
  105. package/dist/src/hooks/hookRunner.js +12 -4
  106. package/dist/src/hooks/hookRunner.js.map +1 -1
  107. package/dist/src/hooks/hookRunner.test.js +33 -0
  108. package/dist/src/hooks/hookRunner.test.js.map +1 -1
  109. package/dist/src/index.d.ts +3 -1
  110. package/dist/src/index.js +3 -2
  111. package/dist/src/index.js.map +1 -1
  112. package/dist/src/policy/config.js +60 -22
  113. package/dist/src/policy/config.js.map +1 -1
  114. package/dist/src/policy/config.test.js +21 -0
  115. package/dist/src/policy/config.test.js.map +1 -1
  116. package/dist/src/policy/persistence.test.js +1 -1
  117. package/dist/src/policy/persistence.test.js.map +1 -1
  118. package/dist/src/policy/policy-engine.js +22 -6
  119. package/dist/src/policy/policy-engine.js.map +1 -1
  120. package/dist/src/policy/policy-engine.test.js +206 -1
  121. package/dist/src/policy/policy-engine.test.js.map +1 -1
  122. package/dist/src/policy/toml-loader.d.ts +0 -8
  123. package/dist/src/policy/toml-loader.js +7 -70
  124. package/dist/src/policy/toml-loader.js.map +1 -1
  125. package/dist/src/policy/toml-loader.test.js +16 -6
  126. package/dist/src/policy/toml-loader.test.js.map +1 -1
  127. package/dist/src/policy/utils.d.ts +21 -0
  128. package/dist/src/policy/utils.js +42 -0
  129. package/dist/src/policy/utils.js.map +1 -0
  130. package/dist/src/policy/utils.test.js +64 -0
  131. package/dist/src/policy/utils.test.js.map +1 -0
  132. package/dist/src/scheduler/tool-executor.d.ts +22 -0
  133. package/dist/src/scheduler/tool-executor.js +198 -0
  134. package/dist/src/scheduler/tool-executor.js.map +1 -0
  135. package/dist/src/scheduler/tool-executor.test.d.ts +6 -0
  136. package/dist/src/scheduler/tool-executor.test.js +231 -0
  137. package/dist/src/scheduler/tool-executor.test.js.map +1 -0
  138. package/dist/src/skills/skillLoader.d.ts +28 -0
  139. package/dist/src/skills/skillLoader.js +77 -0
  140. package/dist/src/skills/skillLoader.js.map +1 -0
  141. package/dist/src/skills/skillLoader.test.d.ts +6 -0
  142. package/dist/src/skills/skillLoader.test.js +73 -0
  143. package/dist/src/skills/skillLoader.test.js.map +1 -0
  144. package/dist/src/{services → skills}/skillManager.d.ts +10 -20
  145. package/dist/src/skills/skillManager.js +89 -0
  146. package/dist/src/skills/skillManager.js.map +1 -0
  147. package/dist/src/skills/skillManager.test.d.ts +6 -0
  148. package/dist/src/skills/skillManager.test.js +128 -0
  149. package/dist/src/skills/skillManager.test.js.map +1 -0
  150. package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +5 -5
  151. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +8 -8
  152. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
  153. package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +2 -2
  154. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +4 -4
  155. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
  156. package/dist/src/telemetry/loggers.d.ts +3 -3
  157. package/dist/src/telemetry/loggers.js +4 -4
  158. package/dist/src/telemetry/loggers.js.map +1 -1
  159. package/dist/src/telemetry/loggers.test.js +6 -5
  160. package/dist/src/telemetry/loggers.test.js.map +1 -1
  161. package/dist/src/telemetry/types.d.ts +7 -7
  162. package/dist/src/telemetry/types.js +10 -10
  163. package/dist/src/telemetry/types.js.map +1 -1
  164. package/dist/src/test-utils/mock-message-bus.d.ts +1 -0
  165. package/dist/src/test-utils/mock-message-bus.js +29 -0
  166. package/dist/src/test-utils/mock-message-bus.js.map +1 -1
  167. package/dist/src/test-utils/mock-tool.d.ts +5 -3
  168. package/dist/src/test-utils/mock-tool.js +11 -10
  169. package/dist/src/test-utils/mock-tool.js.map +1 -1
  170. package/dist/src/tools/activate-skill.d.ts +2 -2
  171. package/dist/src/tools/activate-skill.js +6 -1
  172. package/dist/src/tools/activate-skill.js.map +1 -1
  173. package/dist/src/tools/activate-skill.test.js +7 -5
  174. package/dist/src/tools/activate-skill.test.js.map +1 -1
  175. package/dist/src/tools/confirmation-policy.test.js +2 -12
  176. package/dist/src/tools/confirmation-policy.test.js.map +1 -1
  177. package/dist/src/tools/edit.d.ts +27 -5
  178. package/dist/src/tools/edit.js +444 -137
  179. package/dist/src/tools/edit.js.map +1 -1
  180. package/dist/src/tools/edit.test.js +257 -525
  181. package/dist/src/tools/edit.test.js.map +1 -1
  182. package/dist/src/tools/get-internal-docs.d.ts +2 -2
  183. package/dist/src/tools/get-internal-docs.js +6 -6
  184. package/dist/src/tools/get-internal-docs.js.map +1 -1
  185. package/dist/src/tools/get-internal-docs.test.js +2 -1
  186. package/dist/src/tools/get-internal-docs.test.js.map +1 -1
  187. package/dist/src/tools/glob.d.ts +2 -2
  188. package/dist/src/tools/glob.js +1 -1
  189. package/dist/src/tools/glob.js.map +1 -1
  190. package/dist/src/tools/glob.test.js +2 -1
  191. package/dist/src/tools/glob.test.js.map +1 -1
  192. package/dist/src/tools/grep.d.ts +2 -2
  193. package/dist/src/tools/grep.js +1 -1
  194. package/dist/src/tools/grep.js.map +1 -1
  195. package/dist/src/tools/grep.test.js +5 -4
  196. package/dist/src/tools/grep.test.js.map +1 -1
  197. package/dist/src/tools/ls.d.ts +2 -2
  198. package/dist/src/tools/ls.js +2 -2
  199. package/dist/src/tools/ls.js.map +1 -1
  200. package/dist/src/tools/ls.test.js +2 -1
  201. package/dist/src/tools/ls.test.js.map +1 -1
  202. package/dist/src/tools/mcp-client.d.ts +2 -2
  203. package/dist/src/tools/mcp-client.js +2 -1
  204. package/dist/src/tools/mcp-client.js.map +1 -1
  205. package/dist/src/tools/mcp-tool.d.ts +2 -2
  206. package/dist/src/tools/mcp-tool.js +7 -7
  207. package/dist/src/tools/mcp-tool.js.map +1 -1
  208. package/dist/src/tools/mcp-tool.test.js +11 -6
  209. package/dist/src/tools/mcp-tool.test.js.map +1 -1
  210. package/dist/src/tools/memoryTool.d.ts +3 -3
  211. package/dist/src/tools/memoryTool.js +2 -2
  212. package/dist/src/tools/memoryTool.js.map +1 -1
  213. package/dist/src/tools/memoryTool.test.js +5 -2
  214. package/dist/src/tools/memoryTool.test.js.map +1 -1
  215. package/dist/src/tools/message-bus-integration.test.js +10 -37
  216. package/dist/src/tools/message-bus-integration.test.js.map +1 -1
  217. package/dist/src/tools/read-file.d.ts +2 -2
  218. package/dist/src/tools/read-file.js +1 -1
  219. package/dist/src/tools/read-file.js.map +1 -1
  220. package/dist/src/tools/read-file.test.js +3 -2
  221. package/dist/src/tools/read-file.test.js.map +1 -1
  222. package/dist/src/tools/read-many-files.d.ts +2 -2
  223. package/dist/src/tools/read-many-files.js +2 -3
  224. package/dist/src/tools/read-many-files.js.map +1 -1
  225. package/dist/src/tools/read-many-files.test.js +3 -2
  226. package/dist/src/tools/read-many-files.test.js.map +1 -1
  227. package/dist/src/tools/ripGrep.d.ts +2 -2
  228. package/dist/src/tools/ripGrep.js +3 -4
  229. package/dist/src/tools/ripGrep.js.map +1 -1
  230. package/dist/src/tools/ripGrep.test.js +7 -6
  231. package/dist/src/tools/ripGrep.test.js.map +1 -1
  232. package/dist/src/tools/shell.d.ts +3 -4
  233. package/dist/src/tools/shell.js +9 -35
  234. package/dist/src/tools/shell.js.map +1 -1
  235. package/dist/src/tools/shell.test.js +40 -57
  236. package/dist/src/tools/shell.test.js.map +1 -1
  237. package/dist/src/tools/tool-registry.d.ts +11 -6
  238. package/dist/src/tools/tool-registry.js +13 -8
  239. package/dist/src/tools/tool-registry.js.map +1 -1
  240. package/dist/src/tools/tool-registry.test.js +14 -10
  241. package/dist/src/tools/tool-registry.test.js.map +1 -1
  242. package/dist/src/tools/tools.d.ts +5 -5
  243. package/dist/src/tools/tools.js +15 -17
  244. package/dist/src/tools/tools.js.map +1 -1
  245. package/dist/src/tools/tools.test.js +3 -1
  246. package/dist/src/tools/tools.test.js.map +1 -1
  247. package/dist/src/tools/web-fetch.d.ts +2 -2
  248. package/dist/src/tools/web-fetch.js +4 -4
  249. package/dist/src/tools/web-fetch.js.map +1 -1
  250. package/dist/src/tools/web-fetch.test.js +17 -19
  251. package/dist/src/tools/web-fetch.test.js.map +1 -1
  252. package/dist/src/tools/web-search.d.ts +2 -2
  253. package/dist/src/tools/web-search.js +3 -4
  254. package/dist/src/tools/web-search.js.map +1 -1
  255. package/dist/src/tools/web-search.test.js +2 -1
  256. package/dist/src/tools/web-search.test.js.map +1 -1
  257. package/dist/src/tools/write-file.d.ts +2 -2
  258. package/dist/src/tools/write-file.js +3 -3
  259. package/dist/src/tools/write-file.js.map +1 -1
  260. package/dist/src/tools/write-file.test.js +4 -1
  261. package/dist/src/tools/write-file.test.js.map +1 -1
  262. package/dist/src/tools/write-todos.d.ts +2 -2
  263. package/dist/src/tools/write-todos.js +5 -4
  264. package/dist/src/tools/write-todos.js.map +1 -1
  265. package/dist/src/tools/write-todos.test.js +2 -1
  266. package/dist/src/tools/write-todos.test.js.map +1 -1
  267. package/dist/src/utils/editCorrector.test.js +1 -1
  268. package/dist/src/utils/editCorrector.test.js.map +1 -1
  269. package/dist/src/utils/events.d.ts +46 -1
  270. package/dist/src/utils/events.js +21 -0
  271. package/dist/src/utils/events.js.map +1 -1
  272. package/dist/src/utils/events.test.js +25 -0
  273. package/dist/src/utils/events.test.js.map +1 -1
  274. package/dist/src/utils/shell-permissions.test.js +27 -0
  275. package/dist/src/utils/shell-permissions.test.js.map +1 -1
  276. package/dist/src/utils/terminal.d.ts +2 -0
  277. package/dist/src/utils/terminal.js +6 -0
  278. package/dist/src/utils/terminal.js.map +1 -1
  279. package/dist/src/utils/tokenCalculation.js +20 -5
  280. package/dist/src/utils/tokenCalculation.js.map +1 -1
  281. package/dist/src/utils/tokenCalculation.test.js +11 -2
  282. package/dist/src/utils/tokenCalculation.test.js.map +1 -1
  283. package/dist/src/utils/tool-utils.test.js +2 -1
  284. package/dist/src/utils/tool-utils.test.js.map +1 -1
  285. package/dist/tsconfig.tsbuildinfo +1 -1
  286. package/package.json +1 -1
  287. package/dist/google-gemini-cli-core-0.24.0-nightly.20251227.37be16243.tgz +0 -0
  288. package/dist/src/services/skillManager.js +0 -157
  289. package/dist/src/services/skillManager.js.map +0 -1
  290. package/dist/src/services/skillManager.test.js +0 -169
  291. package/dist/src/services/skillManager.test.js.map +0 -1
  292. package/dist/src/tools/smart-edit.d.ts +0 -78
  293. package/dist/src/tools/smart-edit.js +0 -722
  294. package/dist/src/tools/smart-edit.js.map +0 -1
  295. package/dist/src/tools/smart-edit.test.js +0 -591
  296. package/dist/src/tools/smart-edit.test.js.map +0 -1
  297. /package/dist/src/{services/skillManager.test.d.ts → agents/a2aUtils.test.d.ts} +0 -0
  298. /package/dist/src/{tools/smart-edit.test.d.ts → policy/utils.test.d.ts} +0 -0
@@ -0,0 +1,231 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
7
+ import { ToolExecutor } from './tool-executor.js';
8
+ import { makeFakeConfig } from '../test-utils/config.js';
9
+ import { MockTool } from '../test-utils/mock-tool.js';
10
+ import { SHELL_TOOL_NAME } from '../tools/tool-names.js';
11
+ import * as fileUtils from '../utils/fileUtils.js';
12
+ import * as coreToolHookTriggers from '../core/coreToolHookTriggers.js';
13
+ import { ShellToolInvocation } from '../tools/shell.js';
14
+ import { createMockMessageBus } from '../test-utils/mock-message-bus.js';
15
+ // Mock file utils
16
+ vi.mock('../utils/fileUtils.js', () => ({
17
+ saveTruncatedContent: vi.fn(),
18
+ }));
19
+ // Mock executeToolWithHooks
20
+ vi.mock('../core/coreToolHookTriggers.js', () => ({
21
+ executeToolWithHooks: vi.fn(),
22
+ }));
23
+ describe('ToolExecutor', () => {
24
+ let config;
25
+ let executor;
26
+ beforeEach(() => {
27
+ // Use the standard fake config factory
28
+ config = makeFakeConfig();
29
+ executor = new ToolExecutor(config);
30
+ // Reset mocks
31
+ vi.resetAllMocks();
32
+ // Default mock implementation for saveTruncatedContent
33
+ vi.mocked(fileUtils.saveTruncatedContent).mockImplementation(async (_content, _callId, _tempDir, _threshold, _lines) => ({
34
+ content: 'TruncatedContent...',
35
+ outputFile: '/tmp/truncated_output.txt',
36
+ }));
37
+ });
38
+ afterEach(() => {
39
+ vi.restoreAllMocks();
40
+ });
41
+ it('should execute a tool successfully', async () => {
42
+ const mockTool = new MockTool({
43
+ name: 'testTool',
44
+ execute: async () => ({
45
+ llmContent: 'Tool output',
46
+ returnDisplay: 'Tool output',
47
+ }),
48
+ });
49
+ const invocation = mockTool.build({});
50
+ // Mock executeToolWithHooks to return success
51
+ vi.mocked(coreToolHookTriggers.executeToolWithHooks).mockResolvedValue({
52
+ llmContent: 'Tool output',
53
+ returnDisplay: 'Tool output',
54
+ });
55
+ const scheduledCall = {
56
+ status: 'scheduled',
57
+ request: {
58
+ callId: 'call-1',
59
+ name: 'testTool',
60
+ args: {},
61
+ isClientInitiated: false,
62
+ prompt_id: 'prompt-1',
63
+ },
64
+ tool: mockTool,
65
+ invocation: invocation,
66
+ startTime: Date.now(),
67
+ };
68
+ const onUpdateToolCall = vi.fn();
69
+ const result = await executor.execute({
70
+ call: scheduledCall,
71
+ signal: new AbortController().signal,
72
+ onUpdateToolCall,
73
+ });
74
+ expect(result.status).toBe('success');
75
+ if (result.status === 'success') {
76
+ const response = result.response.responseParts[0]?.functionResponse
77
+ ?.response;
78
+ expect(response).toEqual({ output: 'Tool output' });
79
+ }
80
+ });
81
+ it('should handle execution errors', async () => {
82
+ const mockTool = new MockTool({
83
+ name: 'failTool',
84
+ });
85
+ const invocation = mockTool.build({});
86
+ // Mock executeToolWithHooks to throw
87
+ vi.mocked(coreToolHookTriggers.executeToolWithHooks).mockRejectedValue(new Error('Tool Failed'));
88
+ const scheduledCall = {
89
+ status: 'scheduled',
90
+ request: {
91
+ callId: 'call-2',
92
+ name: 'failTool',
93
+ args: {},
94
+ isClientInitiated: false,
95
+ prompt_id: 'prompt-2',
96
+ },
97
+ tool: mockTool,
98
+ invocation: invocation,
99
+ startTime: Date.now(),
100
+ };
101
+ const result = await executor.execute({
102
+ call: scheduledCall,
103
+ signal: new AbortController().signal,
104
+ onUpdateToolCall: vi.fn(),
105
+ });
106
+ expect(result.status).toBe('error');
107
+ if (result.status === 'error') {
108
+ expect(result.response.error?.message).toBe('Tool Failed');
109
+ }
110
+ });
111
+ it('should return cancelled result when signal is aborted', async () => {
112
+ const mockTool = new MockTool({
113
+ name: 'slowTool',
114
+ });
115
+ const invocation = mockTool.build({});
116
+ // Mock executeToolWithHooks to simulate slow execution or cancellation check
117
+ vi.mocked(coreToolHookTriggers.executeToolWithHooks).mockImplementation(async () => {
118
+ await new Promise((r) => setTimeout(r, 100));
119
+ return { llmContent: 'Done', returnDisplay: 'Done' };
120
+ });
121
+ const scheduledCall = {
122
+ status: 'scheduled',
123
+ request: {
124
+ callId: 'call-3',
125
+ name: 'slowTool',
126
+ args: {},
127
+ isClientInitiated: false,
128
+ prompt_id: 'prompt-3',
129
+ },
130
+ tool: mockTool,
131
+ invocation: invocation,
132
+ startTime: Date.now(),
133
+ };
134
+ const controller = new AbortController();
135
+ const promise = executor.execute({
136
+ call: scheduledCall,
137
+ signal: controller.signal,
138
+ onUpdateToolCall: vi.fn(),
139
+ });
140
+ controller.abort();
141
+ const result = await promise;
142
+ expect(result.status).toBe('cancelled');
143
+ });
144
+ it('should truncate large shell output', async () => {
145
+ // 1. Setup Config for Truncation
146
+ vi.spyOn(config, 'getEnableToolOutputTruncation').mockReturnValue(true);
147
+ vi.spyOn(config, 'getTruncateToolOutputThreshold').mockReturnValue(10);
148
+ vi.spyOn(config, 'getTruncateToolOutputLines').mockReturnValue(5);
149
+ const mockTool = new MockTool({ name: SHELL_TOOL_NAME });
150
+ const invocation = mockTool.build({});
151
+ const longOutput = 'This is a very long output that should be truncated.';
152
+ // 2. Mock execution returning long content
153
+ vi.mocked(coreToolHookTriggers.executeToolWithHooks).mockResolvedValue({
154
+ llmContent: longOutput,
155
+ returnDisplay: longOutput,
156
+ });
157
+ const scheduledCall = {
158
+ status: 'scheduled',
159
+ request: {
160
+ callId: 'call-trunc',
161
+ name: SHELL_TOOL_NAME,
162
+ args: { command: 'echo long' },
163
+ isClientInitiated: false,
164
+ prompt_id: 'prompt-trunc',
165
+ },
166
+ tool: mockTool,
167
+ invocation: invocation,
168
+ startTime: Date.now(),
169
+ };
170
+ // 3. Execute
171
+ const result = await executor.execute({
172
+ call: scheduledCall,
173
+ signal: new AbortController().signal,
174
+ onUpdateToolCall: vi.fn(),
175
+ });
176
+ // 4. Verify Truncation Logic
177
+ expect(fileUtils.saveTruncatedContent).toHaveBeenCalledWith(longOutput, 'call-trunc', expect.any(String), // temp dir
178
+ 10, // threshold
179
+ 5);
180
+ expect(result.status).toBe('success');
181
+ if (result.status === 'success') {
182
+ const response = result.response.responseParts[0]?.functionResponse
183
+ ?.response;
184
+ // The content should be the *truncated* version returned by the mock saveTruncatedContent
185
+ expect(response).toEqual({ output: 'TruncatedContent...' });
186
+ expect(result.response.outputFile).toBe('/tmp/truncated_output.txt');
187
+ }
188
+ });
189
+ it('should report PID updates for shell tools', async () => {
190
+ // 1. Setup ShellToolInvocation
191
+ const messageBus = createMockMessageBus();
192
+ const shellInvocation = new ShellToolInvocation(config, { command: 'sleep 10' }, messageBus);
193
+ // We need a dummy tool that matches the invocation just for structure
194
+ const mockTool = new MockTool({ name: SHELL_TOOL_NAME });
195
+ // 2. Mock executeToolWithHooks to trigger the PID callback
196
+ const testPid = 12345;
197
+ vi.mocked(coreToolHookTriggers.executeToolWithHooks).mockImplementation(async (_inv, _name, _sig, _bus, _hooks, _tool, _liveCb, _shellCfg, setPidCallback) => {
198
+ // Simulate the shell tool reporting a PID
199
+ if (setPidCallback) {
200
+ setPidCallback(testPid);
201
+ }
202
+ return { llmContent: 'done', returnDisplay: 'done' };
203
+ });
204
+ const scheduledCall = {
205
+ status: 'scheduled',
206
+ request: {
207
+ callId: 'call-pid',
208
+ name: SHELL_TOOL_NAME,
209
+ args: { command: 'sleep 10' },
210
+ isClientInitiated: false,
211
+ prompt_id: 'prompt-pid',
212
+ },
213
+ tool: mockTool,
214
+ invocation: shellInvocation,
215
+ startTime: Date.now(),
216
+ };
217
+ const onUpdateToolCall = vi.fn();
218
+ // 3. Execute
219
+ await executor.execute({
220
+ call: scheduledCall,
221
+ signal: new AbortController().signal,
222
+ onUpdateToolCall,
223
+ });
224
+ // 4. Verify PID was reported
225
+ expect(onUpdateToolCall).toHaveBeenCalledWith(expect.objectContaining({
226
+ status: 'executing',
227
+ pid: testPid,
228
+ }));
229
+ });
230
+ });
231
+ //# sourceMappingURL=tool-executor.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-executor.test.js","sourceRoot":"","sources":["../../../src/scheduler/tool-executor.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ /**
7
+ * Represents the definition of an Agent Skill.
8
+ */
9
+ export interface SkillDefinition {
10
+ /** The unique name of the skill. */
11
+ name: string;
12
+ /** A concise description of what the skill does. */
13
+ description: string;
14
+ /** The absolute path to the skill's source file on disk. */
15
+ location: string;
16
+ /** The core logic/instructions of the skill. */
17
+ body: string;
18
+ /** Whether the skill is currently disabled. */
19
+ disabled?: boolean;
20
+ }
21
+ /**
22
+ * Discovers and loads all skills in the provided directory.
23
+ */
24
+ export declare function loadSkillsFromDir(dir: string): Promise<SkillDefinition[]>;
25
+ /**
26
+ * Loads a single skill from a SKILL.md file.
27
+ */
28
+ export declare function loadSkillFromFile(filePath: string): Promise<SkillDefinition | null>;
@@ -0,0 +1,77 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import * as fs from 'node:fs/promises';
7
+ import * as path from 'node:path';
8
+ import { glob } from 'glob';
9
+ import yaml from 'js-yaml';
10
+ import { debugLogger } from '../utils/debugLogger.js';
11
+ import { coreEvents } from '../utils/events.js';
12
+ const FRONTMATTER_REGEX = /^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)/;
13
+ /**
14
+ * Discovers and loads all skills in the provided directory.
15
+ */
16
+ export async function loadSkillsFromDir(dir) {
17
+ const discoveredSkills = [];
18
+ try {
19
+ const absoluteSearchPath = path.resolve(dir);
20
+ const stats = await fs.stat(absoluteSearchPath).catch(() => null);
21
+ if (!stats || !stats.isDirectory()) {
22
+ return [];
23
+ }
24
+ const skillFiles = await glob('*/SKILL.md', {
25
+ cwd: absoluteSearchPath,
26
+ absolute: true,
27
+ nodir: true,
28
+ });
29
+ for (const skillFile of skillFiles) {
30
+ const metadata = await loadSkillFromFile(skillFile);
31
+ if (metadata) {
32
+ discoveredSkills.push(metadata);
33
+ }
34
+ }
35
+ if (discoveredSkills.length === 0) {
36
+ const files = await fs.readdir(absoluteSearchPath);
37
+ if (files.length > 0) {
38
+ coreEvents.emitFeedback('warning', `Failed to load skills from ${absoluteSearchPath}. The directory is not empty but no valid skills were discovered. Please ensure SKILL.md files are present in subdirectories and have valid frontmatter.`);
39
+ }
40
+ }
41
+ }
42
+ catch (error) {
43
+ coreEvents.emitFeedback('warning', `Error discovering skills in ${dir}:`, error);
44
+ }
45
+ return discoveredSkills;
46
+ }
47
+ /**
48
+ * Loads a single skill from a SKILL.md file.
49
+ */
50
+ export async function loadSkillFromFile(filePath) {
51
+ try {
52
+ const content = await fs.readFile(filePath, 'utf-8');
53
+ const match = content.match(FRONTMATTER_REGEX);
54
+ if (!match) {
55
+ return null;
56
+ }
57
+ const frontmatter = yaml.load(match[1]);
58
+ if (!frontmatter || typeof frontmatter !== 'object') {
59
+ return null;
60
+ }
61
+ const { name, description } = frontmatter;
62
+ if (typeof name !== 'string' || typeof description !== 'string') {
63
+ return null;
64
+ }
65
+ return {
66
+ name,
67
+ description,
68
+ location: filePath,
69
+ body: match[2].trim(),
70
+ };
71
+ }
72
+ catch (error) {
73
+ debugLogger.log(`Error parsing skill file ${filePath}:`, error);
74
+ return null;
75
+ }
76
+ }
77
+ //# sourceMappingURL=skillLoader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skillLoader.js","sourceRoot":"","sources":["../../../src/skills/skillLoader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export {};
@@ -0,0 +1,73 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
7
+ import * as fs from 'node:fs/promises';
8
+ import * as os from 'node:os';
9
+ import * as path from 'node:path';
10
+ import { loadSkillsFromDir } from './skillLoader.js';
11
+ import { coreEvents } from '../utils/events.js';
12
+ describe('skillLoader', () => {
13
+ let testRootDir;
14
+ beforeEach(async () => {
15
+ testRootDir = await fs.mkdtemp(path.join(os.tmpdir(), 'skill-loader-test-'));
16
+ vi.spyOn(coreEvents, 'emitFeedback');
17
+ });
18
+ afterEach(async () => {
19
+ await fs.rm(testRootDir, { recursive: true, force: true });
20
+ vi.restoreAllMocks();
21
+ });
22
+ it('should load skills from a directory with valid SKILL.md', async () => {
23
+ const skillDir = path.join(testRootDir, 'my-skill');
24
+ await fs.mkdir(skillDir, { recursive: true });
25
+ const skillFile = path.join(skillDir, 'SKILL.md');
26
+ await fs.writeFile(skillFile, `---\nname: my-skill\ndescription: A test skill\n---\n# Instructions\nDo something.\n`);
27
+ const skills = await loadSkillsFromDir(testRootDir);
28
+ expect(skills).toHaveLength(1);
29
+ expect(skills[0].name).toBe('my-skill');
30
+ expect(skills[0].description).toBe('A test skill');
31
+ expect(skills[0].location).toBe(skillFile);
32
+ expect(skills[0].body).toBe('# Instructions\nDo something.');
33
+ expect(coreEvents.emitFeedback).not.toHaveBeenCalled();
34
+ });
35
+ it('should emit feedback when no valid skills are found in a non-empty directory', async () => {
36
+ const notASkillDir = path.join(testRootDir, 'not-a-skill');
37
+ await fs.mkdir(notASkillDir, { recursive: true });
38
+ await fs.writeFile(path.join(notASkillDir, 'some-file.txt'), 'hello');
39
+ const skills = await loadSkillsFromDir(testRootDir);
40
+ expect(skills).toHaveLength(0);
41
+ expect(coreEvents.emitFeedback).toHaveBeenCalledWith('warning', expect.stringContaining('Failed to load skills from'));
42
+ });
43
+ it('should ignore empty directories and not emit feedback', async () => {
44
+ const skills = await loadSkillsFromDir(testRootDir);
45
+ expect(skills).toHaveLength(0);
46
+ expect(coreEvents.emitFeedback).not.toHaveBeenCalled();
47
+ });
48
+ it('should ignore directories without SKILL.md', async () => {
49
+ const notASkillDir = path.join(testRootDir, 'not-a-skill');
50
+ await fs.mkdir(notASkillDir, { recursive: true });
51
+ // With a subdirectory, even if empty, it might still trigger readdir
52
+ // But my current logic is if discoveredSkills.length === 0, then check readdir
53
+ // If readdir is empty, it's fine.
54
+ const skills = await loadSkillsFromDir(testRootDir);
55
+ expect(skills).toHaveLength(0);
56
+ // If notASkillDir is empty, no warning.
57
+ });
58
+ it('should ignore SKILL.md without valid frontmatter and emit warning if directory is not empty', async () => {
59
+ const skillDir = path.join(testRootDir, 'invalid-skill');
60
+ await fs.mkdir(skillDir, { recursive: true });
61
+ const skillFile = path.join(skillDir, 'SKILL.md');
62
+ await fs.writeFile(skillFile, '# No frontmatter here');
63
+ const skills = await loadSkillsFromDir(testRootDir);
64
+ expect(skills).toHaveLength(0);
65
+ expect(coreEvents.emitFeedback).toHaveBeenCalledWith('warning', expect.stringContaining('Failed to load skills from'));
66
+ });
67
+ it('should return empty array for non-existent directory', async () => {
68
+ const skills = await loadSkillsFromDir('/non/existent/path');
69
+ expect(skills).toEqual([]);
70
+ expect(coreEvents.emitFeedback).not.toHaveBeenCalled();
71
+ });
72
+ });
73
+ //# sourceMappingURL=skillLoader.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skillLoader.test.js","sourceRoot":"","sources":["../../../src/skills/skillLoader.test.ts"],"names":[],"mappings":"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"}
@@ -4,13 +4,9 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
  import { Storage } from '../config/storage.js';
7
- export interface SkillMetadata {
8
- name: string;
9
- description: string;
10
- location: string;
11
- body: string;
12
- disabled?: boolean;
13
- }
7
+ import { type SkillDefinition } from './skillLoader.js';
8
+ import type { GeminiCLIExtension } from '../config/config.js';
9
+ export { type SkillDefinition };
14
10
  export declare class SkillManager {
15
11
  private skills;
16
12
  private activeSkillNames;
@@ -19,28 +15,23 @@ export declare class SkillManager {
19
15
  */
20
16
  clearSkills(): void;
21
17
  /**
22
- * Discovers skills from standard user and project locations.
23
- * Project skills take precedence over user skills.
18
+ * Discovers skills from standard user and project locations, as well as extensions.
19
+ * Precedence: Extensions (lowest) -> User -> Project (highest).
24
20
  */
25
- discoverSkills(storage: Storage): Promise<void>;
21
+ discoverSkills(storage: Storage, extensions?: GeminiCLIExtension[]): Promise<void>;
26
22
  private addSkillsWithPrecedence;
27
- /**
28
- * Discovered skills in the provided paths and adds them to the manager.
29
- * Internal helper for tiered discovery.
30
- */
31
- discoverSkillsInternal(paths: string[]): Promise<SkillMetadata[]>;
32
23
  /**
33
24
  * Returns the list of enabled discovered skills.
34
25
  */
35
- getSkills(): SkillMetadata[];
26
+ getSkills(): SkillDefinition[];
36
27
  /**
37
28
  * Returns all discovered skills, including disabled ones.
38
29
  */
39
- getAllSkills(): SkillMetadata[];
30
+ getAllSkills(): SkillDefinition[];
40
31
  /**
41
32
  * Filters discovered skills by name.
42
33
  */
43
- filterSkills(predicate: (skill: SkillMetadata) => boolean): void;
34
+ filterSkills(predicate: (skill: SkillDefinition) => boolean): void;
44
35
  /**
45
36
  * Sets the list of disabled skill names.
46
37
  */
@@ -48,7 +39,7 @@ export declare class SkillManager {
48
39
  /**
49
40
  * Reads the full content (metadata + body) of a skill by name.
50
41
  */
51
- getSkill(name: string): SkillMetadata | null;
42
+ getSkill(name: string): SkillDefinition | null;
52
43
  /**
53
44
  * Activates a skill by name.
54
45
  */
@@ -57,5 +48,4 @@ export declare class SkillManager {
57
48
  * Checks if a skill is active.
58
49
  */
59
50
  isSkillActive(name: string): boolean;
60
- private parseSkillFile;
61
51
  }
@@ -0,0 +1,89 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { Storage } from '../config/storage.js';
7
+ import { loadSkillsFromDir } from './skillLoader.js';
8
+ export {};
9
+ export class SkillManager {
10
+ skills = [];
11
+ activeSkillNames = new Set();
12
+ /**
13
+ * Clears all discovered skills.
14
+ */
15
+ clearSkills() {
16
+ this.skills = [];
17
+ }
18
+ /**
19
+ * Discovers skills from standard user and project locations, as well as extensions.
20
+ * Precedence: Extensions (lowest) -> User -> Project (highest).
21
+ */
22
+ async discoverSkills(storage, extensions = []) {
23
+ this.clearSkills();
24
+ // 1. Extension skills (lowest precedence)
25
+ for (const extension of extensions) {
26
+ if (extension.isActive && extension.skills) {
27
+ this.addSkillsWithPrecedence(extension.skills);
28
+ }
29
+ }
30
+ // 2. User skills
31
+ const userSkills = await loadSkillsFromDir(Storage.getUserSkillsDir());
32
+ this.addSkillsWithPrecedence(userSkills);
33
+ // 3. Project skills (highest precedence)
34
+ const projectSkills = await loadSkillsFromDir(storage.getProjectSkillsDir());
35
+ this.addSkillsWithPrecedence(projectSkills);
36
+ }
37
+ addSkillsWithPrecedence(newSkills) {
38
+ const skillMap = new Map();
39
+ for (const skill of [...this.skills, ...newSkills]) {
40
+ skillMap.set(skill.name, skill);
41
+ }
42
+ this.skills = Array.from(skillMap.values());
43
+ }
44
+ /**
45
+ * Returns the list of enabled discovered skills.
46
+ */
47
+ getSkills() {
48
+ return this.skills.filter((s) => !s.disabled);
49
+ }
50
+ /**
51
+ * Returns all discovered skills, including disabled ones.
52
+ */
53
+ getAllSkills() {
54
+ return this.skills;
55
+ }
56
+ /**
57
+ * Filters discovered skills by name.
58
+ */
59
+ filterSkills(predicate) {
60
+ this.skills = this.skills.filter(predicate);
61
+ }
62
+ /**
63
+ * Sets the list of disabled skill names.
64
+ */
65
+ setDisabledSkills(disabledNames) {
66
+ for (const skill of this.skills) {
67
+ skill.disabled = disabledNames.includes(skill.name);
68
+ }
69
+ }
70
+ /**
71
+ * Reads the full content (metadata + body) of a skill by name.
72
+ */
73
+ getSkill(name) {
74
+ return this.skills.find((s) => s.name === name) ?? null;
75
+ }
76
+ /**
77
+ * Activates a skill by name.
78
+ */
79
+ activateSkill(name) {
80
+ this.activeSkillNames.add(name);
81
+ }
82
+ /**
83
+ * Checks if a skill is active.
84
+ */
85
+ isSkillActive(name) {
86
+ return this.activeSkillNames.has(name);
87
+ }
88
+ }
89
+ //# sourceMappingURL=skillManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skillManager.js","sourceRoot":"","sources":["../../../src/skills/skillManager.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAwB,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAG3E,OAAO,EAAwB,CAAC;AAEhC,MAAM,OAAO,YAAY;IACf,MAAM,GAAsB,EAAE,CAAC;IAC/B,gBAAgB,GAAgB,IAAI,GAAG,EAAE,CAAC;IAElD;;OAEG;IACH,WAAW;QACT,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;IACnB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,cAAc,CAClB,OAAgB,EAChB,aAAmC,EAAE;QAErC,IAAI,CAAC,WAAW,EAAE,CAAC;QAEnB,0CAA0C;QAC1C,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,IAAI,SAAS,CAAC,QAAQ,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;gBAC3C,IAAI,CAAC,uBAAuB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;YACjD,CAAC;QACH,CAAC;QAED,iBAAiB;QACjB,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;QACvE,IAAI,CAAC,uBAAuB,CAAC,UAAU,CAAC,CAAC;QAEzC,yCAAyC;QACzC,MAAM,aAAa,GAAG,MAAM,iBAAiB,CAC3C,OAAO,CAAC,mBAAmB,EAAE,CAC9B,CAAC;QACF,IAAI,CAAC,uBAAuB,CAAC,aAAa,CAAC,CAAC;IAC9C,CAAC;IAEO,uBAAuB,CAAC,SAA4B;QAC1D,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA2B,CAAC;QACpD,KAAK,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,SAAS,CAAC,EAAE,CAAC;YACnD,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAClC,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED;;OAEG;IACH,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAChD,CAAC;IAED;;OAEG;IACH,YAAY;QACV,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,SAA8C;QACzD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAC9C,CAAC;IAED;;OAEG;IACH,iBAAiB,CAAC,aAAuB;QACvC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChC,KAAK,CAAC,QAAQ,GAAG,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IAED;;OAEG;IACH,QAAQ,CAAC,IAAY;QACnB,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC;IAC1D,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,IAAY;QACxB,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,IAAY;QACxB,OAAO,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACzC,CAAC;CACF"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export {};