@gitkraken/core-gitlens 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (451) hide show
  1. package/CHANGELOG.md +25 -1
  2. package/dist/git/cache.d.ts +49 -9
  3. package/dist/git/cache.d.ts.map +1 -1
  4. package/dist/git/cache.js +174 -14
  5. package/dist/git/cache.js.map +1 -1
  6. package/dist/git/context.d.ts +11 -2
  7. package/dist/git/context.d.ts.map +1 -1
  8. package/dist/git/context.js.map +1 -1
  9. package/dist/git/models/branch.d.ts +1 -0
  10. package/dist/git/models/branch.d.ts.map +1 -1
  11. package/dist/git/models/branch.js.map +1 -1
  12. package/dist/git/models/commit.d.ts +1 -9
  13. package/dist/git/models/commit.d.ts.map +1 -1
  14. package/dist/git/models/commit.js +4 -9
  15. package/dist/git/models/commit.js.map +1 -1
  16. package/dist/git/models/graph.d.ts +2 -4
  17. package/dist/git/models/graph.d.ts.map +1 -1
  18. package/dist/git/models/reference.d.ts +31 -0
  19. package/dist/git/models/reference.d.ts.map +1 -1
  20. package/dist/git/models/remote.d.ts.map +1 -1
  21. package/dist/git/models/remote.js.map +1 -1
  22. package/dist/git/models/repository.d.ts +20 -3
  23. package/dist/git/models/repository.d.ts.map +1 -1
  24. package/dist/git/models/repository.js +42 -5
  25. package/dist/git/models/repository.js.map +1 -1
  26. package/dist/git/models/search.d.ts +2 -2
  27. package/dist/git/models/search.d.ts.map +1 -1
  28. package/dist/git/models/worktree.d.ts +4 -1
  29. package/dist/git/models/worktree.d.ts.map +1 -1
  30. package/dist/git/models/worktree.js +2 -2
  31. package/dist/git/models/worktree.js.map +1 -1
  32. package/dist/git/parsers/diffParser.d.ts +0 -1
  33. package/dist/git/parsers/diffParser.d.ts.map +1 -1
  34. package/dist/git/parsers/diffParser.js +22 -61
  35. package/dist/git/parsers/diffParser.js.map +1 -1
  36. package/dist/git/providers/branches.d.ts +18 -4
  37. package/dist/git/providers/branches.d.ts.map +1 -1
  38. package/dist/git/providers/commits.d.ts +6 -0
  39. package/dist/git/providers/commits.d.ts.map +1 -1
  40. package/dist/git/providers/config.d.ts +6 -1
  41. package/dist/git/providers/config.d.ts.map +1 -1
  42. package/dist/git/providers/diff.d.ts +2 -0
  43. package/dist/git/providers/diff.d.ts.map +1 -1
  44. package/dist/git/providers/operations.d.ts +39 -10
  45. package/dist/git/providers/operations.d.ts.map +1 -1
  46. package/dist/git/providers/pausedOperations.d.ts +3 -1
  47. package/dist/git/providers/pausedOperations.d.ts.map +1 -1
  48. package/dist/git/providers/refs.d.ts +23 -2
  49. package/dist/git/providers/refs.d.ts.map +1 -1
  50. package/dist/git/providers/revision.d.ts +1 -1
  51. package/dist/git/providers/revision.d.ts.map +1 -1
  52. package/dist/git/providers/staging.d.ts +18 -0
  53. package/dist/git/providers/staging.d.ts.map +1 -1
  54. package/dist/git/providers/status.d.ts +4 -1
  55. package/dist/git/providers/status.d.ts.map +1 -1
  56. package/dist/git/remotes/azure-devops.d.ts.map +1 -1
  57. package/dist/git/remotes/azure-devops.js.map +1 -1
  58. package/dist/git/{exec.types.d.ts → run.types.d.ts} +22 -3
  59. package/dist/git/run.types.d.ts.map +1 -0
  60. package/dist/git/run.types.js +2 -0
  61. package/dist/git/run.types.js.map +1 -0
  62. package/dist/git/service.d.ts.map +1 -1
  63. package/dist/git/service.js.map +1 -1
  64. package/dist/git/utils/autolink.utils.d.ts.map +1 -1
  65. package/dist/git/utils/autolink.utils.js.map +1 -1
  66. package/dist/git/utils/blame.utils.d.ts.map +1 -1
  67. package/dist/git/utils/blame.utils.js.map +1 -1
  68. package/dist/git/utils/conflictResolution.utils.d.ts +6 -0
  69. package/dist/git/utils/conflictResolution.utils.d.ts.map +1 -0
  70. package/dist/git/utils/conflictResolution.utils.js +25 -0
  71. package/dist/git/utils/conflictResolution.utils.js.map +1 -0
  72. package/dist/git/utils/fileStatus.utils.d.ts +2 -1
  73. package/dist/git/utils/fileStatus.utils.d.ts.map +1 -1
  74. package/dist/git/utils/fileStatus.utils.js +4 -0
  75. package/dist/git/utils/fileStatus.utils.js.map +1 -1
  76. package/dist/git/utils/search.utils.d.ts.map +1 -1
  77. package/dist/git/utils/search.utils.js +3 -0
  78. package/dist/git/utils/search.utils.js.map +1 -1
  79. package/dist/git/utils/sorting.d.ts +14 -0
  80. package/dist/git/utils/sorting.d.ts.map +1 -1
  81. package/dist/git/utils/sorting.js +34 -0
  82. package/dist/git/utils/sorting.js.map +1 -1
  83. package/dist/git/utils/status.utils.d.ts.map +1 -1
  84. package/dist/git/utils/status.utils.js.map +1 -1
  85. package/dist/git/watching/classifyChange.d.ts.map +1 -1
  86. package/dist/git/watching/classifyChange.js +8 -0
  87. package/dist/git/watching/classifyChange.js.map +1 -1
  88. package/dist/git/watching/gitIgnoreFilter.js +1 -1
  89. package/dist/git/watching/gitIgnoreFilter.js.map +1 -1
  90. package/dist/git/watching/initWatcher.d.ts.map +1 -1
  91. package/dist/git/watching/initWatcher.js.map +1 -1
  92. package/dist/git/watching/watchGroup.d.ts.map +1 -1
  93. package/dist/git/watching/watchGroup.js.map +1 -1
  94. package/dist/git/watching/watchService.d.ts.map +1 -1
  95. package/dist/git/watching/watchService.js +24 -4
  96. package/dist/git/watching/watchService.js.map +1 -1
  97. package/dist/git/watching/watchSession.d.ts.map +1 -1
  98. package/dist/git/watching/watchSession.js.map +1 -1
  99. package/dist/git-cli/cliGitProvider.js +1 -1
  100. package/dist/git-cli/cliGitProvider.js.map +1 -1
  101. package/dist/git-cli/exec/exec.types.d.ts +1 -1
  102. package/dist/git-cli/exec/exec.types.d.ts.map +1 -1
  103. package/dist/git-cli/exec/git.d.ts +31 -6
  104. package/dist/git-cli/exec/git.d.ts.map +1 -1
  105. package/dist/git-cli/exec/git.js +70 -9
  106. package/dist/git-cli/exec/git.js.map +1 -1
  107. package/dist/git-cli/exec/gitQueue.d.ts +22 -6
  108. package/dist/git-cli/exec/gitQueue.d.ts.map +1 -1
  109. package/dist/git-cli/exec/gitQueue.js +88 -24
  110. package/dist/git-cli/exec/gitQueue.js.map +1 -1
  111. package/dist/git-cli/parsers/blameParser.d.ts.map +1 -1
  112. package/dist/git-cli/parsers/blameParser.js.map +1 -1
  113. package/dist/git-cli/parsers/logParser.d.ts +1 -0
  114. package/dist/git-cli/parsers/logParser.d.ts.map +1 -1
  115. package/dist/git-cli/parsers/logParser.js +4 -0
  116. package/dist/git-cli/parsers/logParser.js.map +1 -1
  117. package/dist/git-cli/parsers/refParser.d.ts +3 -30
  118. package/dist/git-cli/parsers/refParser.d.ts.map +1 -1
  119. package/dist/git-cli/parsers/refParser.js +30 -30
  120. package/dist/git-cli/parsers/refParser.js.map +1 -1
  121. package/dist/git-cli/providers/blame.d.ts.map +1 -1
  122. package/dist/git-cli/providers/blame.js +1 -1
  123. package/dist/git-cli/providers/blame.js.map +1 -1
  124. package/dist/git-cli/providers/branches.d.ts +17 -5
  125. package/dist/git-cli/providers/branches.d.ts.map +1 -1
  126. package/dist/git-cli/providers/branches.js +245 -162
  127. package/dist/git-cli/providers/branches.js.map +1 -1
  128. package/dist/git-cli/providers/commits.d.ts +4 -0
  129. package/dist/git-cli/providers/commits.d.ts.map +1 -1
  130. package/dist/git-cli/providers/commits.js +120 -35
  131. package/dist/git-cli/providers/commits.js.map +1 -1
  132. package/dist/git-cli/providers/config.d.ts +11 -2
  133. package/dist/git-cli/providers/config.d.ts.map +1 -1
  134. package/dist/git-cli/providers/config.js +36 -11
  135. package/dist/git-cli/providers/config.js.map +1 -1
  136. package/dist/git-cli/providers/contributors.d.ts.map +1 -1
  137. package/dist/git-cli/providers/contributors.js +7 -4
  138. package/dist/git-cli/providers/contributors.js.map +1 -1
  139. package/dist/git-cli/providers/diff.d.ts +2 -0
  140. package/dist/git-cli/providers/diff.d.ts.map +1 -1
  141. package/dist/git-cli/providers/diff.js +92 -20
  142. package/dist/git-cli/providers/diff.js.map +1 -1
  143. package/dist/git-cli/providers/graph.d.ts.map +1 -1
  144. package/dist/git-cli/providers/graph.js +49 -28
  145. package/dist/git-cli/providers/graph.js.map +1 -1
  146. package/dist/git-cli/providers/operations.d.ts +30 -11
  147. package/dist/git-cli/providers/operations.d.ts.map +1 -1
  148. package/dist/git-cli/providers/operations.js +146 -43
  149. package/dist/git-cli/providers/operations.js.map +1 -1
  150. package/dist/git-cli/providers/patch.d.ts.map +1 -1
  151. package/dist/git-cli/providers/patch.js +15 -30
  152. package/dist/git-cli/providers/patch.js.map +1 -1
  153. package/dist/git-cli/providers/pausedOperations.d.ts +3 -1
  154. package/dist/git-cli/providers/pausedOperations.d.ts.map +1 -1
  155. package/dist/git-cli/providers/pausedOperations.js +13 -7
  156. package/dist/git-cli/providers/pausedOperations.js.map +1 -1
  157. package/dist/git-cli/providers/refs.d.ts +19 -2
  158. package/dist/git-cli/providers/refs.d.ts.map +1 -1
  159. package/dist/git-cli/providers/refs.js +312 -9
  160. package/dist/git-cli/providers/refs.js.map +1 -1
  161. package/dist/git-cli/providers/remotes.js +4 -4
  162. package/dist/git-cli/providers/remotes.js.map +1 -1
  163. package/dist/git-cli/providers/revision.d.ts +1 -1
  164. package/dist/git-cli/providers/revision.d.ts.map +1 -1
  165. package/dist/git-cli/providers/revision.js +15 -11
  166. package/dist/git-cli/providers/revision.js.map +1 -1
  167. package/dist/git-cli/providers/staging.d.ts +8 -0
  168. package/dist/git-cli/providers/staging.d.ts.map +1 -1
  169. package/dist/git-cli/providers/staging.js +52 -8
  170. package/dist/git-cli/providers/staging.js.map +1 -1
  171. package/dist/git-cli/providers/stash.d.ts +0 -8
  172. package/dist/git-cli/providers/stash.d.ts.map +1 -1
  173. package/dist/git-cli/providers/stash.js +63 -119
  174. package/dist/git-cli/providers/stash.js.map +1 -1
  175. package/dist/git-cli/providers/status.d.ts +4 -1
  176. package/dist/git-cli/providers/status.d.ts.map +1 -1
  177. package/dist/git-cli/providers/status.js +10 -9
  178. package/dist/git-cli/providers/status.js.map +1 -1
  179. package/dist/git-cli/providers/tags.d.ts.map +1 -1
  180. package/dist/git-cli/providers/tags.js +13 -9
  181. package/dist/git-cli/providers/tags.js.map +1 -1
  182. package/dist/git-cli/providers/worktrees.js +3 -3
  183. package/dist/git-cli/providers/worktrees.js.map +1 -1
  184. package/dist/ipc/discovery.d.ts +27 -0
  185. package/dist/ipc/discovery.d.ts.map +1 -0
  186. package/dist/ipc/discovery.js +38 -0
  187. package/dist/ipc/discovery.js.map +1 -0
  188. package/dist/ipc/ipcServer.d.ts +20 -0
  189. package/dist/ipc/ipcServer.d.ts.map +1 -0
  190. package/dist/ipc/ipcServer.js +162 -0
  191. package/dist/ipc/ipcServer.js.map +1 -0
  192. package/dist/plus/agents/providers/claudeCodeProvider.d.ts +114 -0
  193. package/dist/plus/agents/providers/claudeCodeProvider.d.ts.map +1 -0
  194. package/dist/plus/agents/providers/claudeCodeProvider.js +1480 -0
  195. package/dist/plus/agents/providers/claudeCodeProvider.js.map +1 -0
  196. package/dist/plus/agents/providers/claudeCodeTranscript.d.ts +36 -0
  197. package/dist/plus/agents/providers/claudeCodeTranscript.d.ts.map +1 -0
  198. package/dist/plus/agents/providers/claudeCodeTranscript.js +171 -0
  199. package/dist/plus/agents/providers/claudeCodeTranscript.js.map +1 -0
  200. package/dist/plus/agents/sanitizePrompt.d.ts +15 -0
  201. package/dist/plus/agents/sanitizePrompt.d.ts.map +1 -0
  202. package/dist/plus/agents/sanitizePrompt.js +103 -0
  203. package/dist/plus/agents/sanitizePrompt.js.map +1 -0
  204. package/dist/plus/agents/stateMachine.d.ts +32 -0
  205. package/dist/plus/agents/stateMachine.d.ts.map +1 -0
  206. package/dist/plus/agents/stateMachine.js +180 -0
  207. package/dist/plus/agents/stateMachine.js.map +1 -0
  208. package/dist/plus/agents/types.d.ts +203 -0
  209. package/dist/plus/agents/types.d.ts.map +1 -0
  210. package/dist/plus/agents/types.js +49 -0
  211. package/dist/plus/agents/types.js.map +1 -0
  212. package/dist/plus/ai/constants.d.ts +2 -1
  213. package/dist/plus/ai/constants.d.ts.map +1 -1
  214. package/dist/plus/ai/constants.js +7 -0
  215. package/dist/plus/ai/constants.js.map +1 -1
  216. package/dist/plus/ai/errors.d.ts +4 -1
  217. package/dist/plus/ai/errors.d.ts.map +1 -1
  218. package/dist/plus/ai/errors.js +38 -0
  219. package/dist/plus/ai/errors.js.map +1 -1
  220. package/dist/plus/ai/models/model.d.ts +1 -1
  221. package/dist/plus/ai/models/model.d.ts.map +1 -1
  222. package/dist/plus/ai/models/model.js.map +1 -1
  223. package/dist/plus/ai/models/promptTemplates.d.ts +28 -2
  224. package/dist/plus/ai/models/promptTemplates.d.ts.map +1 -1
  225. package/dist/plus/ai/models/results.d.ts +28 -0
  226. package/dist/plus/ai/models/results.d.ts.map +1 -1
  227. package/dist/plus/ai/prompts.d.ts +4 -0
  228. package/dist/plus/ai/prompts.d.ts.map +1 -1
  229. package/dist/plus/ai/prompts.js +167 -1
  230. package/dist/plus/ai/prompts.js.map +1 -1
  231. package/dist/plus/ai/utils/ai.utils.d.ts.map +1 -1
  232. package/dist/plus/ai/utils/ai.utils.js +2 -0
  233. package/dist/plus/ai/utils/ai.utils.js.map +1 -1
  234. package/dist/plus/ai/utils/results.utils.d.ts +3 -0
  235. package/dist/plus/ai/utils/results.utils.d.ts.map +1 -1
  236. package/dist/plus/ai/utils/results.utils.js +75 -0
  237. package/dist/plus/ai/utils/results.utils.js.map +1 -1
  238. package/dist/plus/ai/utils/truncation.utils.d.ts +1 -1
  239. package/dist/plus/ai/utils/truncation.utils.d.ts.map +1 -1
  240. package/dist/plus/ai/utils/truncation.utils.js.map +1 -1
  241. package/dist/plus/git-github/api/github.d.ts +10 -1
  242. package/dist/plus/git-github/api/github.d.ts.map +1 -1
  243. package/dist/plus/git-github/api/github.js +156 -49
  244. package/dist/plus/git-github/api/github.js.map +1 -1
  245. package/dist/plus/git-github/api/types.d.ts +8 -0
  246. package/dist/plus/git-github/api/types.d.ts.map +1 -1
  247. package/dist/plus/git-github/models.d.ts +1 -1
  248. package/dist/plus/git-github/models.d.ts.map +1 -1
  249. package/dist/plus/git-github/models.js.map +1 -1
  250. package/dist/plus/git-github/providers/github/blame.d.ts.map +1 -1
  251. package/dist/plus/git-github/providers/github/blame.js.map +1 -1
  252. package/dist/plus/git-github/providers/github/branches.d.ts +5 -1
  253. package/dist/plus/git-github/providers/github/branches.d.ts.map +1 -1
  254. package/dist/plus/git-github/providers/github/branches.js +60 -22
  255. package/dist/plus/git-github/providers/github/branches.js.map +1 -1
  256. package/dist/plus/git-github/providers/github/commits.d.ts.map +1 -1
  257. package/dist/plus/git-github/providers/github/commits.js +144 -92
  258. package/dist/plus/git-github/providers/github/commits.js.map +1 -1
  259. package/dist/plus/git-github/providers/github/diff.d.ts +3 -1
  260. package/dist/plus/git-github/providers/github/diff.d.ts.map +1 -1
  261. package/dist/plus/git-github/providers/github/diff.js +23 -9
  262. package/dist/plus/git-github/providers/github/diff.js.map +1 -1
  263. package/dist/plus/git-github/providers/github/refs.d.ts +9 -1
  264. package/dist/plus/git-github/providers/github/refs.d.ts.map +1 -1
  265. package/dist/plus/git-github/providers/github/refs.js +38 -13
  266. package/dist/plus/git-github/providers/github/refs.js.map +1 -1
  267. package/dist/plus/git-github/providers/github/revision.d.ts.map +1 -1
  268. package/dist/plus/git-github/providers/github/revision.js +1 -2
  269. package/dist/plus/git-github/providers/github/revision.js.map +1 -1
  270. package/dist/plus/git-github/providers/github/status.d.ts +4 -1
  271. package/dist/plus/git-github/providers/github/status.d.ts.map +1 -1
  272. package/dist/plus/git-github/providers/github/status.js +1 -1
  273. package/dist/plus/git-github/providers/github/status.js.map +1 -1
  274. package/dist/plus/git-github/providers/github/tags.d.ts.map +1 -1
  275. package/dist/plus/git-github/providers/github/tags.js +35 -36
  276. package/dist/plus/git-github/providers/github/tags.js.map +1 -1
  277. package/dist/plus/git-github/providers/githubGitProvider.d.ts.map +1 -1
  278. package/dist/plus/git-github/providers/githubGitProvider.js.map +1 -1
  279. package/dist/utils/color.d.ts.map +1 -1
  280. package/dist/utils/color.js.map +1 -1
  281. package/dist/utils/decorators/log.js +1 -1
  282. package/dist/utils/decorators/log.js.map +1 -1
  283. package/dist/utils/decorators/sequentialize.d.ts.map +1 -1
  284. package/dist/utils/decorators/sequentialize.js +4 -2
  285. package/dist/utils/decorators/sequentialize.js.map +1 -1
  286. package/dist/utils/decorators/serializable.d.ts.map +1 -1
  287. package/dist/utils/decorators/serializable.js.map +1 -1
  288. package/dist/utils/dedupedAsyncCache.d.ts +37 -0
  289. package/dist/utils/dedupedAsyncCache.d.ts.map +1 -0
  290. package/dist/utils/dedupedAsyncCache.js +68 -0
  291. package/dist/utils/dedupedAsyncCache.js.map +1 -0
  292. package/dist/utils/diff.d.ts +2 -0
  293. package/dist/utils/diff.d.ts.map +1 -0
  294. package/dist/utils/diff.js +53 -0
  295. package/dist/utils/diff.js.map +1 -0
  296. package/dist/utils/disposable.d.ts.map +1 -1
  297. package/dist/utils/disposable.js.map +1 -1
  298. package/dist/utils/env/node/base64.js.map +1 -1
  299. package/dist/utils/env/node/exec.d.ts.map +1 -1
  300. package/dist/utils/env/node/exec.js.map +1 -1
  301. package/dist/utils/error.d.ts.map +1 -1
  302. package/dist/utils/error.js.map +1 -1
  303. package/dist/utils/formatter.d.ts.map +1 -1
  304. package/dist/utils/formatter.js +4 -10
  305. package/dist/utils/formatter.js.map +1 -1
  306. package/dist/utils/iterable.d.ts.map +1 -1
  307. package/dist/utils/iterable.js.map +1 -1
  308. package/dist/utils/logger.d.ts.map +1 -1
  309. package/dist/utils/logger.js.map +1 -1
  310. package/dist/utils/lruMap.d.ts +49 -0
  311. package/dist/utils/lruMap.d.ts.map +1 -0
  312. package/dist/utils/lruMap.js +103 -0
  313. package/dist/utils/lruMap.js.map +1 -0
  314. package/dist/utils/markdown.d.ts.map +1 -1
  315. package/dist/utils/markdown.js.map +1 -1
  316. package/dist/utils/mru.d.ts.map +1 -1
  317. package/dist/utils/mru.js.map +1 -1
  318. package/dist/utils/path.d.ts.map +1 -1
  319. package/dist/utils/path.js.map +1 -1
  320. package/dist/utils/promise.d.ts +1 -0
  321. package/dist/utils/promise.d.ts.map +1 -1
  322. package/dist/utils/promise.js +17 -0
  323. package/dist/utils/promise.js.map +1 -1
  324. package/dist/utils/promiseCache.d.ts +10 -0
  325. package/dist/utils/promiseCache.d.ts.map +1 -1
  326. package/dist/utils/promiseCache.js +22 -0
  327. package/dist/utils/promiseCache.js.map +1 -1
  328. package/dist/utils/string.d.ts.map +1 -1
  329. package/dist/utils/string.js.map +1 -1
  330. package/dist/utils/uri.d.ts.map +1 -1
  331. package/dist/utils/uri.js.map +1 -1
  332. package/dist/utils/version.d.ts +14 -0
  333. package/dist/utils/version.d.ts.map +1 -1
  334. package/dist/utils/version.js +48 -0
  335. package/dist/utils/version.js.map +1 -1
  336. package/package.json +13 -1
  337. package/src/git/cache.ts +309 -29
  338. package/src/git/context.ts +11 -2
  339. package/src/git/models/branch.ts +1 -0
  340. package/src/git/models/commit.ts +2 -17
  341. package/src/git/models/graph.ts +2 -4
  342. package/src/git/models/reference.ts +33 -0
  343. package/src/git/models/remote.ts +1 -0
  344. package/src/git/models/repository.ts +44 -6
  345. package/src/git/models/search.ts +2 -2
  346. package/src/git/models/worktree.ts +10 -2
  347. package/src/git/parsers/diffParser.ts +9 -44
  348. package/src/git/providers/branches.ts +25 -4
  349. package/src/git/providers/commits.ts +7 -0
  350. package/src/git/providers/config.ts +4 -0
  351. package/src/git/providers/diff.ts +8 -2
  352. package/src/git/providers/operations.ts +54 -3
  353. package/src/git/providers/pausedOperations.ts +1 -0
  354. package/src/git/providers/refs.ts +32 -3
  355. package/src/git/providers/revision.ts +5 -1
  356. package/src/git/providers/staging.ts +14 -0
  357. package/src/git/providers/status.ts +6 -1
  358. package/src/git/remotes/azure-devops.ts +2 -0
  359. package/src/git/{exec.types.ts → run.types.ts} +22 -2
  360. package/src/git/service.ts +1 -0
  361. package/src/git/utils/autolink.utils.ts +1 -0
  362. package/src/git/utils/blame.utils.ts +2 -0
  363. package/src/git/utils/conflictResolution.utils.ts +31 -0
  364. package/src/git/utils/fileStatus.utils.ts +7 -1
  365. package/src/git/utils/search.utils.ts +2 -0
  366. package/src/git/utils/sorting.ts +38 -0
  367. package/src/git/utils/status.utils.ts +1 -0
  368. package/src/git/watching/classifyChange.ts +9 -0
  369. package/src/git/watching/gitIgnoreFilter.ts +2 -2
  370. package/src/git/watching/initWatcher.ts +2 -0
  371. package/src/git/watching/watchGroup.ts +3 -0
  372. package/src/git/watching/watchService.ts +38 -5
  373. package/src/git/watching/watchSession.ts +10 -0
  374. package/src/git-cli/cliGitProvider.ts +1 -1
  375. package/src/git-cli/exec/exec.types.ts +2 -2
  376. package/src/git-cli/exec/git.ts +76 -23
  377. package/src/git-cli/exec/gitQueue.ts +98 -25
  378. package/src/git-cli/parsers/blameParser.ts +1 -0
  379. package/src/git-cli/parsers/logParser.ts +6 -1
  380. package/src/git-cli/parsers/refParser.ts +33 -34
  381. package/src/git-cli/providers/blame.ts +2 -1
  382. package/src/git-cli/providers/branches.ts +341 -196
  383. package/src/git-cli/providers/commits.ts +145 -46
  384. package/src/git-cli/providers/config.ts +50 -16
  385. package/src/git-cli/providers/contributors.ts +7 -12
  386. package/src/git-cli/providers/diff.ts +107 -20
  387. package/src/git-cli/providers/graph.ts +58 -29
  388. package/src/git-cli/providers/operations.ts +253 -57
  389. package/src/git-cli/providers/patch.ts +16 -37
  390. package/src/git-cli/providers/pausedOperations.ts +14 -6
  391. package/src/git-cli/providers/refs.ts +274 -11
  392. package/src/git-cli/providers/remotes.ts +4 -4
  393. package/src/git-cli/providers/revision.ts +22 -15
  394. package/src/git-cli/providers/staging.ts +51 -8
  395. package/src/git-cli/providers/stash.ts +67 -134
  396. package/src/git-cli/providers/status.ts +21 -10
  397. package/src/git-cli/providers/tags.ts +18 -19
  398. package/src/git-cli/providers/worktrees.ts +3 -3
  399. package/src/ipc/discovery.ts +56 -0
  400. package/src/ipc/ipcServer.ts +171 -0
  401. package/src/plus/agents/providers/claudeCodeProvider.ts +1782 -0
  402. package/src/plus/agents/providers/claudeCodeTranscript.ts +214 -0
  403. package/src/plus/agents/sanitizePrompt.ts +109 -0
  404. package/src/plus/agents/stateMachine.ts +197 -0
  405. package/src/plus/agents/types.ts +277 -0
  406. package/src/plus/ai/constants.ts +8 -0
  407. package/src/plus/ai/errors.ts +40 -0
  408. package/src/plus/ai/models/model.ts +1 -0
  409. package/src/plus/ai/models/promptTemplates.ts +42 -0
  410. package/src/plus/ai/models/results.ts +30 -0
  411. package/src/plus/ai/prompts.ts +171 -1
  412. package/src/plus/ai/utils/ai.utils.ts +2 -0
  413. package/src/plus/ai/utils/results.utils.ts +101 -0
  414. package/src/plus/ai/utils/truncation.utils.ts +3 -1
  415. package/src/plus/git-github/api/github.ts +199 -53
  416. package/src/plus/git-github/api/types.ts +15 -0
  417. package/src/plus/git-github/models.ts +1 -1
  418. package/src/plus/git-github/providers/github/blame.ts +2 -0
  419. package/src/plus/git-github/providers/github/branches.ts +75 -33
  420. package/src/plus/git-github/providers/github/commits.ts +231 -160
  421. package/src/plus/git-github/providers/github/diff.ts +35 -21
  422. package/src/plus/git-github/providers/github/refs.ts +57 -22
  423. package/src/plus/git-github/providers/github/revision.ts +1 -2
  424. package/src/plus/git-github/providers/github/status.ts +6 -1
  425. package/src/plus/git-github/providers/github/tags.ts +61 -62
  426. package/src/plus/git-github/providers/githubGitProvider.ts +1 -0
  427. package/src/utils/color.ts +2 -0
  428. package/src/utils/decorators/log.ts +1 -1
  429. package/src/utils/decorators/sequentialize.ts +8 -6
  430. package/src/utils/decorators/serializable.ts +1 -0
  431. package/src/utils/dedupedAsyncCache.ts +74 -0
  432. package/src/utils/diff.ts +61 -0
  433. package/src/utils/disposable.ts +2 -0
  434. package/src/utils/env/node/base64.ts +1 -1
  435. package/src/utils/env/node/exec.ts +4 -2
  436. package/src/utils/error.ts +1 -0
  437. package/src/utils/formatter.ts +4 -11
  438. package/src/utils/iterable.ts +4 -1
  439. package/src/utils/logger.ts +1 -0
  440. package/src/utils/lruMap.ts +112 -0
  441. package/src/utils/markdown.ts +1 -0
  442. package/src/utils/mru.ts +2 -0
  443. package/src/utils/path.ts +1 -0
  444. package/src/utils/promise.ts +22 -0
  445. package/src/utils/promiseCache.ts +24 -0
  446. package/src/utils/string.ts +2 -0
  447. package/src/utils/uri.ts +1 -0
  448. package/src/utils/version.ts +49 -0
  449. package/dist/git/exec.types.d.ts.map +0 -1
  450. package/dist/git/exec.types.js +0 -2
  451. package/dist/git/exec.types.js.map +0 -1
@@ -75,7 +75,6 @@ import { getSettledValue } from '../../utils/promise.js';
75
75
  import { maybeStopWatch } from '../../utils/stopwatch.js';
76
76
  import { getGitCommandError, gitConfigsBranch, gitConfigsLog, GitError, GitErrors, GitWarnings } from '../exec/git.js';
77
77
  import { parseMergeTreeConflict } from '../parsers/mergeTreeParser.js';
78
- import { getBranchParser } from '../parsers/refParser.js';
79
78
  /** Minimum time between writes to the config for last accessed/modified dates */
80
79
  const dateMetadataStaleThresholdMs = 5 * 60 * 1000; // 5 minutes
81
80
  export class BranchesGitSubProvider {
@@ -110,10 +109,10 @@ export class BranchesGitSubProvider {
110
109
  return undefined;
111
110
  const [pausedOpStatusResult, committerDateResult, defaultWorktreePathResult, metadataMapResult] = await Promise.allSettled([
112
111
  isDetachedHead(ref.name)
113
- ? this.provider.pausedOps?.getPausedOperationStatus(repoPath, cancellation)
112
+ ? this.provider.pausedOps?.getPausedOperationStatus(repoPath, undefined, cancellation)
114
113
  : undefined,
115
114
  this.git
116
- .exec({
115
+ .run({
117
116
  cwd: repoPath,
118
117
  cancellation: cancellation,
119
118
  configs: gitConfigsLog,
@@ -147,32 +146,37 @@ export class BranchesGitSubProvider {
147
146
  try {
148
147
  const env_1 = { stack: [], error: void 0, hasError: false };
149
148
  try {
150
- const supported = await this.git.supported('git:for-each-ref');
151
- const parser = getBranchParser(supported);
152
- const [gitResult, defaultWorktreePathResult, metadataMapResult] = await Promise.allSettled([
153
- this.git.exec({ cwd: commonPath, cancellation: signal }, 'for-each-ref', ...parser.arguments, 'refs/heads/', 'refs/remotes/'),
149
+ const [recordsResult, supportedResult, defaultWorktreePathResult, metadataMapResult] = await Promise.allSettled([
150
+ this.provider.refs.getRefs(commonPath, signal),
151
+ this.git.supported('git:for-each-ref'),
154
152
  this.provider.config.getDefaultWorktreePath?.(commonPath),
155
153
  this.getBranchMetadataMap(commonPath),
156
154
  ]);
157
- const result = getSettledValue(gitResult);
155
+ const records = getSettledValue(recordsResult) ?? [];
156
+ const supported = getSettledValue(supportedResult) ?? [];
158
157
  const metadataMap = getSettledValue(metadataMapResult) ?? new Map();
159
158
  const defaultWorktreePath = getSettledValue(defaultWorktreePathResult);
159
+ const worktreePathSupported = supported.includes('git:for-each-ref:worktreePath');
160
160
  // If we don't get any data, assume the repo doesn't have any commits yet so check if we have a current branch
161
- if (!result?.stdout) {
161
+ if (!records.length) {
162
162
  const current = await this.getCurrentBranch(commonPath, metadataMap, options?.ordering ?? this.context.config?.commits.ordering ?? undefined, signal);
163
163
  return current != null ? { values: [current] } : emptyPagedResult;
164
164
  }
165
165
  const sw = __addDisposableResource(env_1, maybeStopWatch(scope, { log: { onlyExit: true, level: 'debug' } }), false);
166
166
  const branches = [];
167
- for (const entry of parser.parse(result.stdout)) {
167
+ for (const record of records) {
168
+ const fullName = record.name;
169
+ // Filter to branches and remote-tracking branches; skip tags from the unified records.
170
+ if (!fullName.startsWith('refs/heads/') && !fullName.startsWith('refs/remotes/'))
171
+ continue;
168
172
  // Skip HEAD refs in remote branches
169
- if (isRemoteHEAD(entry.name))
173
+ if (isRemoteHEAD(fullName))
170
174
  continue;
171
- const upstream = parseUpstream(entry.upstream, entry.upstreamTracking);
172
- const metadata = metadataMap.get(parseRefName(entry.name).name);
173
- const worktreePath = entry.worktreePath ? normalizePath(entry.worktreePath) : undefined;
174
- branches.push(new GitBranch(commonPath, entry.name, false, // Don't trust %(HEAD) for current as it's per-worktree -- we will set it later
175
- entry.date ? new Date(entry.date) : undefined, metadata, entry.sha, upstream, supported.includes('git:for-each-ref:worktreePath')
175
+ const upstream = parseUpstream(record.upstream, record.upstreamTracking);
176
+ const metadata = metadataMap.get(parseRefName(fullName).name);
177
+ const worktreePath = record.worktreePath ? normalizePath(record.worktreePath) : undefined;
178
+ branches.push(new GitBranch(commonPath, fullName, false, // Don't trust %(HEAD) for current as it's per-worktree -- we will set it later
179
+ record.committerDate ? new Date(record.committerDate) : undefined, metadata, record.objectname, upstream, worktreePathSupported
176
180
  ? worktreePath
177
181
  ? { path: worktreePath, isDefault: worktreePath === defaultWorktreePath }
178
182
  : false
@@ -286,35 +290,25 @@ export class BranchesGitSubProvider {
286
290
  }
287
291
  async getBranchContributionsOverview(repoPath, ref, options, cancellation) {
288
292
  const scope = getScopedLogger();
289
- try {
290
- const branch = await this.getBranch(repoPath, ref, cancellation);
291
- if (branch == null)
292
- return undefined;
293
- let mergeTarget;
294
- // Tier 1: Check stored merge target (user-set or previously detected from PR)
295
- const storedTarget = await this.getStoredMergeTargetBranchName(repoPath, ref);
296
- if (storedTarget) {
297
- const validated = await this.provider.refs.getSymbolicReferenceName(repoPath, storedTarget);
298
- mergeTarget = validated || storedTarget;
299
- }
300
- // Tier 2: PR-based lookup (caller provides the PR promise)
301
- if (mergeTarget == null && options?.associatedPullRequest != null) {
302
- const pr = await options.associatedPullRequest;
303
- if (pr?.refs?.base != null) {
304
- mergeTarget = `${branch.remoteName}/${pr.refs.base.branch}`;
305
- // Store for future reuse
306
- void this.storeMergeTargetBranchName(repoPath, ref, mergeTarget);
307
- }
308
- }
309
- // Tier 3: Base branch, then default branch
310
- mergeTarget ??= await this.getBaseBranchName(repoPath, ref, cancellation);
311
- mergeTarget ??= await this.getDefaultBranchName(repoPath, undefined, cancellation);
312
- if (mergeTarget == null)
313
- return undefined;
314
- const mergeBase = await this.provider.refs.getMergeBase(repoPath, ref, mergeTarget, undefined, cancellation);
293
+ const priority = options?.priority;
294
+ const priorityOpts = priority != null ? { priority: priority } : undefined;
295
+ // Expensive body — runs only on cache miss. Closes over `mergeTarget` so the cache key
296
+ // (`${ref}|${mergeTarget}`) fully captures every input that affects the result.
297
+ const fetchBody = async (mergeTarget, signal) => {
298
+ const mergeBase = await this.provider.refs.getMergeBase(repoPath, ref, mergeTarget, priorityOpts, signal);
315
299
  if (mergeBase == null)
316
300
  return undefined;
317
- const result = await this.provider.contributors.getContributors(repoPath, createRevisionRange(mergeBase, ref, '..'), { stats: true }, cancellation);
301
+ // Fetch the merge-base commit's dates in parallel with contributors so consumers
302
+ // (e.g. the graph minimap scope window) don't pay a separate round-trip for them.
303
+ // `allSettled` so a transient failure in one side doesn't drop the overview entirely.
304
+ const [contributorsSettled, mergeBaseDatesSettled] = await Promise.allSettled([
305
+ this.provider.contributors.getContributors(repoPath, createRevisionRange(mergeBase, ref, '..'), { stats: true }, signal),
306
+ this.provider.commits.getCommitDates(repoPath, mergeBase, signal),
307
+ ]);
308
+ if (signal?.aborted)
309
+ throw new CancellationError();
310
+ const result = getSettledValue(contributorsSettled) ?? { contributors: [] };
311
+ const mergeBaseDates = getSettledValue(mergeBaseDatesSettled);
318
312
  sortContributors(result.contributors, { orderBy: 'score:desc' });
319
313
  let totalCommits = 0;
320
314
  let totalFiles = 0;
@@ -345,6 +339,7 @@ export class BranchesGitSubProvider {
345
339
  branch: ref,
346
340
  mergeTarget: mergeTarget,
347
341
  mergeBase: mergeBase,
342
+ mergeBaseDate: mergeBaseDates?.committerDate,
348
343
  commits: totalCommits,
349
344
  files: totalFiles,
350
345
  additions: totalAdditions,
@@ -353,6 +348,49 @@ export class BranchesGitSubProvider {
353
348
  firstCommitDate: firstCommitTimestamp != null ? new Date(firstCommitTimestamp) : undefined,
354
349
  contributors: result.contributors,
355
350
  };
351
+ };
352
+ try {
353
+ // Resolve `mergeTarget` through Tier 1 → Tier 2 → Tier 3. The pieces of each tier are
354
+ // already individually cached (`getStoredMergeTargetBranchName`, `getBaseBranchName`,
355
+ // `getDefaultBranchName`), so this resolution path is cheap on warm caches. Only the
356
+ // expensive body below (`getMergeBase` + `getContributors` w/ stats + `getCommitDates`)
357
+ // is wrapped by `cache.getBranchOverview`, keyed on the resolved `mergeTarget` so any
358
+ // caller that resolves to the same target shares; differing targets get independent
359
+ // slots, which is the correctness constraint that previously forced the Tier 2/3 paths
360
+ // to bypass the cache entirely.
361
+ let mergeTarget;
362
+ // Tier 1: Stored merge target (user-set or previously detected from PR).
363
+ const storedTarget = await this.getStoredMergeTargetBranchName(repoPath, ref);
364
+ if (storedTarget) {
365
+ const validated = await this.provider.refs.getSymbolicReferenceName(repoPath, storedTarget, priorityOpts, cancellation);
366
+ mergeTarget = validated || storedTarget;
367
+ }
368
+ // Tier 2: PR-based lookup. The branch object is only needed here (for `remoteName`),
369
+ // so lazy-load it on the cold path instead of paying for it on every call.
370
+ if (mergeTarget == null && options?.associatedPullRequest != null) {
371
+ const pr = await options.associatedPullRequest;
372
+ if (pr?.refs?.base != null) {
373
+ const branch = await this.getBranch(repoPath, ref, cancellation);
374
+ if (branch == null)
375
+ return undefined;
376
+ mergeTarget = `${branch.remoteName}/${pr.refs.base.branch}`;
377
+ // Store for future reuse — turns the next call into a Tier 1 path. Skip the
378
+ // `branchOverviews` invalidation that the write would otherwise trigger: we're
379
+ // about to populate `${ref}|${mergeTarget}` with this exact target, so evicting
380
+ // it would just force the next caller to redo the body. (gk-merge-target writes
381
+ // do not affect `baseBranchName`, so no need to skip that target.)
382
+ void this.storeMergeTargetBranchName(repoPath, ref, mergeTarget, {
383
+ skipInvalidation: ['branchOverviews'],
384
+ });
385
+ }
386
+ }
387
+ // Tier 3: Base branch, then default branch.
388
+ mergeTarget ??= await this.getBaseBranchName(repoPath, ref, priorityOpts, cancellation);
389
+ mergeTarget ??= await this.getDefaultBranchName(repoPath, undefined, priorityOpts, cancellation);
390
+ if (mergeTarget == null)
391
+ return undefined;
392
+ const resolvedTarget = mergeTarget;
393
+ return await this.cache.getBranchOverview(repoPath, `${ref}|${resolvedTarget}`, (_commonPath, _cacheable, signal) => fetchBody(resolvedTarget, signal ?? cancellation), { cancellation: cancellation });
356
394
  }
357
395
  catch (ex) {
358
396
  scope?.error(ex);
@@ -387,7 +425,7 @@ export class BranchesGitSubProvider {
387
425
  if (options?.name != null) {
388
426
  params.push(options.name);
389
427
  }
390
- return this.git.exec({
428
+ return this.git.run({
391
429
  cwd: repoPath,
392
430
  cancellation: cancellation,
393
431
  configs: gitConfigsBranch,
@@ -414,7 +452,7 @@ export class BranchesGitSubProvider {
414
452
  let data;
415
453
  let result;
416
454
  try {
417
- result = await this.git.exec({ cwd: repoPath, cancellation: signal, errors: 'throw' }, 'rev-parse', '--abbrev-ref', '--symbolic-full-name', '@', '@{u}', '--');
455
+ result = await this.git.run({ cwd: repoPath, cancellation: signal, errors: 'throw' }, 'rev-parse', '--abbrev-ref', '--symbolic-full-name', '@', '@{u}', '--');
418
456
  data = [result.stdout, undefined];
419
457
  }
420
458
  catch (ex) {
@@ -427,7 +465,7 @@ export class BranchesGitSubProvider {
427
465
  }
428
466
  else {
429
467
  try {
430
- result = await this.git.exec({ cwd: repoPath, cancellation: signal }, 'symbolic-ref', '--short', 'HEAD');
468
+ result = await this.git.run({ cwd: repoPath, cancellation: signal }, 'symbolic-ref', '--short', 'HEAD');
431
469
  if (result.stdout) {
432
470
  data = [result.stdout.trim(), undefined];
433
471
  }
@@ -437,7 +475,7 @@ export class BranchesGitSubProvider {
437
475
  throw ex;
438
476
  }
439
477
  if (data == null) {
440
- const symbolicRef = await this.getDefaultBranchName(repoPath, 'origin', signal);
478
+ const symbolicRef = await this.getDefaultBranchName(repoPath, 'origin', undefined, signal);
441
479
  if (symbolicRef != null) {
442
480
  data = [
443
481
  symbolicRef.startsWith('origin/')
@@ -463,7 +501,7 @@ export class BranchesGitSubProvider {
463
501
  }
464
502
  }
465
503
  else if (GitWarnings.headNotABranch.test(msg)) {
466
- result = await this.git.exec({
504
+ result = await this.git.run({
467
505
  cwd: repoPath,
468
506
  cancellation: signal,
469
507
  configs: gitConfigsLog,
@@ -494,15 +532,17 @@ export class BranchesGitSubProvider {
494
532
  });
495
533
  }, { cancellation: cancellation });
496
534
  }
497
- async getDefaultBranchName(repoPath, remote, cancellation) {
535
+ async getDefaultBranchName(repoPath, remote, options, cancellation) {
498
536
  if (repoPath == null)
499
537
  return undefined;
500
538
  remote ??= 'origin';
539
+ const priority = options?.priority;
540
+ const priorityOpts = priority != null ? { priority: priority } : undefined;
501
541
  return this.cache.getDefaultBranchName(repoPath, remote, async (commonPath) => {
502
542
  let retried = false;
503
543
  while (true) {
504
544
  try {
505
- const result = await this.git.exec({ cwd: commonPath, cancellation: cancellation }, 'symbolic-ref', '--short', `refs/remotes/${remote}/HEAD`);
545
+ const result = await this.git.run({ cwd: commonPath, cancellation: cancellation, ...priorityOpts }, 'symbolic-ref', '--short', `refs/remotes/${remote}/HEAD`);
506
546
  return result.stdout.trim() || undefined;
507
547
  }
508
548
  catch (ex) {
@@ -510,10 +550,10 @@ export class BranchesGitSubProvider {
510
550
  try {
511
551
  if (!retried) {
512
552
  retried = true;
513
- await this.git.exec({ cwd: commonPath, cancellation: cancellation }, 'remote', 'set-head', '-a', remote);
553
+ await this.git.run({ cwd: commonPath, cancellation: cancellation, ...priorityOpts }, 'remote', 'set-head', '-a', remote);
514
554
  continue;
515
555
  }
516
- const result = await this.git.exec({ cwd: commonPath, cancellation: cancellation }, 'ls-remote', '--symref', remote, 'HEAD');
556
+ const result = await this.git.run({ cwd: commonPath, cancellation: cancellation, ...priorityOpts }, 'ls-remote', '--symref', remote, 'HEAD');
517
557
  if (result.stdout) {
518
558
  const match = /ref:\s(\S+)\s+HEAD/m.exec(result.stdout);
519
559
  if (match != null) {
@@ -538,7 +578,7 @@ export class BranchesGitSubProvider {
538
578
  args.push('--no-track');
539
579
  }
540
580
  try {
541
- await this.git.exec({ cwd: repoPath }, ...args);
581
+ await this.git.run({ cwd: repoPath }, ...args);
542
582
  this.context.hooks?.cache?.onReset?.(repoPath, 'branches');
543
583
  this.context.hooks?.repository?.onChanged?.(repoPath, ['heads']);
544
584
  }
@@ -555,7 +595,7 @@ export class BranchesGitSubProvider {
555
595
  const branches = ensureArray(names);
556
596
  const args = ['branch', options?.force ? '-D' : '-d', ...branches];
557
597
  try {
558
- await this.git.exec({ cwd: repoPath }, ...args);
598
+ await this.git.run({ cwd: repoPath }, ...args);
559
599
  this.context.hooks?.cache?.onReset?.(repoPath, 'branches');
560
600
  this.context.hooks?.repository?.onChanged?.(repoPath, ['heads']);
561
601
  }
@@ -578,7 +618,7 @@ export class BranchesGitSubProvider {
578
618
  const branches = ensureArray(names);
579
619
  const args = ['push', '-d', remote, ...branches];
580
620
  try {
581
- await this.git.exec({ cwd: repoPath }, ...args);
621
+ await this.git.run({ cwd: repoPath }, ...args);
582
622
  this.context.hooks?.cache?.onReset?.(repoPath, 'branches');
583
623
  this.context.hooks?.repository?.onChanged?.(repoPath, ['remotes']);
584
624
  }
@@ -593,42 +633,55 @@ export class BranchesGitSubProvider {
593
633
  throw new BranchError({ action: 'delete', branch: branches.join(', '), gitCommand: { repoPath: repoPath, args: args } }, ex);
594
634
  }
595
635
  }
596
- async getBranchMergedStatus(repoPath, branch, into, cancellation) {
636
+ getBranchMergedStatus(repoPath, branch, into, cancellation) {
597
637
  if (branch.name === into.name || branch.upstream?.name === into.name) {
598
- return { merged: false };
638
+ return Promise.resolve({ merged: false });
599
639
  }
600
- const result = await this.getBranchMergedStatusCore(repoPath, branch, into, cancellation);
601
- if (result.merged)
602
- return result;
603
- // If the branch we are checking is a remote branch, check if it has been merged into its local branch (if there is one)
604
- if (into.remote) {
605
- const localIntoBranch = await this.getLocalBranchByUpstream(repoPath, into.name, cancellation);
606
- // If there is a local branch and it is not the branch we are checking, check if it has been merged into it
607
- if (localIntoBranch != null && localIntoBranch.name !== branch.name) {
608
- const result = await this.getBranchMergedStatusCore(repoPath, branch, localIntoBranch, cancellation);
609
- if (result.merged) {
610
- return {
611
- ...result,
612
- localBranchOnly: createReference(localIntoBranch.ref, localIntoBranch.repoPath, {
613
- id: localIntoBranch.id,
614
- refType: 'branch',
615
- name: localIntoBranch.name,
616
- remote: localIntoBranch.remote,
617
- upstream: localIntoBranch.upstream,
618
- sha: localIntoBranch.sha,
619
- }),
620
- };
640
+ // Cache key omits repoPath so worktrees of the same common repo share the cached answer.
641
+ // Branch refs (`refs/heads/*` / `refs/remotes/*`) are unique within a common repo, so
642
+ // `name` + `remote` flag is the minimal stable identity.
643
+ const cacheKey = `${branch.remote ? 'r' : 'l'}:${branch.name}|${into.remote ? 'r' : 'l'}:${into.name}`;
644
+ return this.cache.getBranchMergedStatus(repoPath, cacheKey, async (commonPath, _cacheable, signal) => {
645
+ const result = await this.getBranchMergedStatusCore(commonPath, branch, into, signal);
646
+ if (result.merged)
647
+ return result;
648
+ // If the branch we are checking is a remote branch, check if it has been merged into its local branch (if there is one)
649
+ if (into.remote) {
650
+ const localIntoBranch = await this.getLocalBranchByUpstream(commonPath, into.name, signal);
651
+ // If there is a local branch and it is not the branch we are checking, check if it has been merged into it
652
+ if (localIntoBranch != null && localIntoBranch.name !== branch.name) {
653
+ // Skip the second full merge-check cycle when the local branch points at the same commit as the remote —
654
+ // the merge-base/cherry/diff/apply pipeline would produce the same answer we already got for `into` above
655
+ if (localIntoBranch.sha != null && localIntoBranch.sha === into.sha) {
656
+ return { merged: false };
657
+ }
658
+ const result = await this.getBranchMergedStatusCore(commonPath, branch, localIntoBranch, signal);
659
+ if (result.merged) {
660
+ // `localBranchOnly` is built against `commonPath` here; the cache mapper rewrites
661
+ // `repoPath`/`id` to the requesting worktree on retrieval.
662
+ return {
663
+ ...result,
664
+ localBranchOnly: createReference(localIntoBranch.ref, localIntoBranch.repoPath, {
665
+ id: localIntoBranch.id,
666
+ refType: 'branch',
667
+ name: localIntoBranch.name,
668
+ remote: localIntoBranch.remote,
669
+ upstream: localIntoBranch.upstream,
670
+ sha: localIntoBranch.sha,
671
+ }),
672
+ };
673
+ }
621
674
  }
622
675
  }
623
- }
624
- return { merged: false };
676
+ return { merged: false };
677
+ }, cancellation);
625
678
  }
626
679
  async getBranchMergedStatusCore(repoPath, branch, into, cancellation) {
627
680
  const scope = getScopedLogger();
628
681
  try {
629
682
  // Check if branch is direct ancestor (handles FF merges)
630
683
  try {
631
- await this.git.exec({ cwd: repoPath, cancellation: cancellation, errors: 'throw' }, 'merge-base', '--is-ancestor', branch.name, into.name);
684
+ await this.git.run({ cwd: repoPath, cancellation: cancellation, errors: 'throw' }, 'merge-base', '--is-ancestor', branch.name, into.name);
632
685
  return { merged: true, confidence: 'highest' };
633
686
  }
634
687
  catch (ex) {
@@ -636,7 +689,7 @@ export class BranchesGitSubProvider {
636
689
  throw ex;
637
690
  }
638
691
  // Cherry-pick detection (handles cherry-picks, rebases, etc)
639
- let result = await this.git.exec({ cwd: repoPath, cancellation: cancellation }, 'cherry', '--abbrev', '-v', into.name, branch.name);
692
+ let result = await this.git.run({ cwd: repoPath, cancellation: cancellation }, 'cherry', '--abbrev', '-v', into.name, branch.name);
640
693
  // Check if there are no lines or all lines startwith a `-` (i.e. likely merged)
641
694
  if (!result.stdout ||
642
695
  result.stdout
@@ -647,14 +700,14 @@ export class BranchesGitSubProvider {
647
700
  }
648
701
  // Attempt to detect squash merges by checking if the diff of the branch can be cleanly removed from the target
649
702
  const mergeBase = await this.provider.refs.getMergeBase(repoPath, into.name, branch.name, undefined, cancellation);
650
- result = await this.git.exec({ cwd: repoPath, cancellation: cancellation }, 'diff', mergeBase, branch.name);
703
+ result = await this.git.run({ cwd: repoPath, cancellation: cancellation }, 'diff', mergeBase, branch.name);
651
704
  if (result.stdout) {
652
705
  const env_2 = { stack: [], error: void 0, hasError: false };
653
706
  try {
654
707
  // Create a temporary index file
655
708
  const disposableIndex = __addDisposableResource(env_2, await this.provider.staging.createTemporaryIndex(repoPath, 'ref', into.name), true);
656
709
  const { env } = disposableIndex;
657
- result = await this.git.exec({
710
+ result = await this.git.run({
658
711
  cwd: repoPath,
659
712
  cancellation: cancellation,
660
713
  env: env,
@@ -700,7 +753,7 @@ export class BranchesGitSubProvider {
700
753
  const parentRefs = shas.map(c => `${c}^`);
701
754
  let parentShas;
702
755
  try {
703
- const result = await this.git.exec({ cwd: repoPath, cancellation: signal, errors: 'throw' }, 'rev-parse', ...parentRefs);
756
+ const result = await this.git.run({ cwd: repoPath, cancellation: signal, errors: 'throw' }, 'rev-parse', ...parentRefs);
704
757
  parentShas = result.stdout.trim().split('\n');
705
758
  }
706
759
  catch (ex) {
@@ -727,7 +780,7 @@ export class BranchesGitSubProvider {
727
780
  }
728
781
  let data;
729
782
  try {
730
- const result = await this.git.exec({ cwd: repoPath, cancellation: signal, errors: 'throw' }, 'merge-tree', '-z', '--name-only', '--no-messages', branch, targetBranch);
783
+ const result = await this.git.run({ cwd: repoPath, cancellation: signal, errors: 'throw' }, 'merge-tree', '-z', '--name-only', '--no-messages', branch, targetBranch);
731
784
  data = result.stdout;
732
785
  }
733
786
  catch (ex) {
@@ -780,7 +833,7 @@ export class BranchesGitSubProvider {
780
833
  let currentTreeOid;
781
834
  try {
782
835
  // Get the initial target branch tree OID
783
- const treeResult = await this.git.exec({ cwd: repoPath, cancellation: cancellation, errors: 'throw' }, 'rev-parse', `${targetBranch}^{tree}`);
836
+ const treeResult = await this.git.run({ cwd: repoPath, cancellation: cancellation, errors: 'throw' }, 'rev-parse', `${targetBranch}^{tree}`);
784
837
  currentTreeOid = treeResult.stdout.trim();
785
838
  }
786
839
  catch (ex) {
@@ -802,7 +855,7 @@ export class BranchesGitSubProvider {
802
855
  // - base = commit.parent (where the commit started)
803
856
  // - ours = currentTreeOid (current state of the target)
804
857
  // - theirs = commit.sha (what we're cherry-picking)
805
- const result = await this.git.exec({ cwd: repoPath, cancellation: cancellation, errors: 'throw' }, 'merge-tree', '--write-tree', '-z', '--name-only', '--no-messages', `--merge-base=${commit.parent}`, currentTreeOid, commit.sha);
858
+ const result = await this.git.run({ cwd: repoPath, cancellation: cancellation, errors: 'throw' }, 'merge-tree', '--write-tree', '-z', '--name-only', '--no-messages', `--merge-base=${commit.parent}`, currentTreeOid, commit.sha);
806
859
  data = result.stdout;
807
860
  }
808
861
  catch (ex) {
@@ -872,37 +925,51 @@ export class BranchesGitSubProvider {
872
925
  }
873
926
  return { status: 'clean' };
874
927
  }
875
- async getBaseBranchName(repoPath, ref, cancellation) {
876
- try {
877
- // getGkConfig has built-in fallback to regular config for backward compatibility
878
- let mergeBase = await this.provider.config.getGkConfig(repoPath, `branch.${ref}.gk-merge-base`);
879
- let update = false;
880
- // Also check vscode-merge-base in regular config (VS Code compatibility)
881
- if (mergeBase == null) {
882
- mergeBase = await this.provider.config.getConfig(repoPath, `branch.${ref}.vscode-merge-base`);
883
- update = mergeBase != null;
884
- }
885
- if (mergeBase != null) {
886
- const branch = await this.provider.refs.getSymbolicReferenceName(repoPath, mergeBase);
887
- if (branch != null) {
888
- if (update) {
889
- void this.storeBaseBranchName(repoPath, ref, branch);
928
+ getBaseBranchName(repoPath, ref, options, cancellation) {
929
+ const priority = options?.priority;
930
+ const priorityOpts = priority != null ? { priority: priority } : undefined;
931
+ return this.cache.getBaseBranchName(repoPath, ref, async (commonPath, signal) => {
932
+ try {
933
+ // getGkConfig has built-in fallback to regular config for backward compatibility
934
+ let mergeBase = await this.provider.config.getGkConfig(commonPath, `branch.${ref}.gk-merge-base`);
935
+ let update = false;
936
+ // Also check vscode-merge-base in regular config (VS Code compatibility)
937
+ if (mergeBase == null) {
938
+ mergeBase = await this.provider.config.getConfig(commonPath, `branch.${ref}.vscode-merge-base`);
939
+ update = mergeBase != null;
940
+ }
941
+ if (mergeBase != null) {
942
+ const branch = await this.provider.refs.getSymbolicReferenceName(commonPath, mergeBase, priorityOpts);
943
+ if (branch != null) {
944
+ if (update) {
945
+ // Self-write: the value we're storing is exactly what this factory is
946
+ // returning, so any in-flight `branchOverviews` or `baseBranchName` entry
947
+ // being populated against this resolution should NOT be evicted.
948
+ void this.storeBaseBranchName(commonPath, ref, branch, {
949
+ skipInvalidation: ['branchOverviews', 'baseBranchName'],
950
+ });
951
+ }
952
+ return branch;
890
953
  }
891
- return branch;
892
954
  }
893
955
  }
894
- }
895
- catch { }
896
- const branch = await this.getBaseBranchFromReflog(repoPath, ref, { upstream: true }, cancellation);
897
- if (branch != null) {
898
- void this.storeBaseBranchName(repoPath, ref, branch);
899
- return branch;
900
- }
901
- return undefined;
956
+ catch { }
957
+ const branch = await this.getBaseBranchFromReflog(commonPath, ref, { upstream: true, priority: priority }, signal);
958
+ if (branch != null) {
959
+ // Self-write: see comment on the migration path above.
960
+ void this.storeBaseBranchName(commonPath, ref, branch, {
961
+ skipInvalidation: ['branchOverviews', 'baseBranchName'],
962
+ });
963
+ return branch;
964
+ }
965
+ return undefined;
966
+ }, cancellation);
902
967
  }
903
968
  async getBaseBranchFromReflog(repoPath, ref, options, cancellation) {
969
+ const priority = options?.priority;
970
+ const priorityOpts = priority != null ? { priority: priority } : undefined;
904
971
  try {
905
- let result = await this.git.exec({ cwd: repoPath, cancellation: cancellation }, 'reflog', ref, '--grep-reflog=branch: Created from *.');
972
+ let result = await this.git.run({ cwd: repoPath, cancellation: cancellation, ...priorityOpts }, 'reflog', ref, '--grep-reflog=branch: Created from *.');
906
973
  let entries = result.stdout.split('\n').filter(entry => Boolean(entry));
907
974
  if (entries.length !== 1)
908
975
  return undefined;
@@ -912,17 +979,17 @@ export class BranchesGitSubProvider {
912
979
  let name = match[1];
913
980
  if (name !== 'HEAD') {
914
981
  if (options?.upstream) {
915
- const upstream = await this.provider.refs.getSymbolicReferenceName(repoPath, `${name}@{u}`);
982
+ const upstream = await this.provider.refs.getSymbolicReferenceName(repoPath, `${name}@{u}`, priorityOpts);
916
983
  if (upstream)
917
984
  return upstream;
918
985
  }
919
- name = await this.provider.refs.getSymbolicReferenceName(repoPath, name);
986
+ name = await this.provider.refs.getSymbolicReferenceName(repoPath, name, priorityOpts);
920
987
  if (name)
921
988
  return name;
922
989
  }
923
990
  }
924
991
  // Check if branch was created from HEAD
925
- result = await this.git.exec({ cwd: repoPath, cancellation: cancellation }, 'reflog', 'HEAD', `--grep-reflog=checkout: moving from .* to ${ref.replace('refs/heads/', '')}`);
992
+ result = await this.git.run({ cwd: repoPath, cancellation: cancellation, ...priorityOpts }, 'reflog', 'HEAD', `--grep-reflog=checkout: moving from .* to ${ref.replace('refs/heads/', '')}`);
926
993
  entries = result.stdout.split('\n').filter(entry => Boolean(entry));
927
994
  if (!entries.length)
928
995
  return undefined;
@@ -930,11 +997,11 @@ export class BranchesGitSubProvider {
930
997
  if (match?.length === 2) {
931
998
  let name = match[1];
932
999
  if (options?.upstream) {
933
- const upstream = await this.provider.refs.getSymbolicReferenceName(repoPath, `${name}@{u}`);
1000
+ const upstream = await this.provider.refs.getSymbolicReferenceName(repoPath, `${name}@{u}`, priorityOpts);
934
1001
  if (upstream)
935
1002
  return upstream;
936
1003
  }
937
- name = await this.provider.refs.getSymbolicReferenceName(repoPath, name);
1004
+ name = await this.provider.refs.getSymbolicReferenceName(repoPath, name, priorityOpts);
938
1005
  if (name)
939
1006
  return name;
940
1007
  }
@@ -975,10 +1042,17 @@ export class BranchesGitSubProvider {
975
1042
  await this.storeBranchMetadata(repoPath, 'gk-last-accessed', branch.name, now);
976
1043
  await this.storeBranchMetadata(repoPath, 'gk-last-modified', branch.name, now);
977
1044
  }
1045
+ /** Updates the agent last activity timestamp for the current branch */
1046
+ async onCurrentBranchAgentActivity(repoPath) {
1047
+ const branch = await this.getBranch(repoPath);
1048
+ if (branch == null || branch.remote || branch.detached)
1049
+ return;
1050
+ await this.storeBranchMetadata(repoPath, 'gk-agent-last-activity', branch.name, new Date());
1051
+ }
978
1052
  async renameBranch(repoPath, oldName, newName) {
979
1053
  const args = ['branch', '-m', oldName, newName];
980
1054
  try {
981
- await this.git.exec({ cwd: repoPath }, ...args);
1055
+ await this.git.run({ cwd: repoPath }, ...args);
982
1056
  this.context.hooks?.cache?.onReset?.(repoPath, 'branches');
983
1057
  this.context.hooks?.repository?.onChanged?.(repoPath, ['heads']);
984
1058
  }
@@ -994,7 +1068,7 @@ export class BranchesGitSubProvider {
994
1068
  async setUpstreamBranch(repoPath, name, upstream) {
995
1069
  const args = upstream == null ? ['branch', '--unset-upstream', name] : ['branch', '--set-upstream-to', upstream, name];
996
1070
  try {
997
- await this.git.exec({ cwd: repoPath }, ...args);
1071
+ await this.git.run({ cwd: repoPath }, ...args);
998
1072
  this.context.hooks?.cache?.onReset?.(repoPath, 'branches');
999
1073
  this.context.hooks?.repository?.onChanged?.(repoPath, ['heads']);
1000
1074
  }
@@ -1007,11 +1081,11 @@ export class BranchesGitSubProvider {
1007
1081
  }, ex));
1008
1082
  }
1009
1083
  }
1010
- async storeBaseBranchName(repoPath, ref, base) {
1011
- await this.provider.config.setGkConfig(repoPath, `branch.${ref}.gk-merge-base`, base);
1084
+ async storeBaseBranchName(repoPath, ref, base, options) {
1085
+ await this.provider.config.setGkConfig(repoPath, `branch.${ref}.gk-merge-base`, base, options);
1012
1086
  }
1013
- async storeMergeTargetBranchName(repoPath, ref, target) {
1014
- await this.provider.config.setGkConfig(repoPath, `branch.${ref}.gk-merge-target`, target);
1087
+ async storeMergeTargetBranchName(repoPath, ref, target, options) {
1088
+ await this.provider.config.setGkConfig(repoPath, `branch.${ref}.gk-merge-target`, target, options);
1015
1089
  }
1016
1090
  async storeUserMergeTargetBranchName(repoPath, ref, target) {
1017
1091
  await this.provider.config.setGkConfig(repoPath, `branch.${ref}.gk-merge-target-user`, target);
@@ -1020,47 +1094,52 @@ export class BranchesGitSubProvider {
1020
1094
  * Gets all branch metadata (dates and disposition) from git config in a single batch operation.
1021
1095
  * @returns A map of branch name to metadata.
1022
1096
  */
1023
- async getBranchMetadataMap(repoPath) {
1024
- const scope = getScopedLogger();
1025
- const metadataMap = new Map();
1026
- try {
1027
- // Use git config --get-regexp to load all gk-* branch metadata in one call
1028
- const configMap = await this.provider.config.getGkConfigRegex(repoPath, '^branch\\..*\\.gk-(last-(accessed|modified)|disposition)$');
1029
- if (!configMap.size)
1030
- return metadataMap;
1031
- for (const [key, value] of configMap) {
1032
- // Extract branch name and metadata key from "branch.{name}.gk-{key}"
1033
- if (!key.startsWith('branch.'))
1034
- continue;
1035
- const keyParts = key.split('.');
1036
- if (keyParts.length < 3)
1037
- continue;
1038
- // Branch name is everything between "branch." and the last ".gk-*"
1039
- const metaKey = keyParts.at(-1);
1040
- const branchName = keyParts.slice(1, -1).join('.');
1041
- let metadata = metadataMap.get(branchName);
1042
- if (metadata == null) {
1043
- metadata = {};
1044
- metadataMap.set(branchName, metadata);
1045
- }
1046
- if (metaKey === 'gk-last-accessed') {
1047
- metadata.lastAccessedAt = value;
1048
- }
1049
- else if (metaKey === 'gk-last-modified') {
1050
- metadata.lastModifiedAt = value;
1051
- }
1052
- else if (metaKey === 'gk-disposition') {
1053
- if (value === 'starred' || value === 'archived') {
1054
- metadata.disposition = value;
1097
+ getBranchMetadataMap(repoPath) {
1098
+ return this.cache.getBranchMetadataMap(repoPath, async (commonPath) => {
1099
+ const scope = getScopedLogger();
1100
+ const metadataMap = new Map();
1101
+ try {
1102
+ // Use git config --get-regexp to load all gk-* branch metadata in one call
1103
+ const configMap = await this.provider.config.getGkConfigRegex(commonPath, '^branch\\..*\\.gk-(last-(accessed|modified)|disposition|agent-last-activity)$');
1104
+ if (!configMap.size)
1105
+ return metadataMap;
1106
+ for (const [key, value] of configMap) {
1107
+ // Extract branch name and metadata key from "branch.{name}.gk-{key}"
1108
+ if (!key.startsWith('branch.'))
1109
+ continue;
1110
+ const keyParts = key.split('.');
1111
+ if (keyParts.length < 3)
1112
+ continue;
1113
+ // Branch name is everything between "branch." and the last ".gk-*"
1114
+ const metaKey = keyParts.at(-1);
1115
+ const branchName = keyParts.slice(1, -1).join('.');
1116
+ let metadata = metadataMap.get(branchName);
1117
+ if (metadata == null) {
1118
+ metadata = {};
1119
+ metadataMap.set(branchName, metadata);
1120
+ }
1121
+ if (metaKey === 'gk-last-accessed') {
1122
+ metadata.lastAccessedAt = value;
1123
+ }
1124
+ else if (metaKey === 'gk-last-modified') {
1125
+ metadata.lastModifiedAt = value;
1126
+ }
1127
+ else if (metaKey === 'gk-agent-last-activity') {
1128
+ metadata.agentLastActivityAt = value;
1129
+ }
1130
+ else if (metaKey === 'gk-disposition') {
1131
+ if (value === 'starred' || value === 'archived') {
1132
+ metadata.disposition = value;
1133
+ }
1055
1134
  }
1056
1135
  }
1057
1136
  }
1058
- }
1059
- catch (ex) {
1060
- debugger;
1061
- scope?.error(ex);
1062
- }
1063
- return metadataMap;
1137
+ catch (ex) {
1138
+ debugger;
1139
+ scope?.error(ex);
1140
+ }
1141
+ return metadataMap;
1142
+ });
1064
1143
  }
1065
1144
  async storeBranchMetadata(repoPath, key, ref, date) {
1066
1145
  const value = await this.provider.config.getGkConfig(repoPath, `branch.${ref}.${key}`);
@@ -1135,6 +1214,10 @@ __decorate([
1135
1214
  debounce(2.5 * 60 * 1000),
1136
1215
  debug()
1137
1216
  ], BranchesGitSubProvider.prototype, "onCurrentBranchModified", null);
1217
+ __decorate([
1218
+ debounce(2.5 * 60 * 1000),
1219
+ debug()
1220
+ ], BranchesGitSubProvider.prototype, "onCurrentBranchAgentActivity", null);
1138
1221
  __decorate([
1139
1222
  debug()
1140
1223
  ], BranchesGitSubProvider.prototype, "renameBranch", null);