@google/gemini-cli-core 0.5.5 → 0.6.0-preview.0

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 (332) hide show
  1. package/LICENSE +2 -2
  2. package/README.md +12 -2
  3. package/dist/index.d.ts +3 -3
  4. package/dist/index.js +3 -3
  5. package/dist/index.js.map +1 -1
  6. package/dist/src/code_assist/converter.d.ts +1 -0
  7. package/dist/src/code_assist/converter.js +1 -0
  8. package/dist/src/code_assist/converter.js.map +1 -1
  9. package/dist/src/code_assist/converter.test.js +10 -0
  10. package/dist/src/code_assist/converter.test.js.map +1 -1
  11. package/dist/src/code_assist/oauth-credential-storage.d.ts +5 -7
  12. package/dist/src/code_assist/oauth-credential-storage.js +5 -8
  13. package/dist/src/code_assist/oauth-credential-storage.js.map +1 -1
  14. package/dist/src/code_assist/oauth-credential-storage.test.js +35 -33
  15. package/dist/src/code_assist/oauth-credential-storage.test.js.map +1 -1
  16. package/dist/src/code_assist/oauth2.js +28 -2
  17. package/dist/src/code_assist/oauth2.js.map +1 -1
  18. package/dist/src/code_assist/oauth2.test.js +674 -536
  19. package/dist/src/code_assist/oauth2.test.js.map +1 -1
  20. package/dist/src/config/config.d.ts +32 -1
  21. package/dist/src/config/config.js +73 -16
  22. package/dist/src/config/config.js.map +1 -1
  23. package/dist/src/config/config.test.js +104 -16
  24. package/dist/src/config/config.test.js.map +1 -1
  25. package/dist/src/config/models.d.ts +15 -0
  26. package/dist/src/config/models.js +27 -0
  27. package/dist/src/config/models.js.map +1 -1
  28. package/dist/src/config/models.test.d.ts +6 -0
  29. package/dist/src/config/models.test.js +55 -0
  30. package/dist/src/config/models.test.js.map +1 -0
  31. package/dist/src/confirmation-bus/index.d.ts +7 -0
  32. package/dist/src/confirmation-bus/index.js +8 -0
  33. package/dist/src/confirmation-bus/index.js.map +1 -0
  34. package/dist/src/confirmation-bus/message-bus.d.ts +17 -0
  35. package/dist/src/confirmation-bus/message-bus.js +81 -0
  36. package/dist/src/confirmation-bus/message-bus.js.map +1 -0
  37. package/dist/src/confirmation-bus/message-bus.test.d.ts +6 -0
  38. package/dist/src/confirmation-bus/message-bus.test.js +164 -0
  39. package/dist/src/confirmation-bus/message-bus.test.js.map +1 -0
  40. package/dist/src/confirmation-bus/types.d.ts +38 -0
  41. package/dist/src/confirmation-bus/types.js +15 -0
  42. package/dist/src/confirmation-bus/types.js.map +1 -0
  43. package/dist/src/core/baseLlmClient.d.ts +1 -0
  44. package/dist/src/core/baseLlmClient.js +24 -0
  45. package/dist/src/core/baseLlmClient.js.map +1 -1
  46. package/dist/src/core/baseLlmClient.test.js +63 -0
  47. package/dist/src/core/baseLlmClient.test.js.map +1 -1
  48. package/dist/src/core/client.d.ts +5 -4
  49. package/dist/src/core/client.js +80 -140
  50. package/dist/src/core/client.js.map +1 -1
  51. package/dist/src/core/client.test.js +247 -186
  52. package/dist/src/core/client.test.js.map +1 -1
  53. package/dist/src/core/contentGenerator.d.ts +0 -1
  54. package/dist/src/core/contentGenerator.js +0 -4
  55. package/dist/src/core/contentGenerator.js.map +1 -1
  56. package/dist/src/core/contentGenerator.test.js +0 -3
  57. package/dist/src/core/contentGenerator.test.js.map +1 -1
  58. package/dist/src/core/coreToolScheduler.d.ts +4 -3
  59. package/dist/src/core/coreToolScheduler.js +42 -5
  60. package/dist/src/core/coreToolScheduler.js.map +1 -1
  61. package/dist/src/core/coreToolScheduler.test.js +43 -0
  62. package/dist/src/core/coreToolScheduler.test.js.map +1 -1
  63. package/dist/src/core/geminiChat.d.ts +3 -30
  64. package/dist/src/core/geminiChat.js +32 -228
  65. package/dist/src/core/geminiChat.js.map +1 -1
  66. package/dist/src/core/geminiChat.test.js +58 -489
  67. package/dist/src/core/geminiChat.test.js.map +1 -1
  68. package/dist/src/core/loggingContentGenerator.js +5 -5
  69. package/dist/src/core/loggingContentGenerator.js.map +1 -1
  70. package/dist/src/core/nonInteractiveToolExecutor.test.js +49 -0
  71. package/dist/src/core/nonInteractiveToolExecutor.test.js.map +1 -1
  72. package/dist/src/core/subagent.js +1 -1
  73. package/dist/src/core/subagent.js.map +1 -1
  74. package/dist/src/core/subagent.test.js +9 -8
  75. package/dist/src/core/subagent.test.js.map +1 -1
  76. package/dist/src/core/turn.d.ts +2 -1
  77. package/dist/src/core/turn.js +2 -2
  78. package/dist/src/core/turn.js.map +1 -1
  79. package/dist/src/core/turn.test.js +18 -18
  80. package/dist/src/core/turn.test.js.map +1 -1
  81. package/dist/src/generated/git-commit.d.ts +2 -2
  82. package/dist/src/generated/git-commit.js +2 -2
  83. package/dist/src/generated/git-commit.js.map +1 -1
  84. package/dist/src/ide/constants.d.ts +1 -0
  85. package/dist/src/ide/constants.js +1 -0
  86. package/dist/src/ide/constants.js.map +1 -1
  87. package/dist/src/ide/ide-client.d.ts +51 -13
  88. package/dist/src/ide/ide-client.js +182 -35
  89. package/dist/src/ide/ide-client.js.map +1 -1
  90. package/dist/src/ide/ide-client.test.js +71 -0
  91. package/dist/src/ide/ide-client.test.js.map +1 -1
  92. package/dist/src/ide/ide-installer.js +8 -2
  93. package/dist/src/ide/ide-installer.js.map +1 -1
  94. package/dist/src/ide/ide-installer.test.js +13 -2
  95. package/dist/src/ide/ide-installer.test.js.map +1 -1
  96. package/dist/src/ide/ideContext.d.ts +34 -113
  97. package/dist/src/ide/ideContext.js +20 -78
  98. package/dist/src/ide/ideContext.js.map +1 -1
  99. package/dist/src/ide/ideContext.test.js +37 -39
  100. package/dist/src/ide/ideContext.test.js.map +1 -1
  101. package/dist/src/ide/types.d.ts +141 -0
  102. package/dist/src/ide/types.js +73 -0
  103. package/dist/src/ide/types.js.map +1 -1
  104. package/dist/src/index.d.ts +3 -1
  105. package/dist/src/index.js +3 -1
  106. package/dist/src/index.js.map +1 -1
  107. package/dist/src/mcp/oauth-token-storage.d.ts +2 -0
  108. package/dist/src/mcp/oauth-token-storage.js +25 -0
  109. package/dist/src/mcp/oauth-token-storage.js.map +1 -1
  110. package/dist/src/mcp/oauth-token-storage.test.js +251 -160
  111. package/dist/src/mcp/oauth-token-storage.test.js.map +1 -1
  112. package/dist/src/mcp/token-storage/index.d.ts +11 -0
  113. package/dist/src/mcp/token-storage/index.js +12 -0
  114. package/dist/src/mcp/token-storage/index.js.map +1 -0
  115. package/dist/src/output/json-formatter.d.ts +11 -0
  116. package/dist/src/output/json-formatter.js +30 -0
  117. package/dist/src/output/json-formatter.js.map +1 -0
  118. package/dist/src/output/json-formatter.test.d.ts +6 -0
  119. package/dist/src/output/json-formatter.test.js +266 -0
  120. package/dist/src/output/json-formatter.test.js.map +1 -0
  121. package/dist/src/output/types.d.ts +20 -0
  122. package/dist/src/output/types.js +11 -0
  123. package/dist/src/output/types.js.map +1 -0
  124. package/dist/src/policy/index.d.ts +7 -0
  125. package/dist/src/policy/index.js +8 -0
  126. package/dist/src/policy/index.js.map +1 -0
  127. package/dist/src/policy/policy-engine.d.ts +30 -0
  128. package/dist/src/policy/policy-engine.js +83 -0
  129. package/dist/src/policy/policy-engine.js.map +1 -0
  130. package/dist/src/policy/policy-engine.test.d.ts +6 -0
  131. package/dist/src/policy/policy-engine.test.js +470 -0
  132. package/dist/src/policy/policy-engine.test.js.map +1 -0
  133. package/dist/src/policy/stable-stringify.d.ts +58 -0
  134. package/dist/src/policy/stable-stringify.js +122 -0
  135. package/dist/src/policy/stable-stringify.js.map +1 -0
  136. package/dist/src/policy/types.d.ts +47 -0
  137. package/dist/src/policy/types.js +12 -0
  138. package/dist/src/policy/types.js.map +1 -0
  139. package/dist/src/routing/modelRouterService.d.ts +23 -0
  140. package/dist/src/routing/modelRouterService.js +70 -0
  141. package/dist/src/routing/modelRouterService.js.map +1 -0
  142. package/dist/src/routing/modelRouterService.test.d.ts +6 -0
  143. package/dist/src/routing/modelRouterService.test.js +98 -0
  144. package/dist/src/routing/modelRouterService.test.js.map +1 -0
  145. package/dist/src/routing/routingStrategy.d.ts +62 -0
  146. package/dist/src/routing/routingStrategy.js +7 -0
  147. package/dist/src/routing/routingStrategy.js.map +1 -0
  148. package/dist/src/routing/strategies/classifierStrategy.d.ts +12 -0
  149. package/dist/src/routing/strategies/classifierStrategy.js +173 -0
  150. package/dist/src/routing/strategies/classifierStrategy.js.map +1 -0
  151. package/dist/src/routing/strategies/classifierStrategy.test.d.ts +6 -0
  152. package/dist/src/routing/strategies/classifierStrategy.test.js +192 -0
  153. package/dist/src/routing/strategies/classifierStrategy.test.js.map +1 -0
  154. package/dist/src/routing/strategies/compositeStrategy.d.ts +26 -0
  155. package/dist/src/routing/strategies/compositeStrategy.js +67 -0
  156. package/dist/src/routing/strategies/compositeStrategy.js.map +1 -0
  157. package/dist/src/routing/strategies/compositeStrategy.test.d.ts +6 -0
  158. package/dist/src/routing/strategies/compositeStrategy.test.js +123 -0
  159. package/dist/src/routing/strategies/compositeStrategy.test.js.map +1 -0
  160. package/dist/src/routing/strategies/defaultStrategy.d.ts +12 -0
  161. package/dist/src/routing/strategies/defaultStrategy.js +20 -0
  162. package/dist/src/routing/strategies/defaultStrategy.js.map +1 -0
  163. package/dist/src/routing/strategies/defaultStrategy.test.d.ts +6 -0
  164. package/dist/src/routing/strategies/defaultStrategy.test.js +26 -0
  165. package/dist/src/routing/strategies/defaultStrategy.test.js.map +1 -0
  166. package/dist/src/routing/strategies/fallbackStrategy.d.ts +12 -0
  167. package/dist/src/routing/strategies/fallbackStrategy.js +25 -0
  168. package/dist/src/routing/strategies/fallbackStrategy.js.map +1 -0
  169. package/dist/src/routing/strategies/fallbackStrategy.test.d.ts +6 -0
  170. package/dist/src/routing/strategies/fallbackStrategy.test.js +55 -0
  171. package/dist/src/routing/strategies/fallbackStrategy.test.js.map +1 -0
  172. package/dist/src/routing/strategies/overrideStrategy.d.ts +15 -0
  173. package/dist/src/routing/strategies/overrideStrategy.js +28 -0
  174. package/dist/src/routing/strategies/overrideStrategy.js.map +1 -0
  175. package/dist/src/routing/strategies/overrideStrategy.test.d.ts +6 -0
  176. package/dist/src/routing/strategies/overrideStrategy.test.js +42 -0
  177. package/dist/src/routing/strategies/overrideStrategy.test.js.map +1 -0
  178. package/dist/src/services/chatRecordingService.d.ts +2 -1
  179. package/dist/src/services/chatRecordingService.js +3 -3
  180. package/dist/src/services/chatRecordingService.js.map +1 -1
  181. package/dist/src/services/chatRecordingService.test.js +8 -3
  182. package/dist/src/services/chatRecordingService.test.js.map +1 -1
  183. package/dist/src/services/fileDiscoveryService.d.ts +10 -0
  184. package/dist/src/services/fileDiscoveryService.js +31 -17
  185. package/dist/src/services/fileDiscoveryService.js.map +1 -1
  186. package/dist/src/services/gitService.js +9 -12
  187. package/dist/src/services/gitService.js.map +1 -1
  188. package/dist/src/services/gitService.test.js +10 -20
  189. package/dist/src/services/gitService.test.js.map +1 -1
  190. package/dist/src/services/loopDetectionService.d.ts +5 -0
  191. package/dist/src/services/loopDetectionService.js +36 -20
  192. package/dist/src/services/loopDetectionService.js.map +1 -1
  193. package/dist/src/services/loopDetectionService.test.js +41 -12
  194. package/dist/src/services/loopDetectionService.test.js.map +1 -1
  195. package/dist/src/services/shellExecutionService.d.ts +34 -2
  196. package/dist/src/services/shellExecutionService.js +177 -43
  197. package/dist/src/services/shellExecutionService.js.map +1 -1
  198. package/dist/src/services/shellExecutionService.test.js +153 -56
  199. package/dist/src/services/shellExecutionService.test.js.map +1 -1
  200. package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +10 -2
  201. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +85 -5
  202. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
  203. package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js +63 -5
  204. package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js.map +1 -1
  205. package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +12 -2
  206. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +31 -2
  207. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
  208. package/dist/src/telemetry/constants.d.ts +3 -0
  209. package/dist/src/telemetry/constants.js +3 -0
  210. package/dist/src/telemetry/constants.js.map +1 -1
  211. package/dist/src/telemetry/gcp-exporters.d.ts +34 -0
  212. package/dist/src/telemetry/gcp-exporters.js +117 -0
  213. package/dist/src/telemetry/gcp-exporters.js.map +1 -0
  214. package/dist/src/telemetry/gcp-exporters.test.d.ts +6 -0
  215. package/dist/src/telemetry/gcp-exporters.test.js +318 -0
  216. package/dist/src/telemetry/gcp-exporters.test.js.map +1 -0
  217. package/dist/src/telemetry/index.d.ts +3 -2
  218. package/dist/src/telemetry/index.js +3 -2
  219. package/dist/src/telemetry/index.js.map +1 -1
  220. package/dist/src/telemetry/loggers.d.ts +4 -1
  221. package/dist/src/telemetry/loggers.js +42 -7
  222. package/dist/src/telemetry/loggers.js.map +1 -1
  223. package/dist/src/telemetry/loggers.test.js +84 -36
  224. package/dist/src/telemetry/loggers.test.js.map +1 -1
  225. package/dist/src/telemetry/metrics.d.ts +3 -1
  226. package/dist/src/telemetry/metrics.js +32 -3
  227. package/dist/src/telemetry/metrics.js.map +1 -1
  228. package/dist/src/telemetry/metrics.test.js +42 -0
  229. package/dist/src/telemetry/metrics.test.js.map +1 -1
  230. package/dist/src/telemetry/sdk.js +16 -1
  231. package/dist/src/telemetry/sdk.js.map +1 -1
  232. package/dist/src/telemetry/sdk.test.js +95 -0
  233. package/dist/src/telemetry/sdk.test.js.map +1 -1
  234. package/dist/src/telemetry/types.d.ts +47 -3
  235. package/dist/src/telemetry/types.js +67 -3
  236. package/dist/src/telemetry/types.js.map +1 -1
  237. package/dist/src/tools/edit.js +6 -5
  238. package/dist/src/tools/edit.js.map +1 -1
  239. package/dist/src/tools/edit.test.js +79 -9
  240. package/dist/src/tools/edit.test.js.map +1 -1
  241. package/dist/src/tools/glob.d.ts +5 -1
  242. package/dist/src/tools/glob.js +24 -17
  243. package/dist/src/tools/glob.js.map +1 -1
  244. package/dist/src/tools/glob.test.js +51 -0
  245. package/dist/src/tools/glob.test.js.map +1 -1
  246. package/dist/src/tools/ls.js +19 -32
  247. package/dist/src/tools/ls.js.map +1 -1
  248. package/dist/src/tools/ls.test.js +140 -280
  249. package/dist/src/tools/ls.test.js.map +1 -1
  250. package/dist/src/tools/read-many-files.d.ts +1 -1
  251. package/dist/src/tools/read-many-files.js +17 -49
  252. package/dist/src/tools/read-many-files.js.map +1 -1
  253. package/dist/src/tools/ripGrep.d.ts +4 -0
  254. package/dist/src/tools/ripGrep.js +11 -1
  255. package/dist/src/tools/ripGrep.js.map +1 -1
  256. package/dist/src/tools/ripGrep.test.js +51 -1
  257. package/dist/src/tools/ripGrep.test.js.map +1 -1
  258. package/dist/src/tools/shell.d.ts +12 -2
  259. package/dist/src/tools/shell.js +20 -27
  260. package/dist/src/tools/shell.js.map +1 -1
  261. package/dist/src/tools/shell.test.js +33 -68
  262. package/dist/src/tools/shell.test.js.map +1 -1
  263. package/dist/src/tools/smart-edit.d.ts +0 -1
  264. package/dist/src/tools/smart-edit.js +5 -18
  265. package/dist/src/tools/smart-edit.js.map +1 -1
  266. package/dist/src/tools/smart-edit.test.js +18 -9
  267. package/dist/src/tools/smart-edit.test.js.map +1 -1
  268. package/dist/src/tools/tools.d.ts +7 -5
  269. package/dist/src/tools/tools.js +2 -2
  270. package/dist/src/tools/tools.js.map +1 -1
  271. package/dist/src/tools/write-file.js +4 -5
  272. package/dist/src/tools/write-file.js.map +1 -1
  273. package/dist/src/tools/write-file.test.js +94 -10
  274. package/dist/src/tools/write-file.test.js.map +1 -1
  275. package/dist/src/utils/bfsFileSearch.js +11 -5
  276. package/dist/src/utils/bfsFileSearch.js.map +1 -1
  277. package/dist/src/utils/editCorrector.d.ts +7 -6
  278. package/dist/src/utils/editCorrector.js +61 -18
  279. package/dist/src/utils/editCorrector.js.map +1 -1
  280. package/dist/src/utils/editCorrector.test.js +30 -79
  281. package/dist/src/utils/editCorrector.test.js.map +1 -1
  282. package/dist/src/utils/editor.js +31 -44
  283. package/dist/src/utils/editor.js.map +1 -1
  284. package/dist/src/utils/editor.test.js +61 -75
  285. package/dist/src/utils/editor.test.js.map +1 -1
  286. package/dist/src/utils/errorParsing.js +2 -2
  287. package/dist/src/utils/errorParsing.js.map +1 -1
  288. package/dist/src/utils/errorParsing.test.js +7 -7
  289. package/dist/src/utils/errorParsing.test.js.map +1 -1
  290. package/dist/src/utils/errors.d.ts +6 -0
  291. package/dist/src/utils/errors.js +10 -0
  292. package/dist/src/utils/errors.js.map +1 -1
  293. package/dist/src/utils/fileUtils.test.js +17 -8
  294. package/dist/src/utils/fileUtils.test.js.map +1 -1
  295. package/dist/src/utils/geminiIgnoreParser.d.ts +18 -0
  296. package/dist/src/utils/geminiIgnoreParser.js +61 -0
  297. package/dist/src/utils/geminiIgnoreParser.js.map +1 -0
  298. package/dist/src/utils/geminiIgnoreParser.test.d.ts +6 -0
  299. package/dist/src/utils/geminiIgnoreParser.test.js +50 -0
  300. package/dist/src/utils/geminiIgnoreParser.test.js.map +1 -0
  301. package/dist/src/utils/gitIgnoreParser.d.ts +3 -9
  302. package/dist/src/utils/gitIgnoreParser.js +60 -69
  303. package/dist/src/utils/gitIgnoreParser.js.map +1 -1
  304. package/dist/src/utils/gitIgnoreParser.test.js +18 -53
  305. package/dist/src/utils/gitIgnoreParser.test.js.map +1 -1
  306. package/dist/src/utils/memoryDiscovery.test.js +12 -6
  307. package/dist/src/utils/memoryDiscovery.test.js.map +1 -1
  308. package/dist/src/utils/nextSpeakerChecker.d.ts +2 -2
  309. package/dist/src/utils/nextSpeakerChecker.js +8 -2
  310. package/dist/src/utils/nextSpeakerChecker.js.map +1 -1
  311. package/dist/src/utils/nextSpeakerChecker.test.js +40 -33
  312. package/dist/src/utils/nextSpeakerChecker.test.js.map +1 -1
  313. package/dist/src/utils/shell-utils.d.ts +5 -0
  314. package/dist/src/utils/shell-utils.js +23 -0
  315. package/dist/src/utils/shell-utils.js.map +1 -1
  316. package/dist/src/utils/terminalSerializer.d.ts +28 -0
  317. package/dist/src/utils/terminalSerializer.js +432 -0
  318. package/dist/src/utils/terminalSerializer.js.map +1 -0
  319. package/dist/src/utils/terminalSerializer.test.d.ts +6 -0
  320. package/dist/src/utils/terminalSerializer.test.js +176 -0
  321. package/dist/src/utils/terminalSerializer.test.js.map +1 -0
  322. package/dist/src/utils/textUtils.d.ts +5 -0
  323. package/dist/src/utils/textUtils.js +14 -0
  324. package/dist/src/utils/textUtils.js.map +1 -1
  325. package/dist/src/utils/textUtils.test.d.ts +6 -0
  326. package/dist/src/utils/textUtils.test.js +59 -0
  327. package/dist/src/utils/textUtils.test.js.map +1 -0
  328. package/dist/tsconfig.tsbuildinfo +1 -1
  329. package/package.json +5 -1
  330. package/dist/src/utils/ide-trust.d.ts +0 -10
  331. package/dist/src/utils/ide-trust.js +0 -14
  332. package/dist/src/utils/ide-trust.js.map +0 -1
@@ -0,0 +1,266 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { expect, describe, it } from 'vitest';
7
+ import { JsonFormatter } from './json-formatter.js';
8
+ describe('JsonFormatter', () => {
9
+ it('should format the response as JSON', () => {
10
+ const formatter = new JsonFormatter();
11
+ const response = 'This is a test response.';
12
+ const formatted = formatter.format(response);
13
+ const expected = {
14
+ response,
15
+ };
16
+ expect(JSON.parse(formatted)).toEqual(expected);
17
+ });
18
+ it('should strip ANSI escape sequences from response text', () => {
19
+ const formatter = new JsonFormatter();
20
+ const responseWithAnsi = '\x1B[31mRed text\x1B[0m and \x1B[32mGreen text\x1B[0m';
21
+ const formatted = formatter.format(responseWithAnsi);
22
+ const parsed = JSON.parse(formatted);
23
+ expect(parsed.response).toBe('Red text and Green text');
24
+ });
25
+ it('should strip control characters from response text', () => {
26
+ const formatter = new JsonFormatter();
27
+ const responseWithControlChars = 'Text with\x07 bell\x08 and\x0B vertical tab';
28
+ const formatted = formatter.format(responseWithControlChars);
29
+ const parsed = JSON.parse(formatted);
30
+ // Only ANSI codes are stripped, other control chars are preserved
31
+ expect(parsed.response).toBe('Text with\x07 bell\x08 and\x0B vertical tab');
32
+ });
33
+ it('should preserve newlines and tabs in response text', () => {
34
+ const formatter = new JsonFormatter();
35
+ const responseWithWhitespace = 'Line 1\nLine 2\r\nLine 3\twith tab';
36
+ const formatted = formatter.format(responseWithWhitespace);
37
+ const parsed = JSON.parse(formatted);
38
+ expect(parsed.response).toBe('Line 1\nLine 2\r\nLine 3\twith tab');
39
+ });
40
+ it('should format the response as JSON with stats', () => {
41
+ const formatter = new JsonFormatter();
42
+ const response = 'This is a test response.';
43
+ const stats = {
44
+ models: {
45
+ 'gemini-2.5-pro': {
46
+ api: {
47
+ totalRequests: 2,
48
+ totalErrors: 0,
49
+ totalLatencyMs: 5672,
50
+ },
51
+ tokens: {
52
+ prompt: 24401,
53
+ candidates: 215,
54
+ total: 24719,
55
+ cached: 10656,
56
+ thoughts: 103,
57
+ tool: 0,
58
+ },
59
+ },
60
+ 'gemini-2.5-flash': {
61
+ api: {
62
+ totalRequests: 2,
63
+ totalErrors: 0,
64
+ totalLatencyMs: 5914,
65
+ },
66
+ tokens: {
67
+ prompt: 20803,
68
+ candidates: 716,
69
+ total: 21657,
70
+ cached: 0,
71
+ thoughts: 138,
72
+ tool: 0,
73
+ },
74
+ },
75
+ },
76
+ tools: {
77
+ totalCalls: 1,
78
+ totalSuccess: 1,
79
+ totalFail: 0,
80
+ totalDurationMs: 4582,
81
+ totalDecisions: {
82
+ accept: 0,
83
+ reject: 0,
84
+ modify: 0,
85
+ auto_accept: 1,
86
+ },
87
+ byName: {
88
+ google_web_search: {
89
+ count: 1,
90
+ success: 1,
91
+ fail: 0,
92
+ durationMs: 4582,
93
+ decisions: {
94
+ accept: 0,
95
+ reject: 0,
96
+ modify: 0,
97
+ auto_accept: 1,
98
+ },
99
+ },
100
+ },
101
+ },
102
+ files: {
103
+ totalLinesAdded: 0,
104
+ totalLinesRemoved: 0,
105
+ },
106
+ };
107
+ const formatted = formatter.format(response, stats);
108
+ const expected = {
109
+ response,
110
+ stats,
111
+ };
112
+ expect(JSON.parse(formatted)).toEqual(expected);
113
+ });
114
+ it('should format error as JSON', () => {
115
+ const formatter = new JsonFormatter();
116
+ const error = {
117
+ type: 'ValidationError',
118
+ message: 'Invalid input provided',
119
+ code: 400,
120
+ };
121
+ const formatted = formatter.format(undefined, undefined, error);
122
+ const expected = {
123
+ error,
124
+ };
125
+ expect(JSON.parse(formatted)).toEqual(expected);
126
+ });
127
+ it('should format response with error as JSON', () => {
128
+ const formatter = new JsonFormatter();
129
+ const response = 'Partial response';
130
+ const error = {
131
+ type: 'TimeoutError',
132
+ message: 'Request timed out',
133
+ code: 'TIMEOUT',
134
+ };
135
+ const formatted = formatter.format(response, undefined, error);
136
+ const expected = {
137
+ response,
138
+ error,
139
+ };
140
+ expect(JSON.parse(formatted)).toEqual(expected);
141
+ });
142
+ it('should format error using formatError method', () => {
143
+ const formatter = new JsonFormatter();
144
+ const error = new Error('Something went wrong');
145
+ const formatted = formatter.formatError(error, 500);
146
+ const parsed = JSON.parse(formatted);
147
+ expect(parsed).toEqual({
148
+ error: {
149
+ type: 'Error',
150
+ message: 'Something went wrong',
151
+ code: 500,
152
+ },
153
+ });
154
+ });
155
+ it('should format custom error using formatError method', () => {
156
+ class CustomError extends Error {
157
+ constructor(message) {
158
+ super(message);
159
+ this.name = 'CustomError';
160
+ }
161
+ }
162
+ const formatter = new JsonFormatter();
163
+ const error = new CustomError('Custom error occurred');
164
+ const formatted = formatter.formatError(error);
165
+ const parsed = JSON.parse(formatted);
166
+ expect(parsed).toEqual({
167
+ error: {
168
+ type: 'CustomError',
169
+ message: 'Custom error occurred',
170
+ },
171
+ });
172
+ });
173
+ it('should format complete JSON output with response, stats, and error', () => {
174
+ const formatter = new JsonFormatter();
175
+ const response = 'Partial response before error';
176
+ const stats = {
177
+ models: {},
178
+ tools: {
179
+ totalCalls: 0,
180
+ totalSuccess: 0,
181
+ totalFail: 1,
182
+ totalDurationMs: 0,
183
+ totalDecisions: {
184
+ accept: 0,
185
+ reject: 0,
186
+ modify: 0,
187
+ auto_accept: 0,
188
+ },
189
+ byName: {},
190
+ },
191
+ files: {
192
+ totalLinesAdded: 0,
193
+ totalLinesRemoved: 0,
194
+ },
195
+ };
196
+ const error = {
197
+ type: 'ApiError',
198
+ message: 'Rate limit exceeded',
199
+ code: 429,
200
+ };
201
+ const formatted = formatter.format(response, stats, error);
202
+ const expected = {
203
+ response,
204
+ stats,
205
+ error,
206
+ };
207
+ expect(JSON.parse(formatted)).toEqual(expected);
208
+ });
209
+ it('should handle error messages containing JSON content', () => {
210
+ const formatter = new JsonFormatter();
211
+ const errorWithJson = new Error('API returned: {"error": "Invalid request", "code": 400}');
212
+ const formatted = formatter.formatError(errorWithJson, 'API_ERROR');
213
+ const parsed = JSON.parse(formatted);
214
+ expect(parsed).toEqual({
215
+ error: {
216
+ type: 'Error',
217
+ message: 'API returned: {"error": "Invalid request", "code": 400}',
218
+ code: 'API_ERROR',
219
+ },
220
+ });
221
+ // Verify the entire output is valid JSON
222
+ expect(() => JSON.parse(formatted)).not.toThrow();
223
+ });
224
+ it('should handle error messages with quotes and special characters', () => {
225
+ const formatter = new JsonFormatter();
226
+ const errorWithQuotes = new Error('Error: "quoted text" and \\backslash');
227
+ const formatted = formatter.formatError(errorWithQuotes);
228
+ const parsed = JSON.parse(formatted);
229
+ expect(parsed).toEqual({
230
+ error: {
231
+ type: 'Error',
232
+ message: 'Error: "quoted text" and \\backslash',
233
+ },
234
+ });
235
+ // Verify the entire output is valid JSON
236
+ expect(() => JSON.parse(formatted)).not.toThrow();
237
+ });
238
+ it('should handle error messages with control characters', () => {
239
+ const formatter = new JsonFormatter();
240
+ const errorWithControlChars = new Error('Error with\n newline and\t tab');
241
+ const formatted = formatter.formatError(errorWithControlChars);
242
+ const parsed = JSON.parse(formatted);
243
+ // Should preserve newlines and tabs as they are common whitespace characters
244
+ expect(parsed.error.message).toBe('Error with\n newline and\t tab');
245
+ // Verify the entire output is valid JSON
246
+ expect(() => JSON.parse(formatted)).not.toThrow();
247
+ });
248
+ it('should strip ANSI escape sequences from error messages', () => {
249
+ const formatter = new JsonFormatter();
250
+ const errorWithAnsi = new Error('\x1B[31mRed error\x1B[0m message');
251
+ const formatted = formatter.formatError(errorWithAnsi);
252
+ const parsed = JSON.parse(formatted);
253
+ expect(parsed.error.message).toBe('Red error message');
254
+ expect(() => JSON.parse(formatted)).not.toThrow();
255
+ });
256
+ it('should strip unsafe control characters from error messages', () => {
257
+ const formatter = new JsonFormatter();
258
+ const errorWithControlChars = new Error('Error\x07 with\x08 control\x0B chars');
259
+ const formatted = formatter.formatError(errorWithControlChars);
260
+ const parsed = JSON.parse(formatted);
261
+ // Only ANSI codes are stripped, other control chars are preserved
262
+ expect(parsed.error.message).toBe('Error\x07 with\x08 control\x0B chars');
263
+ expect(() => JSON.parse(formatted)).not.toThrow();
264
+ });
265
+ });
266
+ //# sourceMappingURL=json-formatter.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-formatter.test.js","sourceRoot":"","sources":["../../../src/output/json-formatter.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { SessionMetrics } from '../telemetry/uiTelemetry.js';
7
+ export declare enum OutputFormat {
8
+ TEXT = "text",
9
+ JSON = "json"
10
+ }
11
+ export interface JsonError {
12
+ type: string;
13
+ message: string;
14
+ code?: string | number;
15
+ }
16
+ export interface JsonOutput {
17
+ response?: string;
18
+ stats?: SessionMetrics;
19
+ error?: JsonError;
20
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export var OutputFormat;
7
+ (function (OutputFormat) {
8
+ OutputFormat["TEXT"] = "text";
9
+ OutputFormat["JSON"] = "json";
10
+ })(OutputFormat || (OutputFormat = {}));
11
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/output/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,MAAM,CAAN,IAAY,YAGX;AAHD,WAAY,YAAY;IACtB,6BAAa,CAAA;IACb,6BAAa,CAAA;AACf,CAAC,EAHW,YAAY,KAAZ,YAAY,QAGvB"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export * from './policy-engine.js';
7
+ export * from './types.js';
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export * from './policy-engine.js';
7
+ export * from './types.js';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/policy/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,oBAAoB,CAAC;AACnC,cAAc,YAAY,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { type FunctionCall } from '@google/genai';
7
+ import { PolicyDecision, type PolicyEngineConfig, type PolicyRule } from './types.js';
8
+ export declare class PolicyEngine {
9
+ private rules;
10
+ private readonly defaultDecision;
11
+ private readonly nonInteractive;
12
+ constructor(config?: PolicyEngineConfig);
13
+ /**
14
+ * Check if a tool call is allowed based on the configured policies.
15
+ */
16
+ check(toolCall: FunctionCall): PolicyDecision;
17
+ /**
18
+ * Add a new rule to the policy engine.
19
+ */
20
+ addRule(rule: PolicyRule): void;
21
+ /**
22
+ * Remove rules for a specific tool.
23
+ */
24
+ removeRulesForTool(toolName: string): void;
25
+ /**
26
+ * Get all current rules.
27
+ */
28
+ getRules(): readonly PolicyRule[];
29
+ private applyNonInteractiveMode;
30
+ }
@@ -0,0 +1,83 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import {} from '@google/genai';
7
+ import { PolicyDecision, } from './types.js';
8
+ import { stableStringify } from './stable-stringify.js';
9
+ function ruleMatches(rule, toolCall, stringifiedArgs) {
10
+ // Check tool name if specified
11
+ if (rule.toolName && toolCall.name !== rule.toolName) {
12
+ return false;
13
+ }
14
+ // Check args pattern if specified
15
+ if (rule.argsPattern) {
16
+ // If rule has an args pattern but tool has no args, no match
17
+ if (!toolCall.args) {
18
+ return false;
19
+ }
20
+ // Use stable JSON stringification with sorted keys to ensure consistent matching
21
+ if (stringifiedArgs === undefined ||
22
+ !rule.argsPattern.test(stringifiedArgs)) {
23
+ return false;
24
+ }
25
+ }
26
+ return true;
27
+ }
28
+ export class PolicyEngine {
29
+ rules;
30
+ defaultDecision;
31
+ nonInteractive;
32
+ constructor(config = {}) {
33
+ this.rules = (config.rules ?? []).sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
34
+ this.defaultDecision = config.defaultDecision ?? PolicyDecision.ASK_USER;
35
+ this.nonInteractive = config.nonInteractive ?? false;
36
+ }
37
+ /**
38
+ * Check if a tool call is allowed based on the configured policies.
39
+ */
40
+ check(toolCall) {
41
+ let stringifiedArgs;
42
+ // Compute stringified args once before the loop
43
+ if (toolCall.args && this.rules.some((rule) => rule.argsPattern)) {
44
+ stringifiedArgs = stableStringify(toolCall.args);
45
+ }
46
+ // Find the first matching rule (already sorted by priority)
47
+ for (const rule of this.rules) {
48
+ if (ruleMatches(rule, toolCall, stringifiedArgs)) {
49
+ return this.applyNonInteractiveMode(rule.decision);
50
+ }
51
+ }
52
+ // No matching rule found, use default decision
53
+ return this.applyNonInteractiveMode(this.defaultDecision);
54
+ }
55
+ /**
56
+ * Add a new rule to the policy engine.
57
+ */
58
+ addRule(rule) {
59
+ this.rules.push(rule);
60
+ // Re-sort rules by priority
61
+ this.rules.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
62
+ }
63
+ /**
64
+ * Remove rules for a specific tool.
65
+ */
66
+ removeRulesForTool(toolName) {
67
+ this.rules = this.rules.filter((rule) => rule.toolName !== toolName);
68
+ }
69
+ /**
70
+ * Get all current rules.
71
+ */
72
+ getRules() {
73
+ return this.rules;
74
+ }
75
+ applyNonInteractiveMode(decision) {
76
+ // In non-interactive mode, ASK_USER becomes DENY
77
+ if (this.nonInteractive && decision === PolicyDecision.ASK_USER) {
78
+ return PolicyDecision.DENY;
79
+ }
80
+ return decision;
81
+ }
82
+ }
83
+ //# sourceMappingURL=policy-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy-engine.js","sourceRoot":"","sources":["../../../src/policy/policy-engine.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 {};