@gitkraken/core-gitlens 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (448) hide show
  1. package/CHANGELOG.md +11 -1
  2. package/dist/git/cache.d.ts +38 -8
  3. package/dist/git/cache.d.ts.map +1 -1
  4. package/dist/git/cache.js +120 -55
  5. package/dist/git/cache.js.map +1 -1
  6. package/dist/git/context.d.ts +19 -0
  7. package/dist/git/context.d.ts.map +1 -1
  8. package/dist/git/context.js.map +1 -1
  9. package/dist/git/features.d.ts +1 -1
  10. package/dist/git/features.d.ts.map +1 -1
  11. package/dist/git/features.js +1 -0
  12. package/dist/git/features.js.map +1 -1
  13. package/dist/git/models/commit.d.ts.map +1 -1
  14. package/dist/git/models/commit.js.map +1 -1
  15. package/dist/git/models/graph.d.ts +96 -0
  16. package/dist/git/models/graph.d.ts.map +1 -1
  17. package/dist/git/models/graph.js +24 -1
  18. package/dist/git/models/graph.js.map +1 -1
  19. package/dist/git/models/reference.d.ts +31 -0
  20. package/dist/git/models/reference.d.ts.map +1 -1
  21. package/dist/git/models/remote.d.ts.map +1 -1
  22. package/dist/git/models/remote.js.map +1 -1
  23. package/dist/git/models/remoteProvider.d.ts +1 -0
  24. package/dist/git/models/remoteProvider.d.ts.map +1 -1
  25. package/dist/git/models/remoteProvider.js.map +1 -1
  26. package/dist/git/models/repository.d.ts +30 -13
  27. package/dist/git/models/repository.d.ts.map +1 -1
  28. package/dist/git/models/repository.js +89 -87
  29. package/dist/git/models/repository.js.map +1 -1
  30. package/dist/git/models/search.d.ts +2 -2
  31. package/dist/git/models/search.d.ts.map +1 -1
  32. package/dist/git/models/statusFile.d.ts +9 -0
  33. package/dist/git/models/statusFile.d.ts.map +1 -1
  34. package/dist/git/models/statusFile.js +11 -0
  35. package/dist/git/models/statusFile.js.map +1 -1
  36. package/dist/git/models/worktree.d.ts +4 -1
  37. package/dist/git/models/worktree.d.ts.map +1 -1
  38. package/dist/git/models/worktree.js +2 -2
  39. package/dist/git/models/worktree.js.map +1 -1
  40. package/dist/git/parsers/diffParser.d.ts.map +1 -1
  41. package/dist/git/parsers/diffParser.js.map +1 -1
  42. package/dist/git/providers/branches.d.ts +15 -4
  43. package/dist/git/providers/branches.d.ts.map +1 -1
  44. package/dist/git/providers/commits.d.ts +4 -0
  45. package/dist/git/providers/commits.d.ts.map +1 -1
  46. package/dist/git/providers/config.d.ts +5 -4
  47. package/dist/git/providers/config.d.ts.map +1 -1
  48. package/dist/git/providers/operations.d.ts +61 -12
  49. package/dist/git/providers/operations.d.ts.map +1 -1
  50. package/dist/git/providers/pausedOperations.d.ts +3 -1
  51. package/dist/git/providers/pausedOperations.d.ts.map +1 -1
  52. package/dist/git/providers/refs.d.ts +23 -2
  53. package/dist/git/providers/refs.d.ts.map +1 -1
  54. package/dist/git/providers/staging.d.ts +16 -0
  55. package/dist/git/providers/staging.d.ts.map +1 -1
  56. package/dist/git/providers/status.d.ts +4 -1
  57. package/dist/git/providers/status.d.ts.map +1 -1
  58. package/dist/git/remotes/azure-devops.d.ts.map +1 -1
  59. package/dist/git/remotes/azure-devops.js.map +1 -1
  60. package/dist/git/remotes/custom.d.ts +2 -0
  61. package/dist/git/remotes/custom.d.ts.map +1 -1
  62. package/dist/git/remotes/custom.js +20 -0
  63. package/dist/git/remotes/custom.js.map +1 -1
  64. package/dist/git/{exec.types.d.ts → run.types.d.ts} +22 -3
  65. package/dist/git/run.types.d.ts.map +1 -0
  66. package/dist/git/run.types.js +2 -0
  67. package/dist/git/run.types.js.map +1 -0
  68. package/dist/git/service.d.ts.map +1 -1
  69. package/dist/git/service.js.map +1 -1
  70. package/dist/git/utils/autolink.utils.d.ts.map +1 -1
  71. package/dist/git/utils/autolink.utils.js.map +1 -1
  72. package/dist/git/utils/blame.utils.d.ts.map +1 -1
  73. package/dist/git/utils/blame.utils.js.map +1 -1
  74. package/dist/git/utils/conflictResolution.utils.d.ts +6 -0
  75. package/dist/git/utils/conflictResolution.utils.d.ts.map +1 -0
  76. package/dist/git/utils/conflictResolution.utils.js +25 -0
  77. package/dist/git/utils/conflictResolution.utils.js.map +1 -0
  78. package/dist/git/utils/contributor.utils.d.ts +3 -0
  79. package/dist/git/utils/contributor.utils.d.ts.map +1 -1
  80. package/dist/git/utils/contributor.utils.js +22 -0
  81. package/dist/git/utils/contributor.utils.js.map +1 -1
  82. package/dist/git/utils/fileStatus.utils.d.ts +2 -1
  83. package/dist/git/utils/fileStatus.utils.d.ts.map +1 -1
  84. package/dist/git/utils/fileStatus.utils.js +4 -0
  85. package/dist/git/utils/fileStatus.utils.js.map +1 -1
  86. package/dist/git/utils/reachability.utils.d.ts +37 -0
  87. package/dist/git/utils/reachability.utils.d.ts.map +1 -0
  88. package/dist/git/utils/reachability.utils.js +96 -0
  89. package/dist/git/utils/reachability.utils.js.map +1 -0
  90. package/dist/git/utils/search.utils.d.ts.map +1 -1
  91. package/dist/git/utils/search.utils.js +3 -0
  92. package/dist/git/utils/search.utils.js.map +1 -1
  93. package/dist/git/utils/sorting.d.ts +8 -0
  94. package/dist/git/utils/sorting.d.ts.map +1 -1
  95. package/dist/git/utils/sorting.js +15 -0
  96. package/dist/git/utils/sorting.js.map +1 -1
  97. package/dist/git/utils/status.utils.d.ts.map +1 -1
  98. package/dist/git/utils/status.utils.js.map +1 -1
  99. package/dist/git/watching/classifyChange.d.ts.map +1 -1
  100. package/dist/git/watching/classifyChange.js +8 -0
  101. package/dist/git/watching/classifyChange.js.map +1 -1
  102. package/dist/git/watching/gitIgnoreFilter.js +1 -1
  103. package/dist/git/watching/gitIgnoreFilter.js.map +1 -1
  104. package/dist/git/watching/initWatcher.d.ts.map +1 -1
  105. package/dist/git/watching/initWatcher.js.map +1 -1
  106. package/dist/git/watching/watchGroup.d.ts.map +1 -1
  107. package/dist/git/watching/watchGroup.js.map +1 -1
  108. package/dist/git/watching/watchService.d.ts +4 -2
  109. package/dist/git/watching/watchService.d.ts.map +1 -1
  110. package/dist/git/watching/watchService.js +31 -6
  111. package/dist/git/watching/watchService.js.map +1 -1
  112. package/dist/git/watching/watchSession.d.ts +14 -12
  113. package/dist/git/watching/watchSession.d.ts.map +1 -1
  114. package/dist/git/watching/watchSession.js +56 -55
  115. package/dist/git/watching/watchSession.js.map +1 -1
  116. package/dist/git-cli/exec/exec.types.d.ts +1 -1
  117. package/dist/git-cli/exec/exec.types.d.ts.map +1 -1
  118. package/dist/git-cli/exec/git.d.ts +3 -3
  119. package/dist/git-cli/exec/git.d.ts.map +1 -1
  120. package/dist/git-cli/exec/git.js.map +1 -1
  121. package/dist/git-cli/exec/gitQueue.d.ts +10 -2
  122. package/dist/git-cli/exec/gitQueue.d.ts.map +1 -1
  123. package/dist/git-cli/exec/gitQueue.js +39 -12
  124. package/dist/git-cli/exec/gitQueue.js.map +1 -1
  125. package/dist/git-cli/parsers/blameParser.d.ts.map +1 -1
  126. package/dist/git-cli/parsers/blameParser.js.map +1 -1
  127. package/dist/git-cli/parsers/logParser.js.map +1 -1
  128. package/dist/git-cli/parsers/refParser.d.ts +3 -30
  129. package/dist/git-cli/parsers/refParser.d.ts.map +1 -1
  130. package/dist/git-cli/parsers/refParser.js +30 -30
  131. package/dist/git-cli/parsers/refParser.js.map +1 -1
  132. package/dist/git-cli/providers/blame.d.ts.map +1 -1
  133. package/dist/git-cli/providers/blame.js.map +1 -1
  134. package/dist/git-cli/providers/branches.d.ts +15 -5
  135. package/dist/git-cli/providers/branches.d.ts.map +1 -1
  136. package/dist/git-cli/providers/branches.js +99 -68
  137. package/dist/git-cli/providers/branches.js.map +1 -1
  138. package/dist/git-cli/providers/commits.d.ts +1 -0
  139. package/dist/git-cli/providers/commits.d.ts.map +1 -1
  140. package/dist/git-cli/providers/commits.js +86 -30
  141. package/dist/git-cli/providers/commits.js.map +1 -1
  142. package/dist/git-cli/providers/config.d.ts +19 -6
  143. package/dist/git-cli/providers/config.d.ts.map +1 -1
  144. package/dist/git-cli/providers/config.js +86 -38
  145. package/dist/git-cli/providers/config.js.map +1 -1
  146. package/dist/git-cli/providers/diff.d.ts.map +1 -1
  147. package/dist/git-cli/providers/diff.js +5 -3
  148. package/dist/git-cli/providers/diff.js.map +1 -1
  149. package/dist/git-cli/providers/graph.d.ts.map +1 -1
  150. package/dist/git-cli/providers/graph.js +139 -16
  151. package/dist/git-cli/providers/graph.js.map +1 -1
  152. package/dist/git-cli/providers/operations.d.ts +17 -14
  153. package/dist/git-cli/providers/operations.d.ts.map +1 -1
  154. package/dist/git-cli/providers/operations.js +135 -63
  155. package/dist/git-cli/providers/operations.js.map +1 -1
  156. package/dist/git-cli/providers/patch.d.ts.map +1 -1
  157. package/dist/git-cli/providers/patch.js.map +1 -1
  158. package/dist/git-cli/providers/pausedOperations.d.ts +3 -1
  159. package/dist/git-cli/providers/pausedOperations.d.ts.map +1 -1
  160. package/dist/git-cli/providers/pausedOperations.js +7 -1
  161. package/dist/git-cli/providers/pausedOperations.js.map +1 -1
  162. package/dist/git-cli/providers/refs.d.ts +19 -2
  163. package/dist/git-cli/providers/refs.d.ts.map +1 -1
  164. package/dist/git-cli/providers/refs.js +286 -2
  165. package/dist/git-cli/providers/refs.js.map +1 -1
  166. package/dist/git-cli/providers/revision.js.map +1 -1
  167. package/dist/git-cli/providers/staging.d.ts +6 -0
  168. package/dist/git-cli/providers/staging.d.ts.map +1 -1
  169. package/dist/git-cli/providers/staging.js +32 -0
  170. package/dist/git-cli/providers/staging.js.map +1 -1
  171. package/dist/git-cli/providers/stash.d.ts.map +1 -1
  172. package/dist/git-cli/providers/stash.js +20 -2
  173. package/dist/git-cli/providers/stash.js.map +1 -1
  174. package/dist/git-cli/providers/status.d.ts +4 -1
  175. package/dist/git-cli/providers/status.d.ts.map +1 -1
  176. package/dist/git-cli/providers/status.js +8 -4
  177. package/dist/git-cli/providers/status.js.map +1 -1
  178. package/dist/git-cli/providers/tags.d.ts.map +1 -1
  179. package/dist/git-cli/providers/tags.js +10 -6
  180. package/dist/git-cli/providers/tags.js.map +1 -1
  181. package/dist/ipc/discovery.d.ts +49 -0
  182. package/dist/ipc/discovery.d.ts.map +1 -0
  183. package/dist/ipc/discovery.js +147 -0
  184. package/dist/ipc/discovery.js.map +1 -0
  185. package/dist/ipc/ipcServer.d.ts +20 -0
  186. package/dist/ipc/ipcServer.d.ts.map +1 -0
  187. package/dist/ipc/ipcServer.js +162 -0
  188. package/dist/ipc/ipcServer.js.map +1 -0
  189. package/dist/plus/agents/providers/claudeCodeProvider.d.ts +167 -0
  190. package/dist/plus/agents/providers/claudeCodeProvider.d.ts.map +1 -0
  191. package/dist/plus/agents/providers/claudeCodeProvider.js +1786 -0
  192. package/dist/plus/agents/providers/claudeCodeProvider.js.map +1 -0
  193. package/dist/plus/agents/providers/claudeCodeTranscript.d.ts +36 -0
  194. package/dist/plus/agents/providers/claudeCodeTranscript.d.ts.map +1 -0
  195. package/dist/plus/agents/providers/claudeCodeTranscript.js +171 -0
  196. package/dist/plus/agents/providers/claudeCodeTranscript.js.map +1 -0
  197. package/dist/plus/agents/sanitizePrompt.d.ts +15 -0
  198. package/dist/plus/agents/sanitizePrompt.d.ts.map +1 -0
  199. package/dist/plus/agents/sanitizePrompt.js +103 -0
  200. package/dist/plus/agents/sanitizePrompt.js.map +1 -0
  201. package/dist/plus/agents/stateMachine.d.ts +32 -0
  202. package/dist/plus/agents/stateMachine.d.ts.map +1 -0
  203. package/dist/plus/agents/stateMachine.js +180 -0
  204. package/dist/plus/agents/stateMachine.js.map +1 -0
  205. package/dist/plus/agents/types.d.ts +254 -0
  206. package/dist/plus/agents/types.d.ts.map +1 -0
  207. package/dist/plus/agents/types.js +49 -0
  208. package/dist/plus/agents/types.js.map +1 -0
  209. package/dist/plus/ai/errors.d.ts +4 -1
  210. package/dist/plus/ai/errors.d.ts.map +1 -1
  211. package/dist/plus/ai/errors.js +38 -0
  212. package/dist/plus/ai/errors.js.map +1 -1
  213. package/dist/plus/ai/models/model.d.ts +1 -1
  214. package/dist/plus/ai/models/model.d.ts.map +1 -1
  215. package/dist/plus/ai/models/model.js.map +1 -1
  216. package/dist/plus/ai/models/promptTemplates.d.ts +11 -2
  217. package/dist/plus/ai/models/promptTemplates.d.ts.map +1 -1
  218. package/dist/plus/ai/models/provider.d.ts +3 -0
  219. package/dist/plus/ai/models/provider.d.ts.map +1 -1
  220. package/dist/plus/ai/prompts.d.ts +1 -0
  221. package/dist/plus/ai/prompts.d.ts.map +1 -1
  222. package/dist/plus/ai/prompts.js +48 -8
  223. package/dist/plus/ai/prompts.js.map +1 -1
  224. package/dist/plus/ai/providers/gitkrakenProvider.d.ts +1 -1
  225. package/dist/plus/ai/providers/gitkrakenProvider.d.ts.map +1 -1
  226. package/dist/plus/ai/providers/gitkrakenProvider.js +4 -1
  227. package/dist/plus/ai/providers/gitkrakenProvider.js.map +1 -1
  228. package/dist/plus/ai/providers/openAICompatibleProviderBase.d.ts +4 -3
  229. package/dist/plus/ai/providers/openAICompatibleProviderBase.d.ts.map +1 -1
  230. package/dist/plus/ai/providers/openAICompatibleProviderBase.js +9 -6
  231. package/dist/plus/ai/providers/openAICompatibleProviderBase.js.map +1 -1
  232. package/dist/plus/ai/utils/ai.utils.d.ts.map +1 -1
  233. package/dist/plus/ai/utils/ai.utils.js +2 -0
  234. package/dist/plus/ai/utils/ai.utils.js.map +1 -1
  235. package/dist/plus/ai/utils/results.utils.d.ts.map +1 -1
  236. package/dist/plus/ai/utils/results.utils.js.map +1 -1
  237. package/dist/plus/git-github/api/github.d.ts +12 -1
  238. package/dist/plus/git-github/api/github.d.ts.map +1 -1
  239. package/dist/plus/git-github/api/github.js +245 -51
  240. package/dist/plus/git-github/api/github.js.map +1 -1
  241. package/dist/plus/git-github/api/types.d.ts +8 -0
  242. package/dist/plus/git-github/api/types.d.ts.map +1 -1
  243. package/dist/plus/git-github/models.d.ts +1 -1
  244. package/dist/plus/git-github/models.d.ts.map +1 -1
  245. package/dist/plus/git-github/models.js.map +1 -1
  246. package/dist/plus/git-github/providers/github/blame.d.ts.map +1 -1
  247. package/dist/plus/git-github/providers/github/blame.js.map +1 -1
  248. package/dist/plus/git-github/providers/github/branches.d.ts +5 -1
  249. package/dist/plus/git-github/providers/github/branches.d.ts.map +1 -1
  250. package/dist/plus/git-github/providers/github/branches.js +47 -24
  251. package/dist/plus/git-github/providers/github/branches.js.map +1 -1
  252. package/dist/plus/git-github/providers/github/commits.d.ts.map +1 -1
  253. package/dist/plus/git-github/providers/github/commits.js +144 -92
  254. package/dist/plus/git-github/providers/github/commits.js.map +1 -1
  255. package/dist/plus/git-github/providers/github/diff.d.ts +1 -1
  256. package/dist/plus/git-github/providers/github/diff.d.ts.map +1 -1
  257. package/dist/plus/git-github/providers/github/diff.js +23 -9
  258. package/dist/plus/git-github/providers/github/diff.js.map +1 -1
  259. package/dist/plus/git-github/providers/github/refs.d.ts +9 -1
  260. package/dist/plus/git-github/providers/github/refs.d.ts.map +1 -1
  261. package/dist/plus/git-github/providers/github/refs.js +39 -14
  262. package/dist/plus/git-github/providers/github/refs.js.map +1 -1
  263. package/dist/plus/git-github/providers/github/revision.d.ts.map +1 -1
  264. package/dist/plus/git-github/providers/github/revision.js +1 -2
  265. package/dist/plus/git-github/providers/github/revision.js.map +1 -1
  266. package/dist/plus/git-github/providers/github/status.d.ts +4 -1
  267. package/dist/plus/git-github/providers/github/status.d.ts.map +1 -1
  268. package/dist/plus/git-github/providers/github/status.js +1 -1
  269. package/dist/plus/git-github/providers/github/status.js.map +1 -1
  270. package/dist/plus/git-github/providers/github/tags.d.ts.map +1 -1
  271. package/dist/plus/git-github/providers/github/tags.js +35 -36
  272. package/dist/plus/git-github/providers/github/tags.js.map +1 -1
  273. package/dist/plus/git-github/providers/githubGitProvider.d.ts.map +1 -1
  274. package/dist/plus/git-github/providers/githubGitProvider.js.map +1 -1
  275. package/dist/utils/color.d.ts.map +1 -1
  276. package/dist/utils/color.js.map +1 -1
  277. package/dist/utils/date.d.ts.map +1 -1
  278. package/dist/utils/date.js +6 -0
  279. package/dist/utils/date.js.map +1 -1
  280. package/dist/utils/debounce.js +1 -1
  281. package/dist/utils/decorators/serializable.d.ts.map +1 -1
  282. package/dist/utils/decorators/serializable.js.map +1 -1
  283. package/dist/utils/dedupedAsyncCache.d.ts +37 -0
  284. package/dist/utils/dedupedAsyncCache.d.ts.map +1 -0
  285. package/dist/utils/dedupedAsyncCache.js +68 -0
  286. package/dist/utils/dedupedAsyncCache.js.map +1 -0
  287. package/dist/utils/diff.d.ts +2 -0
  288. package/dist/utils/diff.d.ts.map +1 -0
  289. package/dist/utils/diff.js +53 -0
  290. package/dist/utils/diff.js.map +1 -0
  291. package/dist/utils/disposable.d.ts.map +1 -1
  292. package/dist/utils/disposable.js.map +1 -1
  293. package/dist/utils/env/node/exec.d.ts.map +1 -1
  294. package/dist/utils/env/node/exec.js.map +1 -1
  295. package/dist/utils/error.d.ts.map +1 -1
  296. package/dist/utils/error.js.map +1 -1
  297. package/dist/utils/iterable.d.ts +7 -1
  298. package/dist/utils/iterable.d.ts.map +1 -1
  299. package/dist/utils/iterable.js +12 -4
  300. package/dist/utils/iterable.js.map +1 -1
  301. package/dist/utils/logger.d.ts.map +1 -1
  302. package/dist/utils/logger.js.map +1 -1
  303. package/dist/utils/lruMap.d.ts +9 -0
  304. package/dist/utils/lruMap.d.ts.map +1 -1
  305. package/dist/utils/lruMap.js +26 -4
  306. package/dist/utils/lruMap.js.map +1 -1
  307. package/dist/utils/markdown.d.ts.map +1 -1
  308. package/dist/utils/markdown.js.map +1 -1
  309. package/dist/utils/mru.d.ts.map +1 -1
  310. package/dist/utils/mru.js.map +1 -1
  311. package/dist/utils/object.d.ts +22 -1
  312. package/dist/utils/object.d.ts.map +1 -1
  313. package/dist/utils/object.js +56 -3
  314. package/dist/utils/object.js.map +1 -1
  315. package/dist/utils/paging.js +14 -15
  316. package/dist/utils/paging.js.map +1 -1
  317. package/dist/utils/path.d.ts.map +1 -1
  318. package/dist/utils/path.js.map +1 -1
  319. package/dist/utils/promise.d.ts +1 -0
  320. package/dist/utils/promise.d.ts.map +1 -1
  321. package/dist/utils/promise.js +17 -0
  322. package/dist/utils/promise.js.map +1 -1
  323. package/dist/utils/promiseCache.d.ts +10 -0
  324. package/dist/utils/promiseCache.d.ts.map +1 -1
  325. package/dist/utils/promiseCache.js +34 -4
  326. package/dist/utils/promiseCache.js.map +1 -1
  327. package/dist/utils/string.d.ts.map +1 -1
  328. package/dist/utils/string.js +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.map +1 -1
  333. package/dist/utils/version.js.map +1 -1
  334. package/package.json +13 -1
  335. package/src/git/cache.ts +192 -90
  336. package/src/git/context.ts +21 -0
  337. package/src/git/features.ts +2 -0
  338. package/src/git/models/commit.ts +1 -0
  339. package/src/git/models/graph.ts +97 -0
  340. package/src/git/models/reference.ts +33 -0
  341. package/src/git/models/remote.ts +1 -0
  342. package/src/git/models/remoteProvider.ts +1 -0
  343. package/src/git/models/repository.ts +105 -96
  344. package/src/git/models/search.ts +2 -2
  345. package/src/git/models/statusFile.ts +12 -0
  346. package/src/git/models/worktree.ts +10 -2
  347. package/src/git/parsers/diffParser.ts +2 -0
  348. package/src/git/providers/branches.ts +22 -4
  349. package/src/git/providers/commits.ts +4 -0
  350. package/src/git/providers/config.ts +3 -5
  351. package/src/git/providers/operations.ts +65 -1
  352. package/src/git/providers/pausedOperations.ts +1 -0
  353. package/src/git/providers/refs.ts +32 -3
  354. package/src/git/providers/staging.ts +12 -0
  355. package/src/git/providers/status.ts +6 -1
  356. package/src/git/remotes/azure-devops.ts +2 -0
  357. package/src/git/remotes/custom.ts +23 -0
  358. package/src/git/{exec.types.ts → run.types.ts} +22 -2
  359. package/src/git/service.ts +1 -0
  360. package/src/git/utils/autolink.utils.ts +1 -0
  361. package/src/git/utils/blame.utils.ts +2 -0
  362. package/src/git/utils/conflictResolution.utils.ts +31 -0
  363. package/src/git/utils/contributor.utils.ts +24 -0
  364. package/src/git/utils/fileStatus.utils.ts +7 -1
  365. package/src/git/utils/reachability.utils.ts +109 -0
  366. package/src/git/utils/search.utils.ts +2 -0
  367. package/src/git/utils/sorting.ts +17 -0
  368. package/src/git/utils/status.utils.ts +1 -0
  369. package/src/git/watching/classifyChange.ts +9 -0
  370. package/src/git/watching/gitIgnoreFilter.ts +2 -2
  371. package/src/git/watching/initWatcher.ts +2 -0
  372. package/src/git/watching/watchGroup.ts +3 -0
  373. package/src/git/watching/watchService.ts +45 -7
  374. package/src/git/watching/watchSession.ts +71 -55
  375. package/src/git-cli/exec/exec.types.ts +2 -2
  376. package/src/git-cli/exec/git.ts +6 -5
  377. package/src/git-cli/exec/gitQueue.ts +41 -12
  378. package/src/git-cli/parsers/blameParser.ts +1 -0
  379. package/src/git-cli/parsers/logParser.ts +1 -0
  380. package/src/git-cli/parsers/refParser.ts +33 -34
  381. package/src/git-cli/providers/blame.ts +1 -0
  382. package/src/git-cli/providers/branches.ts +165 -93
  383. package/src/git-cli/providers/commits.ts +107 -37
  384. package/src/git-cli/providers/config.ts +101 -48
  385. package/src/git-cli/providers/diff.ts +10 -3
  386. package/src/git-cli/providers/graph.ts +156 -16
  387. package/src/git-cli/providers/operations.ts +208 -83
  388. package/src/git-cli/providers/patch.ts +1 -0
  389. package/src/git-cli/providers/pausedOperations.ts +8 -0
  390. package/src/git-cli/providers/refs.ts +247 -3
  391. package/src/git-cli/providers/revision.ts +2 -2
  392. package/src/git-cli/providers/staging.ts +33 -0
  393. package/src/git-cli/providers/stash.ts +20 -2
  394. package/src/git-cli/providers/status.ts +24 -5
  395. package/src/git-cli/providers/tags.ts +15 -16
  396. package/src/ipc/discovery.ts +186 -0
  397. package/src/ipc/ipcServer.ts +171 -0
  398. package/src/plus/agents/providers/claudeCodeProvider.ts +2122 -0
  399. package/src/plus/agents/providers/claudeCodeTranscript.ts +214 -0
  400. package/src/plus/agents/sanitizePrompt.ts +109 -0
  401. package/src/plus/agents/stateMachine.ts +197 -0
  402. package/src/plus/agents/types.ts +325 -0
  403. package/src/plus/ai/errors.ts +40 -0
  404. package/src/plus/ai/models/model.ts +1 -0
  405. package/src/plus/ai/models/promptTemplates.ts +13 -0
  406. package/src/plus/ai/models/provider.ts +7 -1
  407. package/src/plus/ai/prompts.ts +49 -8
  408. package/src/plus/ai/providers/gitkrakenProvider.ts +4 -0
  409. package/src/plus/ai/providers/openAICompatibleProviderBase.ts +21 -4
  410. package/src/plus/ai/utils/ai.utils.ts +2 -0
  411. package/src/plus/ai/utils/results.utils.ts +2 -0
  412. package/src/plus/git-github/api/github.ts +315 -57
  413. package/src/plus/git-github/api/types.ts +15 -0
  414. package/src/plus/git-github/models.ts +1 -1
  415. package/src/plus/git-github/providers/github/blame.ts +2 -0
  416. package/src/plus/git-github/providers/github/branches.ts +61 -31
  417. package/src/plus/git-github/providers/github/commits.ts +231 -160
  418. package/src/plus/git-github/providers/github/diff.ts +27 -19
  419. package/src/plus/git-github/providers/github/refs.ts +58 -23
  420. package/src/plus/git-github/providers/github/revision.ts +1 -2
  421. package/src/plus/git-github/providers/github/status.ts +6 -1
  422. package/src/plus/git-github/providers/github/tags.ts +61 -62
  423. package/src/plus/git-github/providers/githubGitProvider.ts +1 -0
  424. package/src/utils/color.ts +2 -0
  425. package/src/utils/date.ts +5 -0
  426. package/src/utils/debounce.ts +1 -1
  427. package/src/utils/decorators/serializable.ts +1 -0
  428. package/src/utils/dedupedAsyncCache.ts +74 -0
  429. package/src/utils/diff.ts +61 -0
  430. package/src/utils/disposable.ts +2 -0
  431. package/src/utils/env/node/exec.ts +2 -0
  432. package/src/utils/error.ts +1 -0
  433. package/src/utils/iterable.ts +17 -3
  434. package/src/utils/logger.ts +1 -0
  435. package/src/utils/lruMap.ts +29 -4
  436. package/src/utils/markdown.ts +1 -0
  437. package/src/utils/mru.ts +2 -0
  438. package/src/utils/object.ts +55 -4
  439. package/src/utils/paging.ts +14 -14
  440. package/src/utils/path.ts +1 -0
  441. package/src/utils/promise.ts +22 -0
  442. package/src/utils/promiseCache.ts +48 -16
  443. package/src/utils/string.ts +3 -1
  444. package/src/utils/uri.ts +1 -0
  445. package/src/utils/version.ts +1 -0
  446. package/dist/git/exec.types.d.ts.map +0 -1
  447. package/dist/git/exec.types.js +0 -2
  448. package/dist/git/exec.types.js.map +0 -1
@@ -16,11 +16,16 @@ import {
16
16
  import type { GitBranchReference, GitReference } from '../../git/models/reference.js';
17
17
  import type { SigningFormat } from '../../git/models/signature.js';
18
18
  import type { GitConflictFile } from '../../git/models/staging.js';
19
- import type { GitOperationResult, GitOperationsSubProvider } from '../../git/providers/operations.js';
19
+ import type {
20
+ GitOperationResult,
21
+ GitOperationRunOptions,
22
+ GitOperationsSubProvider,
23
+ } from '../../git/providers/operations.js';
20
24
  import { getBranchNameAndRemote, getBranchTrackingWithoutRemote } from '../../git/utils/branch.utils.js';
21
25
  import { isBranchReference } from '../../git/utils/reference.utils.js';
22
26
  import { debug } from '../../utils/decorators/log.js';
23
27
  import { sequentialize } from '../../utils/decorators/sequentialize.js';
28
+ import { chunkByStringLength } from '../../utils/iterable.js';
24
29
  import { Logger } from '../../utils/logger.js';
25
30
  import { getScopedLogger } from '../../utils/logger.scoped.js';
26
31
  import { normalizePath, splitPath } from '../../utils/path.js';
@@ -32,6 +37,7 @@ import {
32
37
  gitConfigsPull,
33
38
  GitErrors,
34
39
  inferSigningFormatFromError,
40
+ maxGitCliLength,
35
41
  } from '../exec/git.js';
36
42
 
37
43
  export class OperationsGitSubProvider implements GitOperationsSubProvider {
@@ -46,40 +52,24 @@ export class OperationsGitSubProvider implements GitOperationsSubProvider {
46
52
  async checkout(
47
53
  repoPath: string,
48
54
  ref: string,
49
- options?: { createBranch?: string } | { path?: string },
55
+ options?: { createBranch?: string },
56
+ runOptions?: GitOperationRunOptions,
50
57
  ): Promise<void> {
51
58
  const scope = getScopedLogger();
52
59
 
53
- try {
54
- await this.checkoutCore(repoPath, ref, options);
55
- this.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status');
56
- this.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads', 'index']);
57
- } catch (ex) {
58
- scope?.error(ex);
59
- throw ex;
60
- }
61
- }
62
-
63
- private async checkoutCore(
64
- repoPath: string,
65
- ref: string,
66
- { createBranch, path }: { createBranch?: string; path?: string } = {},
67
- ): Promise<void> {
68
60
  const params = ['checkout'];
69
- if (createBranch) {
70
- params.push('-b', createBranch, ref, '--');
61
+ if (options?.createBranch) {
62
+ params.push('-b', options.createBranch, ref, '--');
71
63
  } else {
72
64
  params.push(ref, '--');
73
-
74
- if (path) {
75
- [path, repoPath] = splitPath(path, repoPath, true);
76
- params.push(path);
77
- }
78
65
  }
79
66
 
80
67
  try {
81
- await this.git.run({ cwd: repoPath }, ...params);
68
+ await this.git.run({ cwd: repoPath, errors: 'throw', ...runOptions }, ...params);
69
+ this.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status');
70
+ this.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads', 'index']);
82
71
  } catch (ex) {
72
+ scope?.error(ex);
83
73
  throw getGitCommandError(
84
74
  'checkout',
85
75
  ex,
@@ -98,6 +88,7 @@ export class OperationsGitSubProvider implements GitOperationsSubProvider {
98
88
  repoPath: string,
99
89
  revs: string[],
100
90
  options?: { edit?: boolean; noCommit?: boolean; source?: unknown },
91
+ runOptions?: GitOperationRunOptions,
101
92
  ): Promise<GitOperationResult> {
102
93
  const scope = getScopedLogger();
103
94
 
@@ -110,7 +101,8 @@ export class OperationsGitSubProvider implements GitOperationsSubProvider {
110
101
  }
111
102
 
112
103
  if (revs.length > 1) {
113
- // Sort commits in topological order (oldest ancestor first) so cherry-pick applies them correctly
104
+ // Sort commits in topological order (oldest ancestor first) so cherry-pick applies them correctly.
105
+ // This is a local read-only pre-flight, not the user-initiated op — don't subject it to caller env/timeout.
114
106
  const revsSet = new Set(revs);
115
107
  const result = await this.git.run({ cwd: repoPath }, 'rev-list', '--topo-order', '--reverse', ...revs);
116
108
 
@@ -131,7 +123,7 @@ export class OperationsGitSubProvider implements GitOperationsSubProvider {
131
123
  args.push(...revs);
132
124
 
133
125
  try {
134
- await this.git.run({ cwd: repoPath, errors: 'throw' }, ...args);
126
+ await this.git.run({ cwd: repoPath, errors: 'throw', ...runOptions }, ...args);
135
127
  this.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status');
136
128
  this.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads', 'index']);
137
129
  return { conflicted: false };
@@ -168,6 +160,7 @@ export class OperationsGitSubProvider implements GitOperationsSubProvider {
168
160
  signoff?: boolean;
169
161
  source?: unknown;
170
162
  },
163
+ runOptions?: GitOperationRunOptions,
171
164
  ): Promise<void> {
172
165
  const scope = getScopedLogger();
173
166
 
@@ -194,7 +187,10 @@ export class OperationsGitSubProvider implements GitOperationsSubProvider {
194
187
  params.push('-F', '-');
195
188
 
196
189
  try {
197
- await this.git.run({ cwd: repoPath, stdin: message, stdinEncoding: 'utf8', errors: 'throw' }, ...params);
190
+ await this.git.run(
191
+ { cwd: repoPath, stdin: message, stdinEncoding: 'utf8', errors: 'throw', ...runOptions },
192
+ ...params,
193
+ );
198
194
  this.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status');
199
195
  this.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads', 'index']);
200
196
  } catch (ex) {
@@ -217,6 +213,7 @@ export class OperationsGitSubProvider implements GitOperationsSubProvider {
217
213
  async fetch(
218
214
  repoPath: string,
219
215
  options?: { all?: boolean; branch?: GitBranchReference; prune?: boolean; pull?: boolean; remote?: string },
216
+ runOptions?: GitOperationRunOptions,
220
217
  ): Promise<void> {
221
218
  const scope = getScopedLogger();
222
219
 
@@ -226,14 +223,18 @@ export class OperationsGitSubProvider implements GitOperationsSubProvider {
226
223
  const [branchName, remoteName] = getBranchNameAndRemote(branch);
227
224
  if (remoteName == null) return;
228
225
 
229
- await this.fetchCore(repoPath, {
230
- branch: branchName,
231
- remote: remoteName,
232
- upstream: getBranchTrackingWithoutRemote(branch)!,
233
- pull: options?.pull,
234
- });
226
+ await this.fetchCore(
227
+ repoPath,
228
+ {
229
+ branch: branchName,
230
+ remote: remoteName,
231
+ upstream: getBranchTrackingWithoutRemote(branch)!,
232
+ pull: options?.pull,
233
+ },
234
+ runOptions,
235
+ );
235
236
  } else {
236
- await this.fetchCore(repoPath, opts);
237
+ await this.fetchCore(repoPath, opts, runOptions);
237
238
  }
238
239
 
239
240
  this.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'tags');
@@ -256,6 +257,7 @@ export class OperationsGitSubProvider implements GitOperationsSubProvider {
256
257
  remote: string;
257
258
  upstream: string;
258
259
  },
260
+ runOptions?: GitOperationRunOptions,
259
261
  ): Promise<void> {
260
262
  const params = ['fetch'];
261
263
 
@@ -276,7 +278,7 @@ export class OperationsGitSubProvider implements GitOperationsSubProvider {
276
278
  }
277
279
 
278
280
  try {
279
- await this.git.run({ cwd: repoPath }, ...params);
281
+ await this.git.run({ cwd: repoPath, errors: 'throw', ...runOptions }, ...params);
280
282
  } catch (ex) {
281
283
  throw getGitCommandError(
282
284
  'fetch',
@@ -301,6 +303,7 @@ export class OperationsGitSubProvider implements GitOperationsSubProvider {
301
303
  repoPath: string,
302
304
  ref: string,
303
305
  options?: { fastForward?: boolean | 'only'; noCommit?: boolean; squash?: boolean; source?: unknown },
306
+ runOptions?: GitOperationRunOptions,
304
307
  ): Promise<GitOperationResult> {
305
308
  const scope = getScopedLogger();
306
309
 
@@ -325,7 +328,7 @@ export class OperationsGitSubProvider implements GitOperationsSubProvider {
325
328
  try {
326
329
  await this.git.run(
327
330
  // Avoid a timeout since merges can take a long time (set to 0 to disable)
328
- { cwd: repoPath, errors: 'throw', timeout: 0 },
331
+ { cwd: repoPath, errors: 'throw', timeout: 0, ...runOptions },
329
332
  ...args,
330
333
  );
331
334
 
@@ -356,6 +359,7 @@ export class OperationsGitSubProvider implements GitOperationsSubProvider {
356
359
  async pull(
357
360
  repoPath: string,
358
361
  options?: { branch?: GitBranchReference; rebase?: boolean; tags?: boolean; source?: unknown },
362
+ runOptions?: GitOperationRunOptions,
359
363
  ): Promise<void> {
360
364
  const scope = getScopedLogger();
361
365
 
@@ -369,25 +373,33 @@ export class OperationsGitSubProvider implements GitOperationsSubProvider {
369
373
  );
370
374
  if (worktree != null) {
371
375
  // Branch is checked out in a worktree — run git pull in that worktree's directory
372
- await this.pullCore(normalizePath(worktree.uri.fsPath), {
373
- rebase: options?.rebase,
374
- tags: options?.tags,
375
- source: options?.source,
376
- });
376
+ await this.pullCore(
377
+ normalizePath(worktree.uri.fsPath),
378
+ {
379
+ rebase: options?.rebase,
380
+ tags: options?.tags,
381
+ source: options?.source,
382
+ },
383
+ runOptions,
384
+ );
377
385
  this.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status', 'tags');
378
386
  this.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads', 'remotes', 'index']);
379
387
  } else {
380
388
  // Branch is not checked out anywhere — can only fetch (no working tree to merge into)
381
- await this.fetch(repoPath, { branch: branch });
389
+ await this.fetch(repoPath, { branch: branch }, runOptions);
382
390
  }
383
391
  return;
384
392
  }
385
393
 
386
- await this.pullCore(repoPath, {
387
- rebase: options?.rebase,
388
- tags: options?.tags,
389
- source: options?.source,
390
- });
394
+ await this.pullCore(
395
+ repoPath,
396
+ {
397
+ rebase: options?.rebase,
398
+ tags: options?.tags,
399
+ source: options?.source,
400
+ },
401
+ runOptions,
402
+ );
391
403
 
392
404
  this.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status', 'tags');
393
405
  this.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads', 'remotes', 'index']);
@@ -400,6 +412,7 @@ export class OperationsGitSubProvider implements GitOperationsSubProvider {
400
412
  private async pullCore(
401
413
  repoPath: string,
402
414
  options: { rebase?: boolean; tags?: boolean; source?: unknown },
415
+ runOptions?: GitOperationRunOptions,
403
416
  ): Promise<void> {
404
417
  const params = ['pull'];
405
418
 
@@ -412,7 +425,7 @@ export class OperationsGitSubProvider implements GitOperationsSubProvider {
412
425
  }
413
426
 
414
427
  try {
415
- await this.git.run({ cwd: repoPath, configs: gitConfigsPull }, ...params);
428
+ await this.git.run({ cwd: repoPath, configs: gitConfigsPull, errors: 'throw', ...runOptions }, ...params);
416
429
  } catch (ex) {
417
430
  await this.throwIfSigningError(repoPath, params, ex, options.source);
418
431
  throw getGitCommandError(
@@ -429,6 +442,7 @@ export class OperationsGitSubProvider implements GitOperationsSubProvider {
429
442
  async push(
430
443
  repoPath: string,
431
444
  options?: { reference?: GitReference; force?: boolean; publish?: { remote: string } },
445
+ runOptions?: GitOperationRunOptions,
432
446
  ): Promise<void> {
433
447
  const scope = getScopedLogger();
434
448
 
@@ -455,12 +469,17 @@ export class OperationsGitSubProvider implements GitOperationsSubProvider {
455
469
  const branch = await this.provider.branches.getBranch(repoPath);
456
470
  if (branch == null) return;
457
471
 
458
- branchName =
459
- options?.reference != null
460
- ? `${options.reference.ref}:${
461
- options?.publish != null ? 'refs/heads/' : ''
462
- }${branch.nameWithoutRemote}`
463
- : branch.name;
472
+ if (options?.reference != null) {
473
+ branchName = `${options.reference.ref}:${
474
+ options?.publish != null ? 'refs/heads/' : ''
475
+ }${branch.nameWithoutRemote}`;
476
+ } else {
477
+ const tracking = options?.publish == null ? branch.trackingWithoutRemote : undefined;
478
+ branchName =
479
+ tracking != null && tracking !== branch.nameWithoutRemote
480
+ ? `${branch.name}:${tracking}`
481
+ : branch.name;
482
+ }
464
483
  remoteName = branch.remoteName ?? options?.publish?.remote;
465
484
  upstreamName = options?.reference == null && options?.publish != null ? branch.name : undefined;
466
485
 
@@ -480,34 +499,49 @@ export class OperationsGitSubProvider implements GitOperationsSubProvider {
480
499
 
481
500
  let forceOpts: PushForceOptions | undefined;
482
501
  if (options?.force) {
483
- forceOpts = {
484
- withLease: true,
485
- ifIncludes: true,
486
- };
502
+ // Honor the host's force-push preferences (e.g. VS Code's `git.useForcePushWithLease` /
503
+ // `git.useForcePushIfIncludes`); fall back to the safer `--force-with-lease` behavior.
504
+ const useForceWithLease = this.context.config?.push?.useForceWithLease ?? true;
505
+ forceOpts = useForceWithLease
506
+ ? { withLease: true, ifIncludes: this.context.config?.push?.useForceIfIncludes ?? true }
507
+ : { withLease: false };
487
508
  }
488
509
 
489
510
  try {
490
- await this.pushCore(repoPath, {
491
- branch: branchName,
492
- remote: remoteName,
493
- upstream: upstreamName,
494
- force: forceOpts,
495
- publish: options?.publish != null,
496
- });
497
-
498
- // Since Git can't setup upstream tracking when publishing a new branch to a specific commit, do it now
511
+ await this.pushCore(
512
+ repoPath,
513
+ {
514
+ branch: branchName,
515
+ remote: remoteName,
516
+ upstream: upstreamName,
517
+ force: forceOpts,
518
+ publish: options?.publish != null,
519
+ },
520
+ runOptions,
521
+ );
522
+
523
+ // Since Git can't setup upstream tracking when publishing a new branch to a specific commit, do it now.
524
+ // Soft-fail: the push already succeeded, so don't let a local upstream-tracking failure (cancellation
525
+ // arriving mid-spawn, transient git error) suppress the post-push hook fan-out below.
499
526
  if (setUpstream != null) {
500
- await this.git.run(
501
- { cwd: repoPath },
502
- 'branch',
503
- '--set-upstream-to',
504
- `${setUpstream.remote}/${setUpstream.remoteBranch}`,
505
- setUpstream.branch,
506
- );
527
+ try {
528
+ await this.git.run(
529
+ { cwd: repoPath, ...runOptions },
530
+ 'branch',
531
+ '--set-upstream-to',
532
+ `${setUpstream.remote}/${setUpstream.remoteBranch}`,
533
+ setUpstream.branch,
534
+ );
535
+ } catch (ex) {
536
+ scope?.error(ex, 'Unable to set upstream tracking after publish');
537
+ }
507
538
  }
508
539
 
509
540
  this.context.hooks?.cache?.onReset?.(repoPath, 'branches');
510
- this.context.hooks?.repository?.onChanged?.(repoPath, ['remotes']);
541
+ this.context.hooks?.repository?.onChanged?.(
542
+ repoPath,
543
+ options?.publish != null ? ['config', 'heads', 'remotes'] : ['remotes'],
544
+ );
511
545
  } catch (ex) {
512
546
  scope?.error(ex);
513
547
  throw ex;
@@ -524,6 +558,7 @@ export class OperationsGitSubProvider implements GitOperationsSubProvider {
524
558
  upstream?: string;
525
559
  delete?: { remote: string; branch: string };
526
560
  },
561
+ runOptions?: GitOperationRunOptions,
527
562
  ): Promise<void> {
528
563
  const params = ['push'];
529
564
 
@@ -555,7 +590,7 @@ export class OperationsGitSubProvider implements GitOperationsSubProvider {
555
590
  }
556
591
 
557
592
  try {
558
- await this.git.run({ cwd: repoPath }, ...params);
593
+ await this.git.run({ cwd: repoPath, errors: 'throw', ...runOptions }, ...params);
559
594
  } catch (ex) {
560
595
  const error = getGitCommandError(
561
596
  'push',
@@ -625,15 +660,18 @@ export class OperationsGitSubProvider implements GitOperationsSubProvider {
625
660
  branch?: string;
626
661
  editor?: string;
627
662
  interactive?: boolean;
663
+ programmaticEditor?: boolean;
664
+ messageEditor?: string;
628
665
  onto?: string;
629
666
  updateRefs?: boolean;
630
667
  source?: unknown;
631
668
  },
669
+ runOptions?: GitOperationRunOptions,
632
670
  ): Promise<GitOperationResult> {
633
671
  const scope = getScopedLogger();
634
672
 
635
673
  const args = ['rebase'];
636
- let configs: string[] | undefined;
674
+ const configs: string[] = [];
637
675
 
638
676
  if (options?.autoStash !== false) {
639
677
  args.push('--autostash');
@@ -643,8 +681,24 @@ export class OperationsGitSubProvider implements GitOperationsSubProvider {
643
681
  args.push('--interactive');
644
682
 
645
683
  if (options.editor) {
646
- configs = ['-c', `sequence.editor=${options.editor}`];
684
+ configs.push('-c', `sequence.editor=${options.editor}`);
647
685
  }
686
+
687
+ // A script-based sequence editor rewrites the todo by command word + SHA, so git must emit a
688
+ // plain, natural-order todo regardless of the user's rebase config: `rebase.autosquash` would
689
+ // reorder commits and rewrite `pick`→`fixup`, and `rebase.abbreviateCommands` would emit `p`.
690
+ if (options.programmaticEditor) {
691
+ configs.push('-c', 'rebase.autosquash=false', '-c', 'rebase.abbreviateCommands=false');
692
+ }
693
+ }
694
+
695
+ // Drive per-commit message editing (the combined message a `squash` produces, or a `reword`).
696
+ // `GIT_EDITOR` (not `core.editor`) is what git's interactive-rebase backend honors for the `reword`
697
+ // amend step, so set it on the environment; also set `core.editor` config as a fallback.
698
+ let env = runOptions?.env;
699
+ if (options?.messageEditor) {
700
+ configs.push('-c', `core.editor=${options.messageEditor}`);
701
+ env = { ...env, GIT_EDITOR: options.messageEditor };
648
702
  }
649
703
 
650
704
  if (options?.updateRefs) {
@@ -664,7 +718,7 @@ export class OperationsGitSubProvider implements GitOperationsSubProvider {
664
718
  try {
665
719
  await this.git.run(
666
720
  // Avoid a timeout since rebases can take a long time (set to 0 to disable)
667
- { cwd: repoPath, errors: 'throw', configs: configs, timeout: 0 },
721
+ { cwd: repoPath, errors: 'throw', configs: configs, timeout: 0, ...runOptions, env: env },
668
722
  ...args,
669
723
  );
670
724
  this.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status');
@@ -698,11 +752,12 @@ export class OperationsGitSubProvider implements GitOperationsSubProvider {
698
752
  repoPath: string,
699
753
  rev: string,
700
754
  options?: { mode?: 'hard' | 'keep' | 'merge' | 'mixed' | 'soft' },
755
+ runOptions?: GitOperationRunOptions,
701
756
  ): Promise<void> {
702
757
  const scope = getScopedLogger();
703
758
 
704
759
  try {
705
- await this.resetCore(repoPath, rev, options?.mode);
760
+ await this.resetCore(repoPath, rev, options?.mode, runOptions);
706
761
  this.context.hooks?.cache?.onReset?.(repoPath, 'branches', 'status');
707
762
  this.context.hooks?.repository?.onChanged?.(repoPath, ['head', 'heads', 'index']);
708
763
  } catch (ex) {
@@ -715,6 +770,7 @@ export class OperationsGitSubProvider implements GitOperationsSubProvider {
715
770
  repoPath: string,
716
771
  rev: string,
717
772
  mode?: 'hard' | 'keep' | 'merge' | 'mixed' | 'soft',
773
+ runOptions?: GitOperationRunOptions,
718
774
  ): Promise<void> {
719
775
  const params = ['reset', '-q'];
720
776
  if (mode) {
@@ -723,7 +779,7 @@ export class OperationsGitSubProvider implements GitOperationsSubProvider {
723
779
  params.push(rev, '--');
724
780
 
725
781
  try {
726
- await this.git.run({ cwd: repoPath }, ...params);
782
+ await this.git.run({ cwd: repoPath, errors: 'throw', ...runOptions }, ...params);
727
783
  } catch (ex) {
728
784
  throw getGitCommandError(
729
785
  'reset',
@@ -734,12 +790,81 @@ export class OperationsGitSubProvider implements GitOperationsSubProvider {
734
790
  }
735
791
  }
736
792
 
793
+ @sequentialize({ getQueueKey: rp => rp })
794
+ @debug()
795
+ async restore(
796
+ repoPath: string,
797
+ path: string | string[],
798
+ options?: { ref?: string; side?: 'ours' | 'theirs' },
799
+ runOptions?: GitOperationRunOptions,
800
+ ): Promise<void> {
801
+ const paths = Array.isArray(path) ? path : [path];
802
+ if (!paths.length) return;
803
+
804
+ const scope = getScopedLogger();
805
+ const normalized = paths.map(p => splitPath(p, repoPath, true)[0]);
806
+
807
+ // `side` and `ref` are mutually exclusive in git (--ours/--theirs apply during conflict
808
+ // resolution and take no source ref); side takes precedence if both are somehow supplied.
809
+ // Use a truthy check on `ref` so an empty string falls through to index-restore rather than
810
+ // producing a malformed `git checkout '' -- …`. Implemented via `checkout` rather than
811
+ // `git restore` for compatibility with the minimum supported git (2.7.2); `git restore`
812
+ // only landed in 2.23.
813
+ const selector = options?.side != null ? `--${options.side}` : options?.ref || undefined;
814
+ const prefix = selector != null ? ['checkout', selector, '--'] : ['checkout', '--'];
815
+
816
+ try {
817
+ if (await this.git.supports('git:checkout:pathspec-from-file')) {
818
+ // Git ≥ 2.26: stream all pathspecs via stdin (NUL-separated) in a single invocation —
819
+ // no CLI-length limit (so no batching), and robust for paths with spaces/newlines.
820
+ // Pathspecs come from the file rather than argv, so `--` isn't used.
821
+ const args = ['checkout'];
822
+ if (selector != null) {
823
+ args.push(selector);
824
+ }
825
+ args.push('--pathspec-from-file=-', '--pathspec-file-nul');
826
+ await this.git.run(
827
+ { cwd: repoPath, errors: 'throw', ...runOptions, stdin: normalized.join('\0') },
828
+ ...args,
829
+ );
830
+ } else {
831
+ // Older git: pass pathspecs as args, one git invocation per chunk (collapsing N
832
+ // path-mode checkouts into ⌈N / chunk⌉ spawns). Reserve the command prefix length and
833
+ // a per-arg overhead (separator + possible quoting) so the assembled command line
834
+ // can't exceed the OS limit even with many short paths.
835
+ const perArgOverhead = 3;
836
+ const prefixLength = prefix.reduce((sum, arg) => sum + arg.length + perArgOverhead, 0);
837
+ for (const batch of chunkByStringLength(normalized, maxGitCliLength - prefixLength, perArgOverhead)) {
838
+ await this.git.run({ cwd: repoPath, errors: 'throw', ...runOptions }, ...prefix, ...batch);
839
+ }
840
+ }
841
+ this.context.hooks?.cache?.onReset?.(repoPath, 'status');
842
+ this.context.hooks?.repository?.onChanged?.(repoPath, ['index']);
843
+ } catch (ex) {
844
+ scope?.error(ex);
845
+ throw getGitCommandError(
846
+ 'checkout',
847
+ ex,
848
+ reason =>
849
+ new CheckoutError(
850
+ {
851
+ reason: reason ?? 'other',
852
+ ref: options?.side ?? options?.ref,
853
+ gitCommand: { repoPath: repoPath, args: [...prefix, ...normalized] },
854
+ },
855
+ ex,
856
+ ),
857
+ );
858
+ }
859
+ }
860
+
737
861
  @sequentialize({ getQueueKey: rp => rp })
738
862
  @debug()
739
863
  async revert(
740
864
  repoPath: string,
741
865
  refs: string[],
742
866
  options?: { editMessage?: boolean; source?: unknown },
867
+ runOptions?: GitOperationRunOptions,
743
868
  ): Promise<GitOperationResult> {
744
869
  const scope = getScopedLogger();
745
870
 
@@ -756,7 +881,7 @@ export class OperationsGitSubProvider implements GitOperationsSubProvider {
756
881
  try {
757
882
  await this.git.run(
758
883
  // Avoid a timeout since reverts can take a long time (set to 0 to disable)
759
- { cwd: repoPath, errors: 'throw', timeout: 0 },
884
+ { cwd: repoPath, errors: 'throw', timeout: 0, ...runOptions },
760
885
  ...args,
761
886
  );
762
887
 
@@ -113,6 +113,7 @@ export class PatchGitSubProvider implements GitPatchSubProvider {
113
113
  }
114
114
  } catch (ex) {
115
115
  if (ex instanceof ApplyPatchCommitError) throw ex;
116
+
116
117
  scope?.error(ex);
117
118
 
118
119
  if (CherryPickError.is(ex, 'wouldOverwriteChanges')) {
@@ -43,10 +43,18 @@ export class PausedOperationsGitSubProvider implements GitPausedOperationsSubPro
43
43
  @debug()
44
44
  getPausedOperationStatus(
45
45
  repoPath: string,
46
+ options?: { force?: boolean },
46
47
  cancellation?: AbortSignal,
47
48
  ): Promise<GitPausedOperationStatus | undefined> {
48
49
  const scope = getScopedLogger();
49
50
 
51
+ // Self-heal callers (WIP refresh) bypass the cache so a missed `'pausedOp'` FS-watcher
52
+ // event (CLI-driven completion, torn-down secondary-worktree watcher) can't leave the
53
+ // status stuck — the readdir-based detection is cheap enough to repeat on every tick.
54
+ if (options?.force) {
55
+ this.cache.pausedOperationStatus.delete(repoPath);
56
+ }
57
+
50
58
  const status = this.cache.pausedOperationStatus.getOrCreate(repoPath, async _cancellable => {
51
59
  const gitDir = await this.provider.config.getGitDir(repoPath);
52
60