@gitkraken/core-gitlens 0.5.110 → 0.5.112

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 (362) hide show
  1. package/CHANGELOG.md +19 -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 +38 -2
  18. package/dist/git/models/pullRequest.d.ts.map +1 -1
  19. package/dist/git/models/pullRequest.js +12 -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 +14 -1
  52. package/dist/git/utils/pullRequest.utils.d.ts.map +1 -1
  53. package/dist/git/utils/pullRequest.utils.js +31 -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 +55 -0
  203. package/dist/plus/git-github/api/github.d.ts.map +1 -1
  204. package/dist/plus/git-github/api/github.js +177 -4
  205. package/dist/plus/git-github/api/github.js.map +1 -1
  206. package/dist/plus/git-github/models.d.ts +16 -0
  207. package/dist/plus/git-github/models.d.ts.map +1 -1
  208. package/dist/plus/git-github/models.js +29 -3
  209. package/dist/plus/git-github/models.js.map +1 -1
  210. package/dist/plus/git-github/providers/github/status.d.ts +1 -0
  211. package/dist/plus/git-github/providers/github/status.d.ts.map +1 -1
  212. package/dist/plus/git-github/providers/github/status.js.map +1 -1
  213. package/dist/plus/integrations/context.d.ts +4 -0
  214. package/dist/plus/integrations/context.d.ts.map +1 -1
  215. package/dist/plus/integrations/index.d.ts.map +1 -1
  216. package/dist/plus/integrations/index.js +2 -0
  217. package/dist/plus/integrations/index.js.map +1 -1
  218. package/dist/plus/integrations/models/gitHostIntegration.d.ts +6 -3
  219. package/dist/plus/integrations/models/gitHostIntegration.d.ts.map +1 -1
  220. package/dist/plus/integrations/models/gitHostIntegration.js +12 -2
  221. package/dist/plus/integrations/models/gitHostIntegration.js.map +1 -1
  222. package/dist/plus/integrations/models/integration.d.ts +3 -1
  223. package/dist/plus/integrations/models/integration.d.ts.map +1 -1
  224. package/dist/plus/integrations/models/integration.js +2 -2
  225. package/dist/plus/integrations/models/integration.js.map +1 -1
  226. package/dist/plus/integrations/providers/accounts.d.ts.map +1 -1
  227. package/dist/plus/integrations/providers/accounts.js +4 -0
  228. package/dist/plus/integrations/providers/accounts.js.map +1 -1
  229. package/dist/plus/integrations/providers/azure/models.d.ts.map +1 -1
  230. package/dist/plus/integrations/providers/azure/models.js +3 -0
  231. package/dist/plus/integrations/providers/azure/models.js.map +1 -1
  232. package/dist/plus/integrations/providers/bitbucket/models.d.ts.map +1 -1
  233. package/dist/plus/integrations/providers/bitbucket/models.js +1 -0
  234. package/dist/plus/integrations/providers/bitbucket/models.js.map +1 -1
  235. package/dist/plus/integrations/providers/github.d.ts +14 -2
  236. package/dist/plus/integrations/providers/github.d.ts.map +1 -1
  237. package/dist/plus/integrations/providers/github.js +55 -3
  238. package/dist/plus/integrations/providers/github.js.map +1 -1
  239. package/dist/plus/integrations/providers/gitlab.d.ts.map +1 -1
  240. package/dist/plus/integrations/providers/gitlab.js.map +1 -1
  241. package/dist/plus/integrations/providers/models.d.ts.map +1 -1
  242. package/dist/plus/integrations/providers/models.js +30 -4
  243. package/dist/plus/integrations/providers/models.js.map +1 -1
  244. package/dist/plus/integrations/reads/broaden.d.ts.map +1 -1
  245. package/dist/plus/integrations/reads/broaden.js +6 -1
  246. package/dist/plus/integrations/reads/broaden.js.map +1 -1
  247. package/dist/plus/integrations/reads/drains.d.ts.map +1 -1
  248. package/dist/plus/integrations/reads/drains.js +7 -4
  249. package/dist/plus/integrations/reads/drains.js.map +1 -1
  250. package/dist/plus/integrations/reads/hierarchy.d.ts.map +1 -1
  251. package/dist/plus/integrations/reads/hierarchy.js +3 -1
  252. package/dist/plus/integrations/reads/hierarchy.js.map +1 -1
  253. package/dist/plus/integrations/reads/issueTracker.d.ts.map +1 -1
  254. package/dist/plus/integrations/reads/issueTracker.js +8 -3
  255. package/dist/plus/integrations/reads/issueTracker.js.map +1 -1
  256. package/dist/plus/integrations/reads/issues.d.ts.map +1 -1
  257. package/dist/plus/integrations/reads/issues.js +9 -4
  258. package/dist/plus/integrations/reads/issues.js.map +1 -1
  259. package/dist/plus/integrations/reads/pullRequests.d.ts.map +1 -1
  260. package/dist/plus/integrations/reads/pullRequests.js +9 -4
  261. package/dist/plus/integrations/reads/pullRequests.js.map +1 -1
  262. package/dist/utils/env/browser/base64.d.ts +1 -1
  263. package/dist/utils/env/browser/base64.d.ts.map +1 -1
  264. package/dist/utils/env/node/base64.d.ts +1 -1
  265. package/dist/utils/env/node/base64.d.ts.map +1 -1
  266. package/dist/utils/env/node/base64.js +2 -0
  267. package/dist/utils/env/node/base64.js.map +1 -1
  268. package/dist/utils/keys/chord.d.ts +52 -0
  269. package/dist/utils/keys/chord.d.ts.map +1 -0
  270. package/dist/utils/keys/chord.js +135 -0
  271. package/dist/utils/keys/chord.js.map +1 -0
  272. package/dist/utils/keys/keybinding.d.ts +53 -0
  273. package/dist/utils/keys/keybinding.d.ts.map +1 -0
  274. package/dist/utils/keys/keybinding.js +58 -0
  275. package/dist/utils/keys/keybinding.js.map +1 -0
  276. package/dist/utils/path.d.ts +11 -0
  277. package/dist/utils/path.d.ts.map +1 -1
  278. package/dist/utils/path.js +13 -0
  279. package/dist/utils/path.js.map +1 -1
  280. package/package.json +13 -5
  281. package/src/git/cache.ts +383 -47
  282. package/src/git/context.ts +11 -0
  283. package/src/git/models/fileStatus.ts +1 -0
  284. package/src/git/models/issue.ts +4 -0
  285. package/src/git/models/mergeConflicts.ts +3 -2
  286. package/src/git/models/pullRequest.ts +33 -1
  287. package/src/git/models/repository.ts +58 -17
  288. package/src/git/models/statusFile.ts +3 -0
  289. package/src/git/providers/branches.ts +6 -0
  290. package/src/git/providers/commits.ts +11 -0
  291. package/src/git/providers/config.ts +18 -0
  292. package/src/git/providers/operations.ts +1 -0
  293. package/src/git/providers/pausedOperations.ts +2 -0
  294. package/src/git/providers/status.ts +1 -0
  295. package/src/git/utils/config.utils.ts +8 -0
  296. package/src/git/utils/issue.utils.ts +2 -0
  297. package/src/git/utils/pausedOperationStatus.utils.ts +28 -0
  298. package/src/git/utils/pullRequest.utils.ts +36 -0
  299. package/src/git/watching/changeEvent.ts +6 -1
  300. package/src/git/watching/classifyChange.ts +15 -1
  301. package/src/git/watching/watchService.ts +20 -3
  302. package/src/git/watching/watchSession.ts +41 -6
  303. package/src/git/watching/watcherPatterns.ts +1 -1
  304. package/src/git-cli/exec/git.ts +13 -3
  305. package/src/git-cli/providers/branches.ts +384 -132
  306. package/src/git-cli/providers/commits.ts +106 -15
  307. package/src/git-cli/providers/config.ts +229 -8
  308. package/src/git-cli/providers/contributors.ts +5 -1
  309. package/src/git-cli/providers/graph.ts +26 -13
  310. package/src/git-cli/providers/operations.ts +45 -20
  311. package/src/git-cli/providers/pausedOperations.ts +109 -17
  312. package/src/git-cli/providers/refs.ts +33 -3
  313. package/src/git-cli/providers/status.ts +25 -4
  314. package/src/git-cli/providers/worktrees.ts +5 -0
  315. package/src/git-cli/service.ts +0 -1
  316. package/src/plus/agents/providers/claudeCodeProvider.ts +1130 -87
  317. package/src/plus/agents/providers/claudeCodeTranscript.ts +95 -9
  318. package/src/plus/agents/types.ts +46 -2
  319. package/src/plus/ai/errors.ts +30 -0
  320. package/src/plus/ai/models/model.ts +56 -6
  321. package/src/plus/ai/models/promptTemplates.ts +1 -1
  322. package/src/plus/ai/models/provider.ts +69 -2
  323. package/src/plus/ai/prompts.ts +186 -61
  324. package/src/plus/ai/providers/anthropicProvider.ts +155 -47
  325. package/src/plus/ai/providers/deepSeekProvider.ts +11 -21
  326. package/src/plus/ai/providers/geminiProvider.ts +19 -0
  327. package/src/plus/ai/providers/gitkrakenProvider.ts +126 -3
  328. package/src/plus/ai/providers/huggingFaceProvider.ts +6 -0
  329. package/src/plus/ai/providers/mistralProvider.ts +102 -19
  330. package/src/plus/ai/providers/ollamaProvider.ts +55 -4
  331. package/src/plus/ai/providers/openAICompatibleProvider.ts +5 -0
  332. package/src/plus/ai/providers/openAICompatibleProviderBase.ts +360 -17
  333. package/src/plus/ai/providers/openRouterProvider.ts +17 -0
  334. package/src/plus/ai/providers/openaiProvider.ts +1 -0
  335. package/src/plus/ai/providers/responseFormatCache.ts +39 -0
  336. package/src/plus/ai/providers/xaiProvider.ts +10 -1
  337. package/src/plus/ai/utils/ai.utils.ts +14 -0
  338. package/src/plus/ai/utils/results.utils.ts +255 -31
  339. package/src/plus/git-github/api/github.ts +291 -7
  340. package/src/plus/git-github/models.ts +48 -2
  341. package/src/plus/git-github/providers/github/status.ts +1 -0
  342. package/src/plus/integrations/context.ts +4 -0
  343. package/src/plus/integrations/index.ts +2 -0
  344. package/src/plus/integrations/models/gitHostIntegration.ts +25 -2
  345. package/src/plus/integrations/models/integration.ts +23 -13
  346. package/src/plus/integrations/providers/accounts.ts +4 -0
  347. package/src/plus/integrations/providers/azure/models.ts +3 -0
  348. package/src/plus/integrations/providers/bitbucket/models.ts +1 -0
  349. package/src/plus/integrations/providers/github.ts +85 -1
  350. package/src/plus/integrations/providers/gitlab.ts +2 -10
  351. package/src/plus/integrations/providers/models.ts +36 -4
  352. package/src/plus/integrations/reads/broaden.ts +6 -1
  353. package/src/plus/integrations/reads/drains.ts +7 -4
  354. package/src/plus/integrations/reads/hierarchy.ts +3 -1
  355. package/src/plus/integrations/reads/issueTracker.ts +9 -3
  356. package/src/plus/integrations/reads/issues.ts +9 -4
  357. package/src/plus/integrations/reads/pullRequests.ts +9 -4
  358. package/src/utils/env/browser/base64.ts +1 -1
  359. package/src/utils/env/node/base64.ts +3 -1
  360. package/src/utils/keys/chord.ts +184 -0
  361. package/src/utils/keys/keybinding.ts +116 -0
  362. package/src/utils/path.ts +14 -0
@@ -929,7 +929,11 @@ export abstract class IntegrationBase<
929
929
  }
930
930
 
931
931
  @trace()
932
- async getPullRequest(resource: T, id: string): Promise<PullRequest | undefined> {
932
+ async getPullRequest(
933
+ resource: T,
934
+ id: string,
935
+ options?: { expiryOverride?: boolean | number },
936
+ ): Promise<PullRequest | undefined> {
933
937
  const scope = getScopedLogger();
934
938
 
935
939
  const connected = this.maybeConnected ?? (await this.isConnected());
@@ -937,18 +941,24 @@ export abstract class IntegrationBase<
937
941
 
938
942
  await this.refreshSessionIfExpired(scope);
939
943
 
940
- const pr = await this.ctx.cache.getPullRequest(id, resource, this, () => ({
941
- value: (async () => {
942
- try {
943
- const result = await this.getProviderPullRequest?.(this._session!, resource, id);
944
- this.resetRequestExceptionCount('getPullRequest');
945
- return result;
946
- } catch (ex) {
947
- this.handleProviderException('getPullRequest', ex, { scope: scope });
948
- return undefined;
949
- }
950
- })(),
951
- }));
944
+ const pr = await this.ctx.cache.getPullRequest(
945
+ id,
946
+ resource,
947
+ this,
948
+ () => ({
949
+ value: (async () => {
950
+ try {
951
+ const result = await this.getProviderPullRequest?.(this._session!, resource, id);
952
+ this.resetRequestExceptionCount('getPullRequest');
953
+ return result;
954
+ } catch (ex) {
955
+ this.handleProviderException('getPullRequest', ex, { scope: scope });
956
+ return undefined;
957
+ }
958
+ })(),
959
+ }),
960
+ { expiryOverride: options?.expiryOverride },
961
+ );
952
962
  return pr;
953
963
  }
954
964
 
@@ -4,6 +4,9 @@ import type { PullRequestMember } from '../../../git/models/pullRequest.js';
4
4
 
5
5
  export function toProviderAccount(account: PullRequestMember | IssueMember): ProviderAccount {
6
6
  return {
7
+ // Stays the provider id because the categorizer matches the viewer to a pull request's people by `id`,
8
+ // and every provider but GitHub already agrees on that namespace. Re-keying to the login breaks Azure,
9
+ // whose account `username` is a display name while its members' is a UPN — different namespaces.
7
10
  id: account.id ?? null,
8
11
  avatarUrl: account.avatarUrl ?? null,
9
12
  name: account.name ?? null,
@@ -23,6 +26,7 @@ export function fromProviderAccount(account: ProviderAccount | null): PullReques
23
26
  // `Assignees: unknown` reads as a real assignee). It also disagreed with {@link toIssueShape}, which
24
27
  // collapsed the same absent name to `''` — same facade method, two fallbacks. Both now emit `undefined`.
25
28
  name: account?.name ?? undefined,
29
+ username: account?.username ?? undefined,
26
30
  avatarUrl: account?.avatarUrl ?? undefined,
27
31
  // `url` is optional, so an absent one must be `undefined`, not `''`. `''` passes a `!= null` presence
28
32
  // check and renders as a link to nowhere, and it disagreed with {@link toIssueShape} — which already
@@ -475,6 +475,7 @@ export function fromAzureUserWithVoteToReviewer(reviewer: AzureUserWithVote): Pu
475
475
  avatarUrl: reviewer.imageUrl,
476
476
  id: reviewer.id,
477
477
  name: reviewer.displayName,
478
+ username: reviewer.uniqueName,
478
479
  url: reviewer.url,
479
480
  },
480
481
  state: fromAzurePullRequestVoteToReviewState(reviewer.vote ?? 0),
@@ -505,6 +506,7 @@ export function fromAzureReviewerToPullRequestMember(reviewer: AzureUser): PullR
505
506
  avatarUrl: reviewer.imageUrl,
506
507
  id: reviewer.id,
507
508
  name: reviewer.displayName,
509
+ username: reviewer.uniqueName,
508
510
  url: reviewer.url,
509
511
  };
510
512
  }
@@ -520,6 +522,7 @@ function fromAzureUserToMember(user: AzureUser, _type: 'issue' | 'pullRequest'):
520
522
  avatarUrl: user.imageUrl,
521
523
  id: user.id,
522
524
  name: user.displayName,
525
+ username: user.uniqueName,
523
526
  url: user.url,
524
527
  };
525
528
  }
@@ -297,6 +297,7 @@ export function fromBitbucketUser(user: BitbucketUser): PullRequestMember {
297
297
  return {
298
298
  avatarUrl: user.links.avatar.href,
299
299
  name: user.display_name,
300
+ username: user.nickname,
300
301
  url: user.links.html.href,
301
302
  id: user.uuid,
302
303
  };
@@ -7,6 +7,7 @@ import type {
7
7
  PullRequest,
8
8
  PullRequestMergeMethod,
9
9
  PullRequestSearchCriteria,
10
+ PullRequestStackInfo,
10
11
  PullRequestState,
11
12
  PullRequestStateFilter,
12
13
  } from '../../../git/models/pullRequest.js';
@@ -728,18 +729,100 @@ abstract class GitHubIntegrationBase<ID extends GitHubIntegrationIds> extends Gi
728
729
  );
729
730
  }
730
731
 
732
+ /**
733
+ * Stack membership for every stacked pull request in the repository, keyed by pull request number.
734
+ *
735
+ * List surfaces get their pull requests from the shared providers API, whose type carries no stack
736
+ * membership, so the `stack`/`stackEntry` fields selected on the native per-pull-request reads never
737
+ * reach them. This fills that gap in a single request for the whole repository, rather than a
738
+ * per-pull-request enrichment that would scale with the list.
739
+ *
740
+ * `undefined` means unavailable (not enrolled in the preview, or not connected) as distinct from an
741
+ * empty map, which means the repository genuinely has no stacks.
742
+ */
743
+ override async getStacksByPullRequestNumber(
744
+ owner: string,
745
+ repo: string,
746
+ cancellation?: AbortSignal,
747
+ ): Promise<Map<number, PullRequestStackInfo> | undefined> {
748
+ // The shared read path — it refreshes an expired session before use, which a bare `getSession()`
749
+ // does not (it returns the cached session verbatim once one exists, expired or not).
750
+ const session = await this.resolveReadSession(undefined, undefined);
751
+ if (session == null) return undefined;
752
+
753
+ const stacks = await (
754
+ await this.authenticationService.apis.github
755
+ )?.getRepositoryStacks(
756
+ this,
757
+ toTokenWithInfo(this.id, session),
758
+ owner,
759
+ repo,
760
+ {
761
+ baseUrl: this.apiBaseUrl,
762
+ },
763
+ cancellation,
764
+ );
765
+ if (stacks == null) return undefined;
766
+
767
+ const byNumber = new Map<number, PullRequestStackInfo>();
768
+ for (const stack of stacks) {
769
+ // Defensive: this is a public-preview payload reaching us through an unvalidated cast, and a
770
+ // malformed entry must cost its own stack's badges, not the whole panel.
771
+ const members = stack?.pull_requests;
772
+ const baseRef = stack?.base?.ref;
773
+ if (members == null || baseRef == null) continue;
774
+
775
+ // `pull_requests` is ordered bottom to top, and `position` is 1-based from the bottom.
776
+ members.forEach((pr, i) => {
777
+ byNumber.set(pr.number, {
778
+ id: stack.id,
779
+ number: stack.number,
780
+ size: members.length,
781
+ position: i + 1,
782
+ baseRef: baseRef,
783
+ });
784
+ });
785
+ }
786
+
787
+ return byNumber;
788
+ }
789
+
731
790
  protected override async mergeProviderPullRequest(
732
791
  session: ProviderAuthenticationSession,
733
792
  pr: PullRequest,
734
793
  options?: {
735
794
  mergeMethod?: PullRequestMergeMethod;
736
795
  },
796
+ cancellation?: AbortSignal,
737
797
  ): Promise<boolean> {
738
798
  const id = pr.nodeId;
739
799
  const headRefSha = pr.refs?.head?.sha;
740
800
  if (id == null || headRefSha == null) return false;
801
+
802
+ const api = await this.authenticationService.apis.github;
803
+
804
+ // GitHub rejects stacked pull requests on the legacy merge mutation, so they take the
805
+ // asynchronous merge instead — which also lands every layer below this one.
806
+ if (pr.stack != null) {
807
+ return (
808
+ (await api?.mergeStackedPullRequest(
809
+ this,
810
+ toTokenWithInfo(this.id, session),
811
+ pr.repository.owner,
812
+ pr.repository.repo,
813
+ Number(pr.id),
814
+ headRefSha,
815
+ {
816
+ mergeMethod: options?.mergeMethod,
817
+ baseUrl: this.apiBaseUrl,
818
+ },
819
+ cancellation,
820
+ )) ?? false
821
+ );
822
+ }
823
+
741
824
  return (
742
- (await this.authenticationService.apis.github)?.mergePullRequest(
825
+ api?.mergePullRequest(
743
826
  this,
744
827
  toTokenWithInfo(this.id, session),
745
828
  id,
@@ -748,6 +831,7 @@ abstract class GitHubIntegrationBase<ID extends GitHubIntegrationIds> extends Gi
748
831
  mergeMethod: options?.mergeMethod,
749
832
  baseUrl: this.apiBaseUrl,
750
833
  },
834
+ cancellation,
751
835
  ) ?? false
752
836
  );
753
837
  }
@@ -585,16 +585,8 @@ abstract class GitLabIntegrationBase<ID extends GitLabIntegrationIds> extends Gi
585
585
  }
586
586
 
587
587
  const repoIdsResult = await Promise.allSettled(
588
- repos.map(
589
- (r: GitLabRepositoryDescriptor): Promise<string | undefined> =>
590
- api.getProjectId(
591
- this,
592
- toTokenWithInfo(this.id, session),
593
- r.owner,
594
- r.name,
595
- this.apiBaseUrl,
596
- undefined,
597
- ),
588
+ repos.map((r: GitLabRepositoryDescriptor): Promise<string | undefined> =>
589
+ api.getProjectId(this, toTokenWithInfo(this.id, session), r.owner, r.name, this.apiBaseUrl, undefined),
598
590
  ) ?? [],
599
591
  );
600
592
  const repoInput = repoIdsResult
@@ -13,6 +13,7 @@ import type {
13
13
  CursorPageInput,
14
14
  EnterpriseOptions,
15
15
  GetRepoInput,
16
+ GitBuildStatus,
16
17
  GitBuildStatusState as GitBuildStatusStateType,
17
18
  GitHub,
18
19
  GitIssueState as GitIssueStateType,
@@ -1349,6 +1350,36 @@ export const fromProviderBuildStatusState = {
1349
1350
  [GitBuildStatusState.Warning]: undefined,
1350
1351
  };
1351
1352
 
1353
+ /** Rolls every check context up into one state, the way a provider's own rollup does: failed, errored, or
1354
+ * action-required fails; else pending or running is pending; else success — reading only the first context
1355
+ * would call a pull request passing on the strength of whichever check happens to come back first. States
1356
+ * carrying no verdict (cancelled, skipped, optional action required, warning) don't vote. Reads the raw
1357
+ * state rather than `fromProviderBuildStatusState`, which drops errored and running to `undefined` and
1358
+ * would let a lone success outvote a check still in flight. */
1359
+ function toStatusCheckRollupState(
1360
+ statuses: GitBuildStatus[] | null | undefined,
1361
+ ): PullRequestStatusCheckRollupState | undefined {
1362
+ if (!statuses?.length) return undefined;
1363
+
1364
+ let rollup: PullRequestStatusCheckRollupState | undefined;
1365
+ for (const { state } of statuses) {
1366
+ switch (state) {
1367
+ case GitBuildStatusState.Failed:
1368
+ case GitBuildStatusState.Error:
1369
+ case GitBuildStatusState.ActionRequired:
1370
+ return PullRequestStatusCheckRollupState.Failed;
1371
+ case GitBuildStatusState.Pending:
1372
+ case GitBuildStatusState.Running:
1373
+ rollup = PullRequestStatusCheckRollupState.Pending;
1374
+ break;
1375
+ case GitBuildStatusState.Success:
1376
+ rollup ??= PullRequestStatusCheckRollupState.Success;
1377
+ break;
1378
+ }
1379
+ }
1380
+ return rollup;
1381
+ }
1382
+
1352
1383
  export const toProviderPullRequestMergeableState = {
1353
1384
  [PullRequestMergeableState.Mergeable]: GitPullRequestMergeableState.Mergeable,
1354
1385
  [PullRequestMergeableState.Conflicting]: GitPullRequestMergeableState.Conflicts,
@@ -1472,7 +1503,7 @@ export function toProviderPullRequest(pr: PullRequest): ProviderPullRequest {
1472
1503
  mergedDate: pr.mergedDate ?? null,
1473
1504
  commentCount: pr.commentsCount ?? null,
1474
1505
  upvoteCount: pr.thumbsUpCount ?? null,
1475
- commitCount: null,
1506
+ commitCount: pr.commitCount ?? null,
1476
1507
  fileCount: null,
1477
1508
  additions: pr.additions ?? null,
1478
1509
  deletions: pr.deletions ?? null,
@@ -1633,11 +1664,12 @@ export function fromProviderPullRequest(
1633
1664
  toReviewRequests(pr.reviews),
1634
1665
  toCompletedReviews(pr.reviews),
1635
1666
  pr.assignees?.map(fromProviderAccount) ?? undefined,
1636
- pr.headCommit?.buildStatuses?.[0]?.state
1637
- ? fromProviderBuildStatusState[pr.headCommit.buildStatuses[0].state]
1638
- : undefined,
1667
+ toStatusCheckRollupState(pr.headCommit?.buildStatuses),
1639
1668
  options?.project,
1640
1669
  pr.version,
1670
+ pr.commitCount ?? undefined,
1671
+ undefined, // stack — GK's proxy type has no stack concept; membership is joined host-side
1672
+ pr.fileCount ?? undefined,
1641
1673
  pr.description ?? undefined,
1642
1674
  pr.number,
1643
1675
  options?.currentAccountId != null ? pr.author?.id === options.currentAccountId : undefined,
@@ -140,7 +140,12 @@ export async function broadenIssues(
140
140
  }
141
141
 
142
142
  items.push(...result.items);
143
- warnings.push(...result.warnings);
143
+ // Deduped across orgs: several orgs of one provider commonly fail the same way (one expired token, one
144
+ // rate limit), producing the identical warning per slice, and the array's contract is that no two entries
145
+ // are equal — `traverseToRequestedPage` already dedupes when it folds these same warnings across rounds.
146
+ for (const warning of result.warnings) {
147
+ appendDedupedWarning(warnings, warning);
148
+ }
144
149
  for (const id of result.broadenedProviderIds) {
145
150
  broadenedProviderIds.add(id);
146
151
  }
@@ -174,9 +174,10 @@ export async function drainPullRequests(
174
174
 
175
175
  // Composite account-wide queries can surface the same PR on different relationship/state pages
176
176
  // (for example authored + review-requested, or closed + merged). Keep the first stable position but
177
- // replace its value with the latest representation so a later, richer merged state wins. A provider
178
- // row without a canonical URL falls back to repository-scoped identity; a row with neither stays
179
- // unkeyed and is retained so unrelated incomplete rows are never collapsed.
177
+ // replace its value with the latest representation so a later, richer merged state wins. Repository
178
+ // identity is what keys a row (see `getProviderPullRequestIdentity`), falling back to the canonical
179
+ // URL; a row with neither stays unkeyed and is retained so unrelated incomplete rows are never
180
+ // collapsed.
180
181
  for (const pullRequest of value.values) {
181
182
  const identity = getProviderPullRequestIdentity(pullRequest);
182
183
  if (identity == null) {
@@ -319,7 +320,9 @@ export async function drainRepositories(
319
320
  { warnOnMissingSession: true },
320
321
  );
321
322
  if (warning != null) {
322
- warnings.push(warning);
323
+ // Deduped, like every other accumulation here: a soft warning (`{ value, error }`) repeats verbatim on
324
+ // each page that hits the same condition, and the array's contract is that no two entries are equal.
325
+ appendDedupedWarning(warnings, warning);
323
326
  }
324
327
  if (value == null) {
325
328
  const interruptedAfterProgress = page > 1;
@@ -291,7 +291,9 @@ export async function listRepos(
291
291
  domain?: string;
292
292
  },
293
293
  ): Promise<ProviderPagedResult<ProviderRepositoryShape>> {
294
- const page = Math.max(1, options.page ?? 1);
294
+ // Truncated as well as floored, like every other paged read here: `page` is reported back as
295
+ // `page.currentPage` and bounds the cursor walk below, and neither can be fractional.
296
+ const page = Math.max(1, Math.trunc(options.page ?? 1));
295
297
  if (isIssuesHostIntegrationId(options.providerId)) {
296
298
  return refusedPage(
297
299
  page,
@@ -9,7 +9,7 @@ import { isIssuesIntegration } from '../models/issuesIntegration.js';
9
9
  import { IssueFilter, providersMetadata } from '../providers/models.js';
10
10
  import { mergeCollectionMetadata, parsePageCursor } from '../providers/utils/providerPaging.js';
11
11
  import type { ProviderPagedResult, ProviderWarning } from '../results.js';
12
- import { reconcileOmissionsWithFailure } from '../results.js';
12
+ import { appendDedupedWarning, reconcileOmissionsWithFailure } from '../results.js';
13
13
  import { isIssuesHostIntegrationId } from '../utils/integration.utils.js';
14
14
  import type { ProviderReadContext } from './context.js';
15
15
  import { parseIssueTrackerPageCursor, toIssueTrackerPageCursor } from './cursors.js';
@@ -279,7 +279,11 @@ export async function listIssueTrackerIssuesPage(
279
279
  continue;
280
280
  }
281
281
 
282
- warnings.push(
282
+ // Deduped: a captured `accountWarning` carries only the provider error, with no resource in its
283
+ // message, so one expired token across N resources would otherwise repeat verbatim N times. The
284
+ // synthesized fallback names the resource, so those stay distinct on their own.
285
+ appendDedupedWarning(
286
+ warnings,
283
287
  accountWarning ??
284
288
  otherWarning(
285
289
  options.providerId,
@@ -457,7 +461,9 @@ export async function listIssueTrackerIssuesPage(
457
461
  const key = projectKey(project);
458
462
  const retryProject = result == null;
459
463
  if (warning != null) {
460
- warnings.push(warning);
464
+ // Deduped: the per-project warning is built from the provider error alone and names no project, so a
465
+ // single failing token repeats verbatim once per project in the window.
466
+ appendDedupedWarning(warnings, warning);
461
467
  fetchFailed = true;
462
468
  projectTruncated = true;
463
469
  }
@@ -143,7 +143,9 @@ export async function listIssuesPage(
143
143
  ctx: ProviderReadContext,
144
144
  options: ListIssuesPageOptions,
145
145
  ): Promise<ProviderPagedResult<IssueShape>> {
146
- const page = Math.max(1, options.page ?? 1);
146
+ // Truncated as well as floored, like every other paged read here: `page` is reported back as
147
+ // `page.currentPage` and compared against the position a drain reached, and neither can be fractional.
148
+ const page = Math.max(1, Math.trunc(options.page ?? 1));
147
149
  if (isIssuesHostIntegrationId(options.providerId)) {
148
150
  return refusedPage(
149
151
  page,
@@ -487,7 +489,10 @@ async function readRepoScopedIssuesPage({
487
489
  filters: options.filters,
488
490
  includeAllAssignees: options.includeAllAssignees,
489
491
  cursor: cursor,
490
- page: options.page,
492
+ // The normalized `page`, so the number forwarded to the provider can't disagree with the
493
+ // page-number cursor beside it — both are built from the same value. Only when the caller asked
494
+ // for one: an omitted page is the provider's own first page.
495
+ page: options.page != null ? page : undefined,
491
496
  pageSize: options.itemsPerPage,
492
497
  sort: ordering.sort,
493
498
  },
@@ -507,14 +512,14 @@ async function readRepoScopedIssuesPage({
507
512
  if (
508
513
  issuesPagingMode === PagingMode.Repos &&
509
514
  options.page != null &&
510
- options.page > 1 &&
515
+ page > 1 &&
511
516
  options.cursor == null &&
512
517
  paged.page.currentPage === 1
513
518
  ) {
514
519
  const drained = await drainToRequestedPage(
515
520
  { items: items, paged: paged, metadata: allMetadata, fetchFailed: pageFetchFailed },
516
521
  {
517
- requestedPage: options.page,
522
+ requestedPage: page,
518
523
  itemsPerPage: options.itemsPerPage,
519
524
  warnings: warnings,
520
525
  readPage: (cursor: string) =>
@@ -58,7 +58,9 @@ export async function listPullRequestsPage(
58
58
  domain?: string;
59
59
  },
60
60
  ): Promise<ProviderPagedResult<PullRequestShape>> {
61
- const page = Math.max(1, options.page ?? 1);
61
+ // Truncated as well as floored, like every other paged read here: `page` is reported back as
62
+ // `page.currentPage` and compared against the position a drain reached, and neither can be fractional.
63
+ const page = Math.max(1, Math.trunc(options.page ?? 1));
62
64
  if (isIssuesHostIntegrationId(options.providerId)) {
63
65
  return refusedPage(
64
66
  page,
@@ -140,7 +142,10 @@ export async function listPullRequestsPage(
140
142
  state: options.states,
141
143
  filters: resolvedFilters.filters,
142
144
  cursor: cursor,
143
- page: options.page,
145
+ // The normalized `page`, so the number forwarded to the provider can't disagree with the
146
+ // page-number cursor beside it — both are built from the same value. Only when the caller
147
+ // asked for one: an omitted page is the provider's own first page.
148
+ page: options.page != null ? page : undefined,
144
149
  pageSize: options.itemsPerPage,
145
150
  },
146
151
  options.connectionId,
@@ -165,14 +170,14 @@ export async function listPullRequestsPage(
165
170
  if (
166
171
  (accountWide || providersMetadata[options.providerId]?.pullRequestsPagingMode === PagingMode.Repos) &&
167
172
  options.page != null &&
168
- options.page > 1 &&
173
+ page > 1 &&
169
174
  options.cursor == null &&
170
175
  paged.page.currentPage === 1
171
176
  ) {
172
177
  const drained = await drainToRequestedPage<ProviderPullRequest>(
173
178
  { items: items, paged: paged, metadata: allMetadata, fetchFailed: pageFetchFailed },
174
179
  {
175
- requestedPage: options.page,
180
+ requestedPage: page,
176
181
  itemsPerPage: options.itemsPerPage,
177
182
  warnings: warnings,
178
183
  readPage: (cursor: string) =>
@@ -14,7 +14,7 @@ export function base64(data: string | Uint8Array): string {
14
14
  return globalThis.btoa(output);
15
15
  }
16
16
 
17
- export function fromBase64(s: string): Uint8Array {
17
+ export function fromBase64(s: string): Uint8Array<ArrayBuffer> {
18
18
  const decoded = globalThis.atob(s);
19
19
 
20
20
  const len = decoded.length;
@@ -4,7 +4,9 @@ export function base64(data: string | Uint8Array): string {
4
4
  return Buffer.from(data).toString('base64');
5
5
  }
6
6
 
7
- export function fromBase64(s: string): Uint8Array {
7
+ // Returns `Uint8Array<ArrayBuffer>` rather than a bare `Uint8Array` (which widens to `ArrayBufferLike` and
8
+ // admits `SharedArrayBuffer`) so the result stays assignable to `BufferSource` — what Web Crypto accepts.
9
+ export function fromBase64(s: string): Uint8Array<ArrayBuffer> {
8
10
  return Buffer.from(s, 'base64');
9
11
  }
10
12