@office-ai/aioncli-core 0.30.0 → 0.30.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 (325) hide show
  1. package/dist/docs/assets/theme-ansi-dark.png +0 -0
  2. package/dist/docs/assets/theme-atom-one-dark.png +0 -0
  3. package/dist/docs/assets/theme-ayu-dark.png +0 -0
  4. package/dist/docs/assets/theme-default-dark.png +0 -0
  5. package/dist/docs/assets/theme-dracula-dark.png +0 -0
  6. package/dist/docs/assets/theme-github-dark.png +0 -0
  7. package/dist/docs/assets/theme-holiday-dark.png +0 -0
  8. package/dist/docs/assets/theme-shades-of-purple-dark.png +0 -0
  9. package/dist/docs/assets/theme-solarized-dark.png +0 -0
  10. package/dist/docs/assets/theme-solarized-light.png +0 -0
  11. package/dist/docs/cli/notifications.md +58 -0
  12. package/dist/docs/redirects.json +20 -0
  13. package/dist/docs/reference/commands.md +563 -0
  14. package/dist/docs/reference/configuration.md +1804 -0
  15. package/dist/docs/reference/keyboard-shortcuts.md +168 -0
  16. package/dist/docs/reference/memport.md +246 -0
  17. package/dist/docs/reference/policy-engine.md +386 -0
  18. package/dist/docs/reference/tools.md +106 -0
  19. package/dist/docs/resources/faq.md +175 -0
  20. package/dist/docs/resources/quota-and-pricing.md +199 -0
  21. package/dist/docs/resources/tos-privacy.md +102 -0
  22. package/dist/docs/resources/troubleshooting.md +176 -0
  23. package/dist/docs/resources/uninstall.md +56 -0
  24. package/dist/src/agents/a2a-errors.d.ts +65 -0
  25. package/dist/src/agents/a2a-errors.js +164 -0
  26. package/dist/src/agents/a2a-errors.js.map +1 -0
  27. package/dist/src/agents/a2a-errors.test.d.ts +6 -0
  28. package/dist/src/agents/a2a-errors.test.js +183 -0
  29. package/dist/src/agents/a2a-errors.test.js.map +1 -0
  30. package/dist/src/agents/auth-provider/api-key-provider.d.ts +30 -0
  31. package/dist/src/agents/auth-provider/api-key-provider.js +66 -0
  32. package/dist/src/agents/auth-provider/api-key-provider.js.map +1 -0
  33. package/dist/src/agents/auth-provider/api-key-provider.test.d.ts +6 -0
  34. package/dist/src/agents/auth-provider/api-key-provider.test.js +130 -0
  35. package/dist/src/agents/auth-provider/api-key-provider.test.js.map +1 -0
  36. package/dist/src/agents/auth-provider/http-provider.d.ts +28 -0
  37. package/dist/src/agents/auth-provider/http-provider.js +73 -0
  38. package/dist/src/agents/auth-provider/http-provider.js.map +1 -0
  39. package/dist/src/agents/auth-provider/http-provider.test.d.ts +6 -0
  40. package/dist/src/agents/auth-provider/http-provider.test.js +112 -0
  41. package/dist/src/agents/auth-provider/http-provider.test.js.map +1 -0
  42. package/dist/src/agents/auth-provider/oauth2-provider.d.ts +65 -0
  43. package/dist/src/agents/auth-provider/oauth2-provider.js +233 -0
  44. package/dist/src/agents/auth-provider/oauth2-provider.js.map +1 -0
  45. package/dist/src/agents/auth-provider/oauth2-provider.test.d.ts +6 -0
  46. package/dist/src/agents/auth-provider/oauth2-provider.test.js +490 -0
  47. package/dist/src/agents/auth-provider/oauth2-provider.test.js.map +1 -0
  48. package/dist/src/agents/browser/analyzeScreenshot.d.ts +35 -0
  49. package/dist/src/agents/browser/analyzeScreenshot.js +183 -0
  50. package/dist/src/agents/browser/analyzeScreenshot.js.map +1 -0
  51. package/dist/src/agents/browser/analyzeScreenshot.test.d.ts +6 -0
  52. package/dist/src/agents/browser/analyzeScreenshot.test.js +161 -0
  53. package/dist/src/agents/browser/analyzeScreenshot.test.js.map +1 -0
  54. package/dist/src/agents/browser/automationOverlay.d.ts +26 -0
  55. package/dist/src/agents/browser/automationOverlay.js +100 -0
  56. package/dist/src/agents/browser/automationOverlay.js.map +1 -0
  57. package/dist/src/agents/browser/browserAgentDefinition.d.ts +50 -0
  58. package/dist/src/agents/browser/browserAgentDefinition.js +141 -0
  59. package/dist/src/agents/browser/browserAgentDefinition.js.map +1 -0
  60. package/dist/src/agents/browser/browserAgentFactory.d.ts +42 -0
  61. package/dist/src/agents/browser/browserAgentFactory.js +116 -0
  62. package/dist/src/agents/browser/browserAgentFactory.js.map +1 -0
  63. package/dist/src/agents/browser/browserAgentFactory.test.d.ts +6 -0
  64. package/dist/src/agents/browser/browserAgentFactory.test.js +240 -0
  65. package/dist/src/agents/browser/browserAgentFactory.test.js.map +1 -0
  66. package/dist/src/agents/browser/browserAgentInvocation.d.ts +34 -0
  67. package/dist/src/agents/browser/browserAgentInvocation.js +386 -0
  68. package/dist/src/agents/browser/browserAgentInvocation.js.map +1 -0
  69. package/dist/src/agents/browser/browserAgentInvocation.test.d.ts +6 -0
  70. package/dist/src/agents/browser/browserAgentInvocation.test.js +382 -0
  71. package/dist/src/agents/browser/browserAgentInvocation.test.js.map +1 -0
  72. package/dist/src/agents/browser/browserManager.d.ts +115 -0
  73. package/dist/src/agents/browser/browserManager.js +370 -0
  74. package/dist/src/agents/browser/browserManager.js.map +1 -0
  75. package/dist/src/agents/browser/browserManager.test.d.ts +6 -0
  76. package/dist/src/agents/browser/browserManager.test.js +382 -0
  77. package/dist/src/agents/browser/browserManager.test.js.map +1 -0
  78. package/dist/src/agents/browser/mcpToolWrapper.d.ts +45 -0
  79. package/dist/src/agents/browser/mcpToolWrapper.js +358 -0
  80. package/dist/src/agents/browser/mcpToolWrapper.js.map +1 -0
  81. package/dist/src/agents/browser/mcpToolWrapper.test.d.ts +6 -0
  82. package/dist/src/agents/browser/mcpToolWrapper.test.js +126 -0
  83. package/dist/src/agents/browser/mcpToolWrapper.test.js.map +1 -0
  84. package/dist/src/agents/browser/mcpToolWrapperConfirmation.test.d.ts +6 -0
  85. package/dist/src/agents/browser/mcpToolWrapperConfirmation.test.js +59 -0
  86. package/dist/src/agents/browser/mcpToolWrapperConfirmation.test.js.map +1 -0
  87. package/dist/src/agents/browser/modelAvailability.d.ts +23 -0
  88. package/dist/src/agents/browser/modelAvailability.js +23 -0
  89. package/dist/src/agents/browser/modelAvailability.js.map +1 -0
  90. package/dist/src/agents/cli-help-agent.d.ts +2 -2
  91. package/dist/src/billing/billing.d.ts +80 -0
  92. package/dist/src/billing/billing.js +128 -0
  93. package/dist/src/billing/billing.js.map +1 -0
  94. package/dist/src/billing/billing.test.d.ts +6 -0
  95. package/dist/src/billing/billing.test.js +182 -0
  96. package/dist/src/billing/billing.test.js.map +1 -0
  97. package/dist/src/billing/index.d.ts +6 -0
  98. package/dist/src/billing/index.js +7 -0
  99. package/dist/src/billing/index.js.map +1 -0
  100. package/dist/src/code_assist/oauth2.d.ts +1 -1
  101. package/dist/src/code_assist/types.d.ts +26 -26
  102. package/dist/src/config/agent-loop-context.d.ts +22 -0
  103. package/dist/src/config/agent-loop-context.js +7 -0
  104. package/dist/src/config/agent-loop-context.js.map +1 -0
  105. package/dist/src/config/trackerFeatureFlag.test.d.ts +6 -0
  106. package/dist/src/config/trackerFeatureFlag.test.js +43 -0
  107. package/dist/src/config/trackerFeatureFlag.test.js.map +1 -0
  108. package/dist/src/config/userHintService.d.ts +46 -0
  109. package/dist/src/config/userHintService.js +81 -0
  110. package/dist/src/config/userHintService.js.map +1 -0
  111. package/dist/src/config/userHintService.test.d.ts +6 -0
  112. package/dist/src/config/userHintService.test.js +62 -0
  113. package/dist/src/config/userHintService.test.js.map +1 -0
  114. package/dist/src/core/localLiteRtLmClient.d.ts +24 -0
  115. package/dist/src/core/localLiteRtLmClient.js +77 -0
  116. package/dist/src/core/localLiteRtLmClient.js.map +1 -0
  117. package/dist/src/core/localLiteRtLmClient.test.d.ts +6 -0
  118. package/dist/src/core/localLiteRtLmClient.test.js +87 -0
  119. package/dist/src/core/localLiteRtLmClient.test.js.map +1 -0
  120. package/dist/src/core/openaiContentGenerator.d.ts +1 -0
  121. package/dist/src/core/openaiContentGenerator.js +13 -13
  122. package/dist/src/core/openaiContentGenerator.js.map +1 -1
  123. package/dist/src/hooks/runtimeHooks.test.d.ts +6 -0
  124. package/dist/src/hooks/runtimeHooks.test.js +100 -0
  125. package/dist/src/hooks/runtimeHooks.test.js.map +1 -0
  126. package/dist/src/ide/types.d.ts +6 -6
  127. package/dist/src/mcp/mcp-oauth-provider.d.ts +43 -0
  128. package/dist/src/mcp/mcp-oauth-provider.js +67 -0
  129. package/dist/src/mcp/mcp-oauth-provider.js.map +1 -0
  130. package/dist/src/mcp/mcp-oauth-provider.test.d.ts +6 -0
  131. package/dist/src/mcp/mcp-oauth-provider.test.js +63 -0
  132. package/dist/src/mcp/mcp-oauth-provider.test.js.map +1 -0
  133. package/dist/src/policy/integrity.d.ts +45 -0
  134. package/dist/src/policy/integrity.js +121 -0
  135. package/dist/src/policy/integrity.js.map +1 -0
  136. package/dist/src/policy/integrity.test.d.ts +6 -0
  137. package/dist/src/policy/integrity.test.js +132 -0
  138. package/dist/src/policy/integrity.test.js.map +1 -0
  139. package/dist/src/policy/policies/conseca.toml +6 -0
  140. package/dist/src/policy/workspace-policy.test.js +231 -0
  141. package/dist/src/policy/workspace-policy.test.js.map +1 -0
  142. package/dist/src/routing/strategies/approvalModeStrategy.d.ts +18 -0
  143. package/dist/src/routing/strategies/approvalModeStrategy.js +59 -0
  144. package/dist/src/routing/strategies/approvalModeStrategy.js.map +1 -0
  145. package/dist/src/routing/strategies/approvalModeStrategy.test.d.ts +6 -0
  146. package/dist/src/routing/strategies/approvalModeStrategy.test.js +140 -0
  147. package/dist/src/routing/strategies/approvalModeStrategy.test.js.map +1 -0
  148. package/dist/src/routing/strategies/gemmaClassifierStrategy.d.ts +14 -0
  149. package/dist/src/routing/strategies/gemmaClassifierStrategy.js +182 -0
  150. package/dist/src/routing/strategies/gemmaClassifierStrategy.js.map +1 -0
  151. package/dist/src/routing/strategies/gemmaClassifierStrategy.test.d.ts +6 -0
  152. package/dist/src/routing/strategies/gemmaClassifierStrategy.test.js +218 -0
  153. package/dist/src/routing/strategies/gemmaClassifierStrategy.test.js.map +1 -0
  154. package/dist/src/safety/conseca/conseca.d.ts +31 -0
  155. package/dist/src/safety/conseca/conseca.js +105 -0
  156. package/dist/src/safety/conseca/conseca.js.map +1 -0
  157. package/dist/src/safety/conseca/conseca.test.js +226 -0
  158. package/dist/src/safety/conseca/conseca.test.js.map +1 -0
  159. package/dist/src/safety/conseca/integration.test.js +19 -0
  160. package/dist/src/safety/conseca/integration.test.js.map +1 -0
  161. package/dist/src/safety/conseca/policy-enforcer.d.ts +13 -0
  162. package/dist/src/safety/conseca/policy-enforcer.js +135 -0
  163. package/dist/src/safety/conseca/policy-enforcer.js.map +1 -0
  164. package/dist/src/safety/conseca/policy-enforcer.test.js +141 -0
  165. package/dist/src/safety/conseca/policy-enforcer.test.js.map +1 -0
  166. package/dist/src/safety/conseca/policy-generator.d.ts +15 -0
  167. package/dist/src/safety/conseca/policy-generator.js +144 -0
  168. package/dist/src/safety/conseca/policy-generator.js.map +1 -0
  169. package/dist/src/safety/conseca/policy-generator.test.d.ts +6 -0
  170. package/dist/src/safety/conseca/policy-generator.test.js +84 -0
  171. package/dist/src/safety/conseca/policy-generator.test.js.map +1 -0
  172. package/dist/src/safety/conseca/types.d.ts +15 -0
  173. package/dist/src/safety/conseca/types.js +7 -0
  174. package/dist/src/safety/conseca/types.js.map +1 -0
  175. package/dist/src/scheduler/scheduler_parallel.test.d.ts +6 -0
  176. package/dist/src/scheduler/scheduler_parallel.test.js +401 -0
  177. package/dist/src/scheduler/scheduler_parallel.test.js.map +1 -0
  178. package/dist/src/services/FolderTrustDiscoveryService.d.ts +32 -0
  179. package/dist/src/services/FolderTrustDiscoveryService.js +169 -0
  180. package/dist/src/services/FolderTrustDiscoveryService.js.map +1 -0
  181. package/dist/src/services/FolderTrustDiscoveryService.test.d.ts +6 -0
  182. package/dist/src/services/FolderTrustDiscoveryService.test.js +118 -0
  183. package/dist/src/services/FolderTrustDiscoveryService.test.js.map +1 -0
  184. package/dist/src/services/fileKeychain.d.ts +24 -0
  185. package/dist/src/services/fileKeychain.js +123 -0
  186. package/dist/src/services/fileKeychain.js.map +1 -0
  187. package/dist/src/services/keychainService.d.ts +51 -0
  188. package/dist/src/services/keychainService.js +133 -0
  189. package/dist/src/services/keychainService.js.map +1 -0
  190. package/dist/src/services/keychainService.test.d.ts +6 -0
  191. package/dist/src/services/keychainService.test.js +150 -0
  192. package/dist/src/services/keychainService.test.js.map +1 -0
  193. package/dist/src/services/keychainTypes.d.ts +41 -0
  194. package/dist/src/services/keychainTypes.js +18 -0
  195. package/dist/src/services/keychainTypes.js.map +1 -0
  196. package/dist/src/services/trackerService.d.ts +49 -0
  197. package/dist/src/services/trackerService.js +193 -0
  198. package/dist/src/services/trackerService.js.map +1 -0
  199. package/dist/src/services/trackerService.test.d.ts +6 -0
  200. package/dist/src/services/trackerService.test.js +117 -0
  201. package/dist/src/services/trackerService.test.js.map +1 -0
  202. package/dist/src/services/trackerTypes.d.ts +51 -0
  203. package/dist/src/services/trackerTypes.js +33 -0
  204. package/dist/src/services/trackerTypes.js.map +1 -0
  205. package/dist/src/telemetry/billingEvents.d.ts +75 -0
  206. package/dist/src/telemetry/billingEvents.js +181 -0
  207. package/dist/src/telemetry/billingEvents.js.map +1 -0
  208. package/dist/src/telemetry/billingEvents.test.d.ts +6 -0
  209. package/dist/src/telemetry/billingEvents.test.js +139 -0
  210. package/dist/src/telemetry/billingEvents.test.js.map +1 -0
  211. package/dist/src/telemetry/conseca-logger.d.ts +9 -0
  212. package/dist/src/telemetry/conseca-logger.js +91 -0
  213. package/dist/src/telemetry/conseca-logger.js.map +1 -0
  214. package/dist/src/telemetry/conseca-logger.test.d.ts +6 -0
  215. package/dist/src/telemetry/conseca-logger.test.js +90 -0
  216. package/dist/src/telemetry/conseca-logger.test.js.map +1 -0
  217. package/dist/src/telemetry/trace.test.d.ts +6 -0
  218. package/dist/src/telemetry/trace.test.js +116 -0
  219. package/dist/src/telemetry/trace.test.js.map +1 -0
  220. package/dist/src/tools/definitions/trackerTools.d.ts +12 -0
  221. package/dist/src/tools/definitions/trackerTools.js +146 -0
  222. package/dist/src/tools/definitions/trackerTools.js.map +1 -0
  223. package/dist/src/tools/diff-utils.d.ts +9 -0
  224. package/dist/src/tools/diff-utils.js +66 -0
  225. package/dist/src/tools/diff-utils.js.map +1 -0
  226. package/dist/src/tools/diff-utils.test.d.ts +6 -0
  227. package/dist/src/tools/diff-utils.test.js +53 -0
  228. package/dist/src/tools/diff-utils.test.js.map +1 -0
  229. package/dist/src/tools/grep-utils.d.ts +49 -0
  230. package/dist/src/tools/grep-utils.js +147 -0
  231. package/dist/src/tools/grep-utils.js.map +1 -0
  232. package/dist/src/tools/omissionPlaceholderDetector.d.ts +15 -0
  233. package/dist/src/tools/omissionPlaceholderDetector.js +90 -0
  234. package/dist/src/tools/omissionPlaceholderDetector.js.map +1 -0
  235. package/dist/src/tools/omissionPlaceholderDetector.test.d.ts +6 -0
  236. package/dist/src/tools/omissionPlaceholderDetector.test.js +49 -0
  237. package/dist/src/tools/omissionPlaceholderDetector.test.js.map +1 -0
  238. package/dist/src/tools/trackerTools.d.ts +122 -0
  239. package/dist/src/tools/trackerTools.js +365 -0
  240. package/dist/src/tools/trackerTools.js.map +1 -0
  241. package/dist/src/tools/trackerTools.test.d.ts +6 -0
  242. package/dist/src/tools/trackerTools.test.js +97 -0
  243. package/dist/src/tools/trackerTools.test.js.map +1 -0
  244. package/dist/src/utils/approvalModeUtils.d.ts +14 -0
  245. package/dist/src/utils/approvalModeUtils.js +35 -0
  246. package/dist/src/utils/approvalModeUtils.js.map +1 -0
  247. package/dist/src/utils/approvalModeUtils.test.d.ts +6 -0
  248. package/dist/src/utils/approvalModeUtils.test.js +36 -0
  249. package/dist/src/utils/approvalModeUtils.test.js.map +1 -0
  250. package/dist/src/utils/cache.d.ts +63 -0
  251. package/dist/src/utils/cache.js +103 -0
  252. package/dist/src/utils/cache.js.map +1 -0
  253. package/dist/src/utils/cache.test.d.ts +6 -0
  254. package/dist/src/utils/cache.test.js +158 -0
  255. package/dist/src/utils/cache.test.js.map +1 -0
  256. package/dist/src/utils/checkpointUtils.d.ts +2 -2
  257. package/dist/src/utils/compatibility.d.ts +41 -0
  258. package/dist/src/utils/compatibility.js +112 -0
  259. package/dist/src/utils/compatibility.js.map +1 -0
  260. package/dist/src/utils/compatibility.test.d.ts +6 -0
  261. package/dist/src/utils/compatibility.test.js +233 -0
  262. package/dist/src/utils/compatibility.test.js.map +1 -0
  263. package/dist/src/utils/envExpansion.d.ts +18 -0
  264. package/dist/src/utils/envExpansion.js +46 -0
  265. package/dist/src/utils/envExpansion.js.map +1 -0
  266. package/dist/src/utils/envExpansion.test.d.ts +6 -0
  267. package/dist/src/utils/envExpansion.test.js +110 -0
  268. package/dist/src/utils/envExpansion.test.js.map +1 -0
  269. package/dist/src/utils/errors_timeout.test.d.ts +6 -0
  270. package/dist/src/utils/errors_timeout.test.js +40 -0
  271. package/dist/src/utils/errors_timeout.test.js.map +1 -0
  272. package/dist/src/utils/fetch.test.d.ts +6 -0
  273. package/dist/src/utils/fetch.test.js +206 -0
  274. package/dist/src/utils/fetch.test.js.map +1 -0
  275. package/dist/src/utils/markdownUtils.d.ts +22 -0
  276. package/dist/src/utils/markdownUtils.js +126 -0
  277. package/dist/src/utils/markdownUtils.js.map +1 -0
  278. package/dist/src/utils/markdownUtils.test.d.ts +6 -0
  279. package/dist/src/utils/markdownUtils.test.js +107 -0
  280. package/dist/src/utils/markdownUtils.test.js.map +1 -0
  281. package/dist/src/utils/oauth-flow.d.ts +105 -0
  282. package/dist/src/utils/oauth-flow.js +370 -0
  283. package/dist/src/utils/oauth-flow.js.map +1 -0
  284. package/dist/src/utils/oauth-flow.test.d.ts +6 -0
  285. package/dist/src/utils/oauth-flow.test.js +360 -0
  286. package/dist/src/utils/oauth-flow.test.js.map +1 -0
  287. package/dist/src/utils/sessionUtils.d.ts +14 -0
  288. package/dist/src/utils/sessionUtils.js +122 -0
  289. package/dist/src/utils/sessionUtils.js.map +1 -0
  290. package/dist/src/utils/sessionUtils.test.d.ts +1 -0
  291. package/dist/src/utils/sessionUtils.test.js +171 -0
  292. package/dist/src/utils/sessionUtils.test.js.map +1 -0
  293. package/dist/src/voice/responseFormatter.d.ts +38 -0
  294. package/dist/src/voice/responseFormatter.js +130 -0
  295. package/dist/src/voice/responseFormatter.js.map +1 -0
  296. package/dist/src/voice/responseFormatter.test.d.ts +6 -0
  297. package/dist/src/voice/responseFormatter.test.js +214 -0
  298. package/dist/src/voice/responseFormatter.test.js.map +1 -0
  299. package/dist/tsconfig.tsbuildinfo +1 -1
  300. package/package.json +1 -1
  301. package/dist/docs/CONTRIBUTING.md +0 -555
  302. package/dist/src/agents/executor.d.ts +0 -114
  303. package/dist/src/agents/executor.js +0 -779
  304. package/dist/src/agents/executor.js.map +0 -1
  305. package/dist/src/agents/executor.test.js +0 -1362
  306. package/dist/src/agents/executor.test.js.map +0 -1
  307. package/dist/src/agents/invocation.d.ts +0 -46
  308. package/dist/src/agents/invocation.js +0 -102
  309. package/dist/src/agents/invocation.js.map +0 -1
  310. package/dist/src/agents/invocation.test.js +0 -215
  311. package/dist/src/agents/invocation.test.js.map +0 -1
  312. package/dist/src/core/subagent.d.ts +0 -236
  313. package/dist/src/core/subagent.js +0 -482
  314. package/dist/src/core/subagent.js.map +0 -1
  315. package/dist/src/core/subagent.test.js +0 -530
  316. package/dist/src/core/subagent.test.js.map +0 -1
  317. package/dist/src/tools/smart-edit.d.ts +0 -78
  318. package/dist/src/tools/smart-edit.js +0 -717
  319. package/dist/src/tools/smart-edit.js.map +0 -1
  320. package/dist/src/tools/smart-edit.test.js +0 -592
  321. package/dist/src/tools/smart-edit.test.js.map +0 -1
  322. /package/dist/src/{agents/executor.test.d.ts → policy/workspace-policy.test.d.ts} +0 -0
  323. /package/dist/src/{agents/invocation.test.d.ts → safety/conseca/conseca.test.d.ts} +0 -0
  324. /package/dist/src/{core/subagent.test.d.ts → safety/conseca/integration.test.d.ts} +0 -0
  325. /package/dist/src/{tools/smart-edit.test.d.ts → safety/conseca/policy-enforcer.test.d.ts} +0 -0
@@ -0,0 +1,45 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export declare enum IntegrityStatus {
7
+ MATCH = "MATCH",
8
+ MISMATCH = "MISMATCH",
9
+ NEW = "NEW"
10
+ }
11
+ export interface IntegrityResult {
12
+ status: IntegrityStatus;
13
+ hash: string;
14
+ fileCount: number;
15
+ }
16
+ export declare class PolicyIntegrityManager {
17
+ /**
18
+ * Checks the integrity of policies in a given directory against the stored hash.
19
+ *
20
+ * @param scope The scope of the policy (e.g., 'project', 'user').
21
+ * @param identifier A unique identifier for the policy scope (e.g., project path).
22
+ * @param policyDir The directory containing the policy files.
23
+ * @returns IntegrityResult indicating if the current policies match the stored hash.
24
+ */
25
+ checkIntegrity(scope: string, identifier: string, policyDir: string): Promise<IntegrityResult>;
26
+ /**
27
+ * Accepts and persists the current integrity hash for a given policy scope.
28
+ *
29
+ * @param scope The scope of the policy.
30
+ * @param identifier A unique identifier for the policy scope (e.g., project path).
31
+ * @param hash The hash to persist.
32
+ */
33
+ acceptIntegrity(scope: string, identifier: string, hash: string): Promise<void>;
34
+ /**
35
+ * Calculates a SHA-256 hash of all policy files in the directory.
36
+ * The hash includes the relative file path and content to detect renames and modifications.
37
+ *
38
+ * @param policyDir The directory containing the policy files.
39
+ * @returns The calculated hash and file count
40
+ */
41
+ private static calculateIntegrityHash;
42
+ private getIntegrityKey;
43
+ private loadIntegrityData;
44
+ private saveIntegrityData;
45
+ }
@@ -0,0 +1,121 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import * as crypto from 'node:crypto';
7
+ import * as fs from 'node:fs/promises';
8
+ import * as path from 'node:path';
9
+ import { Storage } from '../config/storage.js';
10
+ import { readPolicyFiles } from './toml-loader.js';
11
+ import { debugLogger } from '../utils/debugLogger.js';
12
+ import { isNodeError } from '../utils/errors.js';
13
+ export var IntegrityStatus;
14
+ (function (IntegrityStatus) {
15
+ IntegrityStatus["MATCH"] = "MATCH";
16
+ IntegrityStatus["MISMATCH"] = "MISMATCH";
17
+ IntegrityStatus["NEW"] = "NEW";
18
+ })(IntegrityStatus || (IntegrityStatus = {}));
19
+ export class PolicyIntegrityManager {
20
+ /**
21
+ * Checks the integrity of policies in a given directory against the stored hash.
22
+ *
23
+ * @param scope The scope of the policy (e.g., 'project', 'user').
24
+ * @param identifier A unique identifier for the policy scope (e.g., project path).
25
+ * @param policyDir The directory containing the policy files.
26
+ * @returns IntegrityResult indicating if the current policies match the stored hash.
27
+ */
28
+ async checkIntegrity(scope, identifier, policyDir) {
29
+ const { hash: currentHash, fileCount } = await PolicyIntegrityManager.calculateIntegrityHash(policyDir);
30
+ const storedData = await this.loadIntegrityData();
31
+ const key = this.getIntegrityKey(scope, identifier);
32
+ const storedHash = storedData[key];
33
+ if (!storedHash) {
34
+ return { status: IntegrityStatus.NEW, hash: currentHash, fileCount };
35
+ }
36
+ if (storedHash === currentHash) {
37
+ return { status: IntegrityStatus.MATCH, hash: currentHash, fileCount };
38
+ }
39
+ return { status: IntegrityStatus.MISMATCH, hash: currentHash, fileCount };
40
+ }
41
+ /**
42
+ * Accepts and persists the current integrity hash for a given policy scope.
43
+ *
44
+ * @param scope The scope of the policy.
45
+ * @param identifier A unique identifier for the policy scope (e.g., project path).
46
+ * @param hash The hash to persist.
47
+ */
48
+ async acceptIntegrity(scope, identifier, hash) {
49
+ const storedData = await this.loadIntegrityData();
50
+ const key = this.getIntegrityKey(scope, identifier);
51
+ storedData[key] = hash;
52
+ await this.saveIntegrityData(storedData);
53
+ }
54
+ /**
55
+ * Calculates a SHA-256 hash of all policy files in the directory.
56
+ * The hash includes the relative file path and content to detect renames and modifications.
57
+ *
58
+ * @param policyDir The directory containing the policy files.
59
+ * @returns The calculated hash and file count
60
+ */
61
+ static async calculateIntegrityHash(policyDir) {
62
+ try {
63
+ const files = await readPolicyFiles(policyDir);
64
+ // Sort files by path to ensure deterministic hashing
65
+ files.sort((a, b) => a.path.localeCompare(b.path));
66
+ const hash = crypto.createHash('sha256');
67
+ for (const file of files) {
68
+ const relativePath = path.relative(policyDir, file.path);
69
+ // Include relative path and content in the hash
70
+ hash.update(relativePath);
71
+ hash.update('\0'); // Separator
72
+ hash.update(file.content);
73
+ hash.update('\0'); // Separator
74
+ }
75
+ return { hash: hash.digest('hex'), fileCount: files.length };
76
+ }
77
+ catch (error) {
78
+ debugLogger.error('Failed to calculate policy integrity hash', error);
79
+ // Return a unique hash (random) to force a mismatch if calculation fails?
80
+ // Or throw? Throwing is better so we don't accidentally accept/deny corrupted state.
81
+ throw error;
82
+ }
83
+ }
84
+ getIntegrityKey(scope, identifier) {
85
+ return `${scope}:${identifier}`;
86
+ }
87
+ async loadIntegrityData() {
88
+ const storagePath = Storage.getPolicyIntegrityStoragePath();
89
+ try {
90
+ const content = await fs.readFile(storagePath, 'utf-8');
91
+ const parsed = JSON.parse(content);
92
+ if (typeof parsed === 'object' &&
93
+ parsed !== null &&
94
+ Object.values(parsed).every((v) => typeof v === 'string')) {
95
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
96
+ return parsed;
97
+ }
98
+ debugLogger.warn('Invalid policy integrity data format');
99
+ return {};
100
+ }
101
+ catch (error) {
102
+ if (isNodeError(error) && error.code === 'ENOENT') {
103
+ return {};
104
+ }
105
+ debugLogger.error('Failed to load policy integrity data', error);
106
+ return {};
107
+ }
108
+ }
109
+ async saveIntegrityData(data) {
110
+ const storagePath = Storage.getPolicyIntegrityStoragePath();
111
+ try {
112
+ await fs.mkdir(path.dirname(storagePath), { recursive: true });
113
+ await fs.writeFile(storagePath, JSON.stringify(data, null, 2), 'utf-8');
114
+ }
115
+ catch (error) {
116
+ debugLogger.error('Failed to save policy integrity data', error);
117
+ throw error;
118
+ }
119
+ }
120
+ }
121
+ //# sourceMappingURL=integrity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integrity.js","sourceRoot":"","sources":["../../../src/policy/integrity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export {};
@@ -0,0 +1,132 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { describe, it, expect, vi, afterEach, beforeEach } from 'vitest';
7
+ import { PolicyIntegrityManager, IntegrityStatus } from './integrity.js';
8
+ import * as fs from 'node:fs/promises';
9
+ import * as path from 'node:path';
10
+ import * as os from 'node:os';
11
+ import { Storage } from '../config/storage.js';
12
+ describe('PolicyIntegrityManager', () => {
13
+ let integrityManager;
14
+ let tempDir;
15
+ let integrityStoragePath;
16
+ beforeEach(async () => {
17
+ tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'gemini-cli-test-'));
18
+ integrityStoragePath = path.join(tempDir, 'policy_integrity.json');
19
+ vi.spyOn(Storage, 'getPolicyIntegrityStoragePath').mockReturnValue(integrityStoragePath);
20
+ integrityManager = new PolicyIntegrityManager();
21
+ });
22
+ afterEach(async () => {
23
+ await fs.rm(tempDir, { recursive: true, force: true });
24
+ vi.restoreAllMocks();
25
+ });
26
+ describe('checkIntegrity', () => {
27
+ it('should return NEW if no stored hash', async () => {
28
+ const policyDir = path.join(tempDir, 'policies');
29
+ await fs.mkdir(policyDir);
30
+ await fs.writeFile(path.join(policyDir, 'a.toml'), 'contentA');
31
+ const result = await integrityManager.checkIntegrity('workspace', 'id', policyDir);
32
+ expect(result.status).toBe(IntegrityStatus.NEW);
33
+ expect(result.hash).toBeDefined();
34
+ expect(result.hash).toHaveLength(64);
35
+ expect(result.fileCount).toBe(1);
36
+ });
37
+ it('should return MATCH if stored hash matches', async () => {
38
+ const policyDir = path.join(tempDir, 'policies');
39
+ await fs.mkdir(policyDir);
40
+ await fs.writeFile(path.join(policyDir, 'a.toml'), 'contentA');
41
+ // First run to get the hash
42
+ const resultNew = await integrityManager.checkIntegrity('workspace', 'id', policyDir);
43
+ const currentHash = resultNew.hash;
44
+ // Save the hash to mock storage
45
+ await fs.writeFile(integrityStoragePath, JSON.stringify({ 'workspace:id': currentHash }));
46
+ const result = await integrityManager.checkIntegrity('workspace', 'id', policyDir);
47
+ expect(result.status).toBe(IntegrityStatus.MATCH);
48
+ expect(result.hash).toBe(currentHash);
49
+ });
50
+ it('should return MISMATCH if stored hash differs', async () => {
51
+ const policyDir = path.join(tempDir, 'policies');
52
+ await fs.mkdir(policyDir);
53
+ await fs.writeFile(path.join(policyDir, 'a.toml'), 'contentA');
54
+ const resultNew = await integrityManager.checkIntegrity('workspace', 'id', policyDir);
55
+ const currentHash = resultNew.hash;
56
+ // Save a different hash
57
+ await fs.writeFile(integrityStoragePath, JSON.stringify({ 'workspace:id': 'different_hash' }));
58
+ const result = await integrityManager.checkIntegrity('workspace', 'id', policyDir);
59
+ expect(result.status).toBe(IntegrityStatus.MISMATCH);
60
+ expect(result.hash).toBe(currentHash);
61
+ });
62
+ it('should result in different hash if filename changes', async () => {
63
+ const policyDir1 = path.join(tempDir, 'policies1');
64
+ await fs.mkdir(policyDir1);
65
+ await fs.writeFile(path.join(policyDir1, 'a.toml'), 'contentA');
66
+ const result1 = await integrityManager.checkIntegrity('workspace', 'id', policyDir1);
67
+ const policyDir2 = path.join(tempDir, 'policies2');
68
+ await fs.mkdir(policyDir2);
69
+ await fs.writeFile(path.join(policyDir2, 'b.toml'), 'contentA');
70
+ const result2 = await integrityManager.checkIntegrity('workspace', 'id', policyDir2);
71
+ expect(result1.hash).not.toBe(result2.hash);
72
+ });
73
+ it('should result in different hash if content changes', async () => {
74
+ const policyDir = path.join(tempDir, 'policies');
75
+ await fs.mkdir(policyDir);
76
+ await fs.writeFile(path.join(policyDir, 'a.toml'), 'contentA');
77
+ const result1 = await integrityManager.checkIntegrity('workspace', 'id', policyDir);
78
+ await fs.writeFile(path.join(policyDir, 'a.toml'), 'contentB');
79
+ const result2 = await integrityManager.checkIntegrity('workspace', 'id', policyDir);
80
+ expect(result1.hash).not.toBe(result2.hash);
81
+ });
82
+ it('should be deterministic (sort order)', async () => {
83
+ const policyDir1 = path.join(tempDir, 'policies1');
84
+ await fs.mkdir(policyDir1);
85
+ await fs.writeFile(path.join(policyDir1, 'a.toml'), 'contentA');
86
+ await fs.writeFile(path.join(policyDir1, 'b.toml'), 'contentB');
87
+ const result1 = await integrityManager.checkIntegrity('workspace', 'id', policyDir1);
88
+ // Re-read with same files but they might be in different order in readdir
89
+ // PolicyIntegrityManager should sort them.
90
+ const result2 = await integrityManager.checkIntegrity('workspace', 'id', policyDir1);
91
+ expect(result1.hash).toBe(result2.hash);
92
+ });
93
+ it('should handle multiple projects correctly', async () => {
94
+ const dirA = path.join(tempDir, 'dirA');
95
+ await fs.mkdir(dirA);
96
+ await fs.writeFile(path.join(dirA, 'p.toml'), 'contentA');
97
+ const dirB = path.join(tempDir, 'dirB');
98
+ await fs.mkdir(dirB);
99
+ await fs.writeFile(path.join(dirB, 'p.toml'), 'contentB');
100
+ const { hash: hashA } = await integrityManager.checkIntegrity('workspace', 'idA', dirA);
101
+ const { hash: hashB } = await integrityManager.checkIntegrity('workspace', 'idB', dirB);
102
+ // Save to storage
103
+ await fs.writeFile(integrityStoragePath, JSON.stringify({
104
+ 'workspace:idA': hashA,
105
+ 'workspace:idB': 'oldHashB',
106
+ }));
107
+ // Project A should match
108
+ const resultA = await integrityManager.checkIntegrity('workspace', 'idA', dirA);
109
+ expect(resultA.status).toBe(IntegrityStatus.MATCH);
110
+ expect(resultA.hash).toBe(hashA);
111
+ // Project B should mismatch
112
+ const resultB = await integrityManager.checkIntegrity('workspace', 'idB', dirB);
113
+ expect(resultB.status).toBe(IntegrityStatus.MISMATCH);
114
+ expect(resultB.hash).toBe(hashB);
115
+ });
116
+ });
117
+ describe('acceptIntegrity', () => {
118
+ it('should save the hash to storage', async () => {
119
+ await integrityManager.acceptIntegrity('workspace', 'id', 'hash123');
120
+ const stored = JSON.parse(await fs.readFile(integrityStoragePath, 'utf-8'));
121
+ expect(stored['workspace:id']).toBe('hash123');
122
+ });
123
+ it('should update existing hash', async () => {
124
+ await fs.writeFile(integrityStoragePath, JSON.stringify({ 'other:id': 'otherhash' }));
125
+ await integrityManager.acceptIntegrity('workspace', 'id', 'hash123');
126
+ const stored = JSON.parse(await fs.readFile(integrityStoragePath, 'utf-8'));
127
+ expect(stored['other:id']).toBe('otherhash');
128
+ expect(stored['workspace:id']).toBe('hash123');
129
+ });
130
+ });
131
+ });
132
+ //# sourceMappingURL=integrity.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integrity.test.js","sourceRoot":"","sources":["../../../src/policy/integrity.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ [[safety_checker]]
2
+ toolName = "*"
3
+ priority = 100
4
+ [safety_checker.checker]
5
+ type = "in-process"
6
+ name = "conseca"
@@ -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, afterEach, beforeEach } from 'vitest';
7
+ import nodePath from 'node:path';
8
+ import { ApprovalMode } from './types.js';
9
+ import { isDirectorySecure } from '../utils/security.js';
10
+ // Mock dependencies
11
+ vi.mock('../utils/security.js', () => ({
12
+ isDirectorySecure: vi.fn().mockResolvedValue({ secure: true }),
13
+ }));
14
+ describe('Workspace-Level Policies', () => {
15
+ beforeEach(async () => {
16
+ vi.resetModules();
17
+ const { Storage } = await import('../config/storage.js');
18
+ vi.spyOn(Storage, 'getUserPoliciesDir').mockReturnValue('/mock/user/policies');
19
+ vi.spyOn(Storage, 'getSystemPoliciesDir').mockReturnValue('/mock/system/policies');
20
+ // Ensure security check always returns secure
21
+ vi.mocked(isDirectorySecure).mockResolvedValue({ secure: true });
22
+ });
23
+ afterEach(() => {
24
+ vi.clearAllMocks();
25
+ vi.restoreAllMocks();
26
+ vi.doUnmock('node:fs/promises');
27
+ });
28
+ it('should load workspace policies with correct priority (Tier 3)', async () => {
29
+ const workspacePoliciesDir = '/mock/workspace/policies';
30
+ const defaultPoliciesDir = '/mock/default/policies';
31
+ // Mock FS
32
+ const actualFs = await vi.importActual('node:fs/promises');
33
+ const mockStat = vi.fn(async (path) => {
34
+ if (typeof path === 'string' && path.startsWith('/mock/')) {
35
+ return {
36
+ isDirectory: () => true,
37
+ isFile: () => false,
38
+ };
39
+ }
40
+ return actualFs.stat(path);
41
+ });
42
+ // Mock readdir to return a policy file for each tier
43
+ const mockReaddir = vi.fn(async (path) => {
44
+ const normalizedPath = nodePath.normalize(path);
45
+ if (normalizedPath.endsWith('default/policies'))
46
+ return [
47
+ {
48
+ name: 'default.toml',
49
+ isFile: () => true,
50
+ isDirectory: () => false,
51
+ },
52
+ ];
53
+ if (normalizedPath.endsWith('user/policies'))
54
+ return [
55
+ { name: 'user.toml', isFile: () => true, isDirectory: () => false },
56
+ ];
57
+ if (normalizedPath.endsWith('workspace/policies'))
58
+ return [
59
+ {
60
+ name: 'workspace.toml',
61
+ isFile: () => true,
62
+ isDirectory: () => false,
63
+ },
64
+ ];
65
+ if (normalizedPath.endsWith('system/policies'))
66
+ return [
67
+ { name: 'admin.toml', isFile: () => true, isDirectory: () => false },
68
+ ];
69
+ return [];
70
+ });
71
+ // Mock readFile to return content with distinct priorities/decisions
72
+ const mockReadFile = vi.fn(async (path) => {
73
+ if (path.includes('default.toml')) {
74
+ return `[[rule]]
75
+ toolName = "test_tool"
76
+ decision = "allow"
77
+ priority = 10
78
+ `; // Tier 1 -> 1.010
79
+ }
80
+ if (path.includes('user.toml')) {
81
+ return `[[rule]]
82
+ toolName = "test_tool"
83
+ decision = "deny"
84
+ priority = 10
85
+ `; // Tier 4 -> 4.010
86
+ }
87
+ if (path.includes('workspace.toml')) {
88
+ return `[[rule]]
89
+ toolName = "test_tool"
90
+ decision = "allow"
91
+ priority = 10
92
+ `; // Tier 3 -> 3.010
93
+ }
94
+ if (path.includes('admin.toml')) {
95
+ return `[[rule]]
96
+ toolName = "test_tool"
97
+ decision = "deny"
98
+ priority = 10
99
+ `; // Tier 5 -> 5.010
100
+ }
101
+ return '';
102
+ });
103
+ vi.doMock('node:fs/promises', () => ({
104
+ ...actualFs,
105
+ default: {
106
+ ...actualFs,
107
+ readdir: mockReaddir,
108
+ readFile: mockReadFile,
109
+ stat: mockStat,
110
+ },
111
+ readdir: mockReaddir,
112
+ readFile: mockReadFile,
113
+ stat: mockStat,
114
+ }));
115
+ const { createPolicyEngineConfig } = await import('./config.js');
116
+ // Test 1: Workspace vs User (User should win)
117
+ const config = await createPolicyEngineConfig({ workspacePoliciesDir }, ApprovalMode.DEFAULT, defaultPoliciesDir);
118
+ const rules = config.rules?.filter((r) => r.toolName === 'test_tool');
119
+ expect(rules).toBeDefined();
120
+ // Check for all 4 rules
121
+ const defaultRule = rules?.find((r) => r.priority === 1.01);
122
+ const workspaceRule = rules?.find((r) => r.priority === 3.01);
123
+ const userRule = rules?.find((r) => r.priority === 4.01);
124
+ const adminRule = rules?.find((r) => r.priority === 5.01);
125
+ expect(defaultRule).toBeDefined();
126
+ expect(userRule).toBeDefined();
127
+ expect(workspaceRule).toBeDefined();
128
+ expect(adminRule).toBeDefined();
129
+ // Verify Hierarchy: Admin > User > Workspace > Default
130
+ expect(adminRule.priority).toBeGreaterThan(userRule.priority);
131
+ expect(userRule.priority).toBeGreaterThan(workspaceRule.priority);
132
+ expect(workspaceRule.priority).toBeGreaterThan(defaultRule.priority);
133
+ });
134
+ it('should ignore workspace policies if workspacePoliciesDir is undefined', async () => {
135
+ const defaultPoliciesDir = '/mock/default/policies';
136
+ // Mock FS (simplified)
137
+ const actualFs = await vi.importActual('node:fs/promises');
138
+ const mockStat = vi.fn(async (path) => {
139
+ if (typeof path === 'string' && path.startsWith('/mock/')) {
140
+ return {
141
+ isDirectory: () => true,
142
+ isFile: () => false,
143
+ };
144
+ }
145
+ return actualFs.stat(path);
146
+ });
147
+ const mockReaddir = vi.fn(async (path) => {
148
+ const normalizedPath = nodePath.normalize(path);
149
+ if (normalizedPath.endsWith('default/policies'))
150
+ return [
151
+ {
152
+ name: 'default.toml',
153
+ isFile: () => true,
154
+ isDirectory: () => false,
155
+ },
156
+ ];
157
+ return [];
158
+ });
159
+ const mockReadFile = vi.fn(async () => `[[rule]]
160
+ toolName="t"
161
+ decision="allow"
162
+ priority=10`);
163
+ vi.doMock('node:fs/promises', () => ({
164
+ ...actualFs,
165
+ default: {
166
+ ...actualFs,
167
+ readdir: mockReaddir,
168
+ readFile: mockReadFile,
169
+ stat: mockStat,
170
+ },
171
+ readdir: mockReaddir,
172
+ readFile: mockReadFile,
173
+ stat: mockStat,
174
+ }));
175
+ const { createPolicyEngineConfig } = await import('./config.js');
176
+ const config = await createPolicyEngineConfig({ workspacePoliciesDir: undefined }, ApprovalMode.DEFAULT, defaultPoliciesDir);
177
+ // Should only have default tier rule (1.01)
178
+ const rules = config.rules;
179
+ expect(rules).toHaveLength(1);
180
+ expect(rules[0].priority).toBe(1.01);
181
+ });
182
+ it('should load workspace policies and correctly transform to Tier 3', async () => {
183
+ const workspacePoliciesDir = '/mock/workspace/policies';
184
+ // Mock FS
185
+ const actualFs = await vi.importActual('node:fs/promises');
186
+ const mockStat = vi.fn(async (path) => {
187
+ if (typeof path === 'string' && path.startsWith('/mock/')) {
188
+ return {
189
+ isDirectory: () => true,
190
+ isFile: () => false,
191
+ };
192
+ }
193
+ return actualFs.stat(path);
194
+ });
195
+ const mockReaddir = vi.fn(async (path) => {
196
+ const normalizedPath = nodePath.normalize(path);
197
+ if (normalizedPath.endsWith('workspace/policies'))
198
+ return [
199
+ {
200
+ name: 'workspace.toml',
201
+ isFile: () => true,
202
+ isDirectory: () => false,
203
+ },
204
+ ];
205
+ return [];
206
+ });
207
+ const mockReadFile = vi.fn(async () => `[[rule]]
208
+ toolName="p_tool"
209
+ decision="allow"
210
+ priority=500`);
211
+ vi.doMock('node:fs/promises', () => ({
212
+ ...actualFs,
213
+ default: {
214
+ ...actualFs,
215
+ readdir: mockReaddir,
216
+ readFile: mockReadFile,
217
+ stat: mockStat,
218
+ },
219
+ readdir: mockReaddir,
220
+ readFile: mockReadFile,
221
+ stat: mockStat,
222
+ }));
223
+ const { createPolicyEngineConfig } = await import('./config.js');
224
+ const config = await createPolicyEngineConfig({ workspacePoliciesDir }, ApprovalMode.DEFAULT);
225
+ const rule = config.rules?.find((r) => r.toolName === 'p_tool');
226
+ expect(rule).toBeDefined();
227
+ // Workspace Tier (3) + 500/1000 = 3.5
228
+ expect(rule?.priority).toBe(3.5);
229
+ });
230
+ });
231
+ //# sourceMappingURL=workspace-policy.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-policy.test.js","sourceRoot":"","sources":["../../../src/policy/workspace-policy.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { Config } from '../../config/config.js';
7
+ import type { BaseLlmClient } from '../../core/baseLlmClient.js';
8
+ import type { RoutingContext, RoutingDecision, RoutingStrategy } from '../routingStrategy.js';
9
+ /**
10
+ * A strategy that routes based on the current ApprovalMode and plan status.
11
+ *
12
+ * - In PLAN mode: Routes to the PRO model for high-quality planning.
13
+ * - In other modes with an approved plan: Routes to the FLASH model for efficient implementation.
14
+ */
15
+ export declare class ApprovalModeStrategy implements RoutingStrategy {
16
+ readonly name = "approval-mode";
17
+ route(context: RoutingContext, config: Config, _baseLlmClient: BaseLlmClient): Promise<RoutingDecision | null>;
18
+ }