@gitkraken/core-gitlens 0.5.109 → 0.5.111

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 (416) hide show
  1. package/CHANGELOG.md +48 -1
  2. package/dist/git/cache.d.ts +111 -6
  3. package/dist/git/cache.d.ts.map +1 -1
  4. package/dist/git/cache.js +312 -43
  5. package/dist/git/cache.js.map +1 -1
  6. package/dist/git/context.d.ts +11 -0
  7. package/dist/git/context.d.ts.map +1 -1
  8. package/dist/git/context.js.map +1 -1
  9. package/dist/git/models/fileStatus.d.ts +1 -0
  10. package/dist/git/models/fileStatus.d.ts.map +1 -1
  11. package/dist/git/models/fileStatus.js +1 -0
  12. package/dist/git/models/fileStatus.js.map +1 -1
  13. package/dist/git/models/issue.d.ts +4 -0
  14. package/dist/git/models/issue.d.ts.map +1 -1
  15. package/dist/git/models/mergeConflicts.d.ts +2 -0
  16. package/dist/git/models/mergeConflicts.d.ts.map +1 -1
  17. package/dist/git/models/pullRequest.d.ts +119 -2
  18. package/dist/git/models/pullRequest.d.ts.map +1 -1
  19. package/dist/git/models/pullRequest.js +27 -1
  20. package/dist/git/models/pullRequest.js.map +1 -1
  21. package/dist/git/models/repository.d.ts +32 -5
  22. package/dist/git/models/repository.d.ts.map +1 -1
  23. package/dist/git/models/repository.js +58 -12
  24. package/dist/git/models/repository.js.map +1 -1
  25. package/dist/git/models/statusFile.d.ts.map +1 -1
  26. package/dist/git/models/statusFile.js +3 -0
  27. package/dist/git/models/statusFile.js.map +1 -1
  28. package/dist/git/providers/branches.d.ts +2 -0
  29. package/dist/git/providers/branches.d.ts.map +1 -1
  30. package/dist/git/providers/commits.d.ts +8 -0
  31. package/dist/git/providers/commits.d.ts.map +1 -1
  32. package/dist/git/providers/config.d.ts +19 -1
  33. package/dist/git/providers/config.d.ts.map +1 -1
  34. package/dist/git/providers/operations.d.ts +1 -0
  35. package/dist/git/providers/operations.d.ts.map +1 -1
  36. package/dist/git/providers/pausedOperations.d.ts +2 -0
  37. package/dist/git/providers/pausedOperations.d.ts.map +1 -1
  38. package/dist/git/providers/status.d.ts +1 -0
  39. package/dist/git/providers/status.d.ts.map +1 -1
  40. package/dist/git/utils/config.utils.d.ts +3 -0
  41. package/dist/git/utils/config.utils.d.ts.map +1 -0
  42. package/dist/git/utils/config.utils.js +8 -0
  43. package/dist/git/utils/config.utils.js.map +1 -0
  44. package/dist/git/utils/issue.utils.d.ts.map +1 -1
  45. package/dist/git/utils/issue.utils.js +2 -0
  46. package/dist/git/utils/issue.utils.js.map +1 -1
  47. package/dist/git/utils/pausedOperationStatus.utils.d.ts +14 -0
  48. package/dist/git/utils/pausedOperationStatus.utils.d.ts.map +1 -1
  49. package/dist/git/utils/pausedOperationStatus.utils.js +23 -0
  50. package/dist/git/utils/pausedOperationStatus.utils.js.map +1 -1
  51. package/dist/git/utils/pullRequest.utils.d.ts +24 -1
  52. package/dist/git/utils/pullRequest.utils.d.ts.map +1 -1
  53. package/dist/git/utils/pullRequest.utils.js +71 -0
  54. package/dist/git/utils/pullRequest.utils.js.map +1 -1
  55. package/dist/git/watching/changeEvent.d.ts +6 -1
  56. package/dist/git/watching/changeEvent.d.ts.map +1 -1
  57. package/dist/git/watching/classifyChange.d.ts.map +1 -1
  58. package/dist/git/watching/classifyChange.js +14 -1
  59. package/dist/git/watching/classifyChange.js.map +1 -1
  60. package/dist/git/watching/watchService.d.ts.map +1 -1
  61. package/dist/git/watching/watchService.js +18 -3
  62. package/dist/git/watching/watchService.js.map +1 -1
  63. package/dist/git/watching/watchSession.d.ts +8 -1
  64. package/dist/git/watching/watchSession.d.ts.map +1 -1
  65. package/dist/git/watching/watchSession.js +38 -6
  66. package/dist/git/watching/watchSession.js.map +1 -1
  67. package/dist/git/watching/watcherPatterns.d.ts +2 -2
  68. package/dist/git/watching/watcherPatterns.d.ts.map +1 -1
  69. package/dist/git/watching/watcherPatterns.js +1 -1
  70. package/dist/git/watching/watcherPatterns.js.map +1 -1
  71. package/dist/git-cli/exec/git.d.ts +1 -1
  72. package/dist/git-cli/exec/git.d.ts.map +1 -1
  73. package/dist/git-cli/exec/git.js +13 -3
  74. package/dist/git-cli/exec/git.js.map +1 -1
  75. package/dist/git-cli/providers/branches.d.ts +19 -0
  76. package/dist/git-cli/providers/branches.d.ts.map +1 -1
  77. package/dist/git-cli/providers/branches.js +282 -78
  78. package/dist/git-cli/providers/branches.js.map +1 -1
  79. package/dist/git-cli/providers/commits.d.ts +4 -0
  80. package/dist/git-cli/providers/commits.d.ts.map +1 -1
  81. package/dist/git-cli/providers/commits.js +84 -11
  82. package/dist/git-cli/providers/commits.js.map +1 -1
  83. package/dist/git-cli/providers/config.d.ts +42 -0
  84. package/dist/git-cli/providers/config.d.ts.map +1 -1
  85. package/dist/git-cli/providers/config.js +186 -5
  86. package/dist/git-cli/providers/config.js.map +1 -1
  87. package/dist/git-cli/providers/contributors.d.ts.map +1 -1
  88. package/dist/git-cli/providers/contributors.js +1 -1
  89. package/dist/git-cli/providers/contributors.js.map +1 -1
  90. package/dist/git-cli/providers/graph.d.ts +2 -2
  91. package/dist/git-cli/providers/graph.d.ts.map +1 -1
  92. package/dist/git-cli/providers/graph.js +27 -9
  93. package/dist/git-cli/providers/graph.js.map +1 -1
  94. package/dist/git-cli/providers/operations.d.ts.map +1 -1
  95. package/dist/git-cli/providers/operations.js +40 -12
  96. package/dist/git-cli/providers/operations.js.map +1 -1
  97. package/dist/git-cli/providers/pausedOperations.d.ts +5 -0
  98. package/dist/git-cli/providers/pausedOperations.d.ts.map +1 -1
  99. package/dist/git-cli/providers/pausedOperations.js +87 -16
  100. package/dist/git-cli/providers/pausedOperations.js.map +1 -1
  101. package/dist/git-cli/providers/refs.d.ts +5 -3
  102. package/dist/git-cli/providers/refs.d.ts.map +1 -1
  103. package/dist/git-cli/providers/refs.js +33 -4
  104. package/dist/git-cli/providers/refs.js.map +1 -1
  105. package/dist/git-cli/providers/status.d.ts +1 -0
  106. package/dist/git-cli/providers/status.d.ts.map +1 -1
  107. package/dist/git-cli/providers/status.js +18 -3
  108. package/dist/git-cli/providers/status.js.map +1 -1
  109. package/dist/git-cli/providers/worktrees.d.ts.map +1 -1
  110. package/dist/git-cli/providers/worktrees.js +4 -0
  111. package/dist/git-cli/providers/worktrees.js.map +1 -1
  112. package/dist/git-cli/service.d.ts.map +1 -1
  113. package/dist/git-cli/service.js.map +1 -1
  114. package/dist/plus/agents/providers/claudeCodeProvider.d.ts +39 -1
  115. package/dist/plus/agents/providers/claudeCodeProvider.d.ts.map +1 -1
  116. package/dist/plus/agents/providers/claudeCodeProvider.js +978 -71
  117. package/dist/plus/agents/providers/claudeCodeProvider.js.map +1 -1
  118. package/dist/plus/agents/providers/claudeCodeTranscript.d.ts +24 -2
  119. package/dist/plus/agents/providers/claudeCodeTranscript.d.ts.map +1 -1
  120. package/dist/plus/agents/providers/claudeCodeTranscript.js +84 -9
  121. package/dist/plus/agents/providers/claudeCodeTranscript.js.map +1 -1
  122. package/dist/plus/agents/types.d.ts +37 -2
  123. package/dist/plus/agents/types.d.ts.map +1 -1
  124. package/dist/plus/agents/types.js +2 -0
  125. package/dist/plus/agents/types.js.map +1 -1
  126. package/dist/plus/ai/errors.d.ts +10 -0
  127. package/dist/plus/ai/errors.d.ts.map +1 -1
  128. package/dist/plus/ai/errors.js +29 -0
  129. package/dist/plus/ai/errors.js.map +1 -1
  130. package/dist/plus/ai/models/model.d.ts +4 -0
  131. package/dist/plus/ai/models/model.d.ts.map +1 -1
  132. package/dist/plus/ai/models/model.js +51 -6
  133. package/dist/plus/ai/models/model.js.map +1 -1
  134. package/dist/plus/ai/models/promptTemplates.d.ts +1 -1
  135. package/dist/plus/ai/models/promptTemplates.d.ts.map +1 -1
  136. package/dist/plus/ai/models/provider.d.ts +60 -2
  137. package/dist/plus/ai/models/provider.d.ts.map +1 -1
  138. package/dist/plus/ai/prompts.d.ts +12 -0
  139. package/dist/plus/ai/prompts.d.ts.map +1 -1
  140. package/dist/plus/ai/prompts.js +177 -61
  141. package/dist/plus/ai/prompts.js.map +1 -1
  142. package/dist/plus/ai/providers/anthropicProvider.d.ts +10 -2
  143. package/dist/plus/ai/providers/anthropicProvider.d.ts.map +1 -1
  144. package/dist/plus/ai/providers/anthropicProvider.js +139 -46
  145. package/dist/plus/ai/providers/anthropicProvider.js.map +1 -1
  146. package/dist/plus/ai/providers/deepSeekProvider.d.ts +2 -0
  147. package/dist/plus/ai/providers/deepSeekProvider.d.ts.map +1 -1
  148. package/dist/plus/ai/providers/deepSeekProvider.js +10 -21
  149. package/dist/plus/ai/providers/deepSeekProvider.js.map +1 -1
  150. package/dist/plus/ai/providers/geminiProvider.d.ts +1 -0
  151. package/dist/plus/ai/providers/geminiProvider.d.ts.map +1 -1
  152. package/dist/plus/ai/providers/geminiProvider.js +19 -0
  153. package/dist/plus/ai/providers/geminiProvider.js.map +1 -1
  154. package/dist/plus/ai/providers/gitkrakenProvider.d.ts +5 -1
  155. package/dist/plus/ai/providers/gitkrakenProvider.d.ts.map +1 -1
  156. package/dist/plus/ai/providers/gitkrakenProvider.js +118 -3
  157. package/dist/plus/ai/providers/gitkrakenProvider.js.map +1 -1
  158. package/dist/plus/ai/providers/huggingFaceProvider.d.ts +1 -0
  159. package/dist/plus/ai/providers/huggingFaceProvider.d.ts.map +1 -1
  160. package/dist/plus/ai/providers/huggingFaceProvider.js +5 -0
  161. package/dist/plus/ai/providers/huggingFaceProvider.js.map +1 -1
  162. package/dist/plus/ai/providers/mistralProvider.d.ts +3 -1
  163. package/dist/plus/ai/providers/mistralProvider.d.ts.map +1 -1
  164. package/dist/plus/ai/providers/mistralProvider.js +99 -19
  165. package/dist/plus/ai/providers/mistralProvider.js.map +1 -1
  166. package/dist/plus/ai/providers/ollamaProvider.d.ts +4 -3
  167. package/dist/plus/ai/providers/ollamaProvider.d.ts.map +1 -1
  168. package/dist/plus/ai/providers/ollamaProvider.js +38 -3
  169. package/dist/plus/ai/providers/ollamaProvider.js.map +1 -1
  170. package/dist/plus/ai/providers/openAICompatibleProvider.d.ts +1 -0
  171. package/dist/plus/ai/providers/openAICompatibleProvider.d.ts.map +1 -1
  172. package/dist/plus/ai/providers/openAICompatibleProvider.js +4 -0
  173. package/dist/plus/ai/providers/openAICompatibleProvider.js.map +1 -1
  174. package/dist/plus/ai/providers/openAICompatibleProviderBase.d.ts +154 -5
  175. package/dist/plus/ai/providers/openAICompatibleProviderBase.d.ts.map +1 -1
  176. package/dist/plus/ai/providers/openAICompatibleProviderBase.js +259 -10
  177. package/dist/plus/ai/providers/openAICompatibleProviderBase.js.map +1 -1
  178. package/dist/plus/ai/providers/openRouterProvider.d.ts +4 -0
  179. package/dist/plus/ai/providers/openRouterProvider.d.ts.map +1 -1
  180. package/dist/plus/ai/providers/openRouterProvider.js +9 -0
  181. package/dist/plus/ai/providers/openRouterProvider.js.map +1 -1
  182. package/dist/plus/ai/providers/openaiProvider.d.ts +1 -0
  183. package/dist/plus/ai/providers/openaiProvider.d.ts.map +1 -1
  184. package/dist/plus/ai/providers/openaiProvider.js +1 -0
  185. package/dist/plus/ai/providers/openaiProvider.js.map +1 -1
  186. package/dist/plus/ai/providers/responseFormatCache.d.ts +8 -0
  187. package/dist/plus/ai/providers/responseFormatCache.d.ts.map +1 -0
  188. package/dist/plus/ai/providers/responseFormatCache.js +25 -0
  189. package/dist/plus/ai/providers/responseFormatCache.js.map +1 -0
  190. package/dist/plus/ai/providers/xaiProvider.d.ts +1 -0
  191. package/dist/plus/ai/providers/xaiProvider.d.ts.map +1 -1
  192. package/dist/plus/ai/providers/xaiProvider.js +10 -1
  193. package/dist/plus/ai/providers/xaiProvider.js.map +1 -1
  194. package/dist/plus/ai/utils/ai.utils.d.ts +3 -0
  195. package/dist/plus/ai/utils/ai.utils.d.ts.map +1 -1
  196. package/dist/plus/ai/utils/ai.utils.js +13 -0
  197. package/dist/plus/ai/utils/ai.utils.js.map +1 -1
  198. package/dist/plus/ai/utils/results.utils.d.ts +16 -2
  199. package/dist/plus/ai/utils/results.utils.d.ts.map +1 -1
  200. package/dist/plus/ai/utils/results.utils.js +204 -28
  201. package/dist/plus/ai/utils/results.utils.js.map +1 -1
  202. package/dist/plus/git-github/api/github.d.ts +92 -4
  203. package/dist/plus/git-github/api/github.d.ts.map +1 -1
  204. package/dist/plus/git-github/api/github.js +324 -20
  205. package/dist/plus/git-github/api/github.js.map +1 -1
  206. package/dist/plus/git-github/api/pullRequestSearchQuery.d.ts +27 -1
  207. package/dist/plus/git-github/api/pullRequestSearchQuery.d.ts.map +1 -1
  208. package/dist/plus/git-github/api/pullRequestSearchQuery.js +73 -6
  209. package/dist/plus/git-github/api/pullRequestSearchQuery.js.map +1 -1
  210. package/dist/plus/git-github/models.d.ts +33 -5
  211. package/dist/plus/git-github/models.d.ts.map +1 -1
  212. package/dist/plus/git-github/models.js +43 -4
  213. package/dist/plus/git-github/models.js.map +1 -1
  214. package/dist/plus/git-github/providers/github/status.d.ts +1 -0
  215. package/dist/plus/git-github/providers/github/status.d.ts.map +1 -1
  216. package/dist/plus/git-github/providers/github/status.js.map +1 -1
  217. package/dist/plus/integrations/context.d.ts +4 -0
  218. package/dist/plus/integrations/context.d.ts.map +1 -1
  219. package/dist/plus/integrations/index.d.ts.map +1 -1
  220. package/dist/plus/integrations/index.js +2 -0
  221. package/dist/plus/integrations/index.js.map +1 -1
  222. package/dist/plus/integrations/integrationService.d.ts +16 -1
  223. package/dist/plus/integrations/integrationService.d.ts.map +1 -1
  224. package/dist/plus/integrations/integrationService.js +9 -1
  225. package/dist/plus/integrations/integrationService.js.map +1 -1
  226. package/dist/plus/integrations/manager.d.ts +45 -5
  227. package/dist/plus/integrations/manager.d.ts.map +1 -1
  228. package/dist/plus/integrations/models/gitHostIntegration.d.ts +18 -3
  229. package/dist/plus/integrations/models/gitHostIntegration.d.ts.map +1 -1
  230. package/dist/plus/integrations/models/gitHostIntegration.js +30 -2
  231. package/dist/plus/integrations/models/gitHostIntegration.js.map +1 -1
  232. package/dist/plus/integrations/models/integration.d.ts +4 -2
  233. package/dist/plus/integrations/models/integration.d.ts.map +1 -1
  234. package/dist/plus/integrations/models/integration.js +2 -2
  235. package/dist/plus/integrations/models/integration.js.map +1 -1
  236. package/dist/plus/integrations/providerFilters.d.ts +1 -1
  237. package/dist/plus/integrations/providerFilters.d.ts.map +1 -1
  238. package/dist/plus/integrations/providers/accounts.d.ts +6 -0
  239. package/dist/plus/integrations/providers/accounts.d.ts.map +1 -0
  240. package/dist/plus/integrations/providers/accounts.js +34 -0
  241. package/dist/plus/integrations/providers/accounts.js.map +1 -0
  242. package/dist/plus/integrations/providers/azure/models.d.ts.map +1 -1
  243. package/dist/plus/integrations/providers/azure/models.js +3 -0
  244. package/dist/plus/integrations/providers/azure/models.js.map +1 -1
  245. package/dist/plus/integrations/providers/bitbucket/models.d.ts.map +1 -1
  246. package/dist/plus/integrations/providers/bitbucket/models.js +1 -0
  247. package/dist/plus/integrations/providers/bitbucket/models.js.map +1 -1
  248. package/dist/plus/integrations/providers/github.d.ts +23 -2
  249. package/dist/plus/integrations/providers/github.d.ts.map +1 -1
  250. package/dist/plus/integrations/providers/github.js +169 -138
  251. package/dist/plus/integrations/providers/github.js.map +1 -1
  252. package/dist/plus/integrations/providers/gitlab.d.ts +9 -0
  253. package/dist/plus/integrations/providers/gitlab.d.ts.map +1 -1
  254. package/dist/plus/integrations/providers/gitlab.js +23 -4
  255. package/dist/plus/integrations/providers/gitlab.js.map +1 -1
  256. package/dist/plus/integrations/providers/models.d.ts +14 -32
  257. package/dist/plus/integrations/providers/models.d.ts.map +1 -1
  258. package/dist/plus/integrations/providers/models.js +66 -109
  259. package/dist/plus/integrations/providers/models.js.map +1 -1
  260. package/dist/plus/integrations/providers/pullRequestReviews.d.ts +50 -0
  261. package/dist/plus/integrations/providers/pullRequestReviews.d.ts.map +1 -0
  262. package/dist/plus/integrations/providers/pullRequestReviews.js +99 -0
  263. package/dist/plus/integrations/providers/pullRequestReviews.js.map +1 -0
  264. package/dist/plus/integrations/reads/broaden.d.ts.map +1 -1
  265. package/dist/plus/integrations/reads/broaden.js +6 -1
  266. package/dist/plus/integrations/reads/broaden.js.map +1 -1
  267. package/dist/plus/integrations/reads/counts.d.ts +55 -0
  268. package/dist/plus/integrations/reads/counts.d.ts.map +1 -1
  269. package/dist/plus/integrations/reads/counts.js +146 -2
  270. package/dist/plus/integrations/reads/counts.js.map +1 -1
  271. package/dist/plus/integrations/reads/drains.d.ts +7 -1
  272. package/dist/plus/integrations/reads/drains.d.ts.map +1 -1
  273. package/dist/plus/integrations/reads/drains.js +20 -6
  274. package/dist/plus/integrations/reads/drains.js.map +1 -1
  275. package/dist/plus/integrations/reads/filters.d.ts.map +1 -1
  276. package/dist/plus/integrations/reads/filters.js +22 -0
  277. package/dist/plus/integrations/reads/filters.js.map +1 -1
  278. package/dist/plus/integrations/reads/hierarchy.d.ts.map +1 -1
  279. package/dist/plus/integrations/reads/hierarchy.js +3 -1
  280. package/dist/plus/integrations/reads/hierarchy.js.map +1 -1
  281. package/dist/plus/integrations/reads/issueTracker.d.ts.map +1 -1
  282. package/dist/plus/integrations/reads/issueTracker.js +8 -3
  283. package/dist/plus/integrations/reads/issueTracker.js.map +1 -1
  284. package/dist/plus/integrations/reads/issues.d.ts.map +1 -1
  285. package/dist/plus/integrations/reads/issues.js +9 -4
  286. package/dist/plus/integrations/reads/issues.js.map +1 -1
  287. package/dist/plus/integrations/reads/pullRequests.d.ts.map +1 -1
  288. package/dist/plus/integrations/reads/pullRequests.js +9 -4
  289. package/dist/plus/integrations/reads/pullRequests.js.map +1 -1
  290. package/dist/plus/integrations/reads/searchPullRequests.d.ts +4 -3
  291. package/dist/plus/integrations/reads/searchPullRequests.d.ts.map +1 -1
  292. package/dist/plus/integrations/reads/searchPullRequests.js +6 -4
  293. package/dist/plus/integrations/reads/searchPullRequests.js.map +1 -1
  294. package/dist/plus/integrations/reads/sweeps.js +1 -1
  295. package/dist/plus/integrations/reads/sweeps.js.map +1 -1
  296. package/dist/plus/integrations/reads/warnings.d.ts +2 -2
  297. package/dist/plus/integrations/reads/warnings.d.ts.map +1 -1
  298. package/dist/plus/integrations/reads/warnings.js +11 -2
  299. package/dist/plus/integrations/reads/warnings.js.map +1 -1
  300. package/dist/plus/integrations/results.d.ts +6 -1
  301. package/dist/plus/integrations/results.d.ts.map +1 -1
  302. package/dist/plus/integrations/results.js.map +1 -1
  303. package/dist/utils/env/browser/base64.d.ts +1 -1
  304. package/dist/utils/env/browser/base64.d.ts.map +1 -1
  305. package/dist/utils/env/node/base64.d.ts +1 -1
  306. package/dist/utils/env/node/base64.d.ts.map +1 -1
  307. package/dist/utils/env/node/base64.js +2 -0
  308. package/dist/utils/env/node/base64.js.map +1 -1
  309. package/dist/utils/keys/chord.d.ts +52 -0
  310. package/dist/utils/keys/chord.d.ts.map +1 -0
  311. package/dist/utils/keys/chord.js +135 -0
  312. package/dist/utils/keys/chord.js.map +1 -0
  313. package/dist/utils/keys/keybinding.d.ts +53 -0
  314. package/dist/utils/keys/keybinding.d.ts.map +1 -0
  315. package/dist/utils/keys/keybinding.js +58 -0
  316. package/dist/utils/keys/keybinding.js.map +1 -0
  317. package/dist/utils/path.d.ts +11 -0
  318. package/dist/utils/path.d.ts.map +1 -1
  319. package/dist/utils/path.js +13 -0
  320. package/dist/utils/path.js.map +1 -1
  321. package/docs/integrations.md +76 -10
  322. package/docs/kepler-read-api-parity.md +9 -0
  323. package/package.json +13 -5
  324. package/src/git/cache.ts +383 -47
  325. package/src/git/context.ts +11 -0
  326. package/src/git/models/fileStatus.ts +1 -0
  327. package/src/git/models/issue.ts +4 -0
  328. package/src/git/models/mergeConflicts.ts +3 -2
  329. package/src/git/models/pullRequest.ts +117 -1
  330. package/src/git/models/repository.ts +58 -17
  331. package/src/git/models/statusFile.ts +3 -0
  332. package/src/git/providers/branches.ts +6 -0
  333. package/src/git/providers/commits.ts +11 -0
  334. package/src/git/providers/config.ts +18 -0
  335. package/src/git/providers/operations.ts +1 -0
  336. package/src/git/providers/pausedOperations.ts +2 -0
  337. package/src/git/providers/status.ts +1 -0
  338. package/src/git/utils/config.utils.ts +8 -0
  339. package/src/git/utils/issue.utils.ts +2 -0
  340. package/src/git/utils/pausedOperationStatus.utils.ts +28 -0
  341. package/src/git/utils/pullRequest.utils.ts +86 -0
  342. package/src/git/watching/changeEvent.ts +6 -1
  343. package/src/git/watching/classifyChange.ts +15 -1
  344. package/src/git/watching/watchService.ts +20 -3
  345. package/src/git/watching/watchSession.ts +41 -6
  346. package/src/git/watching/watcherPatterns.ts +1 -1
  347. package/src/git-cli/exec/git.ts +13 -3
  348. package/src/git-cli/providers/branches.ts +384 -132
  349. package/src/git-cli/providers/commits.ts +106 -15
  350. package/src/git-cli/providers/config.ts +229 -8
  351. package/src/git-cli/providers/contributors.ts +5 -1
  352. package/src/git-cli/providers/graph.ts +26 -13
  353. package/src/git-cli/providers/operations.ts +45 -20
  354. package/src/git-cli/providers/pausedOperations.ts +109 -17
  355. package/src/git-cli/providers/refs.ts +33 -3
  356. package/src/git-cli/providers/status.ts +25 -4
  357. package/src/git-cli/providers/worktrees.ts +5 -0
  358. package/src/git-cli/service.ts +0 -1
  359. package/src/plus/agents/providers/claudeCodeProvider.ts +1130 -87
  360. package/src/plus/agents/providers/claudeCodeTranscript.ts +95 -9
  361. package/src/plus/agents/types.ts +46 -2
  362. package/src/plus/ai/errors.ts +30 -0
  363. package/src/plus/ai/models/model.ts +56 -6
  364. package/src/plus/ai/models/promptTemplates.ts +1 -1
  365. package/src/plus/ai/models/provider.ts +69 -2
  366. package/src/plus/ai/prompts.ts +186 -61
  367. package/src/plus/ai/providers/anthropicProvider.ts +155 -47
  368. package/src/plus/ai/providers/deepSeekProvider.ts +11 -21
  369. package/src/plus/ai/providers/geminiProvider.ts +19 -0
  370. package/src/plus/ai/providers/gitkrakenProvider.ts +126 -3
  371. package/src/plus/ai/providers/huggingFaceProvider.ts +6 -0
  372. package/src/plus/ai/providers/mistralProvider.ts +102 -19
  373. package/src/plus/ai/providers/ollamaProvider.ts +55 -4
  374. package/src/plus/ai/providers/openAICompatibleProvider.ts +5 -0
  375. package/src/plus/ai/providers/openAICompatibleProviderBase.ts +360 -17
  376. package/src/plus/ai/providers/openRouterProvider.ts +17 -0
  377. package/src/plus/ai/providers/openaiProvider.ts +1 -0
  378. package/src/plus/ai/providers/responseFormatCache.ts +39 -0
  379. package/src/plus/ai/providers/xaiProvider.ts +10 -1
  380. package/src/plus/ai/utils/ai.utils.ts +14 -0
  381. package/src/plus/ai/utils/results.utils.ts +255 -31
  382. package/src/plus/git-github/api/github.ts +467 -23
  383. package/src/plus/git-github/api/pullRequestSearchQuery.ts +81 -7
  384. package/src/plus/git-github/models.ts +77 -7
  385. package/src/plus/git-github/providers/github/status.ts +1 -0
  386. package/src/plus/integrations/context.ts +4 -0
  387. package/src/plus/integrations/index.ts +2 -0
  388. package/src/plus/integrations/integrationService.ts +25 -2
  389. package/src/plus/integrations/manager.ts +50 -5
  390. package/src/plus/integrations/models/gitHostIntegration.ts +54 -2
  391. package/src/plus/integrations/models/integration.ts +24 -13
  392. package/src/plus/integrations/providerFilters.ts +6 -1
  393. package/src/plus/integrations/providers/accounts.ts +38 -0
  394. package/src/plus/integrations/providers/azure/models.ts +3 -0
  395. package/src/plus/integrations/providers/bitbucket/models.ts +1 -0
  396. package/src/plus/integrations/providers/github.ts +218 -145
  397. package/src/plus/integrations/providers/gitlab.ts +30 -20
  398. package/src/plus/integrations/providers/models.ts +99 -127
  399. package/src/plus/integrations/providers/pullRequestReviews.ts +122 -0
  400. package/src/plus/integrations/reads/broaden.ts +6 -1
  401. package/src/plus/integrations/reads/counts.ts +273 -2
  402. package/src/plus/integrations/reads/drains.ts +19 -6
  403. package/src/plus/integrations/reads/filters.ts +22 -0
  404. package/src/plus/integrations/reads/hierarchy.ts +3 -1
  405. package/src/plus/integrations/reads/issueTracker.ts +9 -3
  406. package/src/plus/integrations/reads/issues.ts +9 -4
  407. package/src/plus/integrations/reads/pullRequests.ts +9 -4
  408. package/src/plus/integrations/reads/searchPullRequests.ts +12 -4
  409. package/src/plus/integrations/reads/sweeps.ts +1 -1
  410. package/src/plus/integrations/reads/warnings.ts +12 -1
  411. package/src/plus/integrations/results.ts +6 -1
  412. package/src/utils/env/browser/base64.ts +1 -1
  413. package/src/utils/env/node/base64.ts +3 -1
  414. package/src/utils/keys/chord.ts +184 -0
  415. package/src/utils/keys/keybinding.ts +116 -0
  416. package/src/utils/path.ts +14 -0
package/dist/git/cache.js CHANGED
@@ -17,6 +17,12 @@ const uriScopedCachedGitTypes = ['blame', 'diff', 'fileLog'];
17
17
  export function areUriScopedCachedGitTypes(types) {
18
18
  return types.every(t => uriScopedCachedGitTypes.includes(t));
19
19
  }
20
+ /**
21
+ * Ceiling on how long a derived branch base is trusted. Long enough that repeated reads during normal use
22
+ * are served from cache, short enough that a base that changed by a route with no eviction signal (an
23
+ * external delete-and-recreate of a branch that is never checked out) self-heals without a reload.
24
+ */
25
+ const baseBranchNameTTL = 5 * 60 * 1000; // 5 minutes
20
26
  /**
21
27
  * gkConfig keys that participate in the `branchOverviews` cache's mergeTarget/mergeBase lineage.
22
28
  * Capture group 1 is the ref name (which may itself contain `.`/`/`).
@@ -102,6 +108,22 @@ export class Cache {
102
108
  _worktreesByCommonPath = new Map();
103
109
  /** Monotonic per-worktree "status clock" — see {@link getStatusGeneration}. */
104
110
  _statusGenerations = new Map();
111
+ /** Monotonic per-path "close clock" — see {@link getCloseGeneration}. */
112
+ _closeGenerations = new Map();
113
+ /**
114
+ * Per-commonPath snapshot of the merge-relevant subset of `.git/gk/config` (keys matching
115
+ * {@link branchOverviewGkConfigKeysRegex}), used by {@link reconcileGkConfigMap} to diff a watcher
116
+ * `'gkConfig'` event down to only the keys that actually changed, instead of coarsely re-deriving
117
+ * `baseBranchName`/`branchOverviews` on every gk write. Absent means "never observed".
118
+ */
119
+ _gkConfigMergeSnapshots = new Map();
120
+ /**
121
+ * Reconciler registered by the CLI config sub-provider (see {@link setGkConfigReconciler}),
122
+ * invoked on a watcher-observed `'gkConfig'` change instead of the coarse `clearCaches(repoPath,
123
+ * 'gkConfig')` cascade. `undefined` (e.g. the GitHub provider, which has no `.git/gk/config`)
124
+ * falls back to the coarse clear.
125
+ */
126
+ _gkConfigReconciler;
105
127
  [Symbol.dispose]() {
106
128
  this.dispose();
107
129
  }
@@ -348,9 +370,24 @@ export class Cache {
348
370
  keysToClear.add('reachability');
349
371
  keysToClear.add('resolvedRevisions');
350
372
  }
351
- // Shared branch caches (branch list, metadata)
352
- if (types.includes('branches')) {
373
+ // Shared branch caches (branch list, metadata). `baseBranchName` is deliberately NOT cleared
374
+ // here — a branch's base is set at creation and only changes when its stored key changes
375
+ // (`gkConfig`/`config` below) or the branch itself is created/renamed/deleted. Every op that
376
+ // does one of those calls `deleteBaseBranchName` and moves or drops the branch's persisted
377
+ // `branch.<ref>.gk-*` keys: `createBranch`/`deleteLocalBranch`/`renameBranch`, plus the two
378
+ // paths that create a branch as a side effect (`checkout -b`, `worktree add -b`). Tip movement
379
+ // can't change a base, so clearing on every commit only forced a `git reflog` re-derivation.
380
+ if (types.includes('branch')) {
381
+ // `'branch'` comes from a HEAD change — a checkout — which appends `checkout: moving from X
382
+ // to Y` to the reflog, exactly the entry `getBaseBranchName` greps for when nothing is
383
+ // stored. A base derived as "none" BEFORE that entry existed is cached with no TTL, so
384
+ // without this it stays "none" for the session even though the answer now exists.
385
+ //
386
+ // Deliberately not under `'branches'`: a tip move can't change a branch's base, so re-deriving
387
+ // on every commit would be pure cost. Checkouts are user-driven and rare by comparison.
353
388
  keysToClear.add('baseBranchName');
389
+ }
390
+ if (types.includes('branches')) {
354
391
  keysToClear.add('branchMetadataMap');
355
392
  keysToClear.add('branches');
356
393
  keysToClear.add('sharedBranches');
@@ -361,6 +398,10 @@ export class Cache {
361
398
  keysToClear.add('refTips');
362
399
  }
363
400
  if (types.includes('config')) {
401
+ // `getBaseBranchName` falls back to `branch.<ref>.vscode-merge-base` (written by VS Code's
402
+ // built-in Git), which lives in `.git/config` — so a config change is the only signal that
403
+ // source changed. Cheap: config events are rare.
404
+ keysToClear.add('baseBranchName');
364
405
  keysToClear.add('configKeys');
365
406
  keysToClear.add('configPatterns');
366
407
  keysToClear.add('currentBranchReference');
@@ -415,6 +456,11 @@ export class Cache {
415
456
  keysToClear.add('tags');
416
457
  keysToClear.add('refs');
417
458
  keysToClear.add('refTips');
459
+ // `commit`/`commitCount` can be keyed by a tag name (e.g. the tag node's load-more count),
460
+ // which re-points on a force-moved or deleted-and-recreated tag — same drift the
461
+ // `branch`/`branches` cascade above clears for.
462
+ keysToClear.add('commit');
463
+ keysToClear.add('commitCount');
418
464
  }
419
465
  if (types.includes('tracking')) {
420
466
  keysToClear.add('fileExistence');
@@ -436,36 +482,44 @@ export class Cache {
436
482
  cache.clear();
437
483
  }
438
484
  else if (sharedCacheKeys.has(key)) {
439
- const commonPath = this.getCommonPath(repoPath);
440
- // For shared caches, prefer `invalidate` where supported so in-flight work is
441
- // shared across new callers and self-evicts on settle rather than spawning a
442
- // duplicate factory. `invalidate` does the right thing per-entry: entries with
443
- // a `CacheController` (created via `getOrCreate`) are marked invalidated; entries
444
- // without one (created via plain `.set()`, e.g. per-worktree mapper results) are
445
- // hard-deleted. Caches that don't support `invalidate` fall back to `delete`.
446
- const invalidate = cache.invalidate;
447
- if (typeof invalidate === 'function') {
448
- invalidate.call(cache, commonPath);
449
- for (const worktreePath of this.getWorktreePaths(commonPath)) {
450
- if (worktreePath === commonPath)
451
- continue;
452
- invalidate.call(cache, worktreePath);
453
- }
454
- }
455
- else {
456
- cache.delete(commonPath);
457
- for (const worktreePath of this.getWorktreePaths(commonPath)) {
458
- if (worktreePath === commonPath)
459
- continue;
460
- cache.delete(worktreePath);
461
- }
462
- }
485
+ this.evictShared(key, repoPath);
463
486
  }
464
487
  else {
465
488
  cache.delete(repoPath);
466
489
  }
467
490
  }
468
491
  }
492
+ /**
493
+ * Evicts a single shared (commonPath-keyed) cache entry for `repoPath` and its sibling worktrees.
494
+ * Prefers `invalidate` where supported so in-flight work is shared across new callers and
495
+ * self-evicts on settle rather than spawning a duplicate factory. `invalidate` does the right
496
+ * thing per-entry: entries with a `CacheController` (created via `getOrCreate`) are marked
497
+ * invalidated; entries without one (created via plain `.set()`, e.g. per-worktree mapper results)
498
+ * are hard-deleted. Caches that don't support `invalidate` fall back to `delete`.
499
+ */
500
+ evictShared(key, repoPath) {
501
+ const cache = this._caches[key];
502
+ if (cache == null)
503
+ return;
504
+ const commonPath = this.getCommonPath(repoPath);
505
+ const invalidate = cache.invalidate;
506
+ if (typeof invalidate === 'function') {
507
+ invalidate.call(cache, commonPath);
508
+ for (const worktreePath of this.getWorktreePaths(commonPath)) {
509
+ if (worktreePath === commonPath)
510
+ continue;
511
+ invalidate.call(cache, worktreePath);
512
+ }
513
+ }
514
+ else {
515
+ cache.delete(commonPath);
516
+ for (const worktreePath of this.getWorktreePaths(commonPath)) {
517
+ if (worktreePath === commonPath)
518
+ continue;
519
+ cache.delete(worktreePath);
520
+ }
521
+ }
522
+ }
469
523
  /**
470
524
  * Monotonic per-worktree counter, advanced whenever anything that can change `git status` output is
471
525
  * observed. `git status` and its siblings are point-in-time reads of mutable state, so deduplicating them
@@ -518,6 +572,20 @@ export class Cache {
518
572
  const commonPath = this._commonPathRegistry.get(repoPath);
519
573
  return commonPath != null && commonPath !== repoPath;
520
574
  }
575
+ /** Whether `repoPath` is currently registered (via {@link registerRepoPath}, not yet unregistered). */
576
+ isRegistered(repoPath) {
577
+ return this._commonPathRegistry.has(repoPath);
578
+ }
579
+ /**
580
+ * Monotonic per-path counter advanced whenever `repoPath` is unregistered (repo closed, worktree
581
+ * removed). Lets an async post-read step — e.g. the gk-config reconcile — detect that its target was
582
+ * closed (and possibly reopened) mid-flight and bail. Unlike an `isRegistered` check it doesn't
583
+ * require the caller to have registered in the first place, so it stays correct for consumers of
584
+ * this package that don't wire up the host's repo lifecycle.
585
+ */
586
+ getCloseGeneration(repoPath) {
587
+ return this._closeGenerations.get(repoPath) ?? 0;
588
+ }
521
589
  /** Clears file-scoped caches (blame, diff, fileLog) for a specific path within a repo */
522
590
  clearForPath(repoPath, path, ...types) {
523
591
  const prefix = `${normalizePath(path)}:`;
@@ -565,6 +633,9 @@ export class Cache {
565
633
  // Advance the status clock on close so a status read still in flight from this registration can't be
566
634
  // joined by a read issued after the path is reopened (which would otherwise reuse the same generation).
567
635
  this.incrementStatusGeneration(repoPath);
636
+ // Advance the close clock so an async step that captured it before its read (see `getCloseGeneration`)
637
+ // can tell its target went away mid-flight.
638
+ this._closeGenerations.set(repoPath, this.getCloseGeneration(repoPath) + 1);
568
639
  const commonPath = this._commonPathRegistry.get(repoPath) ?? repoPath;
569
640
  const worktrees = this._worktreesByCommonPath.get(commonPath);
570
641
  // After removing repoPath, would the commonPath have any worktrees left?
@@ -595,6 +666,10 @@ export class Cache {
595
666
  evict(repoPath);
596
667
  }
597
668
  }
669
+ // Shared, commonPath-keyed like `gkConfigMap` — only evict once no worktree still depends on it.
670
+ if (isLastWorktree) {
671
+ this._gkConfigMergeSnapshots.delete(commonPath);
672
+ }
598
673
  this._commonPathRegistry.delete(repoPath);
599
674
  if (worktrees != null) {
600
675
  worktrees.delete(repoPath);
@@ -604,9 +679,19 @@ export class Cache {
604
679
  }
605
680
  }
606
681
  reset() {
682
+ // Advance the close clock BEFORE dropping the registry it reads from. Advancing rather than
683
+ // clearing is the point: an async step that captured a generation must see a mismatch and bail,
684
+ // where a cleared map would hand it a fresh `0` that matches and let it repopulate what was just
685
+ // torn down. Union of registered paths and any already carrying a generation, mirroring
686
+ // `incrementStatusGenerations`.
687
+ for (const path of new Set([...this._commonPathRegistry.keys(), ...this._closeGenerations.keys()])) {
688
+ this._closeGenerations.set(path, this.getCloseGeneration(path) + 1);
689
+ }
607
690
  this._commonPathRegistry.clear();
608
691
  this._worktreesByCommonPath.clear();
609
692
  this._statusGenerations.clear();
693
+ this._gkConfigMergeSnapshots.clear();
694
+ this._gkConfigReconciler = undefined;
610
695
  this._caches = createEmptyCaches();
611
696
  }
612
697
  onRepositoryChanged(repoPath, changes) {
@@ -653,7 +738,10 @@ export class Cache {
653
738
  types.add('gitignore');
654
739
  }
655
740
  if (hasAny('gkConfig')) {
656
- types.add('gkConfig');
741
+ // Handled separately (not folded into `types`/`clearCaches` below) — a gk write is usually a
742
+ // bookkeeping timestamp that can't affect `baseBranchName`/`branchOverviews`, so this reconciles
743
+ // down to only the keys that actually changed instead of coarsely clearing both on every write.
744
+ this.handleGkConfigChanged(repoPath);
657
745
  }
658
746
  if (hasAny('lastFetched')) {
659
747
  types.add('lastFetched');
@@ -678,6 +766,48 @@ export class Cache {
678
766
  this.clearCaches(repoPath, ...types);
679
767
  }
680
768
  }
769
+ /**
770
+ * Handles a watcher-observed `'gkConfig'` change. Always evicts the cached bulk map (forcing the
771
+ * next read to hit disk). If a reconciler is registered (see {@link setGkConfigReconciler}),
772
+ * defers to it instead of coarsely clearing `baseBranchName`/`branchOverviews` — it re-reads the
773
+ * map and diffs it against the snapshot captured here (i.e. as it stood right before this change),
774
+ * cascading only the refs whose merge-relevant keys actually changed. Falls back to the coarse
775
+ * clear when no reconciler is registered (e.g. the GitHub provider) so nothing can go stale.
776
+ */
777
+ handleGkConfigChanged(repoPath) {
778
+ const commonPath = this.getCommonPath(repoPath);
779
+ // Hard-delete rather than `evictShared`'s soft-invalidate: the reconcile below needs a
780
+ // point-in-time read of the post-change file, and a soft-invalidated entry stays joinable — the
781
+ // re-read would ride a bulk read that started before this change and diff it as unchanged.
782
+ // Same reasoning as `refs.ts`'s `force: true` path and `deleteGkConfig`'s own hard delete.
783
+ this._caches.gkConfigMap?.delete(commonPath);
784
+ if (this._gkConfigReconciler == null) {
785
+ this.clearCaches(repoPath, 'gkConfig');
786
+ return;
787
+ }
788
+ const priorSnapshot = this._gkConfigMergeSnapshots.get(commonPath);
789
+ // Fire-and-forget, but the outcome still decides whether the coarse clear is owed: a reconcile that
790
+ // FAILED leaves every derived cache holding pre-change values with nothing else to correct them, so
791
+ // it falls back to the blunt behavior that registering a reconciler replaced. Kept here rather than
792
+ // in the reconciler so a bail path added later can't silently skip it — the return type makes each
793
+ // one say what it did.
794
+ void Promise.resolve(this._gkConfigReconciler(repoPath, priorSnapshot)).then(outcome => {
795
+ if (outcome === 'failed') {
796
+ this.clearCaches(repoPath, 'gkConfig');
797
+ }
798
+ },
799
+ // An exception escaping the reconciler is a failure by definition — and one its own `catch`
800
+ // never saw, so nothing else will have cascaded.
801
+ () => this.clearCaches(repoPath, 'gkConfig'));
802
+ }
803
+ /** Hard-evicts the cached bulk `.git/gk/config` map so the next read hits disk. */
804
+ deleteGkConfigMap(repoPath) {
805
+ this._caches.gkConfigMap?.delete(this.getCommonPath(repoPath));
806
+ }
807
+ /** The merge-relevant gk config snapshot currently serving as the reconcile baseline. */
808
+ getGkConfigMergeSnapshot(repoPath) {
809
+ return this._gkConfigMergeSnapshots.get(this.getCommonPath(repoPath));
810
+ }
681
811
  getBranches(repoPath, factory, mapper, cancellation) {
682
812
  const commonPath = this.getCommonPath(repoPath);
683
813
  // Register this caller with the shared factory's aggregate so that invariant 3
@@ -745,10 +875,34 @@ export class Cache {
745
875
  /**
746
876
  * The whole `.git/gk/config` is read once and cached as a single map per commonPath; per-key and
747
877
  * per-namespace gk lookups are served from it in-memory (see `getGkConfigMap` in the CLI config
748
- * sub-provider). Invalidated by `deleteGkConfig` (write) and the coarse `'gkConfig'` clear (watcher).
878
+ * sub-provider). Invalidated by `deleteGkConfig` (write) and, on a watcher `'gkConfig'` event, by
879
+ * `handleGkConfigChanged` (reconciled precisely when a reconciler is registered, or the coarse
880
+ * clear otherwise). The first fresh read seeds the merge-relevant snapshot used by
881
+ * `reconcileGkConfigMap`; later refreshes of that snapshot are owned by the reconcile itself.
749
882
  */
750
883
  getGkConfigMap(repoPath, factory) {
751
- return this.getSharedSimple(this.gkConfigMap, repoPath, factory);
884
+ return this.getSharedSimple(this.gkConfigMap, repoPath, async (commonPath, cacheable) => {
885
+ const map = await factory(cacheable);
886
+ // Seed the reconcile baseline on first observation only. Refreshes belong to
887
+ // `reconcileGkConfigMap` (after it has cascaded) and `recordGkConfigWrite` (our own writes):
888
+ // an incidental read that happens to land between an external write and the watcher event
889
+ // would otherwise advance the baseline to the post-change value, so the reconcile would diff
890
+ // that value against itself and silently drop the change.
891
+ if (!this._gkConfigMergeSnapshots.has(commonPath)) {
892
+ this._gkConfigMergeSnapshots.set(commonPath, this.extractMergeRelevantGkConfig(map));
893
+ }
894
+ return map;
895
+ });
896
+ }
897
+ /** Extracts the subset of a gk config map whose keys participate in the `branchOverviews`/`baseBranchName` lineage. */
898
+ extractMergeRelevantGkConfig(map) {
899
+ const subset = new Map();
900
+ for (const [key, value] of map) {
901
+ if (branchOverviewGkConfigKeysRegex.test(key)) {
902
+ subset.set(key, value);
903
+ }
904
+ }
905
+ return subset;
752
906
  }
753
907
  /**
754
908
  * Clears the cached `.git/gk/config` map and invalidates the derived caches
@@ -762,18 +916,87 @@ export class Cache {
762
916
  * invalidates so subsequent reads see the new value.
763
917
  */
764
918
  deleteGkConfig(repoPath, key, options) {
765
- const cacheKey = this.getCommonPath(repoPath);
766
- this._caches.gkConfigMap?.delete(cacheKey);
919
+ const commonPath = this.getCommonPath(repoPath);
920
+ this._caches.gkConfigMap?.delete(commonPath);
921
+ this.cascadeGkConfigKeyChange(commonPath, key, options?.skipInvalidation);
922
+ }
923
+ /**
924
+ * Keeps the merge-relevant gk config snapshot in sync with OUR OWN writes, so the next
925
+ * watcher-triggered `reconcileGkConfigMap` diffs a self-write as unchanged rather than as an
926
+ * external change (which would otherwise defeat `skipInvalidation`). No-ops for keys outside the
927
+ * merge-relevant subset, and if no snapshot exists yet for this repo — nothing to keep in sync;
928
+ * the next real read (`getGkConfigMap`) populates one from scratch.
929
+ */
930
+ recordGkConfigWrite(repoPath, key, value) {
931
+ if (!branchOverviewGkConfigKeysRegex.test(key))
932
+ return;
933
+ const commonPath = this.getCommonPath(repoPath);
934
+ const snapshot = this._gkConfigMergeSnapshots.get(commonPath);
935
+ if (snapshot == null)
936
+ return;
937
+ // Copy-on-write: a reconcile in flight is holding this map as its `priorSnapshot` baseline, so
938
+ // mutating it in place would silently move that baseline mid-diff.
939
+ const next = new Map(snapshot);
940
+ if (value == null) {
941
+ next.delete(key);
942
+ }
943
+ else {
944
+ next.set(key, value);
945
+ }
946
+ this._gkConfigMergeSnapshots.set(commonPath, next);
947
+ }
948
+ /**
949
+ * Registers the reconciler invoked by {@link handleGkConfigChanged} on a watcher-observed
950
+ * `'gkConfig'` change. Only one reconciler is kept — later registrations replace earlier ones,
951
+ * which is harmless since every CLI config sub-provider sharing this `Cache` reconciles the same
952
+ * underlying `.git/gk/config` file identically.
953
+ */
954
+ setGkConfigReconciler(reconciler) {
955
+ this._gkConfigReconciler = reconciler;
956
+ }
957
+ /**
958
+ * Diffs a freshly-read gk config map's merge-relevant subset against `priorSnapshot` (captured by
959
+ * `handleGkConfigChanged` before the reconcile started, so it reflects the pre-change state even
960
+ * though this call's own re-read already raced ahead and refreshed the live snapshot), cascading
961
+ * `baseBranchName`/`branchOverviews` for every ref whose merge-relevant key actually changed.
962
+ * `priorSnapshot` of `undefined` (never observed before this reconcile) is treated as "everything
963
+ * may have changed" — a full coarse clear, same as the pre-existing watcher behavior. Returns
964
+ * whether anything changed (i.e. whether a follow-up repository-changed event is warranted).
965
+ */
966
+ reconcileGkConfigMap(repoPath, priorSnapshot, freshMap) {
967
+ const commonPath = this.getCommonPath(repoPath);
968
+ const newSubset = this.extractMergeRelevantGkConfig(freshMap);
969
+ this._gkConfigMergeSnapshots.set(commonPath, newSubset);
970
+ if (priorSnapshot == null) {
971
+ this.evictShared('baseBranchName', repoPath);
972
+ this.evictShared('branchOverviews', repoPath);
973
+ return true;
974
+ }
975
+ let changed = false;
976
+ for (const key of new Set([...priorSnapshot.keys(), ...newSubset.keys()])) {
977
+ if (priorSnapshot.get(key) !== newSubset.get(key)) {
978
+ changed = true;
979
+ this.cascadeGkConfigKeyChange(commonPath, key);
980
+ }
981
+ }
982
+ return changed;
983
+ }
984
+ /**
985
+ * Shared per-ref cascade for a changed `branch.<ref>.gk-...` key: invalidates `baseBranchName` (for
986
+ * `gk-merge-base`) and `branchOverviews` (for any merge-relevant key), honoring `skipInvalidation`.
987
+ * Used by both a direct write (`deleteGkConfig`) and a reconciled external change
988
+ * (`reconcileGkConfigMap`). No-ops for keys outside the merge-relevant subset.
989
+ */
990
+ cascadeGkConfigKeyChange(commonPath, key, skip) {
767
991
  const refMatch = key.match(branchOverviewGkConfigKeysRegex);
768
992
  if (refMatch == null)
769
993
  return;
770
994
  const ref = refMatch[1];
771
- const skip = options?.skipInvalidation;
772
995
  // `getBaseBranchName` reads `branch.<ref>.gk-merge-base` and caches the resolved value
773
- // per-ref. A write to that key must invalidate the cached base or Tier 3 of
774
- // `getBranchContributionsOverview` will resolve `mergeTarget` against the pre-write value.
996
+ // per-ref. A change to that key must invalidate the cached base or Tier 3 of
997
+ // `getBranchContributionsOverview` will resolve `mergeTarget` against the pre-change value.
775
998
  if (key.endsWith('.gk-merge-base') && !skip?.includes('baseBranchName')) {
776
- this._caches.baseBranchName?.delete(cacheKey, ref);
999
+ this._caches.baseBranchName?.delete(commonPath, ref);
777
1000
  }
778
1001
  if (skip?.includes('branchOverviews'))
779
1002
  return;
@@ -783,7 +1006,18 @@ export class Cache {
783
1006
  // invalidate every entry for the affected ref regardless of which target it resolved to.
784
1007
  // Uses `invalidateByKeyPrefix` (not `deleteByKeyPrefix`) so an in-flight factory is still
785
1008
  // shared with new callers instead of triggering a duplicate fetch.
786
- this._caches.branchOverviews?.invalidateByKeyPrefix(cacheKey, `${ref}|`);
1009
+ //
1010
+ // Sibling worktrees get their own bucket, not just the shared one: `getSharedOrCreateWithKey`
1011
+ // stores a per-worktree *mapped* entry under that worktree's own path, and prefix-invalidation
1012
+ // only reaches one bucket. The in-flight case self-propagates on settle, but an already-settled
1013
+ // overview would otherwise survive here — which the coarse `evictShared` path this replaced did
1014
+ // clear, since it iterated the worktrees.
1015
+ this._caches.branchOverviews?.invalidateByKeyPrefix(commonPath, `${ref}|`);
1016
+ for (const worktreePath of this.getWorktreePaths(commonPath)) {
1017
+ if (worktreePath === commonPath)
1018
+ continue;
1019
+ this._caches.branchOverviews?.invalidateByKeyPrefix(worktreePath, `${ref}|`);
1020
+ }
787
1021
  }
788
1022
  async getBranchOverview(repoPath, cacheKey, factory, options) {
789
1023
  return this.getSharedOrCreateWithKey(this.branchOverviews, repoPath, cacheKey, factory, (data, newRepoPath) => data == null
@@ -808,9 +1042,31 @@ export class Cache {
808
1042
  }
809
1043
  getBaseBranchName(repoPath, ref, factory, cancellation) {
810
1044
  return this.getSharedSimpleWithKey(this.baseBranchName, repoPath, ref, factory, {
1045
+ // A bounded ceiling, because the eviction signals can't cover every way a base changes. The
1046
+ // `'branches'` cascade deliberately doesn't clear this — a tip move can't change a base, and
1047
+ // re-deriving per commit is the cost this exists to avoid — but that leaves a hole: a branch
1048
+ // deleted and recreated OUTSIDE GitLens, and never checked out, emits only `heads`. A base
1049
+ // derived as "none" before that would otherwise stay "none" for the session.
1050
+ //
1051
+ // `createTTL`, NOT `accessTTL`: the sliding variant resets on every read, so a branch card
1052
+ // polling this entry would hold it alive forever and never re-derive — the exact case the
1053
+ // ceiling exists for. Absolute from creation bounds staleness regardless of read frequency.
1054
+ createTTL: baseBranchNameTTL,
811
1055
  cancellation: cancellation,
812
1056
  });
813
1057
  }
1058
+ /**
1059
+ * Clears the cached base branch for `ref`. Call from ops that create/rename/delete a branch — the
1060
+ * `'branches'` cascade no longer clears these, since tip movement can't change a branch's base.
1061
+ *
1062
+ * Only clears the cache. A branch's base is *persisted* as `branch.<ref>.gk-merge-base` and read back
1063
+ * before the reflog fallback, so an op that ends a branch's identity under a name must drop or move
1064
+ * that key too (`removeGkConfigBranchSection`/`renameGkConfigBranchSection`) — otherwise the
1065
+ * re-derivation this triggers just reads the stale value straight back.
1066
+ */
1067
+ deleteBaseBranchName(repoPath, ref) {
1068
+ this._caches.baseBranchName?.delete(this.getCommonPath(repoPath), ref);
1069
+ }
814
1070
  getBranchMergedStatus(repoPath, cacheKey, factory, cancellation) {
815
1071
  return this.getSharedOrCreateWithKey(this.branchMergedStatus, repoPath, cacheKey, factory, (data, newRepoPath) => {
816
1072
  if (!data.merged)
@@ -834,8 +1090,14 @@ export class Cache {
834
1090
  getBranchMetadataMap(repoPath, factory) {
835
1091
  return this.getSharedSimple(this.branchMetadataMap, repoPath, factory);
836
1092
  }
837
- getDefaultBranchName(repoPath, remote, factory) {
838
- return this.getSharedSimpleWithKey(this.defaultBranchName, repoPath, remote, factory);
1093
+ getDefaultBranchName(repoPath, remote, factory, cancellation) {
1094
+ return this.getSharedSimpleWithKey(this.defaultBranchName, repoPath, remote, factory, {
1095
+ cancellation: cancellation,
1096
+ });
1097
+ }
1098
+ /** Clears the cached default branch for one `remote` key (the networked lookup or its `:local` variant). */
1099
+ deleteDefaultBranchName(repoPath, remote) {
1100
+ this._caches.defaultBranchName?.delete(this.getCommonPath(repoPath), remote);
839
1101
  }
840
1102
  getInitialCommitSha(repoPath, factory) {
841
1103
  return this.getSharedSimple(this.initialCommitSha, repoPath, factory);
@@ -956,19 +1218,26 @@ export class Cache {
956
1218
  }
957
1219
  return sharedPromise;
958
1220
  }
959
- async getSharedSimple(cache, repoPath, factory) {
1221
+ async getSharedSimple(cache, repoPath,
1222
+ // `cacheable` is forwarded so a factory can refuse the entry when the read FAILED rather than
1223
+ // genuinely produced nothing — see `getSharedSimpleWithKey` for why that distinction matters.
1224
+ factory) {
960
1225
  const commonPath = this.getCommonPath(repoPath);
961
1226
  // `PromiseMap.getOrCreate(key, factory, cancellation?)` and
962
1227
  // `PromiseCache.getOrCreate(key, factory, options?)` have different 3rd-argument shapes,
963
1228
  // so we dispatch on cache type. Both register a `CacheController` so `invalidate` works.
964
1229
  if (cache instanceof PromiseCache) {
965
- return cache.getOrCreate(commonPath, () => Promise.resolve(factory(commonPath)));
1230
+ return cache.getOrCreate(commonPath, cacheable => Promise.resolve(factory(commonPath, cacheable)));
966
1231
  }
967
- return cache.getOrCreate(commonPath, () => Promise.resolve(factory(commonPath)));
1232
+ return cache.getOrCreate(commonPath, cacheable => Promise.resolve(factory(commonPath, cacheable)));
968
1233
  }
969
- async getSharedSimpleWithKey(cache, repoPath, cacheKey, factory, options) {
1234
+ async getSharedSimpleWithKey(cache, repoPath, cacheKey,
1235
+ // `cacheable` is forwarded so a factory can distinguish "the answer is genuinely nothing" from "the
1236
+ // read failed": callers here set no TTL by default, so a failure resolved as `undefined` would
1237
+ // otherwise be served as a real answer until something explicitly evicts it.
1238
+ factory, options) {
970
1239
  const commonPath = this.getCommonPath(repoPath);
971
- return cache.getOrCreate(commonPath, cacheKey, (_cacheable, signal) => Promise.resolve(factory(commonPath, signal)), options);
1240
+ return cache.getOrCreate(commonPath, cacheKey, (cacheable, signal) => Promise.resolve(factory(commonPath, cacheable, signal)), options);
972
1241
  }
973
1242
  }
974
1243
  __decorate([