@google/gemini-cli-core 0.10.0-nightly.20250926.1487841d → 0.10.0-nightly.20251009.cd354aeb

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 (246) hide show
  1. package/README.md +108 -71
  2. package/dist/index.d.ts +2 -0
  3. package/dist/index.js +1 -0
  4. package/dist/index.js.map +1 -1
  5. package/dist/src/agents/codebase-investigator.d.ts +46 -0
  6. package/dist/src/agents/codebase-investigator.js +136 -0
  7. package/dist/src/agents/codebase-investigator.js.map +1 -0
  8. package/dist/src/agents/executor.d.ts +92 -0
  9. package/dist/src/agents/executor.js +580 -0
  10. package/dist/src/agents/executor.js.map +1 -0
  11. package/dist/src/agents/executor.test.d.ts +6 -0
  12. package/dist/src/agents/executor.test.js +595 -0
  13. package/dist/src/agents/executor.test.js.map +1 -0
  14. package/dist/src/agents/invocation.d.ts +46 -0
  15. package/dist/src/agents/invocation.js +102 -0
  16. package/dist/src/agents/invocation.js.map +1 -0
  17. package/dist/src/agents/invocation.test.d.ts +6 -0
  18. package/dist/src/agents/invocation.test.js +215 -0
  19. package/dist/src/agents/invocation.test.js.map +1 -0
  20. package/dist/src/agents/registry.d.ts +36 -0
  21. package/dist/src/agents/registry.js +60 -0
  22. package/dist/src/agents/registry.js.map +1 -0
  23. package/dist/src/agents/registry.test.d.ts +6 -0
  24. package/dist/src/agents/registry.test.js +146 -0
  25. package/dist/src/agents/registry.test.js.map +1 -0
  26. package/dist/src/agents/schema-utils.d.ts +39 -0
  27. package/dist/src/agents/schema-utils.js +57 -0
  28. package/dist/src/agents/schema-utils.js.map +1 -0
  29. package/dist/src/agents/schema-utils.test.d.ts +6 -0
  30. package/dist/src/agents/schema-utils.test.js +144 -0
  31. package/dist/src/agents/schema-utils.test.js.map +1 -0
  32. package/dist/src/agents/subagent-tool-wrapper.d.ts +38 -0
  33. package/dist/src/agents/subagent-tool-wrapper.js +48 -0
  34. package/dist/src/agents/subagent-tool-wrapper.js.map +1 -0
  35. package/dist/src/agents/subagent-tool-wrapper.test.d.ts +6 -0
  36. package/dist/src/agents/subagent-tool-wrapper.test.js +112 -0
  37. package/dist/src/agents/subagent-tool-wrapper.test.js.map +1 -0
  38. package/dist/src/agents/types.d.ts +145 -0
  39. package/dist/src/agents/types.js +18 -0
  40. package/dist/src/agents/types.js.map +1 -0
  41. package/dist/src/agents/utils.d.ts +15 -0
  42. package/dist/src/agents/utils.js +29 -0
  43. package/dist/src/agents/utils.js.map +1 -0
  44. package/dist/src/agents/utils.test.d.ts +6 -0
  45. package/dist/src/agents/utils.test.js +87 -0
  46. package/dist/src/agents/utils.test.js.map +1 -0
  47. package/dist/src/code_assist/setup.js +4 -2
  48. package/dist/src/code_assist/setup.js.map +1 -1
  49. package/dist/src/config/config.d.ts +28 -5
  50. package/dist/src/config/config.js +61 -7
  51. package/dist/src/config/config.js.map +1 -1
  52. package/dist/src/config/config.test.js +63 -0
  53. package/dist/src/config/config.test.js.map +1 -1
  54. package/dist/src/core/baseLlmClient.js +19 -21
  55. package/dist/src/core/baseLlmClient.js.map +1 -1
  56. package/dist/src/core/baseLlmClient.test.js +57 -17
  57. package/dist/src/core/baseLlmClient.test.js.map +1 -1
  58. package/dist/src/core/client.d.ts +2 -0
  59. package/dist/src/core/client.js +52 -43
  60. package/dist/src/core/client.js.map +1 -1
  61. package/dist/src/core/client.test.js +300 -95
  62. package/dist/src/core/client.test.js.map +1 -1
  63. package/dist/src/core/contentGenerator.js +3 -1
  64. package/dist/src/core/contentGenerator.js.map +1 -1
  65. package/dist/src/core/coreToolScheduler.test.js +33 -23
  66. package/dist/src/core/coreToolScheduler.test.js.map +1 -1
  67. package/dist/src/core/geminiChat.d.ts +6 -0
  68. package/dist/src/core/geminiChat.js +21 -18
  69. package/dist/src/core/geminiChat.js.map +1 -1
  70. package/dist/src/core/geminiChat.test.js +20 -19
  71. package/dist/src/core/geminiChat.test.js.map +1 -1
  72. package/dist/src/core/nonInteractiveToolExecutor.test.js +11 -11
  73. package/dist/src/core/nonInteractiveToolExecutor.test.js.map +1 -1
  74. package/dist/src/core/prompts.d.ts +2 -1
  75. package/dist/src/core/prompts.js +88 -15
  76. package/dist/src/core/prompts.js.map +1 -1
  77. package/dist/src/core/prompts.test.js +73 -24
  78. package/dist/src/core/prompts.test.js.map +1 -1
  79. package/dist/src/core/turn.d.ts +10 -2
  80. package/dist/src/core/turn.js +6 -1
  81. package/dist/src/core/turn.js.map +1 -1
  82. package/dist/src/core/turn.test.js +1 -1
  83. package/dist/src/core/turn.test.js.map +1 -1
  84. package/dist/src/generated/git-commit.d.ts +2 -2
  85. package/dist/src/generated/git-commit.js +2 -2
  86. package/dist/src/ide/detect-ide.d.ts +1 -0
  87. package/dist/src/ide/detect-ide.js +4 -1
  88. package/dist/src/ide/detect-ide.js.map +1 -1
  89. package/dist/src/ide/detect-ide.test.js +11 -0
  90. package/dist/src/ide/detect-ide.test.js.map +1 -1
  91. package/dist/src/ide/ide-client.js +3 -3
  92. package/dist/src/ide/ide-client.test.js +4 -4
  93. package/dist/src/ide/ide-installer.js +1 -1
  94. package/dist/src/ide/ide-installer.js.map +1 -1
  95. package/dist/src/ide/ide-installer.test.js +13 -1
  96. package/dist/src/ide/ide-installer.test.js.map +1 -1
  97. package/dist/src/index.d.ts +1 -0
  98. package/dist/src/index.js +1 -0
  99. package/dist/src/index.js.map +1 -1
  100. package/dist/src/mcp/sa-impersonation-provider.d.ts +33 -0
  101. package/dist/src/mcp/sa-impersonation-provider.js +130 -0
  102. package/dist/src/mcp/sa-impersonation-provider.js.map +1 -0
  103. package/dist/src/mcp/sa-impersonation-provider.test.d.ts +6 -0
  104. package/dist/src/mcp/sa-impersonation-provider.test.js +117 -0
  105. package/dist/src/mcp/sa-impersonation-provider.test.js.map +1 -0
  106. package/dist/src/services/chatRecordingService.d.ts +2 -1
  107. package/dist/src/services/chatRecordingService.js +2 -1
  108. package/dist/src/services/chatRecordingService.js.map +1 -1
  109. package/dist/src/services/fileSystemService.d.ts +9 -0
  110. package/dist/src/services/fileSystemService.js +11 -0
  111. package/dist/src/services/fileSystemService.js.map +1 -1
  112. package/dist/src/services/shellExecutionService.d.ts +2 -0
  113. package/dist/src/services/shellExecutionService.js +48 -7
  114. package/dist/src/services/shellExecutionService.js.map +1 -1
  115. package/dist/src/services/shellExecutionService.test.js +13 -4
  116. package/dist/src/services/shellExecutionService.test.js.map +1 -1
  117. package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +12 -2
  118. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +79 -9
  119. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
  120. package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js +99 -1
  121. package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js.map +1 -1
  122. package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +11 -3
  123. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +27 -4
  124. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
  125. package/dist/src/telemetry/constants.d.ts +6 -24
  126. package/dist/src/telemetry/constants.js +7 -25
  127. package/dist/src/telemetry/constants.js.map +1 -1
  128. package/dist/src/telemetry/index.d.ts +5 -3
  129. package/dist/src/telemetry/index.js +10 -3
  130. package/dist/src/telemetry/index.js.map +1 -1
  131. package/dist/src/telemetry/loggers.d.ts +6 -1
  132. package/dist/src/telemetry/loggers.js +132 -12
  133. package/dist/src/telemetry/loggers.js.map +1 -1
  134. package/dist/src/telemetry/loggers.test.circular.js +3 -3
  135. package/dist/src/telemetry/loggers.test.circular.js.map +1 -1
  136. package/dist/src/telemetry/loggers.test.js +160 -13
  137. package/dist/src/telemetry/loggers.test.js.map +1 -1
  138. package/dist/src/telemetry/memory-monitor.d.ts +149 -0
  139. package/dist/src/telemetry/memory-monitor.js +335 -0
  140. package/dist/src/telemetry/memory-monitor.js.map +1 -0
  141. package/dist/src/telemetry/memory-monitor.test.d.ts +6 -0
  142. package/dist/src/telemetry/memory-monitor.test.js +472 -0
  143. package/dist/src/telemetry/memory-monitor.test.js.map +1 -0
  144. package/dist/src/telemetry/metrics.d.ts +392 -20
  145. package/dist/src/telemetry/metrics.js +463 -235
  146. package/dist/src/telemetry/metrics.js.map +1 -1
  147. package/dist/src/telemetry/metrics.test.js +391 -55
  148. package/dist/src/telemetry/metrics.test.js.map +1 -1
  149. package/dist/src/telemetry/types.d.ts +37 -1
  150. package/dist/src/telemetry/types.js +60 -0
  151. package/dist/src/telemetry/types.js.map +1 -1
  152. package/dist/src/telemetry/uiTelemetry.test.js +2 -2
  153. package/dist/src/telemetry/uiTelemetry.test.js.map +1 -1
  154. package/dist/src/test-utils/mock-tool.d.ts +28 -3
  155. package/dist/src/test-utils/mock-tool.js +71 -1
  156. package/dist/src/test-utils/mock-tool.js.map +1 -1
  157. package/dist/src/tools/glob.js +2 -1
  158. package/dist/src/tools/glob.js.map +1 -1
  159. package/dist/src/tools/mcp-client.d.ts +3 -2
  160. package/dist/src/tools/mcp-client.js +44 -30
  161. package/dist/src/tools/mcp-client.js.map +1 -1
  162. package/dist/src/tools/mcp-client.test.js +168 -5
  163. package/dist/src/tools/mcp-client.test.js.map +1 -1
  164. package/dist/src/tools/shell.js +2 -2
  165. package/dist/src/tools/shell.js.map +1 -1
  166. package/dist/src/tools/shell.test.js +1 -1
  167. package/dist/src/tools/shell.test.js.map +1 -1
  168. package/dist/src/tools/smart-edit.d.ts +20 -1
  169. package/dist/src/tools/smart-edit.js +149 -9
  170. package/dist/src/tools/smart-edit.js.map +1 -1
  171. package/dist/src/tools/smart-edit.test.js +150 -29
  172. package/dist/src/tools/smart-edit.test.js.map +1 -1
  173. package/dist/src/tools/tool-names.d.ts +8 -0
  174. package/dist/src/tools/tool-names.js +17 -0
  175. package/dist/src/tools/tool-names.js.map +1 -0
  176. package/dist/src/tools/tool-registry.test.js +10 -10
  177. package/dist/src/tools/tool-registry.test.js.map +1 -1
  178. package/dist/src/tools/web-fetch.js +3 -0
  179. package/dist/src/tools/web-fetch.js.map +1 -1
  180. package/dist/src/tools/web-fetch.test.js +44 -0
  181. package/dist/src/tools/web-fetch.test.js.map +1 -1
  182. package/dist/src/tools/write-file.js +2 -1
  183. package/dist/src/tools/write-file.js.map +1 -1
  184. package/dist/src/tools/write-todos.d.ts +1 -1
  185. package/dist/src/tools/write-todos.js +4 -3
  186. package/dist/src/tools/write-todos.js.map +1 -1
  187. package/dist/src/utils/editCorrector.js +2 -2
  188. package/dist/src/utils/editCorrector.js.map +1 -1
  189. package/dist/src/utils/editor.js +1 -0
  190. package/dist/src/utils/editor.js.map +1 -1
  191. package/dist/src/utils/editor.test.js +1 -0
  192. package/dist/src/utils/editor.test.js.map +1 -1
  193. package/dist/src/utils/errorParsing.d.ts +1 -1
  194. package/dist/src/utils/errorParsing.js +5 -33
  195. package/dist/src/utils/errorParsing.js.map +1 -1
  196. package/dist/src/utils/errorParsing.test.js +0 -88
  197. package/dist/src/utils/errorParsing.test.js.map +1 -1
  198. package/dist/src/utils/flashFallback.test.js +26 -45
  199. package/dist/src/utils/flashFallback.test.js.map +1 -1
  200. package/dist/src/utils/formatters.d.ts +1 -0
  201. package/dist/src/utils/formatters.js +2 -1
  202. package/dist/src/utils/formatters.js.map +1 -1
  203. package/dist/src/utils/formatters.test.d.ts +6 -0
  204. package/dist/src/utils/formatters.test.js +26 -0
  205. package/dist/src/utils/formatters.test.js.map +1 -0
  206. package/dist/src/utils/googleErrors.d.ts +104 -0
  207. package/dist/src/utils/googleErrors.js +108 -0
  208. package/dist/src/utils/googleErrors.js.map +1 -0
  209. package/dist/src/utils/googleErrors.test.d.ts +6 -0
  210. package/dist/src/utils/googleErrors.test.js +212 -0
  211. package/dist/src/utils/googleErrors.test.js.map +1 -0
  212. package/dist/src/utils/googleQuotaErrors.d.ts +35 -0
  213. package/dist/src/utils/googleQuotaErrors.js +108 -0
  214. package/dist/src/utils/googleQuotaErrors.js.map +1 -0
  215. package/dist/src/utils/googleQuotaErrors.test.d.ts +6 -0
  216. package/dist/src/utils/googleQuotaErrors.test.js +189 -0
  217. package/dist/src/utils/googleQuotaErrors.test.js.map +1 -0
  218. package/dist/src/utils/llm-edit-fixer.js +13 -4
  219. package/dist/src/utils/llm-edit-fixer.js.map +1 -1
  220. package/dist/src/utils/llm-edit-fixer.test.js +81 -0
  221. package/dist/src/utils/llm-edit-fixer.test.js.map +1 -1
  222. package/dist/src/utils/memoryDiscovery.d.ts +1 -0
  223. package/dist/src/utils/memoryDiscovery.js +2 -1
  224. package/dist/src/utils/memoryDiscovery.js.map +1 -1
  225. package/dist/src/utils/memoryDiscovery.test.js +99 -21
  226. package/dist/src/utils/memoryDiscovery.test.js.map +1 -1
  227. package/dist/src/utils/memoryImportProcessor.js +13 -20
  228. package/dist/src/utils/memoryImportProcessor.js.map +1 -1
  229. package/dist/src/utils/memoryImportProcessor.test.js +14 -0
  230. package/dist/src/utils/memoryImportProcessor.test.js.map +1 -1
  231. package/dist/src/utils/quotaErrorDetection.d.ts +0 -2
  232. package/dist/src/utils/quotaErrorDetection.js +0 -46
  233. package/dist/src/utils/quotaErrorDetection.js.map +1 -1
  234. package/dist/src/utils/retry.d.ts +3 -1
  235. package/dist/src/utils/retry.js +53 -161
  236. package/dist/src/utils/retry.js.map +1 -1
  237. package/dist/src/utils/retry.test.js +87 -146
  238. package/dist/src/utils/retry.test.js.map +1 -1
  239. package/dist/src/utils/terminalSerializer.d.ts +1 -4
  240. package/dist/src/utils/terminalSerializer.js +3 -3
  241. package/dist/src/utils/terminalSerializer.js.map +1 -1
  242. package/dist/tsconfig.tsbuildinfo +1 -1
  243. package/package.json +1 -1
  244. package/dist/src/test-utils/tools.d.ts +0 -45
  245. package/dist/src/test-utils/tools.js +0 -105
  246. package/dist/src/test-utils/tools.js.map +0 -1
@@ -6,7 +6,8 @@
6
6
  import { describe, it, expect, vi, beforeEach } from 'vitest';
7
7
  import { FileOperation, MemoryMetricType, ToolExecutionPhase, ApiRequestPhase, } from './metrics.js';
8
8
  import { makeFakeConfig } from '../test-utils/config.js';
9
- import { ModelRoutingEvent } from './types.js';
9
+ import { ModelRoutingEvent, AgentFinishEvent } from './types.js';
10
+ import { AgentTerminateMode } from '../agents/types.js';
10
11
  const mockCounterAddFn = vi.fn();
11
12
  const mockHistogramRecordFn = vi.fn();
12
13
  const mockCreateCounterFn = vi.fn();
@@ -34,6 +35,11 @@ function originalOtelMockFactory() {
34
35
  setLogger: vi.fn(),
35
36
  warn: vi.fn(),
36
37
  },
38
+ DiagConsoleLogger: vi.fn(),
39
+ DiagLogLevel: {
40
+ NONE: 0,
41
+ INFO: 1,
42
+ },
37
43
  };
38
44
  }
39
45
  vi.mock('@opentelemetry/api');
@@ -53,6 +59,9 @@ describe('Telemetry Metrics', () => {
53
59
  let recordPerformanceScoreModule;
54
60
  let recordPerformanceRegressionModule;
55
61
  let recordBaselineComparisonModule;
62
+ let recordGenAiClientTokenUsageModule;
63
+ let recordGenAiClientOperationDurationModule;
64
+ let recordAgentRunMetricsModule;
56
65
  beforeEach(async () => {
57
66
  vi.resetModules();
58
67
  vi.doMock('@opentelemetry/api', () => {
@@ -79,6 +88,11 @@ describe('Telemetry Metrics', () => {
79
88
  recordPerformanceRegressionModule =
80
89
  metricsJsModule.recordPerformanceRegression;
81
90
  recordBaselineComparisonModule = metricsJsModule.recordBaselineComparison;
91
+ recordGenAiClientTokenUsageModule =
92
+ metricsJsModule.recordGenAiClientTokenUsage;
93
+ recordGenAiClientOperationDurationModule =
94
+ metricsJsModule.recordGenAiClientOperationDuration;
95
+ recordAgentRunMetricsModule = metricsJsModule.recordAgentRunMetrics;
82
96
  const otelApiModule = await import('@opentelemetry/api');
83
97
  mockCounterAddFn.mockClear();
84
98
  mockCreateCounterFn.mockClear();
@@ -118,12 +132,18 @@ describe('Telemetry Metrics', () => {
118
132
  getTelemetryEnabled: () => true,
119
133
  };
120
134
  it('should not record metrics if not initialized', () => {
121
- recordTokenUsageMetricsModule(mockConfig, 'gemini-pro', 100, 'input');
135
+ recordTokenUsageMetricsModule(mockConfig, 100, {
136
+ model: 'gemini-pro',
137
+ type: 'input',
138
+ });
122
139
  expect(mockCounterAddFn).not.toHaveBeenCalled();
123
140
  });
124
141
  it('should record token usage with the correct attributes', () => {
125
142
  initializeMetricsModule(mockConfig);
126
- recordTokenUsageMetricsModule(mockConfig, 'gemini-pro', 100, 'input');
143
+ recordTokenUsageMetricsModule(mockConfig, 100, {
144
+ model: 'gemini-pro',
145
+ type: 'input',
146
+ });
127
147
  expect(mockCounterAddFn).toHaveBeenCalledTimes(2);
128
148
  expect(mockCounterAddFn).toHaveBeenNthCalledWith(1, 1, {
129
149
  'session.id': 'test-session-id',
@@ -137,25 +157,37 @@ describe('Telemetry Metrics', () => {
137
157
  it('should record token usage for different types', () => {
138
158
  initializeMetricsModule(mockConfig);
139
159
  mockCounterAddFn.mockClear();
140
- recordTokenUsageMetricsModule(mockConfig, 'gemini-pro', 50, 'output');
160
+ recordTokenUsageMetricsModule(mockConfig, 50, {
161
+ model: 'gemini-pro',
162
+ type: 'output',
163
+ });
141
164
  expect(mockCounterAddFn).toHaveBeenCalledWith(50, {
142
165
  'session.id': 'test-session-id',
143
166
  model: 'gemini-pro',
144
167
  type: 'output',
145
168
  });
146
- recordTokenUsageMetricsModule(mockConfig, 'gemini-pro', 25, 'thought');
169
+ recordTokenUsageMetricsModule(mockConfig, 25, {
170
+ model: 'gemini-pro',
171
+ type: 'thought',
172
+ });
147
173
  expect(mockCounterAddFn).toHaveBeenCalledWith(25, {
148
174
  'session.id': 'test-session-id',
149
175
  model: 'gemini-pro',
150
176
  type: 'thought',
151
177
  });
152
- recordTokenUsageMetricsModule(mockConfig, 'gemini-pro', 75, 'cache');
178
+ recordTokenUsageMetricsModule(mockConfig, 75, {
179
+ model: 'gemini-pro',
180
+ type: 'cache',
181
+ });
153
182
  expect(mockCounterAddFn).toHaveBeenCalledWith(75, {
154
183
  'session.id': 'test-session-id',
155
184
  model: 'gemini-pro',
156
185
  type: 'cache',
157
186
  });
158
- recordTokenUsageMetricsModule(mockConfig, 'gemini-pro', 125, 'tool');
187
+ recordTokenUsageMetricsModule(mockConfig, 125, {
188
+ model: 'gemini-pro',
189
+ type: 'tool',
190
+ });
159
191
  expect(mockCounterAddFn).toHaveBeenCalledWith(125, {
160
192
  'session.id': 'test-session-id',
161
193
  model: 'gemini-pro',
@@ -165,7 +197,10 @@ describe('Telemetry Metrics', () => {
165
197
  it('should handle different models', () => {
166
198
  initializeMetricsModule(mockConfig);
167
199
  mockCounterAddFn.mockClear();
168
- recordTokenUsageMetricsModule(mockConfig, 'gemini-ultra', 200, 'input');
200
+ recordTokenUsageMetricsModule(mockConfig, 200, {
201
+ model: 'gemini-ultra',
202
+ type: 'input',
203
+ });
169
204
  expect(mockCounterAddFn).toHaveBeenCalledWith(200, {
170
205
  'session.id': 'test-session-id',
171
206
  model: 'gemini-ultra',
@@ -179,12 +214,22 @@ describe('Telemetry Metrics', () => {
179
214
  getTelemetryEnabled: () => true,
180
215
  };
181
216
  it('should not record metrics if not initialized', () => {
182
- recordFileOperationMetricModule(mockConfig, FileOperation.CREATE, 10, 'text/plain', 'txt');
217
+ recordFileOperationMetricModule(mockConfig, {
218
+ operation: FileOperation.CREATE,
219
+ lines: 10,
220
+ mimetype: 'text/plain',
221
+ extension: 'txt',
222
+ });
183
223
  expect(mockCounterAddFn).not.toHaveBeenCalled();
184
224
  });
185
225
  it('should record file creation with all attributes', () => {
186
226
  initializeMetricsModule(mockConfig);
187
- recordFileOperationMetricModule(mockConfig, FileOperation.CREATE, 10, 'text/plain', 'txt');
227
+ recordFileOperationMetricModule(mockConfig, {
228
+ operation: FileOperation.CREATE,
229
+ lines: 10,
230
+ mimetype: 'text/plain',
231
+ extension: 'txt',
232
+ });
188
233
  expect(mockCounterAddFn).toHaveBeenCalledTimes(2);
189
234
  expect(mockCounterAddFn).toHaveBeenNthCalledWith(1, 1, {
190
235
  'session.id': 'test-session-id',
@@ -200,7 +245,9 @@ describe('Telemetry Metrics', () => {
200
245
  it('should record file read with minimal attributes', () => {
201
246
  initializeMetricsModule(mockConfig);
202
247
  mockCounterAddFn.mockClear();
203
- recordFileOperationMetricModule(mockConfig, FileOperation.READ);
248
+ recordFileOperationMetricModule(mockConfig, {
249
+ operation: FileOperation.READ,
250
+ });
204
251
  expect(mockCounterAddFn).toHaveBeenCalledWith(1, {
205
252
  'session.id': 'test-session-id',
206
253
  operation: FileOperation.READ,
@@ -209,7 +256,10 @@ describe('Telemetry Metrics', () => {
209
256
  it('should record file update with some attributes', () => {
210
257
  initializeMetricsModule(mockConfig);
211
258
  mockCounterAddFn.mockClear();
212
- recordFileOperationMetricModule(mockConfig, FileOperation.UPDATE, undefined, 'application/javascript');
259
+ recordFileOperationMetricModule(mockConfig, {
260
+ operation: FileOperation.UPDATE,
261
+ mimetype: 'application/javascript',
262
+ });
213
263
  expect(mockCounterAddFn).toHaveBeenCalledWith(1, {
214
264
  'session.id': 'test-session-id',
215
265
  operation: FileOperation.UPDATE,
@@ -219,7 +269,9 @@ describe('Telemetry Metrics', () => {
219
269
  it('should record file operation without diffStat', () => {
220
270
  initializeMetricsModule(mockConfig);
221
271
  mockCounterAddFn.mockClear();
222
- recordFileOperationMetricModule(mockConfig, FileOperation.UPDATE, undefined, undefined, undefined);
272
+ recordFileOperationMetricModule(mockConfig, {
273
+ operation: FileOperation.UPDATE,
274
+ });
223
275
  expect(mockCounterAddFn).toHaveBeenCalledWith(1, {
224
276
  'session.id': 'test-session-id',
225
277
  operation: FileOperation.UPDATE,
@@ -228,7 +280,12 @@ describe('Telemetry Metrics', () => {
228
280
  it('should record minimal file operation when optional parameters are undefined', () => {
229
281
  initializeMetricsModule(mockConfig);
230
282
  mockCounterAddFn.mockClear();
231
- recordFileOperationMetricModule(mockConfig, FileOperation.UPDATE, 10, 'text/plain', 'txt', undefined);
283
+ recordFileOperationMetricModule(mockConfig, {
284
+ operation: FileOperation.UPDATE,
285
+ lines: 10,
286
+ mimetype: 'text/plain',
287
+ extension: 'txt',
288
+ });
232
289
  expect(mockCounterAddFn).toHaveBeenCalledWith(1, {
233
290
  'session.id': 'test-session-id',
234
291
  operation: FileOperation.UPDATE,
@@ -240,7 +297,9 @@ describe('Telemetry Metrics', () => {
240
297
  it('should not include diffStat attributes when diffStat is not provided', () => {
241
298
  initializeMetricsModule(mockConfig);
242
299
  mockCounterAddFn.mockClear();
243
- recordFileOperationMetricModule(mockConfig, FileOperation.UPDATE, undefined, undefined, undefined);
300
+ recordFileOperationMetricModule(mockConfig, {
301
+ operation: FileOperation.UPDATE,
302
+ });
244
303
  expect(mockCounterAddFn).toHaveBeenCalledWith(1, {
245
304
  'session.id': 'test-session-id',
246
305
  operation: FileOperation.UPDATE,
@@ -287,6 +346,191 @@ describe('Telemetry Metrics', () => {
287
346
  });
288
347
  });
289
348
  });
349
+ describe('recordAgentRunMetrics', () => {
350
+ const mockConfig = {
351
+ getSessionId: () => 'test-session-id',
352
+ getTelemetryEnabled: () => true,
353
+ };
354
+ it('should not record metrics if not initialized', () => {
355
+ const event = new AgentFinishEvent('agent-123', 'TestAgent', 1000, 5, AgentTerminateMode.GOAL);
356
+ recordAgentRunMetricsModule(mockConfig, event);
357
+ expect(mockCounterAddFn).not.toHaveBeenCalled();
358
+ expect(mockHistogramRecordFn).not.toHaveBeenCalled();
359
+ });
360
+ it('should record agent run metrics', () => {
361
+ initializeMetricsModule(mockConfig);
362
+ mockCounterAddFn.mockClear();
363
+ mockHistogramRecordFn.mockClear();
364
+ const event = new AgentFinishEvent('agent-123', 'TestAgent', 1000, 5, AgentTerminateMode.GOAL);
365
+ recordAgentRunMetricsModule(mockConfig, event);
366
+ // Verify agent run counter
367
+ expect(mockCounterAddFn).toHaveBeenCalledWith(1, {
368
+ 'session.id': 'test-session-id',
369
+ agent_name: 'TestAgent',
370
+ terminate_reason: 'GOAL',
371
+ });
372
+ // Verify agent duration histogram
373
+ expect(mockHistogramRecordFn).toHaveBeenCalledWith(1000, {
374
+ 'session.id': 'test-session-id',
375
+ agent_name: 'TestAgent',
376
+ });
377
+ // Verify agent turns histogram
378
+ expect(mockHistogramRecordFn).toHaveBeenCalledWith(5, {
379
+ 'session.id': 'test-session-id',
380
+ agent_name: 'TestAgent',
381
+ });
382
+ });
383
+ });
384
+ describe('OpenTelemetry GenAI Semantic Convention Metrics', () => {
385
+ const mockConfig = {
386
+ getSessionId: () => 'test-session-id',
387
+ getTelemetryEnabled: () => true,
388
+ };
389
+ describe('recordGenAiClientTokenUsage', () => {
390
+ it('should not record metrics when not initialized', () => {
391
+ recordGenAiClientTokenUsageModule(mockConfig, 100, {
392
+ 'gen_ai.operation.name': 'generate_content',
393
+ 'gen_ai.provider.name': 'gcp.gen_ai',
394
+ 'gen_ai.token.type': 'input',
395
+ });
396
+ expect(mockHistogramRecordFn).not.toHaveBeenCalled();
397
+ });
398
+ it('should record input token usage with correct attributes', () => {
399
+ initializeMetricsModule(mockConfig);
400
+ mockHistogramRecordFn.mockClear();
401
+ recordGenAiClientTokenUsageModule(mockConfig, 150, {
402
+ 'gen_ai.operation.name': 'generate_content',
403
+ 'gen_ai.provider.name': 'gcp.gen_ai',
404
+ 'gen_ai.token.type': 'input',
405
+ 'gen_ai.request.model': 'gemini-2.0-flash',
406
+ 'gen_ai.response.model': 'gemini-2.0-flash',
407
+ });
408
+ expect(mockHistogramRecordFn).toHaveBeenCalledWith(150, {
409
+ 'session.id': 'test-session-id',
410
+ 'gen_ai.operation.name': 'generate_content',
411
+ 'gen_ai.provider.name': 'gcp.gen_ai',
412
+ 'gen_ai.token.type': 'input',
413
+ 'gen_ai.request.model': 'gemini-2.0-flash',
414
+ 'gen_ai.response.model': 'gemini-2.0-flash',
415
+ });
416
+ });
417
+ it('should record output token usage with correct attributes', () => {
418
+ initializeMetricsModule(mockConfig);
419
+ mockHistogramRecordFn.mockClear();
420
+ recordGenAiClientTokenUsageModule(mockConfig, 75, {
421
+ 'gen_ai.operation.name': 'generate_content',
422
+ 'gen_ai.provider.name': 'gcp.vertex_ai',
423
+ 'gen_ai.token.type': 'output',
424
+ 'gen_ai.request.model': 'gemini-pro',
425
+ });
426
+ expect(mockHistogramRecordFn).toHaveBeenCalledWith(75, {
427
+ 'session.id': 'test-session-id',
428
+ 'gen_ai.operation.name': 'generate_content',
429
+ 'gen_ai.provider.name': 'gcp.vertex_ai',
430
+ 'gen_ai.token.type': 'output',
431
+ 'gen_ai.request.model': 'gemini-pro',
432
+ });
433
+ });
434
+ it('should record token usage with optional attributes', () => {
435
+ initializeMetricsModule(mockConfig);
436
+ mockHistogramRecordFn.mockClear();
437
+ recordGenAiClientTokenUsageModule(mockConfig, 200, {
438
+ 'gen_ai.operation.name': 'generate_content',
439
+ 'gen_ai.provider.name': 'gcp.vertex_ai',
440
+ 'gen_ai.token.type': 'input',
441
+ 'gen_ai.request.model': 'text-embedding-004',
442
+ 'server.address': 'aiplatform.googleapis.com',
443
+ 'server.port': 443,
444
+ });
445
+ expect(mockHistogramRecordFn).toHaveBeenCalledWith(200, {
446
+ 'session.id': 'test-session-id',
447
+ 'gen_ai.operation.name': 'generate_content',
448
+ 'gen_ai.provider.name': 'gcp.vertex_ai',
449
+ 'gen_ai.token.type': 'input',
450
+ 'gen_ai.request.model': 'text-embedding-004',
451
+ 'server.address': 'aiplatform.googleapis.com',
452
+ 'server.port': 443,
453
+ });
454
+ });
455
+ });
456
+ describe('recordGenAiClientOperationDuration', () => {
457
+ it('should not record metrics when not initialized', () => {
458
+ recordGenAiClientOperationDurationModule(mockConfig, 2.5, {
459
+ 'gen_ai.operation.name': 'generate_content',
460
+ 'gen_ai.provider.name': 'gcp.gen_ai',
461
+ });
462
+ expect(mockHistogramRecordFn).not.toHaveBeenCalled();
463
+ });
464
+ it('should record successful operation duration with correct attributes', () => {
465
+ initializeMetricsModule(mockConfig);
466
+ mockHistogramRecordFn.mockClear();
467
+ recordGenAiClientOperationDurationModule(mockConfig, 1.25, {
468
+ 'gen_ai.operation.name': 'generate_content',
469
+ 'gen_ai.provider.name': 'gcp.gen_ai',
470
+ 'gen_ai.request.model': 'gemini-2.0-flash',
471
+ 'gen_ai.response.model': 'gemini-2.0-flash',
472
+ });
473
+ expect(mockHistogramRecordFn).toHaveBeenCalledWith(1.25, {
474
+ 'session.id': 'test-session-id',
475
+ 'gen_ai.operation.name': 'generate_content',
476
+ 'gen_ai.provider.name': 'gcp.gen_ai',
477
+ 'gen_ai.request.model': 'gemini-2.0-flash',
478
+ 'gen_ai.response.model': 'gemini-2.0-flash',
479
+ });
480
+ });
481
+ it('should record failed operation duration with error type', () => {
482
+ initializeMetricsModule(mockConfig);
483
+ mockHistogramRecordFn.mockClear();
484
+ recordGenAiClientOperationDurationModule(mockConfig, 3.75, {
485
+ 'gen_ai.operation.name': 'generate_content',
486
+ 'gen_ai.provider.name': 'gcp.vertex_ai',
487
+ 'gen_ai.request.model': 'gemini-pro',
488
+ 'error.type': 'quota_exceeded',
489
+ });
490
+ expect(mockHistogramRecordFn).toHaveBeenCalledWith(3.75, {
491
+ 'session.id': 'test-session-id',
492
+ 'gen_ai.operation.name': 'generate_content',
493
+ 'gen_ai.provider.name': 'gcp.vertex_ai',
494
+ 'gen_ai.request.model': 'gemini-pro',
495
+ 'error.type': 'quota_exceeded',
496
+ });
497
+ });
498
+ it('should record operation duration with server details', () => {
499
+ initializeMetricsModule(mockConfig);
500
+ mockHistogramRecordFn.mockClear();
501
+ recordGenAiClientOperationDurationModule(mockConfig, 0.95, {
502
+ 'gen_ai.operation.name': 'generate_content',
503
+ 'gen_ai.provider.name': 'gcp.vertex_ai',
504
+ 'gen_ai.request.model': 'gemini-1.5-pro',
505
+ 'gen_ai.response.model': 'gemini-1.5-pro-001',
506
+ 'server.address': 'us-central1-aiplatform.googleapis.com',
507
+ 'server.port': 443,
508
+ });
509
+ expect(mockHistogramRecordFn).toHaveBeenCalledWith(0.95, {
510
+ 'session.id': 'test-session-id',
511
+ 'gen_ai.operation.name': 'generate_content',
512
+ 'gen_ai.provider.name': 'gcp.vertex_ai',
513
+ 'gen_ai.request.model': 'gemini-1.5-pro',
514
+ 'gen_ai.response.model': 'gemini-1.5-pro-001',
515
+ 'server.address': 'us-central1-aiplatform.googleapis.com',
516
+ 'server.port': 443,
517
+ });
518
+ });
519
+ it('should handle minimal required attributes', () => {
520
+ initializeMetricsModule(mockConfig);
521
+ mockHistogramRecordFn.mockClear();
522
+ recordGenAiClientOperationDurationModule(mockConfig, 2.1, {
523
+ 'gen_ai.operation.name': 'generate_content',
524
+ 'gen_ai.provider.name': 'gcp.gen_ai',
525
+ });
526
+ expect(mockHistogramRecordFn).toHaveBeenCalledWith(2.1, {
527
+ 'session.id': 'test-session-id',
528
+ 'gen_ai.operation.name': 'generate_content',
529
+ 'gen_ai.provider.name': 'gcp.gen_ai',
530
+ });
531
+ });
532
+ });
533
+ });
290
534
  describe('Performance Monitoring Metrics', () => {
291
535
  const mockConfig = {
292
536
  getSessionId: () => 'test-session-id',
@@ -301,18 +545,24 @@ describe('Telemetry Metrics', () => {
301
545
  };
302
546
  initializeMetricsModule(mockConfigDisabled);
303
547
  mockHistogramRecordFn.mockClear();
304
- recordStartupPerformanceModule(mockConfigDisabled, 'settings_loading', 100, {
305
- auth_type: 'gemini',
548
+ recordStartupPerformanceModule(mockConfigDisabled, 100, {
549
+ phase: 'settings_loading',
550
+ details: {
551
+ auth_type: 'gemini',
552
+ },
306
553
  });
307
554
  expect(mockHistogramRecordFn).not.toHaveBeenCalled();
308
555
  });
309
556
  it('should record startup performance with phase and details', () => {
310
557
  initializeMetricsModule(mockConfig);
311
558
  mockHistogramRecordFn.mockClear();
312
- recordStartupPerformanceModule(mockConfig, 'settings_loading', 150, {
313
- auth_type: 'gemini',
314
- telemetry_enabled: true,
315
- settings_sources: 2,
559
+ recordStartupPerformanceModule(mockConfig, 150, {
560
+ phase: 'settings_loading',
561
+ details: {
562
+ auth_type: 'gemini',
563
+ telemetry_enabled: true,
564
+ settings_sources: 2,
565
+ },
316
566
  });
317
567
  expect(mockHistogramRecordFn).toHaveBeenCalledWith(150, {
318
568
  'session.id': 'test-session-id',
@@ -325,7 +575,7 @@ describe('Telemetry Metrics', () => {
325
575
  it('should record startup performance without details', () => {
326
576
  initializeMetricsModule(mockConfig);
327
577
  mockHistogramRecordFn.mockClear();
328
- recordStartupPerformanceModule(mockConfig, 'cleanup', 50);
578
+ recordStartupPerformanceModule(mockConfig, 50, { phase: 'cleanup' });
329
579
  expect(mockHistogramRecordFn).toHaveBeenCalledWith(50, {
330
580
  'session.id': 'test-session-id',
331
581
  phase: 'cleanup',
@@ -336,9 +586,12 @@ describe('Telemetry Metrics', () => {
336
586
  mockHistogramRecordFn.mockClear();
337
587
  // Test with realistic floating-point values that performance.now() would return
338
588
  const floatingPointDuration = 123.45678;
339
- recordStartupPerformanceModule(mockConfig, 'total_startup', floatingPointDuration, {
340
- is_tty: true,
341
- has_question: false,
589
+ recordStartupPerformanceModule(mockConfig, floatingPointDuration, {
590
+ phase: 'total_startup',
591
+ details: {
592
+ is_tty: true,
593
+ has_question: false,
594
+ },
342
595
  });
343
596
  expect(mockHistogramRecordFn).toHaveBeenCalledWith(floatingPointDuration, {
344
597
  'session.id': 'test-session-id',
@@ -352,7 +605,10 @@ describe('Telemetry Metrics', () => {
352
605
  it('should record memory usage for different memory types', () => {
353
606
  initializeMetricsModule(mockConfig);
354
607
  mockHistogramRecordFn.mockClear();
355
- recordMemoryUsageModule(mockConfig, MemoryMetricType.HEAP_USED, 15728640, 'startup');
608
+ recordMemoryUsageModule(mockConfig, 15728640, {
609
+ memory_type: MemoryMetricType.HEAP_USED,
610
+ component: 'startup',
611
+ });
356
612
  expect(mockHistogramRecordFn).toHaveBeenCalledWith(15728640, {
357
613
  'session.id': 'test-session-id',
358
614
  memory_type: 'heap_used',
@@ -362,9 +618,18 @@ describe('Telemetry Metrics', () => {
362
618
  it('should record memory usage for all memory metric types', () => {
363
619
  initializeMetricsModule(mockConfig);
364
620
  mockHistogramRecordFn.mockClear();
365
- recordMemoryUsageModule(mockConfig, MemoryMetricType.HEAP_TOTAL, 31457280, 'api_call');
366
- recordMemoryUsageModule(mockConfig, MemoryMetricType.EXTERNAL, 2097152, 'tool_execution');
367
- recordMemoryUsageModule(mockConfig, MemoryMetricType.RSS, 41943040, 'memory_monitor');
621
+ recordMemoryUsageModule(mockConfig, 31457280, {
622
+ memory_type: MemoryMetricType.HEAP_TOTAL,
623
+ component: 'api_call',
624
+ });
625
+ recordMemoryUsageModule(mockConfig, 2097152, {
626
+ memory_type: MemoryMetricType.EXTERNAL,
627
+ component: 'tool_execution',
628
+ });
629
+ recordMemoryUsageModule(mockConfig, 41943040, {
630
+ memory_type: MemoryMetricType.RSS,
631
+ component: 'memory_monitor',
632
+ });
368
633
  expect(mockHistogramRecordFn).toHaveBeenCalledTimes(3); // One for each call
369
634
  expect(mockHistogramRecordFn).toHaveBeenNthCalledWith(1, 31457280, {
370
635
  'session.id': 'test-session-id',
@@ -385,11 +650,12 @@ describe('Telemetry Metrics', () => {
385
650
  it('should record memory usage without component', () => {
386
651
  initializeMetricsModule(mockConfig);
387
652
  mockHistogramRecordFn.mockClear();
388
- recordMemoryUsageModule(mockConfig, MemoryMetricType.HEAP_USED, 15728640);
653
+ recordMemoryUsageModule(mockConfig, 15728640, {
654
+ memory_type: MemoryMetricType.HEAP_USED,
655
+ });
389
656
  expect(mockHistogramRecordFn).toHaveBeenCalledWith(15728640, {
390
657
  'session.id': 'test-session-id',
391
658
  memory_type: 'heap_used',
392
- component: undefined,
393
659
  });
394
660
  });
395
661
  });
@@ -397,7 +663,9 @@ describe('Telemetry Metrics', () => {
397
663
  it('should record CPU usage percentage', () => {
398
664
  initializeMetricsModule(mockConfig);
399
665
  mockHistogramRecordFn.mockClear();
400
- recordCpuUsageModule(mockConfig, 85.5, 'tool_execution');
666
+ recordCpuUsageModule(mockConfig, 85.5, {
667
+ component: 'tool_execution',
668
+ });
401
669
  expect(mockHistogramRecordFn).toHaveBeenCalledWith(85.5, {
402
670
  'session.id': 'test-session-id',
403
671
  component: 'tool_execution',
@@ -406,10 +674,9 @@ describe('Telemetry Metrics', () => {
406
674
  it('should record CPU usage without component', () => {
407
675
  initializeMetricsModule(mockConfig);
408
676
  mockHistogramRecordFn.mockClear();
409
- recordCpuUsageModule(mockConfig, 42.3);
677
+ recordCpuUsageModule(mockConfig, 42.3, {});
410
678
  expect(mockHistogramRecordFn).toHaveBeenCalledWith(42.3, {
411
679
  'session.id': 'test-session-id',
412
- component: undefined,
413
680
  });
414
681
  });
415
682
  });
@@ -435,7 +702,10 @@ describe('Telemetry Metrics', () => {
435
702
  it('should record tool execution breakdown for all phases', () => {
436
703
  initializeMetricsModule(mockConfig);
437
704
  mockHistogramRecordFn.mockClear();
438
- recordToolExecutionBreakdownModule(mockConfig, 'Read', ToolExecutionPhase.VALIDATION, 25);
705
+ recordToolExecutionBreakdownModule(mockConfig, 25, {
706
+ function_name: 'Read',
707
+ phase: ToolExecutionPhase.VALIDATION,
708
+ });
439
709
  expect(mockHistogramRecordFn).toHaveBeenCalledWith(25, {
440
710
  'session.id': 'test-session-id',
441
711
  function_name: 'Read',
@@ -445,9 +715,18 @@ describe('Telemetry Metrics', () => {
445
715
  it('should record execution breakdown for different phases', () => {
446
716
  initializeMetricsModule(mockConfig);
447
717
  mockHistogramRecordFn.mockClear();
448
- recordToolExecutionBreakdownModule(mockConfig, 'Bash', ToolExecutionPhase.PREPARATION, 50);
449
- recordToolExecutionBreakdownModule(mockConfig, 'Bash', ToolExecutionPhase.EXECUTION, 1500);
450
- recordToolExecutionBreakdownModule(mockConfig, 'Bash', ToolExecutionPhase.RESULT_PROCESSING, 75);
718
+ recordToolExecutionBreakdownModule(mockConfig, 50, {
719
+ function_name: 'Bash',
720
+ phase: ToolExecutionPhase.PREPARATION,
721
+ });
722
+ recordToolExecutionBreakdownModule(mockConfig, 1500, {
723
+ function_name: 'Bash',
724
+ phase: ToolExecutionPhase.EXECUTION,
725
+ });
726
+ recordToolExecutionBreakdownModule(mockConfig, 75, {
727
+ function_name: 'Bash',
728
+ phase: ToolExecutionPhase.RESULT_PROCESSING,
729
+ });
451
730
  expect(mockHistogramRecordFn).toHaveBeenCalledTimes(3); // One for each call
452
731
  expect(mockHistogramRecordFn).toHaveBeenNthCalledWith(1, 50, {
453
732
  'session.id': 'test-session-id',
@@ -470,7 +749,11 @@ describe('Telemetry Metrics', () => {
470
749
  it('should record token efficiency metrics', () => {
471
750
  initializeMetricsModule(mockConfig);
472
751
  mockHistogramRecordFn.mockClear();
473
- recordTokenEfficiencyModule(mockConfig, 'gemini-pro', 'cache_hit_rate', 0.85, 'api_request');
752
+ recordTokenEfficiencyModule(mockConfig, 0.85, {
753
+ model: 'gemini-pro',
754
+ metric: 'cache_hit_rate',
755
+ context: 'api_request',
756
+ });
474
757
  expect(mockHistogramRecordFn).toHaveBeenCalledWith(0.85, {
475
758
  'session.id': 'test-session-id',
476
759
  model: 'gemini-pro',
@@ -481,12 +764,14 @@ describe('Telemetry Metrics', () => {
481
764
  it('should record token efficiency without context', () => {
482
765
  initializeMetricsModule(mockConfig);
483
766
  mockHistogramRecordFn.mockClear();
484
- recordTokenEfficiencyModule(mockConfig, 'gemini-pro', 'tokens_per_operation', 125.5);
767
+ recordTokenEfficiencyModule(mockConfig, 125.5, {
768
+ model: 'gemini-pro',
769
+ metric: 'tokens_per_operation',
770
+ });
485
771
  expect(mockHistogramRecordFn).toHaveBeenCalledWith(125.5, {
486
772
  'session.id': 'test-session-id',
487
773
  model: 'gemini-pro',
488
774
  metric: 'tokens_per_operation',
489
- context: undefined,
490
775
  });
491
776
  });
492
777
  });
@@ -494,7 +779,10 @@ describe('Telemetry Metrics', () => {
494
779
  it('should record API request breakdown for all phases', () => {
495
780
  initializeMetricsModule(mockConfig);
496
781
  mockHistogramRecordFn.mockClear();
497
- recordApiRequestBreakdownModule(mockConfig, 'gemini-pro', ApiRequestPhase.REQUEST_PREPARATION, 15);
782
+ recordApiRequestBreakdownModule(mockConfig, 15, {
783
+ model: 'gemini-pro',
784
+ phase: ApiRequestPhase.REQUEST_PREPARATION,
785
+ });
498
786
  expect(mockHistogramRecordFn).toHaveBeenCalledWith(15, {
499
787
  'session.id': 'test-session-id',
500
788
  model: 'gemini-pro',
@@ -504,9 +792,18 @@ describe('Telemetry Metrics', () => {
504
792
  it('should record API request breakdown for different phases', () => {
505
793
  initializeMetricsModule(mockConfig);
506
794
  mockHistogramRecordFn.mockClear();
507
- recordApiRequestBreakdownModule(mockConfig, 'gemini-pro', ApiRequestPhase.NETWORK_LATENCY, 250);
508
- recordApiRequestBreakdownModule(mockConfig, 'gemini-pro', ApiRequestPhase.RESPONSE_PROCESSING, 100);
509
- recordApiRequestBreakdownModule(mockConfig, 'gemini-pro', ApiRequestPhase.TOKEN_PROCESSING, 50);
795
+ recordApiRequestBreakdownModule(mockConfig, 250, {
796
+ model: 'gemini-pro',
797
+ phase: ApiRequestPhase.NETWORK_LATENCY,
798
+ });
799
+ recordApiRequestBreakdownModule(mockConfig, 100, {
800
+ model: 'gemini-pro',
801
+ phase: ApiRequestPhase.RESPONSE_PROCESSING,
802
+ });
803
+ recordApiRequestBreakdownModule(mockConfig, 50, {
804
+ model: 'gemini-pro',
805
+ phase: ApiRequestPhase.TOKEN_PROCESSING,
806
+ });
510
807
  expect(mockHistogramRecordFn).toHaveBeenCalledTimes(3); // One for each call
511
808
  expect(mockHistogramRecordFn).toHaveBeenNthCalledWith(1, 250, {
512
809
  'session.id': 'test-session-id',
@@ -529,7 +826,10 @@ describe('Telemetry Metrics', () => {
529
826
  it('should record performance score with category and baseline', () => {
530
827
  initializeMetricsModule(mockConfig);
531
828
  mockHistogramRecordFn.mockClear();
532
- recordPerformanceScoreModule(mockConfig, 85.5, 'memory_efficiency', 80.0);
829
+ recordPerformanceScoreModule(mockConfig, 85.5, {
830
+ category: 'memory_efficiency',
831
+ baseline: 80.0,
832
+ });
533
833
  expect(mockHistogramRecordFn).toHaveBeenCalledWith(85.5, {
534
834
  'session.id': 'test-session-id',
535
835
  category: 'memory_efficiency',
@@ -539,11 +839,12 @@ describe('Telemetry Metrics', () => {
539
839
  it('should record performance score without baseline', () => {
540
840
  initializeMetricsModule(mockConfig);
541
841
  mockHistogramRecordFn.mockClear();
542
- recordPerformanceScoreModule(mockConfig, 92.3, 'overall_performance');
842
+ recordPerformanceScoreModule(mockConfig, 92.3, {
843
+ category: 'overall_performance',
844
+ });
543
845
  expect(mockHistogramRecordFn).toHaveBeenCalledWith(92.3, {
544
846
  'session.id': 'test-session-id',
545
847
  category: 'overall_performance',
546
- baseline: undefined,
547
848
  });
548
849
  });
549
850
  });
@@ -552,7 +853,12 @@ describe('Telemetry Metrics', () => {
552
853
  initializeMetricsModule(mockConfig);
553
854
  mockCounterAddFn.mockClear();
554
855
  mockHistogramRecordFn.mockClear();
555
- recordPerformanceRegressionModule(mockConfig, 'startup_time', 1200, 1000, 'medium');
856
+ recordPerformanceRegressionModule(mockConfig, {
857
+ metric: 'startup_time',
858
+ current_value: 1200,
859
+ baseline_value: 1000,
860
+ severity: 'medium',
861
+ });
556
862
  // Verify regression counter
557
863
  expect(mockCounterAddFn).toHaveBeenCalledWith(1, {
558
864
  'session.id': 'test-session-id',
@@ -574,7 +880,12 @@ describe('Telemetry Metrics', () => {
574
880
  initializeMetricsModule(mockConfig);
575
881
  mockCounterAddFn.mockClear();
576
882
  mockHistogramRecordFn.mockClear();
577
- recordPerformanceRegressionModule(mockConfig, 'memory_usage', 100, 0, 'high');
883
+ recordPerformanceRegressionModule(mockConfig, {
884
+ metric: 'memory_usage',
885
+ current_value: 100,
886
+ baseline_value: 0,
887
+ severity: 'high',
888
+ });
578
889
  // Verify regression counter still recorded
579
890
  expect(mockCounterAddFn).toHaveBeenCalledWith(1, {
580
891
  'session.id': 'test-session-id',
@@ -589,8 +900,18 @@ describe('Telemetry Metrics', () => {
589
900
  it('should record different severity levels', () => {
590
901
  initializeMetricsModule(mockConfig);
591
902
  mockCounterAddFn.mockClear();
592
- recordPerformanceRegressionModule(mockConfig, 'api_latency', 500, 400, 'low');
593
- recordPerformanceRegressionModule(mockConfig, 'cpu_usage', 90, 70, 'high');
903
+ recordPerformanceRegressionModule(mockConfig, {
904
+ metric: 'api_latency',
905
+ current_value: 500,
906
+ baseline_value: 400,
907
+ severity: 'low',
908
+ });
909
+ recordPerformanceRegressionModule(mockConfig, {
910
+ metric: 'cpu_usage',
911
+ current_value: 90,
912
+ baseline_value: 70,
913
+ severity: 'high',
914
+ });
594
915
  expect(mockCounterAddFn).toHaveBeenNthCalledWith(1, 1, {
595
916
  'session.id': 'test-session-id',
596
917
  metric: 'api_latency',
@@ -611,7 +932,12 @@ describe('Telemetry Metrics', () => {
611
932
  it('should record baseline comparison with percentage change', () => {
612
933
  initializeMetricsModule(mockConfig);
613
934
  mockHistogramRecordFn.mockClear();
614
- recordBaselineComparisonModule(mockConfig, 'memory_usage', 120, 100, 'performance_tracking');
935
+ recordBaselineComparisonModule(mockConfig, {
936
+ metric: 'memory_usage',
937
+ current_value: 120,
938
+ baseline_value: 100,
939
+ category: 'performance_tracking',
940
+ });
615
941
  // 20% increase: (120 - 100) / 100 * 100 = 20%
616
942
  expect(mockHistogramRecordFn).toHaveBeenCalledWith(20, {
617
943
  'session.id': 'test-session-id',
@@ -624,7 +950,12 @@ describe('Telemetry Metrics', () => {
624
950
  it('should handle negative percentage change (improvement)', () => {
625
951
  initializeMetricsModule(mockConfig);
626
952
  mockHistogramRecordFn.mockClear();
627
- recordBaselineComparisonModule(mockConfig, 'startup_time', 800, 1000, 'optimization');
953
+ recordBaselineComparisonModule(mockConfig, {
954
+ metric: 'startup_time',
955
+ current_value: 800,
956
+ baseline_value: 1000,
957
+ category: 'optimization',
958
+ });
628
959
  // 20% decrease: (800 - 1000) / 1000 * 100 = -20%
629
960
  expect(mockHistogramRecordFn).toHaveBeenCalledWith(-20, {
630
961
  'session.id': 'test-session-id',
@@ -640,7 +971,12 @@ describe('Telemetry Metrics', () => {
640
971
  const diagSpy = vi.spyOn(mockedModule.diag, 'warn');
641
972
  initializeMetricsModule(mockConfig);
642
973
  mockHistogramRecordFn.mockClear();
643
- recordBaselineComparisonModule(mockConfig, 'new_metric', 50, 0, 'testing');
974
+ recordBaselineComparisonModule(mockConfig, {
975
+ metric: 'new_metric',
976
+ current_value: 50,
977
+ baseline_value: 0,
978
+ category: 'testing',
979
+ });
644
980
  expect(diagSpy).toHaveBeenCalledWith('Baseline value is zero, skipping comparison.');
645
981
  expect(mockHistogramRecordFn).not.toHaveBeenCalled();
646
982
  });