@gitkraken/core-gitlens 0.5.109 → 0.5.111

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (416) hide show
  1. package/CHANGELOG.md +48 -1
  2. package/dist/git/cache.d.ts +111 -6
  3. package/dist/git/cache.d.ts.map +1 -1
  4. package/dist/git/cache.js +312 -43
  5. package/dist/git/cache.js.map +1 -1
  6. package/dist/git/context.d.ts +11 -0
  7. package/dist/git/context.d.ts.map +1 -1
  8. package/dist/git/context.js.map +1 -1
  9. package/dist/git/models/fileStatus.d.ts +1 -0
  10. package/dist/git/models/fileStatus.d.ts.map +1 -1
  11. package/dist/git/models/fileStatus.js +1 -0
  12. package/dist/git/models/fileStatus.js.map +1 -1
  13. package/dist/git/models/issue.d.ts +4 -0
  14. package/dist/git/models/issue.d.ts.map +1 -1
  15. package/dist/git/models/mergeConflicts.d.ts +2 -0
  16. package/dist/git/models/mergeConflicts.d.ts.map +1 -1
  17. package/dist/git/models/pullRequest.d.ts +119 -2
  18. package/dist/git/models/pullRequest.d.ts.map +1 -1
  19. package/dist/git/models/pullRequest.js +27 -1
  20. package/dist/git/models/pullRequest.js.map +1 -1
  21. package/dist/git/models/repository.d.ts +32 -5
  22. package/dist/git/models/repository.d.ts.map +1 -1
  23. package/dist/git/models/repository.js +58 -12
  24. package/dist/git/models/repository.js.map +1 -1
  25. package/dist/git/models/statusFile.d.ts.map +1 -1
  26. package/dist/git/models/statusFile.js +3 -0
  27. package/dist/git/models/statusFile.js.map +1 -1
  28. package/dist/git/providers/branches.d.ts +2 -0
  29. package/dist/git/providers/branches.d.ts.map +1 -1
  30. package/dist/git/providers/commits.d.ts +8 -0
  31. package/dist/git/providers/commits.d.ts.map +1 -1
  32. package/dist/git/providers/config.d.ts +19 -1
  33. package/dist/git/providers/config.d.ts.map +1 -1
  34. package/dist/git/providers/operations.d.ts +1 -0
  35. package/dist/git/providers/operations.d.ts.map +1 -1
  36. package/dist/git/providers/pausedOperations.d.ts +2 -0
  37. package/dist/git/providers/pausedOperations.d.ts.map +1 -1
  38. package/dist/git/providers/status.d.ts +1 -0
  39. package/dist/git/providers/status.d.ts.map +1 -1
  40. package/dist/git/utils/config.utils.d.ts +3 -0
  41. package/dist/git/utils/config.utils.d.ts.map +1 -0
  42. package/dist/git/utils/config.utils.js +8 -0
  43. package/dist/git/utils/config.utils.js.map +1 -0
  44. package/dist/git/utils/issue.utils.d.ts.map +1 -1
  45. package/dist/git/utils/issue.utils.js +2 -0
  46. package/dist/git/utils/issue.utils.js.map +1 -1
  47. package/dist/git/utils/pausedOperationStatus.utils.d.ts +14 -0
  48. package/dist/git/utils/pausedOperationStatus.utils.d.ts.map +1 -1
  49. package/dist/git/utils/pausedOperationStatus.utils.js +23 -0
  50. package/dist/git/utils/pausedOperationStatus.utils.js.map +1 -1
  51. package/dist/git/utils/pullRequest.utils.d.ts +24 -1
  52. package/dist/git/utils/pullRequest.utils.d.ts.map +1 -1
  53. package/dist/git/utils/pullRequest.utils.js +71 -0
  54. package/dist/git/utils/pullRequest.utils.js.map +1 -1
  55. package/dist/git/watching/changeEvent.d.ts +6 -1
  56. package/dist/git/watching/changeEvent.d.ts.map +1 -1
  57. package/dist/git/watching/classifyChange.d.ts.map +1 -1
  58. package/dist/git/watching/classifyChange.js +14 -1
  59. package/dist/git/watching/classifyChange.js.map +1 -1
  60. package/dist/git/watching/watchService.d.ts.map +1 -1
  61. package/dist/git/watching/watchService.js +18 -3
  62. package/dist/git/watching/watchService.js.map +1 -1
  63. package/dist/git/watching/watchSession.d.ts +8 -1
  64. package/dist/git/watching/watchSession.d.ts.map +1 -1
  65. package/dist/git/watching/watchSession.js +38 -6
  66. package/dist/git/watching/watchSession.js.map +1 -1
  67. package/dist/git/watching/watcherPatterns.d.ts +2 -2
  68. package/dist/git/watching/watcherPatterns.d.ts.map +1 -1
  69. package/dist/git/watching/watcherPatterns.js +1 -1
  70. package/dist/git/watching/watcherPatterns.js.map +1 -1
  71. package/dist/git-cli/exec/git.d.ts +1 -1
  72. package/dist/git-cli/exec/git.d.ts.map +1 -1
  73. package/dist/git-cli/exec/git.js +13 -3
  74. package/dist/git-cli/exec/git.js.map +1 -1
  75. package/dist/git-cli/providers/branches.d.ts +19 -0
  76. package/dist/git-cli/providers/branches.d.ts.map +1 -1
  77. package/dist/git-cli/providers/branches.js +282 -78
  78. package/dist/git-cli/providers/branches.js.map +1 -1
  79. package/dist/git-cli/providers/commits.d.ts +4 -0
  80. package/dist/git-cli/providers/commits.d.ts.map +1 -1
  81. package/dist/git-cli/providers/commits.js +84 -11
  82. package/dist/git-cli/providers/commits.js.map +1 -1
  83. package/dist/git-cli/providers/config.d.ts +42 -0
  84. package/dist/git-cli/providers/config.d.ts.map +1 -1
  85. package/dist/git-cli/providers/config.js +186 -5
  86. package/dist/git-cli/providers/config.js.map +1 -1
  87. package/dist/git-cli/providers/contributors.d.ts.map +1 -1
  88. package/dist/git-cli/providers/contributors.js +1 -1
  89. package/dist/git-cli/providers/contributors.js.map +1 -1
  90. package/dist/git-cli/providers/graph.d.ts +2 -2
  91. package/dist/git-cli/providers/graph.d.ts.map +1 -1
  92. package/dist/git-cli/providers/graph.js +27 -9
  93. package/dist/git-cli/providers/graph.js.map +1 -1
  94. package/dist/git-cli/providers/operations.d.ts.map +1 -1
  95. package/dist/git-cli/providers/operations.js +40 -12
  96. package/dist/git-cli/providers/operations.js.map +1 -1
  97. package/dist/git-cli/providers/pausedOperations.d.ts +5 -0
  98. package/dist/git-cli/providers/pausedOperations.d.ts.map +1 -1
  99. package/dist/git-cli/providers/pausedOperations.js +87 -16
  100. package/dist/git-cli/providers/pausedOperations.js.map +1 -1
  101. package/dist/git-cli/providers/refs.d.ts +5 -3
  102. package/dist/git-cli/providers/refs.d.ts.map +1 -1
  103. package/dist/git-cli/providers/refs.js +33 -4
  104. package/dist/git-cli/providers/refs.js.map +1 -1
  105. package/dist/git-cli/providers/status.d.ts +1 -0
  106. package/dist/git-cli/providers/status.d.ts.map +1 -1
  107. package/dist/git-cli/providers/status.js +18 -3
  108. package/dist/git-cli/providers/status.js.map +1 -1
  109. package/dist/git-cli/providers/worktrees.d.ts.map +1 -1
  110. package/dist/git-cli/providers/worktrees.js +4 -0
  111. package/dist/git-cli/providers/worktrees.js.map +1 -1
  112. package/dist/git-cli/service.d.ts.map +1 -1
  113. package/dist/git-cli/service.js.map +1 -1
  114. package/dist/plus/agents/providers/claudeCodeProvider.d.ts +39 -1
  115. package/dist/plus/agents/providers/claudeCodeProvider.d.ts.map +1 -1
  116. package/dist/plus/agents/providers/claudeCodeProvider.js +978 -71
  117. package/dist/plus/agents/providers/claudeCodeProvider.js.map +1 -1
  118. package/dist/plus/agents/providers/claudeCodeTranscript.d.ts +24 -2
  119. package/dist/plus/agents/providers/claudeCodeTranscript.d.ts.map +1 -1
  120. package/dist/plus/agents/providers/claudeCodeTranscript.js +84 -9
  121. package/dist/plus/agents/providers/claudeCodeTranscript.js.map +1 -1
  122. package/dist/plus/agents/types.d.ts +37 -2
  123. package/dist/plus/agents/types.d.ts.map +1 -1
  124. package/dist/plus/agents/types.js +2 -0
  125. package/dist/plus/agents/types.js.map +1 -1
  126. package/dist/plus/ai/errors.d.ts +10 -0
  127. package/dist/plus/ai/errors.d.ts.map +1 -1
  128. package/dist/plus/ai/errors.js +29 -0
  129. package/dist/plus/ai/errors.js.map +1 -1
  130. package/dist/plus/ai/models/model.d.ts +4 -0
  131. package/dist/plus/ai/models/model.d.ts.map +1 -1
  132. package/dist/plus/ai/models/model.js +51 -6
  133. package/dist/plus/ai/models/model.js.map +1 -1
  134. package/dist/plus/ai/models/promptTemplates.d.ts +1 -1
  135. package/dist/plus/ai/models/promptTemplates.d.ts.map +1 -1
  136. package/dist/plus/ai/models/provider.d.ts +60 -2
  137. package/dist/plus/ai/models/provider.d.ts.map +1 -1
  138. package/dist/plus/ai/prompts.d.ts +12 -0
  139. package/dist/plus/ai/prompts.d.ts.map +1 -1
  140. package/dist/plus/ai/prompts.js +177 -61
  141. package/dist/plus/ai/prompts.js.map +1 -1
  142. package/dist/plus/ai/providers/anthropicProvider.d.ts +10 -2
  143. package/dist/plus/ai/providers/anthropicProvider.d.ts.map +1 -1
  144. package/dist/plus/ai/providers/anthropicProvider.js +139 -46
  145. package/dist/plus/ai/providers/anthropicProvider.js.map +1 -1
  146. package/dist/plus/ai/providers/deepSeekProvider.d.ts +2 -0
  147. package/dist/plus/ai/providers/deepSeekProvider.d.ts.map +1 -1
  148. package/dist/plus/ai/providers/deepSeekProvider.js +10 -21
  149. package/dist/plus/ai/providers/deepSeekProvider.js.map +1 -1
  150. package/dist/plus/ai/providers/geminiProvider.d.ts +1 -0
  151. package/dist/plus/ai/providers/geminiProvider.d.ts.map +1 -1
  152. package/dist/plus/ai/providers/geminiProvider.js +19 -0
  153. package/dist/plus/ai/providers/geminiProvider.js.map +1 -1
  154. package/dist/plus/ai/providers/gitkrakenProvider.d.ts +5 -1
  155. package/dist/plus/ai/providers/gitkrakenProvider.d.ts.map +1 -1
  156. package/dist/plus/ai/providers/gitkrakenProvider.js +118 -3
  157. package/dist/plus/ai/providers/gitkrakenProvider.js.map +1 -1
  158. package/dist/plus/ai/providers/huggingFaceProvider.d.ts +1 -0
  159. package/dist/plus/ai/providers/huggingFaceProvider.d.ts.map +1 -1
  160. package/dist/plus/ai/providers/huggingFaceProvider.js +5 -0
  161. package/dist/plus/ai/providers/huggingFaceProvider.js.map +1 -1
  162. package/dist/plus/ai/providers/mistralProvider.d.ts +3 -1
  163. package/dist/plus/ai/providers/mistralProvider.d.ts.map +1 -1
  164. package/dist/plus/ai/providers/mistralProvider.js +99 -19
  165. package/dist/plus/ai/providers/mistralProvider.js.map +1 -1
  166. package/dist/plus/ai/providers/ollamaProvider.d.ts +4 -3
  167. package/dist/plus/ai/providers/ollamaProvider.d.ts.map +1 -1
  168. package/dist/plus/ai/providers/ollamaProvider.js +38 -3
  169. package/dist/plus/ai/providers/ollamaProvider.js.map +1 -1
  170. package/dist/plus/ai/providers/openAICompatibleProvider.d.ts +1 -0
  171. package/dist/plus/ai/providers/openAICompatibleProvider.d.ts.map +1 -1
  172. package/dist/plus/ai/providers/openAICompatibleProvider.js +4 -0
  173. package/dist/plus/ai/providers/openAICompatibleProvider.js.map +1 -1
  174. package/dist/plus/ai/providers/openAICompatibleProviderBase.d.ts +154 -5
  175. package/dist/plus/ai/providers/openAICompatibleProviderBase.d.ts.map +1 -1
  176. package/dist/plus/ai/providers/openAICompatibleProviderBase.js +259 -10
  177. package/dist/plus/ai/providers/openAICompatibleProviderBase.js.map +1 -1
  178. package/dist/plus/ai/providers/openRouterProvider.d.ts +4 -0
  179. package/dist/plus/ai/providers/openRouterProvider.d.ts.map +1 -1
  180. package/dist/plus/ai/providers/openRouterProvider.js +9 -0
  181. package/dist/plus/ai/providers/openRouterProvider.js.map +1 -1
  182. package/dist/plus/ai/providers/openaiProvider.d.ts +1 -0
  183. package/dist/plus/ai/providers/openaiProvider.d.ts.map +1 -1
  184. package/dist/plus/ai/providers/openaiProvider.js +1 -0
  185. package/dist/plus/ai/providers/openaiProvider.js.map +1 -1
  186. package/dist/plus/ai/providers/responseFormatCache.d.ts +8 -0
  187. package/dist/plus/ai/providers/responseFormatCache.d.ts.map +1 -0
  188. package/dist/plus/ai/providers/responseFormatCache.js +25 -0
  189. package/dist/plus/ai/providers/responseFormatCache.js.map +1 -0
  190. package/dist/plus/ai/providers/xaiProvider.d.ts +1 -0
  191. package/dist/plus/ai/providers/xaiProvider.d.ts.map +1 -1
  192. package/dist/plus/ai/providers/xaiProvider.js +10 -1
  193. package/dist/plus/ai/providers/xaiProvider.js.map +1 -1
  194. package/dist/plus/ai/utils/ai.utils.d.ts +3 -0
  195. package/dist/plus/ai/utils/ai.utils.d.ts.map +1 -1
  196. package/dist/plus/ai/utils/ai.utils.js +13 -0
  197. package/dist/plus/ai/utils/ai.utils.js.map +1 -1
  198. package/dist/plus/ai/utils/results.utils.d.ts +16 -2
  199. package/dist/plus/ai/utils/results.utils.d.ts.map +1 -1
  200. package/dist/plus/ai/utils/results.utils.js +204 -28
  201. package/dist/plus/ai/utils/results.utils.js.map +1 -1
  202. package/dist/plus/git-github/api/github.d.ts +92 -4
  203. package/dist/plus/git-github/api/github.d.ts.map +1 -1
  204. package/dist/plus/git-github/api/github.js +324 -20
  205. package/dist/plus/git-github/api/github.js.map +1 -1
  206. package/dist/plus/git-github/api/pullRequestSearchQuery.d.ts +27 -1
  207. package/dist/plus/git-github/api/pullRequestSearchQuery.d.ts.map +1 -1
  208. package/dist/plus/git-github/api/pullRequestSearchQuery.js +73 -6
  209. package/dist/plus/git-github/api/pullRequestSearchQuery.js.map +1 -1
  210. package/dist/plus/git-github/models.d.ts +33 -5
  211. package/dist/plus/git-github/models.d.ts.map +1 -1
  212. package/dist/plus/git-github/models.js +43 -4
  213. package/dist/plus/git-github/models.js.map +1 -1
  214. package/dist/plus/git-github/providers/github/status.d.ts +1 -0
  215. package/dist/plus/git-github/providers/github/status.d.ts.map +1 -1
  216. package/dist/plus/git-github/providers/github/status.js.map +1 -1
  217. package/dist/plus/integrations/context.d.ts +4 -0
  218. package/dist/plus/integrations/context.d.ts.map +1 -1
  219. package/dist/plus/integrations/index.d.ts.map +1 -1
  220. package/dist/plus/integrations/index.js +2 -0
  221. package/dist/plus/integrations/index.js.map +1 -1
  222. package/dist/plus/integrations/integrationService.d.ts +16 -1
  223. package/dist/plus/integrations/integrationService.d.ts.map +1 -1
  224. package/dist/plus/integrations/integrationService.js +9 -1
  225. package/dist/plus/integrations/integrationService.js.map +1 -1
  226. package/dist/plus/integrations/manager.d.ts +45 -5
  227. package/dist/plus/integrations/manager.d.ts.map +1 -1
  228. package/dist/plus/integrations/models/gitHostIntegration.d.ts +18 -3
  229. package/dist/plus/integrations/models/gitHostIntegration.d.ts.map +1 -1
  230. package/dist/plus/integrations/models/gitHostIntegration.js +30 -2
  231. package/dist/plus/integrations/models/gitHostIntegration.js.map +1 -1
  232. package/dist/plus/integrations/models/integration.d.ts +4 -2
  233. package/dist/plus/integrations/models/integration.d.ts.map +1 -1
  234. package/dist/plus/integrations/models/integration.js +2 -2
  235. package/dist/plus/integrations/models/integration.js.map +1 -1
  236. package/dist/plus/integrations/providerFilters.d.ts +1 -1
  237. package/dist/plus/integrations/providerFilters.d.ts.map +1 -1
  238. package/dist/plus/integrations/providers/accounts.d.ts +6 -0
  239. package/dist/plus/integrations/providers/accounts.d.ts.map +1 -0
  240. package/dist/plus/integrations/providers/accounts.js +34 -0
  241. package/dist/plus/integrations/providers/accounts.js.map +1 -0
  242. package/dist/plus/integrations/providers/azure/models.d.ts.map +1 -1
  243. package/dist/plus/integrations/providers/azure/models.js +3 -0
  244. package/dist/plus/integrations/providers/azure/models.js.map +1 -1
  245. package/dist/plus/integrations/providers/bitbucket/models.d.ts.map +1 -1
  246. package/dist/plus/integrations/providers/bitbucket/models.js +1 -0
  247. package/dist/plus/integrations/providers/bitbucket/models.js.map +1 -1
  248. package/dist/plus/integrations/providers/github.d.ts +23 -2
  249. package/dist/plus/integrations/providers/github.d.ts.map +1 -1
  250. package/dist/plus/integrations/providers/github.js +169 -138
  251. package/dist/plus/integrations/providers/github.js.map +1 -1
  252. package/dist/plus/integrations/providers/gitlab.d.ts +9 -0
  253. package/dist/plus/integrations/providers/gitlab.d.ts.map +1 -1
  254. package/dist/plus/integrations/providers/gitlab.js +23 -4
  255. package/dist/plus/integrations/providers/gitlab.js.map +1 -1
  256. package/dist/plus/integrations/providers/models.d.ts +14 -32
  257. package/dist/plus/integrations/providers/models.d.ts.map +1 -1
  258. package/dist/plus/integrations/providers/models.js +66 -109
  259. package/dist/plus/integrations/providers/models.js.map +1 -1
  260. package/dist/plus/integrations/providers/pullRequestReviews.d.ts +50 -0
  261. package/dist/plus/integrations/providers/pullRequestReviews.d.ts.map +1 -0
  262. package/dist/plus/integrations/providers/pullRequestReviews.js +99 -0
  263. package/dist/plus/integrations/providers/pullRequestReviews.js.map +1 -0
  264. package/dist/plus/integrations/reads/broaden.d.ts.map +1 -1
  265. package/dist/plus/integrations/reads/broaden.js +6 -1
  266. package/dist/plus/integrations/reads/broaden.js.map +1 -1
  267. package/dist/plus/integrations/reads/counts.d.ts +55 -0
  268. package/dist/plus/integrations/reads/counts.d.ts.map +1 -1
  269. package/dist/plus/integrations/reads/counts.js +146 -2
  270. package/dist/plus/integrations/reads/counts.js.map +1 -1
  271. package/dist/plus/integrations/reads/drains.d.ts +7 -1
  272. package/dist/plus/integrations/reads/drains.d.ts.map +1 -1
  273. package/dist/plus/integrations/reads/drains.js +20 -6
  274. package/dist/plus/integrations/reads/drains.js.map +1 -1
  275. package/dist/plus/integrations/reads/filters.d.ts.map +1 -1
  276. package/dist/plus/integrations/reads/filters.js +22 -0
  277. package/dist/plus/integrations/reads/filters.js.map +1 -1
  278. package/dist/plus/integrations/reads/hierarchy.d.ts.map +1 -1
  279. package/dist/plus/integrations/reads/hierarchy.js +3 -1
  280. package/dist/plus/integrations/reads/hierarchy.js.map +1 -1
  281. package/dist/plus/integrations/reads/issueTracker.d.ts.map +1 -1
  282. package/dist/plus/integrations/reads/issueTracker.js +8 -3
  283. package/dist/plus/integrations/reads/issueTracker.js.map +1 -1
  284. package/dist/plus/integrations/reads/issues.d.ts.map +1 -1
  285. package/dist/plus/integrations/reads/issues.js +9 -4
  286. package/dist/plus/integrations/reads/issues.js.map +1 -1
  287. package/dist/plus/integrations/reads/pullRequests.d.ts.map +1 -1
  288. package/dist/plus/integrations/reads/pullRequests.js +9 -4
  289. package/dist/plus/integrations/reads/pullRequests.js.map +1 -1
  290. package/dist/plus/integrations/reads/searchPullRequests.d.ts +4 -3
  291. package/dist/plus/integrations/reads/searchPullRequests.d.ts.map +1 -1
  292. package/dist/plus/integrations/reads/searchPullRequests.js +6 -4
  293. package/dist/plus/integrations/reads/searchPullRequests.js.map +1 -1
  294. package/dist/plus/integrations/reads/sweeps.js +1 -1
  295. package/dist/plus/integrations/reads/sweeps.js.map +1 -1
  296. package/dist/plus/integrations/reads/warnings.d.ts +2 -2
  297. package/dist/plus/integrations/reads/warnings.d.ts.map +1 -1
  298. package/dist/plus/integrations/reads/warnings.js +11 -2
  299. package/dist/plus/integrations/reads/warnings.js.map +1 -1
  300. package/dist/plus/integrations/results.d.ts +6 -1
  301. package/dist/plus/integrations/results.d.ts.map +1 -1
  302. package/dist/plus/integrations/results.js.map +1 -1
  303. package/dist/utils/env/browser/base64.d.ts +1 -1
  304. package/dist/utils/env/browser/base64.d.ts.map +1 -1
  305. package/dist/utils/env/node/base64.d.ts +1 -1
  306. package/dist/utils/env/node/base64.d.ts.map +1 -1
  307. package/dist/utils/env/node/base64.js +2 -0
  308. package/dist/utils/env/node/base64.js.map +1 -1
  309. package/dist/utils/keys/chord.d.ts +52 -0
  310. package/dist/utils/keys/chord.d.ts.map +1 -0
  311. package/dist/utils/keys/chord.js +135 -0
  312. package/dist/utils/keys/chord.js.map +1 -0
  313. package/dist/utils/keys/keybinding.d.ts +53 -0
  314. package/dist/utils/keys/keybinding.d.ts.map +1 -0
  315. package/dist/utils/keys/keybinding.js +58 -0
  316. package/dist/utils/keys/keybinding.js.map +1 -0
  317. package/dist/utils/path.d.ts +11 -0
  318. package/dist/utils/path.d.ts.map +1 -1
  319. package/dist/utils/path.js +13 -0
  320. package/dist/utils/path.js.map +1 -1
  321. package/docs/integrations.md +76 -10
  322. package/docs/kepler-read-api-parity.md +9 -0
  323. package/package.json +13 -5
  324. package/src/git/cache.ts +383 -47
  325. package/src/git/context.ts +11 -0
  326. package/src/git/models/fileStatus.ts +1 -0
  327. package/src/git/models/issue.ts +4 -0
  328. package/src/git/models/mergeConflicts.ts +3 -2
  329. package/src/git/models/pullRequest.ts +117 -1
  330. package/src/git/models/repository.ts +58 -17
  331. package/src/git/models/statusFile.ts +3 -0
  332. package/src/git/providers/branches.ts +6 -0
  333. package/src/git/providers/commits.ts +11 -0
  334. package/src/git/providers/config.ts +18 -0
  335. package/src/git/providers/operations.ts +1 -0
  336. package/src/git/providers/pausedOperations.ts +2 -0
  337. package/src/git/providers/status.ts +1 -0
  338. package/src/git/utils/config.utils.ts +8 -0
  339. package/src/git/utils/issue.utils.ts +2 -0
  340. package/src/git/utils/pausedOperationStatus.utils.ts +28 -0
  341. package/src/git/utils/pullRequest.utils.ts +86 -0
  342. package/src/git/watching/changeEvent.ts +6 -1
  343. package/src/git/watching/classifyChange.ts +15 -1
  344. package/src/git/watching/watchService.ts +20 -3
  345. package/src/git/watching/watchSession.ts +41 -6
  346. package/src/git/watching/watcherPatterns.ts +1 -1
  347. package/src/git-cli/exec/git.ts +13 -3
  348. package/src/git-cli/providers/branches.ts +384 -132
  349. package/src/git-cli/providers/commits.ts +106 -15
  350. package/src/git-cli/providers/config.ts +229 -8
  351. package/src/git-cli/providers/contributors.ts +5 -1
  352. package/src/git-cli/providers/graph.ts +26 -13
  353. package/src/git-cli/providers/operations.ts +45 -20
  354. package/src/git-cli/providers/pausedOperations.ts +109 -17
  355. package/src/git-cli/providers/refs.ts +33 -3
  356. package/src/git-cli/providers/status.ts +25 -4
  357. package/src/git-cli/providers/worktrees.ts +5 -0
  358. package/src/git-cli/service.ts +0 -1
  359. package/src/plus/agents/providers/claudeCodeProvider.ts +1130 -87
  360. package/src/plus/agents/providers/claudeCodeTranscript.ts +95 -9
  361. package/src/plus/agents/types.ts +46 -2
  362. package/src/plus/ai/errors.ts +30 -0
  363. package/src/plus/ai/models/model.ts +56 -6
  364. package/src/plus/ai/models/promptTemplates.ts +1 -1
  365. package/src/plus/ai/models/provider.ts +69 -2
  366. package/src/plus/ai/prompts.ts +186 -61
  367. package/src/plus/ai/providers/anthropicProvider.ts +155 -47
  368. package/src/plus/ai/providers/deepSeekProvider.ts +11 -21
  369. package/src/plus/ai/providers/geminiProvider.ts +19 -0
  370. package/src/plus/ai/providers/gitkrakenProvider.ts +126 -3
  371. package/src/plus/ai/providers/huggingFaceProvider.ts +6 -0
  372. package/src/plus/ai/providers/mistralProvider.ts +102 -19
  373. package/src/plus/ai/providers/ollamaProvider.ts +55 -4
  374. package/src/plus/ai/providers/openAICompatibleProvider.ts +5 -0
  375. package/src/plus/ai/providers/openAICompatibleProviderBase.ts +360 -17
  376. package/src/plus/ai/providers/openRouterProvider.ts +17 -0
  377. package/src/plus/ai/providers/openaiProvider.ts +1 -0
  378. package/src/plus/ai/providers/responseFormatCache.ts +39 -0
  379. package/src/plus/ai/providers/xaiProvider.ts +10 -1
  380. package/src/plus/ai/utils/ai.utils.ts +14 -0
  381. package/src/plus/ai/utils/results.utils.ts +255 -31
  382. package/src/plus/git-github/api/github.ts +467 -23
  383. package/src/plus/git-github/api/pullRequestSearchQuery.ts +81 -7
  384. package/src/plus/git-github/models.ts +77 -7
  385. package/src/plus/git-github/providers/github/status.ts +1 -0
  386. package/src/plus/integrations/context.ts +4 -0
  387. package/src/plus/integrations/index.ts +2 -0
  388. package/src/plus/integrations/integrationService.ts +25 -2
  389. package/src/plus/integrations/manager.ts +50 -5
  390. package/src/plus/integrations/models/gitHostIntegration.ts +54 -2
  391. package/src/plus/integrations/models/integration.ts +24 -13
  392. package/src/plus/integrations/providerFilters.ts +6 -1
  393. package/src/plus/integrations/providers/accounts.ts +38 -0
  394. package/src/plus/integrations/providers/azure/models.ts +3 -0
  395. package/src/plus/integrations/providers/bitbucket/models.ts +1 -0
  396. package/src/plus/integrations/providers/github.ts +218 -145
  397. package/src/plus/integrations/providers/gitlab.ts +30 -20
  398. package/src/plus/integrations/providers/models.ts +99 -127
  399. package/src/plus/integrations/providers/pullRequestReviews.ts +122 -0
  400. package/src/plus/integrations/reads/broaden.ts +6 -1
  401. package/src/plus/integrations/reads/counts.ts +273 -2
  402. package/src/plus/integrations/reads/drains.ts +19 -6
  403. package/src/plus/integrations/reads/filters.ts +22 -0
  404. package/src/plus/integrations/reads/hierarchy.ts +3 -1
  405. package/src/plus/integrations/reads/issueTracker.ts +9 -3
  406. package/src/plus/integrations/reads/issues.ts +9 -4
  407. package/src/plus/integrations/reads/pullRequests.ts +9 -4
  408. package/src/plus/integrations/reads/searchPullRequests.ts +12 -4
  409. package/src/plus/integrations/reads/sweeps.ts +1 -1
  410. package/src/plus/integrations/reads/warnings.ts +12 -1
  411. package/src/plus/integrations/results.ts +6 -1
  412. package/src/utils/env/browser/base64.ts +1 -1
  413. package/src/utils/env/node/base64.ts +3 -1
  414. package/src/utils/keys/chord.ts +184 -0
  415. package/src/utils/keys/keybinding.ts +116 -0
  416. package/src/utils/path.ts +14 -0
@@ -2,6 +2,7 @@ import { createReadStream } from 'fs';
2
2
  import { open, readdir, stat } from 'fs/promises';
3
3
  import { homedir } from 'os';
4
4
  import { basename, join } from 'path';
5
+ import { createInterface } from 'readline';
5
6
 
6
7
  export interface TranscriptTitles {
7
8
  custom?: string;
@@ -30,6 +31,12 @@ export interface TranscriptSessionListing {
30
31
  readonly total: number;
31
32
  }
32
33
 
34
+ export interface CompletedTranscriptDetails {
35
+ titles: TranscriptTitles;
36
+ firstPrompt?: string;
37
+ lastPrompt?: string;
38
+ }
39
+
33
40
  interface CacheEntry {
34
41
  path: string;
35
42
  mtimeMs: number;
@@ -147,12 +154,70 @@ export class ClaudeCodeTranscriptReader {
147
154
  this._generations.delete(sessionId);
148
155
  }
149
156
 
157
+ /**
158
+ * One-shot read for a *completed* (terminal, static) session: extracts the transcript titles plus
159
+ * the first and last user prompts. Unlike {@link resolve}, it bypasses the tail cache — a finished
160
+ * transcript never grows, so it's read once on demand (when a completed row is opened) and the
161
+ * result applied to the session. `last-prompt` entries carry the prompt as of that point; the first
162
+ * one bearing a value is the session's opening prompt, the last its most recent. Returns `undefined`
163
+ * when no transcript is found (archived/purged) — the caller keeps whatever durable-store fields it
164
+ * already has.
165
+ *
166
+ * Streams the file line-by-line rather than buffering it whole: a finished transcript can run to
167
+ * tens of MB, but this keeps only one line resident at a time. A *full* scan (not a head/tail
168
+ * window) is required for correctness — when the first turn is large the opening `last-prompt` sits
169
+ * past any fixed head window, and a windowed read would then mistake a later prompt for the first,
170
+ * poisoning the derived session name.
171
+ */
172
+ async resolveCompletedDetails(
173
+ sessionId: string,
174
+ cwd: string | undefined,
175
+ ): Promise<CompletedTranscriptDetails | undefined> {
176
+ const path = await this.locateTranscript(sessionId, cwd);
177
+ if (path == null) return undefined;
178
+
179
+ let stats;
180
+ try {
181
+ stats = await stat(path);
182
+ } catch (ex) {
183
+ // A transcript that vanished is terminal; an I/O or permission failure must propagate so
184
+ // the caller retries rather than caching this session as permanently unresolvable.
185
+ if (!isMissingEntry(ex)) throw ex;
186
+
187
+ return undefined;
188
+ }
189
+ if (stats.size === 0) return undefined;
190
+
191
+ const titles: TranscriptTitles = {};
192
+ let firstPrompt: string | undefined;
193
+ let lastPrompt: string | undefined;
194
+
195
+ const rl = createInterface({ input: createReadStream(path, { encoding: 'utf8' }), crlfDelay: Infinity });
196
+ try {
197
+ for await (const line of rl) {
198
+ applyTitleLine(line, sessionId, titles);
199
+ if (!line.includes('last-prompt')) continue;
200
+
201
+ const entry = parseSummaryLine(line, sessionId);
202
+ if (entry?.type === 'last-prompt' && entry.lastPrompt != null && entry.lastPrompt.length > 0) {
203
+ firstPrompt ??= entry.lastPrompt;
204
+ lastPrompt = entry.lastPrompt;
205
+ }
206
+ }
207
+ } finally {
208
+ rl.close();
209
+ }
210
+
211
+ return { titles: titles, firstPrompt: firstPrompt, lastPrompt: lastPrompt };
212
+ }
213
+
150
214
  /**
151
215
  * Lists the transcripts of sessions whose working directory is `cwd`, most-recently-active first,
152
216
  * summarizing until `limit` summarizable transcripts are found (bounded by a small scan slack) —
153
217
  * not just the first `limit` on disk, since junk transcripts (dropped below) would otherwise starve
154
- * the result. `excludeSessionIds` is skipped before `limit` applies, but excluded entries still
155
- * count toward `total`.
218
+ * the result. `excludeSessionIds` is skipped before `limit` applies, and excluded entries are also
219
+ * dropped from `total` — they're already shown elsewhere (e.g. as live sessions), so a caller's
220
+ * "N of M" count must not double-count them.
156
221
  *
157
222
  * Claude homes a transcript under the directory encoding the session's *current* cwd, migrating the
158
223
  * file if the session `cd`s — so this directory is exactly the set `claude --resume <id>` can find
@@ -192,7 +257,7 @@ export class ClaudeCodeTranscriptReader {
192
257
  // limit <= 0 means "no ceiling" — summarize every candidate.
193
258
  if (limit <= 0) {
194
259
  pushSummaries(await Promise.allSettled(candidates.map(e => this.resolveSummary(e))));
195
- return { sessions: sessions, total: entries.length };
260
+ return { sessions: sessions, total: candidates.length };
196
261
  }
197
262
 
198
263
  const ceiling = Math.min(candidates.length, limit + listScanSlack);
@@ -205,7 +270,7 @@ export class ClaudeCodeTranscriptReader {
205
270
  pushSummaries(await Promise.allSettled(batch.map(e => this.resolveSummary(e))));
206
271
  }
207
272
 
208
- return { sessions: sessions, total: entries.length };
273
+ return { sessions: sessions, total: candidates.length };
209
274
  }
210
275
 
211
276
  /** Discovers every transcript in `dir`, newest first. The directory also holds one sibling
@@ -353,7 +418,11 @@ export class ClaudeCodeTranscriptReader {
353
418
  let dirs: string[];
354
419
  try {
355
420
  dirs = await readdir(root);
356
- } catch {
421
+ } catch (ex) {
422
+ // Only a missing projects root means "no transcript". A transient failure propagates so the
423
+ // caller retries instead of caching a permanent miss.
424
+ if (!isMissingEntry(ex)) throw ex;
425
+
357
426
  return undefined;
358
427
  }
359
428
 
@@ -377,7 +446,9 @@ export class ClaudeCodeTranscriptReader {
377
446
  let dirs: string[];
378
447
  try {
379
448
  dirs = await readdir(root);
380
- } catch {
449
+ } catch (ex) {
450
+ if (!isMissingEntry(ex)) throw ex;
451
+
381
452
  return undefined;
382
453
  }
383
454
 
@@ -501,7 +572,10 @@ async function fileExists(path: string): Promise<boolean> {
501
572
  try {
502
573
  const stats = await stat(path);
503
574
  return stats.isFile();
504
- } catch {
575
+ } catch (ex) {
576
+ // See {@link isMissingEntry}: only a genuine absence is an answer.
577
+ if (!isMissingEntry(ex)) throw ex;
578
+
505
579
  return false;
506
580
  }
507
581
  }
@@ -510,11 +584,23 @@ async function directoryExists(path: string): Promise<boolean> {
510
584
  try {
511
585
  const stats = await stat(path);
512
586
  return stats.isDirectory();
513
- } catch {
514
- return false;
587
+ } catch (ex) {
588
+ // "Not there" is an answer; anything else (EACCES, EIO, a mount hiccup) is a transient
589
+ // failure the caller must be able to tell apart — see {@link isMissingEntry}.
590
+ if (isMissingEntry(ex)) return false;
591
+
592
+ throw ex;
515
593
  }
516
594
  }
517
595
 
596
+ /** True for the "path simply isn't there" errno codes, as opposed to a transient I/O or permission
597
+ * failure. Callers cache a genuine absence as terminal, so a transient failure must not look like
598
+ * one — it would pin a session to its fallback name until the window reloads. */
599
+ function isMissingEntry(ex: unknown): boolean {
600
+ const code = (ex as NodeJS.ErrnoException | undefined)?.code;
601
+ return code === 'ENOENT' || code === 'ENOTDIR';
602
+ }
603
+
518
604
  function readSlice(path: string, start: number, end: number): Promise<Buffer> {
519
605
  return new Promise((resolve, reject) => {
520
606
  const chunks: Buffer[] = [];
@@ -43,9 +43,12 @@ export type AgentSessionStatus =
43
43
  | 'waiting'
44
44
  | 'idle'
45
45
  | 'compacting'
46
- | 'permission_requested';
46
+ | 'permission_requested'
47
+ // Terminal state: the session has ended (SessionEnd fired, or the CLI's durable store reports it
48
+ // `ended`). Kept in the list as a de-emphasized "completed" row until archived or 30-day-purged.
49
+ | 'completed';
47
50
 
48
- export type AgentSessionPhase = 'idle' | 'working' | 'waiting';
51
+ export type AgentSessionPhase = 'idle' | 'working' | 'waiting' | 'completed';
49
52
 
50
53
  export function getPhaseForStatus(status: AgentSessionStatus): AgentSessionPhase {
51
54
  switch (status) {
@@ -59,6 +62,8 @@ export function getPhaseForStatus(status: AgentSessionStatus): AgentSessionPhase
59
62
  return 'waiting';
60
63
  case 'idle':
61
64
  return 'idle';
65
+ case 'completed':
66
+ return 'completed';
62
67
  }
63
68
  }
64
69
 
@@ -101,6 +106,12 @@ export interface PendingPermission {
101
106
  readonly questionText?: string;
102
107
  /** Question-mode: total number of questions in the batch. */
103
108
  readonly questionCount?: number;
109
+ /** `false` when GitLens holds no blocking hook entry to answer this ask, so `resolvePermission`
110
+ * can never route an Allow/Deny — the user must respond in the agent's own session. Set for
111
+ * elicitations (delivered on a non-blocking hook) and for asks discovered by the reconciliation
112
+ * poll instead of this window's IPC path. Surfaces must render an explanatory, button-less card
113
+ * when this is `false`. */
114
+ readonly resolvable?: boolean;
104
115
  }
105
116
 
106
117
  export interface AgentSession {
@@ -152,6 +163,16 @@ export interface AgentSession {
152
163
  readonly isInWorkspace: boolean;
153
164
  readonly lastPrompt?: string;
154
165
  readonly firstPrompt?: string;
166
+ /** The model the session is running (e.g. `claude-opus-4-5`). Arrives on every hook event and in
167
+ * the CLI's durable session record. */
168
+ readonly model?: string;
169
+ /** Why the session ended: `session-end | rotated | stale | dead-pid | pid-zero-idle | archived`.
170
+ * Present only for `completed` sessions. */
171
+ readonly endReason?: string;
172
+ /** Epoch ms the session ended — matches the RPC convention for dates crossing to a webview
173
+ * (see `PastAgentSessionState.lastActivity`), and keeps `SerializedAgentSession` free of
174
+ * another `Date`→string override. */
175
+ readonly endedAt?: number;
155
176
  /** Per-file activity record covering both read-class (Read/NotebookRead) and edit-class
156
177
  * (Edit/Write/MultiEdit/NotebookEdit) tool calls. Populated on PreToolUse; each path is retained
157
178
  * and fades for the configured decay window measured from its own last PostToolUse — the tail
@@ -210,6 +231,10 @@ export interface AgentSessionProvider extends UnifiedDisposable {
210
231
  stop(): void;
211
232
  updateWorkspacePaths?(workspacePaths: string[]): void;
212
233
 
234
+ /** Forces an ungated reconciliation with the provider's durable session store (e.g. the sidebar's
235
+ * Refresh action). Omitted by providers with no durable store to poll. */
236
+ sync?(): Promise<void>;
237
+
213
238
  /** Pushed by the host from its cached agent detection. Lets the provider gate its reconciliation
214
239
  * poll (the CLI `list-sessions` call) so an idle window with no sessions and no installed hooks
215
240
  * doesn't spawn the CLI every interval. */
@@ -240,6 +265,25 @@ export interface AgentSessionProvider extends UnifiedDisposable {
240
265
  * set via {@link ResumableSessionsOptions.excludeSessionIds} so exclusion happens before `limit`
241
266
  * applies rather than after. */
242
267
  listResumableSessions?(cwd: string, options?: ResumableSessionsOptions): Promise<ResumableSessionsResult>;
268
+
269
+ /** Archives a completed (non-live) session via the CLI, dismissing it from the list. Ends an
270
+ * active session first (the CLI broadcasts a synthetic SessionEnd) — but callers should only
271
+ * offer this on `completed` sessions, and a provider refuses (returns `false`) any non-completed
272
+ * row that resumed since the click, so the CLI never terminates live work. Resolves to `true` when
273
+ * the session was archived (removed locally; the next reconciliation poll confirms it). */
274
+ archiveSession?(sessionId: string): Promise<boolean>;
275
+
276
+ /** Resolves git identity + the transcript title and first/last prompt for a completed session
277
+ * lazily — called by the host when the user *opens* a completed row (the `Open Session` action),
278
+ * not on mere display. Completed sessions skip eager resolution during the poll so a 30-day
279
+ * cold-start doesn't fan out hundreds of git probes + transcript reads; the row shows its
280
+ * durable-store label until opened. No-op if the session isn't a tracked completed one. */
281
+ resolveCompletedSessionDetails?(sessionId: string): void;
282
+
283
+ /** Lists the ids of sessions that have been archived. Used to exclude them from the "Past"
284
+ * transcript-store listing — the tracked row is gone once archived, but the transcript on disk
285
+ * survives and would otherwise resurface there. Resolves to `[]` on any error. */
286
+ getArchivedSessionIds?(): Promise<string[]>;
243
287
  }
244
288
 
245
289
  export interface ResumableSessionsOptions {
@@ -120,3 +120,33 @@ export function classifyNetworkError(ex: unknown): AIErrorReason.NoNetwork | AIE
120
120
  }
121
121
  return sawFetchFailed ? AIErrorReason.NoNetwork : undefined;
122
122
  }
123
+
124
+ /**
125
+ * Whether an error means AI itself is unavailable, rather than this particular request being
126
+ * unacceptable. The distinction matters to any caller running a loop: an unavailable-AI failure will
127
+ * repeat identically for every remaining item, so the loop should stop and say so, while a
128
+ * request-shaped failure (too large, no data) may well succeed on the next item.
129
+ *
130
+ * `RequestTooLarge` and `NoRequestData` are therefore deliberately excluded — they're properties of
131
+ * the one request that failed.
132
+ */
133
+ export function isAIUnavailableError(ex: unknown): ex is AIError {
134
+ if (!(ex instanceof AIError)) return false;
135
+
136
+ switch (ex.reason) {
137
+ case AIErrorReason.DeniedByOrganization:
138
+ case AIErrorReason.DeniedByUser:
139
+ case AIErrorReason.NoEntitlement:
140
+ case AIErrorReason.RateLimitExceeded:
141
+ case AIErrorReason.RateLimitOrFundsExceeded:
142
+ case AIErrorReason.ServiceCapacityExceeded:
143
+ case AIErrorReason.Unauthorized:
144
+ case AIErrorReason.UserQuotaExceeded:
145
+ case AIErrorReason.NoNetwork:
146
+ case AIErrorReason.Unreachable:
147
+ case AIErrorReason.ModelNotSupported:
148
+ return true;
149
+ default:
150
+ return false;
151
+ }
152
+ }
@@ -15,6 +15,11 @@ export interface AIModel<Provider extends AIProviders = AIProviders, Model exten
15
15
  readonly temperature?: number | null;
16
16
 
17
17
  readonly consumptionRateLabel?: string;
18
+
19
+ /** Whether the model supports native structured output (JSON schema); absent means capable
20
+ * (new models default on). Populated by dynamic catalogs (GitKraken, OpenRouter) and set to
21
+ * false on legacy static-registry entries; provider-wide gaps override the provider hook */
22
+ readonly supportsStructuredOutputs?: boolean;
18
23
  }
19
24
 
20
25
  export interface AIModelDescriptor<Provider extends AIProviders = AIProviders, Model extends string = string> {
@@ -50,36 +55,61 @@ export interface AIProviderDescriptorWithConfiguration<
50
55
  }
51
56
 
52
57
  export const openAIModels = <T extends OpenAIProviders>(provider: AIProviderDescriptor<T>): AIModel<T>[] => [
58
+ {
59
+ id: 'gpt-5.6',
60
+ name: 'GPT-5.6 Sol',
61
+ maxTokens: { input: 922000, output: 128000 }, // 1.05M context, but OpenAI caps input at 922k
62
+ provider: provider,
63
+ },
64
+ {
65
+ id: 'gpt-5.6-sol',
66
+ name: 'GPT-5.6 Sol',
67
+ maxTokens: { input: 922000, output: 128000 },
68
+ provider: provider,
69
+ hidden: true,
70
+ },
71
+ {
72
+ id: 'gpt-5.6-terra',
73
+ name: 'GPT-5.6 Terra',
74
+ maxTokens: { input: 922000, output: 128000 },
75
+ provider: provider,
76
+ },
77
+ {
78
+ id: 'gpt-5.6-luna',
79
+ name: 'GPT-5.6 Luna',
80
+ maxTokens: { input: 922000, output: 128000 },
81
+ provider: provider,
82
+ default: true,
83
+ },
53
84
  {
54
85
  id: 'gpt-5.5',
55
86
  name: 'GPT-5.5',
56
- maxTokens: { input: 400000, output: 128000 },
87
+ maxTokens: { input: 922000, output: 128000 },
57
88
  provider: provider,
58
89
  },
59
90
  {
60
91
  id: 'gpt-5.5-pro',
61
92
  name: 'GPT-5.5 Pro',
62
- maxTokens: { input: 400000, output: 272000 },
93
+ maxTokens: { input: 922000, output: 128000 },
63
94
  provider: provider,
64
95
  hidden: true,
65
96
  },
66
97
  {
67
98
  id: 'gpt-5.4',
68
99
  name: 'GPT-5.4',
69
- maxTokens: { input: 400000, output: 128000 },
100
+ maxTokens: { input: 922000, output: 128000 },
70
101
  provider: provider,
71
102
  },
72
103
  {
73
104
  id: 'gpt-5.4-mini',
74
105
  name: 'GPT-5.4 mini',
75
- maxTokens: { input: 400000, output: 128000 },
106
+ maxTokens: { input: 272000, output: 128000 },
76
107
  provider: provider,
77
- default: true,
78
108
  },
79
109
  {
80
110
  id: 'gpt-5.4-nano',
81
111
  name: 'GPT-5.4 nano',
82
- maxTokens: { input: 400000, output: 128000 },
112
+ maxTokens: { input: 272000, output: 128000 },
83
113
  provider: provider,
84
114
  },
85
115
  {
@@ -310,6 +340,7 @@ export const openAIModels = <T extends OpenAIProviders>(provider: AIProviderDesc
310
340
  provider: provider,
311
341
  temperature: null,
312
342
  hidden: true,
343
+ supportsStructuredOutputs: false,
313
344
  },
314
345
  {
315
346
  id: 'o1-preview-2024-09-12',
@@ -318,6 +349,7 @@ export const openAIModels = <T extends OpenAIProviders>(provider: AIProviderDesc
318
349
  provider: provider,
319
350
  temperature: null,
320
351
  hidden: true,
352
+ supportsStructuredOutputs: false,
321
353
  },
322
354
  {
323
355
  id: 'o1-mini',
@@ -326,6 +358,7 @@ export const openAIModels = <T extends OpenAIProviders>(provider: AIProviderDesc
326
358
  provider: provider,
327
359
  temperature: null,
328
360
  hidden: true,
361
+ supportsStructuredOutputs: false,
329
362
  },
330
363
  {
331
364
  id: 'o1-mini-2024-09-12',
@@ -334,6 +367,7 @@ export const openAIModels = <T extends OpenAIProviders>(provider: AIProviderDesc
334
367
  provider: provider,
335
368
  temperature: null,
336
369
  hidden: true,
370
+ supportsStructuredOutputs: false,
337
371
  },
338
372
  {
339
373
  id: 'gpt-4o',
@@ -362,6 +396,8 @@ export const openAIModels = <T extends OpenAIProviders>(provider: AIProviderDesc
362
396
  maxTokens: { input: 128000, output: 4096 },
363
397
  provider: provider,
364
398
  hidden: true,
399
+ // json_schema needs gpt-4o-2024-08-06+ (or o1+); the flagged legacy ids reject it with a 400
400
+ supportsStructuredOutputs: false,
365
401
  },
366
402
  {
367
403
  id: 'chatgpt-4o-latest',
@@ -369,6 +405,7 @@ export const openAIModels = <T extends OpenAIProviders>(provider: AIProviderDesc
369
405
  maxTokens: { input: 128000, output: 16384 },
370
406
  provider: provider,
371
407
  hidden: true,
408
+ supportsStructuredOutputs: false,
372
409
  },
373
410
  {
374
411
  id: 'gpt-4o-mini',
@@ -390,6 +427,7 @@ export const openAIModels = <T extends OpenAIProviders>(provider: AIProviderDesc
390
427
  maxTokens: { input: 128000, output: 4096 },
391
428
  provider: provider,
392
429
  hidden: true,
430
+ supportsStructuredOutputs: false,
393
431
  },
394
432
  {
395
433
  id: 'gpt-4-turbo-2024-04-09',
@@ -397,6 +435,7 @@ export const openAIModels = <T extends OpenAIProviders>(provider: AIProviderDesc
397
435
  maxTokens: { input: 128000, output: 4096 },
398
436
  provider: provider,
399
437
  hidden: true,
438
+ supportsStructuredOutputs: false,
400
439
  },
401
440
  {
402
441
  id: 'gpt-4-turbo-preview',
@@ -404,6 +443,7 @@ export const openAIModels = <T extends OpenAIProviders>(provider: AIProviderDesc
404
443
  maxTokens: { input: 128000, output: 4096 },
405
444
  provider: provider,
406
445
  hidden: true,
446
+ supportsStructuredOutputs: false,
407
447
  },
408
448
  {
409
449
  id: 'gpt-4-0125-preview',
@@ -411,6 +451,7 @@ export const openAIModels = <T extends OpenAIProviders>(provider: AIProviderDesc
411
451
  maxTokens: { input: 128000, output: 4096 },
412
452
  provider: provider,
413
453
  hidden: true,
454
+ supportsStructuredOutputs: false,
414
455
  },
415
456
  {
416
457
  id: 'gpt-4-1106-preview',
@@ -418,6 +459,7 @@ export const openAIModels = <T extends OpenAIProviders>(provider: AIProviderDesc
418
459
  maxTokens: { input: 128000, output: 4096 },
419
460
  provider: provider,
420
461
  hidden: true,
462
+ supportsStructuredOutputs: false,
421
463
  },
422
464
  {
423
465
  id: 'gpt-4',
@@ -425,6 +467,7 @@ export const openAIModels = <T extends OpenAIProviders>(provider: AIProviderDesc
425
467
  maxTokens: { input: 8192, output: 4096 },
426
468
  provider: provider,
427
469
  hidden: true,
470
+ supportsStructuredOutputs: false,
428
471
  },
429
472
  {
430
473
  id: 'gpt-4-0613',
@@ -432,6 +475,7 @@ export const openAIModels = <T extends OpenAIProviders>(provider: AIProviderDesc
432
475
  maxTokens: { input: 8192, output: 4096 },
433
476
  provider: provider,
434
477
  hidden: true,
478
+ supportsStructuredOutputs: false,
435
479
  },
436
480
  {
437
481
  id: 'gpt-4-32k',
@@ -439,6 +483,7 @@ export const openAIModels = <T extends OpenAIProviders>(provider: AIProviderDesc
439
483
  maxTokens: { input: 32768, output: 4096 },
440
484
  provider: provider,
441
485
  hidden: true,
486
+ supportsStructuredOutputs: false,
442
487
  },
443
488
  {
444
489
  id: 'gpt-4-32k-0613',
@@ -446,6 +491,7 @@ export const openAIModels = <T extends OpenAIProviders>(provider: AIProviderDesc
446
491
  maxTokens: { input: 32768, output: 4096 },
447
492
  provider: provider,
448
493
  hidden: true,
494
+ supportsStructuredOutputs: false,
449
495
  },
450
496
  {
451
497
  id: 'gpt-3.5-turbo',
@@ -453,6 +499,7 @@ export const openAIModels = <T extends OpenAIProviders>(provider: AIProviderDesc
453
499
  maxTokens: { input: 16385, output: 4096 },
454
500
  provider: provider,
455
501
  hidden: true,
502
+ supportsStructuredOutputs: false,
456
503
  },
457
504
  {
458
505
  id: 'gpt-3.5-turbo-0125',
@@ -460,6 +507,7 @@ export const openAIModels = <T extends OpenAIProviders>(provider: AIProviderDesc
460
507
  maxTokens: { input: 16385, output: 4096 },
461
508
  provider: provider,
462
509
  hidden: true,
510
+ supportsStructuredOutputs: false,
463
511
  },
464
512
  {
465
513
  id: 'gpt-3.5-turbo-1106',
@@ -467,6 +515,7 @@ export const openAIModels = <T extends OpenAIProviders>(provider: AIProviderDesc
467
515
  maxTokens: { input: 16385, output: 4096 },
468
516
  provider: provider,
469
517
  hidden: true,
518
+ supportsStructuredOutputs: false,
470
519
  },
471
520
  {
472
521
  id: 'gpt-3.5-turbo-16k',
@@ -474,5 +523,6 @@ export const openAIModels = <T extends OpenAIProviders>(provider: AIProviderDesc
474
523
  maxTokens: { input: 16385, output: 4096 },
475
524
  provider: provider,
476
525
  hidden: true,
526
+ supportsStructuredOutputs: false,
477
527
  },
478
528
  ];
@@ -133,7 +133,7 @@ export type PromptTemplateType =
133
133
  | 'start-review-pullRequest'
134
134
  | 'start-work-issue';
135
135
 
136
- type PromptTemplateVersions = '' | '_v2';
136
+ type PromptTemplateVersions = '' | '_v2' | '_v3';
137
137
 
138
138
  export type PromptTemplateId<T extends PromptTemplateType = PromptTemplateType> = `${T}${PromptTemplateVersions}`;
139
139
 
@@ -3,19 +3,77 @@ import type { Event } from '../../../utils/event.js';
3
3
  import type { AIProviders } from '../constants.js';
4
4
  import type { AIActionType, AIModel } from './model.js';
5
5
 
6
- export type AIChatMessageRole = 'assistant' | 'system' | 'user';
6
+ export type AIChatMessageRole = 'assistant' | 'system' | 'tool' | 'user';
7
+
8
+ /** A tool the model may call. `parameters` is a JSON Schema object — it maps to OpenAI's
9
+ * `function.parameters` and Anthropic's `input_schema` unchanged. */
10
+ export interface AIToolDefinition {
11
+ readonly name: string;
12
+ readonly description: string;
13
+ readonly parameters: Record<string, unknown>;
14
+ }
15
+
16
+ export interface AIToolCall {
17
+ readonly id: string;
18
+ readonly name: string;
19
+ readonly args: Record<string, unknown>;
20
+ /** Opaque provider reasoning token (the GitKraken proxy's `thought_signature`), base64-encoded.
21
+ * Must be echoed back on the next turn's assistant message or Anthropic rejects the tool result. */
22
+ readonly providerSignature?: string;
23
+ }
7
24
 
8
25
  export type AISystemChatMessage = AIChatMessage<'system'>;
9
26
  export interface AIChatMessage<T extends AIChatMessageRole = 'assistant' | 'user'> {
10
27
  role: T;
11
28
  content: string;
29
+ /** Tool calls this assistant turn requested. Only sent to providers with `supportsTools`. */
30
+ toolCalls?: readonly AIToolCall[];
31
+ /** On `tool`-role messages, the {@link AIToolCall.id} this result answers. */
32
+ toolCallId?: string;
33
+ /** On `tool`-role messages, the name of the tool that produced this result. */
34
+ toolName?: string;
12
35
  }
13
36
 
37
+ export type JSONSchemaType = 'object' | 'array' | 'string' | 'number' | 'integer' | 'boolean' | 'null';
38
+
39
+ /** Portable JSON Schema subset accepted by every capable provider (OpenAI strict, Azure, Anthropic,
40
+ * Gemini, Mistral, xAI, Ollama). Keep schemas within it: object root, `additionalProperties: false`
41
+ * on every object, every property in `required` (model optionals as `['x', 'null']` unions), and no
42
+ * pattern/format/min/max/recursion. */
43
+ export type JSONSchema = {
44
+ readonly type: JSONSchemaType | readonly JSONSchemaType[];
45
+ readonly description?: string;
46
+ readonly properties?: Readonly<Record<string, JSONSchema>>;
47
+ readonly required?: readonly string[];
48
+ readonly items?: JSONSchema;
49
+ readonly enum?: readonly string[];
50
+ readonly additionalProperties?: boolean;
51
+ };
52
+
53
+ /** Canonical response format, shaped like OpenAI's `response_format.json_schema`; providers
54
+ * translate it (the OpenAI envelope is always sent `strict: true`) */
55
+ export type AIResponseFormat = {
56
+ /** OpenAI-envelope only ([a-zA-Z0-9_-], ≤64 chars); Anthropic/Ollama drop it */
57
+ readonly name: string;
58
+ readonly schema: JSONSchema;
59
+ };
60
+
61
+ export type AIFinishReason = 'length' | 'content_filter' | 'refusal';
62
+
14
63
  export interface AIProviderResponse<T> {
15
64
  readonly id: string;
16
65
  readonly content: string;
17
66
  readonly model: AIModel;
18
67
 
68
+ /** Abnormal completion only (truncated/filtered/refused); undefined on a normal stop */
69
+ readonly finishReason?: AIFinishReason;
70
+
71
+ /** Tool calls the model requested. Present only when `tools` were sent and the model used them. */
72
+ readonly toolCalls?: readonly AIToolCall[];
73
+ /** Set when the request was retried without tools because the provider rejected them, so the
74
+ * caller can stop offering tools for the rest of the session. */
75
+ readonly toolsRejected?: boolean;
76
+
19
77
  readonly usage?: {
20
78
  readonly promptTokens?: number;
21
79
  readonly completionTokens?: number;
@@ -37,6 +95,10 @@ export interface AIProvider<Provider extends AIProviders = AIProviders> extends
37
95
  readonly id: Provider;
38
96
  readonly name: string;
39
97
 
98
+ /** Whether this provider's wire format carries tool definitions, tool calls, and tool results.
99
+ * Providers that omit it never receive tool-shaped messages — callers fall back to text-only. */
100
+ readonly supportsTools?: boolean;
101
+
40
102
  onDidChange?: Event<void>;
41
103
 
42
104
  configured(silent: boolean): Promise<boolean>;
@@ -46,13 +108,18 @@ export interface AIProvider<Provider extends AIProviders = AIProviders> extends
46
108
  action: T,
47
109
  model: AIModel<Provider>,
48
110
  apiKey: string,
49
- getMessages: (maxInputTokens: number, retries: number) => Promise<AIChatMessage[]>,
111
+ getMessages: (maxInputTokens: number, retries: number) => Promise<AIChatMessage<AIChatMessageRole>[]>,
50
112
  options: {
51
113
  signal: AbortSignal;
52
114
  modelOptions?: { outputTokens?: number; temperature?: number };
53
115
  /** Opaque session ID the GitKraken provider sends as `GK-Conversation-ID` so the backend
54
116
  * charges its per-feature fee once per session; ignored by all other providers. */
55
117
  conversationId?: string;
118
+ /** Schema for the provider to enforce natively when the model supports it; providers
119
+ * without support ignore it and the prompt's JSON description carries the load. */
120
+ responseFormat?: AIResponseFormat;
121
+ /** Tools to advertise to the model. Only passed to providers with `supportsTools`. */
122
+ tools?: readonly AIToolDefinition[];
56
123
  },
57
124
  ): Promise<AIProviderResponse<void> | undefined>;
58
125
  }