@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.
- package/CHANGELOG.md +48 -1
- package/dist/git/cache.d.ts +111 -6
- package/dist/git/cache.d.ts.map +1 -1
- package/dist/git/cache.js +312 -43
- package/dist/git/cache.js.map +1 -1
- package/dist/git/context.d.ts +11 -0
- package/dist/git/context.d.ts.map +1 -1
- package/dist/git/context.js.map +1 -1
- package/dist/git/models/fileStatus.d.ts +1 -0
- package/dist/git/models/fileStatus.d.ts.map +1 -1
- package/dist/git/models/fileStatus.js +1 -0
- package/dist/git/models/fileStatus.js.map +1 -1
- package/dist/git/models/issue.d.ts +4 -0
- package/dist/git/models/issue.d.ts.map +1 -1
- package/dist/git/models/mergeConflicts.d.ts +2 -0
- package/dist/git/models/mergeConflicts.d.ts.map +1 -1
- package/dist/git/models/pullRequest.d.ts +119 -2
- package/dist/git/models/pullRequest.d.ts.map +1 -1
- package/dist/git/models/pullRequest.js +27 -1
- package/dist/git/models/pullRequest.js.map +1 -1
- package/dist/git/models/repository.d.ts +32 -5
- package/dist/git/models/repository.d.ts.map +1 -1
- package/dist/git/models/repository.js +58 -12
- package/dist/git/models/repository.js.map +1 -1
- package/dist/git/models/statusFile.d.ts.map +1 -1
- package/dist/git/models/statusFile.js +3 -0
- package/dist/git/models/statusFile.js.map +1 -1
- package/dist/git/providers/branches.d.ts +2 -0
- package/dist/git/providers/branches.d.ts.map +1 -1
- package/dist/git/providers/commits.d.ts +8 -0
- package/dist/git/providers/commits.d.ts.map +1 -1
- package/dist/git/providers/config.d.ts +19 -1
- package/dist/git/providers/config.d.ts.map +1 -1
- package/dist/git/providers/operations.d.ts +1 -0
- package/dist/git/providers/operations.d.ts.map +1 -1
- package/dist/git/providers/pausedOperations.d.ts +2 -0
- package/dist/git/providers/pausedOperations.d.ts.map +1 -1
- package/dist/git/providers/status.d.ts +1 -0
- package/dist/git/providers/status.d.ts.map +1 -1
- package/dist/git/utils/config.utils.d.ts +3 -0
- package/dist/git/utils/config.utils.d.ts.map +1 -0
- package/dist/git/utils/config.utils.js +8 -0
- package/dist/git/utils/config.utils.js.map +1 -0
- package/dist/git/utils/issue.utils.d.ts.map +1 -1
- package/dist/git/utils/issue.utils.js +2 -0
- package/dist/git/utils/issue.utils.js.map +1 -1
- package/dist/git/utils/pausedOperationStatus.utils.d.ts +14 -0
- package/dist/git/utils/pausedOperationStatus.utils.d.ts.map +1 -1
- package/dist/git/utils/pausedOperationStatus.utils.js +23 -0
- package/dist/git/utils/pausedOperationStatus.utils.js.map +1 -1
- package/dist/git/utils/pullRequest.utils.d.ts +24 -1
- package/dist/git/utils/pullRequest.utils.d.ts.map +1 -1
- package/dist/git/utils/pullRequest.utils.js +71 -0
- package/dist/git/utils/pullRequest.utils.js.map +1 -1
- package/dist/git/watching/changeEvent.d.ts +6 -1
- package/dist/git/watching/changeEvent.d.ts.map +1 -1
- package/dist/git/watching/classifyChange.d.ts.map +1 -1
- package/dist/git/watching/classifyChange.js +14 -1
- package/dist/git/watching/classifyChange.js.map +1 -1
- package/dist/git/watching/watchService.d.ts.map +1 -1
- package/dist/git/watching/watchService.js +18 -3
- package/dist/git/watching/watchService.js.map +1 -1
- package/dist/git/watching/watchSession.d.ts +8 -1
- package/dist/git/watching/watchSession.d.ts.map +1 -1
- package/dist/git/watching/watchSession.js +38 -6
- package/dist/git/watching/watchSession.js.map +1 -1
- package/dist/git/watching/watcherPatterns.d.ts +2 -2
- package/dist/git/watching/watcherPatterns.d.ts.map +1 -1
- package/dist/git/watching/watcherPatterns.js +1 -1
- package/dist/git/watching/watcherPatterns.js.map +1 -1
- package/dist/git-cli/exec/git.d.ts +1 -1
- package/dist/git-cli/exec/git.d.ts.map +1 -1
- package/dist/git-cli/exec/git.js +13 -3
- package/dist/git-cli/exec/git.js.map +1 -1
- package/dist/git-cli/providers/branches.d.ts +19 -0
- package/dist/git-cli/providers/branches.d.ts.map +1 -1
- package/dist/git-cli/providers/branches.js +282 -78
- package/dist/git-cli/providers/branches.js.map +1 -1
- package/dist/git-cli/providers/commits.d.ts +4 -0
- package/dist/git-cli/providers/commits.d.ts.map +1 -1
- package/dist/git-cli/providers/commits.js +84 -11
- package/dist/git-cli/providers/commits.js.map +1 -1
- package/dist/git-cli/providers/config.d.ts +42 -0
- package/dist/git-cli/providers/config.d.ts.map +1 -1
- package/dist/git-cli/providers/config.js +186 -5
- package/dist/git-cli/providers/config.js.map +1 -1
- package/dist/git-cli/providers/contributors.d.ts.map +1 -1
- package/dist/git-cli/providers/contributors.js +1 -1
- package/dist/git-cli/providers/contributors.js.map +1 -1
- package/dist/git-cli/providers/graph.d.ts +2 -2
- package/dist/git-cli/providers/graph.d.ts.map +1 -1
- package/dist/git-cli/providers/graph.js +27 -9
- package/dist/git-cli/providers/graph.js.map +1 -1
- package/dist/git-cli/providers/operations.d.ts.map +1 -1
- package/dist/git-cli/providers/operations.js +40 -12
- package/dist/git-cli/providers/operations.js.map +1 -1
- package/dist/git-cli/providers/pausedOperations.d.ts +5 -0
- package/dist/git-cli/providers/pausedOperations.d.ts.map +1 -1
- package/dist/git-cli/providers/pausedOperations.js +87 -16
- package/dist/git-cli/providers/pausedOperations.js.map +1 -1
- package/dist/git-cli/providers/refs.d.ts +5 -3
- package/dist/git-cli/providers/refs.d.ts.map +1 -1
- package/dist/git-cli/providers/refs.js +33 -4
- package/dist/git-cli/providers/refs.js.map +1 -1
- package/dist/git-cli/providers/status.d.ts +1 -0
- package/dist/git-cli/providers/status.d.ts.map +1 -1
- package/dist/git-cli/providers/status.js +18 -3
- package/dist/git-cli/providers/status.js.map +1 -1
- package/dist/git-cli/providers/worktrees.d.ts.map +1 -1
- package/dist/git-cli/providers/worktrees.js +4 -0
- package/dist/git-cli/providers/worktrees.js.map +1 -1
- package/dist/git-cli/service.d.ts.map +1 -1
- package/dist/git-cli/service.js.map +1 -1
- package/dist/plus/agents/providers/claudeCodeProvider.d.ts +39 -1
- package/dist/plus/agents/providers/claudeCodeProvider.d.ts.map +1 -1
- package/dist/plus/agents/providers/claudeCodeProvider.js +978 -71
- package/dist/plus/agents/providers/claudeCodeProvider.js.map +1 -1
- package/dist/plus/agents/providers/claudeCodeTranscript.d.ts +24 -2
- package/dist/plus/agents/providers/claudeCodeTranscript.d.ts.map +1 -1
- package/dist/plus/agents/providers/claudeCodeTranscript.js +84 -9
- package/dist/plus/agents/providers/claudeCodeTranscript.js.map +1 -1
- package/dist/plus/agents/types.d.ts +37 -2
- package/dist/plus/agents/types.d.ts.map +1 -1
- package/dist/plus/agents/types.js +2 -0
- package/dist/plus/agents/types.js.map +1 -1
- package/dist/plus/ai/errors.d.ts +10 -0
- package/dist/plus/ai/errors.d.ts.map +1 -1
- package/dist/plus/ai/errors.js +29 -0
- package/dist/plus/ai/errors.js.map +1 -1
- package/dist/plus/ai/models/model.d.ts +4 -0
- package/dist/plus/ai/models/model.d.ts.map +1 -1
- package/dist/plus/ai/models/model.js +51 -6
- package/dist/plus/ai/models/model.js.map +1 -1
- package/dist/plus/ai/models/promptTemplates.d.ts +1 -1
- package/dist/plus/ai/models/promptTemplates.d.ts.map +1 -1
- package/dist/plus/ai/models/provider.d.ts +60 -2
- package/dist/plus/ai/models/provider.d.ts.map +1 -1
- package/dist/plus/ai/prompts.d.ts +12 -0
- package/dist/plus/ai/prompts.d.ts.map +1 -1
- package/dist/plus/ai/prompts.js +177 -61
- package/dist/plus/ai/prompts.js.map +1 -1
- package/dist/plus/ai/providers/anthropicProvider.d.ts +10 -2
- package/dist/plus/ai/providers/anthropicProvider.d.ts.map +1 -1
- package/dist/plus/ai/providers/anthropicProvider.js +139 -46
- package/dist/plus/ai/providers/anthropicProvider.js.map +1 -1
- package/dist/plus/ai/providers/deepSeekProvider.d.ts +2 -0
- package/dist/plus/ai/providers/deepSeekProvider.d.ts.map +1 -1
- package/dist/plus/ai/providers/deepSeekProvider.js +10 -21
- package/dist/plus/ai/providers/deepSeekProvider.js.map +1 -1
- package/dist/plus/ai/providers/geminiProvider.d.ts +1 -0
- package/dist/plus/ai/providers/geminiProvider.d.ts.map +1 -1
- package/dist/plus/ai/providers/geminiProvider.js +19 -0
- package/dist/plus/ai/providers/geminiProvider.js.map +1 -1
- package/dist/plus/ai/providers/gitkrakenProvider.d.ts +5 -1
- package/dist/plus/ai/providers/gitkrakenProvider.d.ts.map +1 -1
- package/dist/plus/ai/providers/gitkrakenProvider.js +118 -3
- package/dist/plus/ai/providers/gitkrakenProvider.js.map +1 -1
- package/dist/plus/ai/providers/huggingFaceProvider.d.ts +1 -0
- package/dist/plus/ai/providers/huggingFaceProvider.d.ts.map +1 -1
- package/dist/plus/ai/providers/huggingFaceProvider.js +5 -0
- package/dist/plus/ai/providers/huggingFaceProvider.js.map +1 -1
- package/dist/plus/ai/providers/mistralProvider.d.ts +3 -1
- package/dist/plus/ai/providers/mistralProvider.d.ts.map +1 -1
- package/dist/plus/ai/providers/mistralProvider.js +99 -19
- package/dist/plus/ai/providers/mistralProvider.js.map +1 -1
- package/dist/plus/ai/providers/ollamaProvider.d.ts +4 -3
- package/dist/plus/ai/providers/ollamaProvider.d.ts.map +1 -1
- package/dist/plus/ai/providers/ollamaProvider.js +38 -3
- package/dist/plus/ai/providers/ollamaProvider.js.map +1 -1
- package/dist/plus/ai/providers/openAICompatibleProvider.d.ts +1 -0
- package/dist/plus/ai/providers/openAICompatibleProvider.d.ts.map +1 -1
- package/dist/plus/ai/providers/openAICompatibleProvider.js +4 -0
- package/dist/plus/ai/providers/openAICompatibleProvider.js.map +1 -1
- package/dist/plus/ai/providers/openAICompatibleProviderBase.d.ts +154 -5
- package/dist/plus/ai/providers/openAICompatibleProviderBase.d.ts.map +1 -1
- package/dist/plus/ai/providers/openAICompatibleProviderBase.js +259 -10
- package/dist/plus/ai/providers/openAICompatibleProviderBase.js.map +1 -1
- package/dist/plus/ai/providers/openRouterProvider.d.ts +4 -0
- package/dist/plus/ai/providers/openRouterProvider.d.ts.map +1 -1
- package/dist/plus/ai/providers/openRouterProvider.js +9 -0
- package/dist/plus/ai/providers/openRouterProvider.js.map +1 -1
- package/dist/plus/ai/providers/openaiProvider.d.ts +1 -0
- package/dist/plus/ai/providers/openaiProvider.d.ts.map +1 -1
- package/dist/plus/ai/providers/openaiProvider.js +1 -0
- package/dist/plus/ai/providers/openaiProvider.js.map +1 -1
- package/dist/plus/ai/providers/responseFormatCache.d.ts +8 -0
- package/dist/plus/ai/providers/responseFormatCache.d.ts.map +1 -0
- package/dist/plus/ai/providers/responseFormatCache.js +25 -0
- package/dist/plus/ai/providers/responseFormatCache.js.map +1 -0
- package/dist/plus/ai/providers/xaiProvider.d.ts +1 -0
- package/dist/plus/ai/providers/xaiProvider.d.ts.map +1 -1
- package/dist/plus/ai/providers/xaiProvider.js +10 -1
- package/dist/plus/ai/providers/xaiProvider.js.map +1 -1
- package/dist/plus/ai/utils/ai.utils.d.ts +3 -0
- package/dist/plus/ai/utils/ai.utils.d.ts.map +1 -1
- package/dist/plus/ai/utils/ai.utils.js +13 -0
- package/dist/plus/ai/utils/ai.utils.js.map +1 -1
- package/dist/plus/ai/utils/results.utils.d.ts +16 -2
- package/dist/plus/ai/utils/results.utils.d.ts.map +1 -1
- package/dist/plus/ai/utils/results.utils.js +204 -28
- package/dist/plus/ai/utils/results.utils.js.map +1 -1
- package/dist/plus/git-github/api/github.d.ts +92 -4
- package/dist/plus/git-github/api/github.d.ts.map +1 -1
- package/dist/plus/git-github/api/github.js +324 -20
- package/dist/plus/git-github/api/github.js.map +1 -1
- package/dist/plus/git-github/api/pullRequestSearchQuery.d.ts +27 -1
- package/dist/plus/git-github/api/pullRequestSearchQuery.d.ts.map +1 -1
- package/dist/plus/git-github/api/pullRequestSearchQuery.js +73 -6
- package/dist/plus/git-github/api/pullRequestSearchQuery.js.map +1 -1
- package/dist/plus/git-github/models.d.ts +33 -5
- package/dist/plus/git-github/models.d.ts.map +1 -1
- package/dist/plus/git-github/models.js +43 -4
- package/dist/plus/git-github/models.js.map +1 -1
- package/dist/plus/git-github/providers/github/status.d.ts +1 -0
- package/dist/plus/git-github/providers/github/status.d.ts.map +1 -1
- package/dist/plus/git-github/providers/github/status.js.map +1 -1
- package/dist/plus/integrations/context.d.ts +4 -0
- package/dist/plus/integrations/context.d.ts.map +1 -1
- package/dist/plus/integrations/index.d.ts.map +1 -1
- package/dist/plus/integrations/index.js +2 -0
- package/dist/plus/integrations/index.js.map +1 -1
- package/dist/plus/integrations/integrationService.d.ts +16 -1
- package/dist/plus/integrations/integrationService.d.ts.map +1 -1
- package/dist/plus/integrations/integrationService.js +9 -1
- package/dist/plus/integrations/integrationService.js.map +1 -1
- package/dist/plus/integrations/manager.d.ts +45 -5
- package/dist/plus/integrations/manager.d.ts.map +1 -1
- package/dist/plus/integrations/models/gitHostIntegration.d.ts +18 -3
- package/dist/plus/integrations/models/gitHostIntegration.d.ts.map +1 -1
- package/dist/plus/integrations/models/gitHostIntegration.js +30 -2
- package/dist/plus/integrations/models/gitHostIntegration.js.map +1 -1
- package/dist/plus/integrations/models/integration.d.ts +4 -2
- package/dist/plus/integrations/models/integration.d.ts.map +1 -1
- package/dist/plus/integrations/models/integration.js +2 -2
- package/dist/plus/integrations/models/integration.js.map +1 -1
- package/dist/plus/integrations/providerFilters.d.ts +1 -1
- package/dist/plus/integrations/providerFilters.d.ts.map +1 -1
- package/dist/plus/integrations/providers/accounts.d.ts +6 -0
- package/dist/plus/integrations/providers/accounts.d.ts.map +1 -0
- package/dist/plus/integrations/providers/accounts.js +34 -0
- package/dist/plus/integrations/providers/accounts.js.map +1 -0
- package/dist/plus/integrations/providers/azure/models.d.ts.map +1 -1
- package/dist/plus/integrations/providers/azure/models.js +3 -0
- package/dist/plus/integrations/providers/azure/models.js.map +1 -1
- package/dist/plus/integrations/providers/bitbucket/models.d.ts.map +1 -1
- package/dist/plus/integrations/providers/bitbucket/models.js +1 -0
- package/dist/plus/integrations/providers/bitbucket/models.js.map +1 -1
- package/dist/plus/integrations/providers/github.d.ts +23 -2
- package/dist/plus/integrations/providers/github.d.ts.map +1 -1
- package/dist/plus/integrations/providers/github.js +169 -138
- package/dist/plus/integrations/providers/github.js.map +1 -1
- package/dist/plus/integrations/providers/gitlab.d.ts +9 -0
- package/dist/plus/integrations/providers/gitlab.d.ts.map +1 -1
- package/dist/plus/integrations/providers/gitlab.js +23 -4
- package/dist/plus/integrations/providers/gitlab.js.map +1 -1
- package/dist/plus/integrations/providers/models.d.ts +14 -32
- package/dist/plus/integrations/providers/models.d.ts.map +1 -1
- package/dist/plus/integrations/providers/models.js +66 -109
- package/dist/plus/integrations/providers/models.js.map +1 -1
- package/dist/plus/integrations/providers/pullRequestReviews.d.ts +50 -0
- package/dist/plus/integrations/providers/pullRequestReviews.d.ts.map +1 -0
- package/dist/plus/integrations/providers/pullRequestReviews.js +99 -0
- package/dist/plus/integrations/providers/pullRequestReviews.js.map +1 -0
- package/dist/plus/integrations/reads/broaden.d.ts.map +1 -1
- package/dist/plus/integrations/reads/broaden.js +6 -1
- package/dist/plus/integrations/reads/broaden.js.map +1 -1
- package/dist/plus/integrations/reads/counts.d.ts +55 -0
- package/dist/plus/integrations/reads/counts.d.ts.map +1 -1
- package/dist/plus/integrations/reads/counts.js +146 -2
- package/dist/plus/integrations/reads/counts.js.map +1 -1
- package/dist/plus/integrations/reads/drains.d.ts +7 -1
- package/dist/plus/integrations/reads/drains.d.ts.map +1 -1
- package/dist/plus/integrations/reads/drains.js +20 -6
- package/dist/plus/integrations/reads/drains.js.map +1 -1
- package/dist/plus/integrations/reads/filters.d.ts.map +1 -1
- package/dist/plus/integrations/reads/filters.js +22 -0
- package/dist/plus/integrations/reads/filters.js.map +1 -1
- package/dist/plus/integrations/reads/hierarchy.d.ts.map +1 -1
- package/dist/plus/integrations/reads/hierarchy.js +3 -1
- package/dist/plus/integrations/reads/hierarchy.js.map +1 -1
- package/dist/plus/integrations/reads/issueTracker.d.ts.map +1 -1
- package/dist/plus/integrations/reads/issueTracker.js +8 -3
- package/dist/plus/integrations/reads/issueTracker.js.map +1 -1
- package/dist/plus/integrations/reads/issues.d.ts.map +1 -1
- package/dist/plus/integrations/reads/issues.js +9 -4
- package/dist/plus/integrations/reads/issues.js.map +1 -1
- package/dist/plus/integrations/reads/pullRequests.d.ts.map +1 -1
- package/dist/plus/integrations/reads/pullRequests.js +9 -4
- package/dist/plus/integrations/reads/pullRequests.js.map +1 -1
- package/dist/plus/integrations/reads/searchPullRequests.d.ts +4 -3
- package/dist/plus/integrations/reads/searchPullRequests.d.ts.map +1 -1
- package/dist/plus/integrations/reads/searchPullRequests.js +6 -4
- package/dist/plus/integrations/reads/searchPullRequests.js.map +1 -1
- package/dist/plus/integrations/reads/sweeps.js +1 -1
- package/dist/plus/integrations/reads/sweeps.js.map +1 -1
- package/dist/plus/integrations/reads/warnings.d.ts +2 -2
- package/dist/plus/integrations/reads/warnings.d.ts.map +1 -1
- package/dist/plus/integrations/reads/warnings.js +11 -2
- package/dist/plus/integrations/reads/warnings.js.map +1 -1
- package/dist/plus/integrations/results.d.ts +6 -1
- package/dist/plus/integrations/results.d.ts.map +1 -1
- package/dist/plus/integrations/results.js.map +1 -1
- package/dist/utils/env/browser/base64.d.ts +1 -1
- package/dist/utils/env/browser/base64.d.ts.map +1 -1
- package/dist/utils/env/node/base64.d.ts +1 -1
- package/dist/utils/env/node/base64.d.ts.map +1 -1
- package/dist/utils/env/node/base64.js +2 -0
- package/dist/utils/env/node/base64.js.map +1 -1
- package/dist/utils/keys/chord.d.ts +52 -0
- package/dist/utils/keys/chord.d.ts.map +1 -0
- package/dist/utils/keys/chord.js +135 -0
- package/dist/utils/keys/chord.js.map +1 -0
- package/dist/utils/keys/keybinding.d.ts +53 -0
- package/dist/utils/keys/keybinding.d.ts.map +1 -0
- package/dist/utils/keys/keybinding.js +58 -0
- package/dist/utils/keys/keybinding.js.map +1 -0
- package/dist/utils/path.d.ts +11 -0
- package/dist/utils/path.d.ts.map +1 -1
- package/dist/utils/path.js +13 -0
- package/dist/utils/path.js.map +1 -1
- package/docs/integrations.md +76 -10
- package/docs/kepler-read-api-parity.md +9 -0
- package/package.json +13 -5
- package/src/git/cache.ts +383 -47
- package/src/git/context.ts +11 -0
- package/src/git/models/fileStatus.ts +1 -0
- package/src/git/models/issue.ts +4 -0
- package/src/git/models/mergeConflicts.ts +3 -2
- package/src/git/models/pullRequest.ts +117 -1
- package/src/git/models/repository.ts +58 -17
- package/src/git/models/statusFile.ts +3 -0
- package/src/git/providers/branches.ts +6 -0
- package/src/git/providers/commits.ts +11 -0
- package/src/git/providers/config.ts +18 -0
- package/src/git/providers/operations.ts +1 -0
- package/src/git/providers/pausedOperations.ts +2 -0
- package/src/git/providers/status.ts +1 -0
- package/src/git/utils/config.utils.ts +8 -0
- package/src/git/utils/issue.utils.ts +2 -0
- package/src/git/utils/pausedOperationStatus.utils.ts +28 -0
- package/src/git/utils/pullRequest.utils.ts +86 -0
- package/src/git/watching/changeEvent.ts +6 -1
- package/src/git/watching/classifyChange.ts +15 -1
- package/src/git/watching/watchService.ts +20 -3
- package/src/git/watching/watchSession.ts +41 -6
- package/src/git/watching/watcherPatterns.ts +1 -1
- package/src/git-cli/exec/git.ts +13 -3
- package/src/git-cli/providers/branches.ts +384 -132
- package/src/git-cli/providers/commits.ts +106 -15
- package/src/git-cli/providers/config.ts +229 -8
- package/src/git-cli/providers/contributors.ts +5 -1
- package/src/git-cli/providers/graph.ts +26 -13
- package/src/git-cli/providers/operations.ts +45 -20
- package/src/git-cli/providers/pausedOperations.ts +109 -17
- package/src/git-cli/providers/refs.ts +33 -3
- package/src/git-cli/providers/status.ts +25 -4
- package/src/git-cli/providers/worktrees.ts +5 -0
- package/src/git-cli/service.ts +0 -1
- package/src/plus/agents/providers/claudeCodeProvider.ts +1130 -87
- package/src/plus/agents/providers/claudeCodeTranscript.ts +95 -9
- package/src/plus/agents/types.ts +46 -2
- package/src/plus/ai/errors.ts +30 -0
- package/src/plus/ai/models/model.ts +56 -6
- package/src/plus/ai/models/promptTemplates.ts +1 -1
- package/src/plus/ai/models/provider.ts +69 -2
- package/src/plus/ai/prompts.ts +186 -61
- package/src/plus/ai/providers/anthropicProvider.ts +155 -47
- package/src/plus/ai/providers/deepSeekProvider.ts +11 -21
- package/src/plus/ai/providers/geminiProvider.ts +19 -0
- package/src/plus/ai/providers/gitkrakenProvider.ts +126 -3
- package/src/plus/ai/providers/huggingFaceProvider.ts +6 -0
- package/src/plus/ai/providers/mistralProvider.ts +102 -19
- package/src/plus/ai/providers/ollamaProvider.ts +55 -4
- package/src/plus/ai/providers/openAICompatibleProvider.ts +5 -0
- package/src/plus/ai/providers/openAICompatibleProviderBase.ts +360 -17
- package/src/plus/ai/providers/openRouterProvider.ts +17 -0
- package/src/plus/ai/providers/openaiProvider.ts +1 -0
- package/src/plus/ai/providers/responseFormatCache.ts +39 -0
- package/src/plus/ai/providers/xaiProvider.ts +10 -1
- package/src/plus/ai/utils/ai.utils.ts +14 -0
- package/src/plus/ai/utils/results.utils.ts +255 -31
- package/src/plus/git-github/api/github.ts +467 -23
- package/src/plus/git-github/api/pullRequestSearchQuery.ts +81 -7
- package/src/plus/git-github/models.ts +77 -7
- package/src/plus/git-github/providers/github/status.ts +1 -0
- package/src/plus/integrations/context.ts +4 -0
- package/src/plus/integrations/index.ts +2 -0
- package/src/plus/integrations/integrationService.ts +25 -2
- package/src/plus/integrations/manager.ts +50 -5
- package/src/plus/integrations/models/gitHostIntegration.ts +54 -2
- package/src/plus/integrations/models/integration.ts +24 -13
- package/src/plus/integrations/providerFilters.ts +6 -1
- package/src/plus/integrations/providers/accounts.ts +38 -0
- package/src/plus/integrations/providers/azure/models.ts +3 -0
- package/src/plus/integrations/providers/bitbucket/models.ts +1 -0
- package/src/plus/integrations/providers/github.ts +218 -145
- package/src/plus/integrations/providers/gitlab.ts +30 -20
- package/src/plus/integrations/providers/models.ts +99 -127
- package/src/plus/integrations/providers/pullRequestReviews.ts +122 -0
- package/src/plus/integrations/reads/broaden.ts +6 -1
- package/src/plus/integrations/reads/counts.ts +273 -2
- package/src/plus/integrations/reads/drains.ts +19 -6
- package/src/plus/integrations/reads/filters.ts +22 -0
- package/src/plus/integrations/reads/hierarchy.ts +3 -1
- package/src/plus/integrations/reads/issueTracker.ts +9 -3
- package/src/plus/integrations/reads/issues.ts +9 -4
- package/src/plus/integrations/reads/pullRequests.ts +9 -4
- package/src/plus/integrations/reads/searchPullRequests.ts +12 -4
- package/src/plus/integrations/reads/sweeps.ts +1 -1
- package/src/plus/integrations/reads/warnings.ts +12 -1
- package/src/plus/integrations/results.ts +6 -1
- package/src/utils/env/browser/base64.ts +1 -1
- package/src/utils/env/node/base64.ts +3 -1
- package/src/utils/keys/chord.ts +184 -0
- package/src/utils/keys/keybinding.ts +116 -0
- package/src/utils/path.ts +14 -0
|
@@ -9,13 +9,14 @@ import { request } from '@octokit/request';
|
|
|
9
9
|
import { RequestError } from '@octokit/request-error';
|
|
10
10
|
import { AuthenticationError, AuthenticationErrorReason, RequestClientError, RequestNotFoundError, RequestRateLimitError, } from '../../../git/errors.js';
|
|
11
11
|
import { defaultIssueSort } from '../../../git/models/issue.js';
|
|
12
|
-
import { PullRequestMergeMethod } from '../../../git/models/pullRequest.js';
|
|
12
|
+
import { defaultPullRequestSort, PullRequestMergeMethod } from '../../../git/models/pullRequest.js';
|
|
13
13
|
import { getGitHubNoReplyAddressParts } from '../../../git/remotes/github.js';
|
|
14
14
|
import { effectiveIssueSort, getIssueComparator } from '../../../git/utils/issue.utils.js';
|
|
15
|
+
import { getPullRequestComparator } from '../../../git/utils/pullRequest.utils.js';
|
|
15
16
|
import { createRevisionRange, getRevisionRangeParts, isRevisionRange, isSha, } from '../../../git/utils/revision.utils.js';
|
|
16
17
|
import { chunk } from '../../../utils/array.js';
|
|
17
18
|
import { base64 } from '../../../utils/base64.js';
|
|
18
|
-
import { CancellationError } from '../../../utils/cancellation.js';
|
|
19
|
+
import { CancellationError, isCancellationError } from '../../../utils/cancellation.js';
|
|
19
20
|
import { trace } from '../../../utils/decorators/log.js';
|
|
20
21
|
import { Emitter } from '../../../utils/event.js';
|
|
21
22
|
import { uniqueBy } from '../../../utils/iterable.js';
|
|
@@ -51,10 +52,17 @@ const requestRetryMaxDelay = 2000; // ms
|
|
|
51
52
|
const accountResolveBatchSize = 25;
|
|
52
53
|
// Pull-request search selects the full PR fragment (reviews, requests, refs, commits, etc.),
|
|
53
54
|
// which makes GitHub reject broad 100-node searches with `Resource limits for this query
|
|
54
|
-
// exceeded` on large repositories. Thirty keeps the default within that GraphQL cost budget
|
|
55
|
-
//
|
|
55
|
+
// exceeded` on large repositories. Thirty keeps the default within that GraphQL cost budget;
|
|
56
|
+
// the 100-node maximum the connection accepts is for the lite shape, whose per-node cost is a
|
|
57
|
+
// fraction of it. The budget is per DOCUMENT, and one document holds every relationship × state
|
|
58
|
+
// facet, so the worst case scales with the facet count (five relationships × four states = 20).
|
|
56
59
|
const defaultPullRequestSearchPageSize = 30;
|
|
57
60
|
const maxPullRequestSearchPageSize = 100;
|
|
61
|
+
// Pages `searchMyPullRequests` drains for a caller that wants a whole list rather than a page.
|
|
62
|
+
// Four reduced pages cover more than the single 100-node page this read served before it paged,
|
|
63
|
+
// so the smaller page costs coverage nowhere; it bounds an unbounded drain on a read whose
|
|
64
|
+
// consumers (Launchpad, the Graph pull-request panel) block on it.
|
|
65
|
+
const maxMyPullRequestSearchPages = 4;
|
|
58
66
|
function isRetryableTransientError(ex) {
|
|
59
67
|
// An aborted request is rethrown as the original `AbortError` (not a `RequestError`), so it is
|
|
60
68
|
// excluded here. octokit maps a fetch/network failure to a `RequestError` with status 500 and
|
|
@@ -117,6 +125,42 @@ title
|
|
|
117
125
|
updatedAt
|
|
118
126
|
url
|
|
119
127
|
`;
|
|
128
|
+
/**
|
|
129
|
+
* Stacked-pull-request selections, appended to a pull request's selection set rather than baked into
|
|
130
|
+
* the fragments below: GitHub Enterprise Server schemas lag github.com, and selecting `stack` there
|
|
131
|
+
* fails the entire query with "Field 'stack' doesn't exist on type 'PullRequest'" — which would take
|
|
132
|
+
* every PR feature down with it, not just stacks. Always add these via `gqlPullRequestStackFragmentFor`.
|
|
133
|
+
*/
|
|
134
|
+
const gqlPullRequestStackFragment = `
|
|
135
|
+
stack {
|
|
136
|
+
id
|
|
137
|
+
number
|
|
138
|
+
size
|
|
139
|
+
baseRefName
|
|
140
|
+
}
|
|
141
|
+
stackEntry {
|
|
142
|
+
position
|
|
143
|
+
}
|
|
144
|
+
`;
|
|
145
|
+
function gqlPullRequestStackFragmentFor(options) {
|
|
146
|
+
return isGitHubDotCom(options) ? gqlPullRequestStackFragment : '';
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* A 409 means a merge request is already in flight and carries its ticket, so it resumes rather than fails.
|
|
150
|
+
*
|
|
151
|
+
* The body has to be dug out of `original`: `requestCore` routes every 4xx through `handleRequestError`,
|
|
152
|
+
* which re-wraps octokit's `RequestError` in a `RequestClientError` carrying only `message` and `original`.
|
|
153
|
+
*/
|
|
154
|
+
function getAsyncMergeUuidFromConflict(ex) {
|
|
155
|
+
const err = (RequestClientError.is(ex) ? ex.original : ex);
|
|
156
|
+
if (err?.status !== 409)
|
|
157
|
+
return undefined;
|
|
158
|
+
return err.response?.data?.details?.uuid;
|
|
159
|
+
}
|
|
160
|
+
const asyncMergePollIntervalMs = 2000;
|
|
161
|
+
/** A stack merges one layer at a time and GitHub only promises "a few minutes", so the ceiling is
|
|
162
|
+
* generous — giving up early would report a failure for a merge still in progress. */
|
|
163
|
+
const maxAsyncMergePolls = 300;
|
|
120
164
|
const gqlPullRequestLiteFragment = `
|
|
121
165
|
${gqlIssueOrPullRequestFragment}
|
|
122
166
|
author {
|
|
@@ -153,6 +197,24 @@ repository {
|
|
|
153
197
|
viewerPermission
|
|
154
198
|
}
|
|
155
199
|
`;
|
|
200
|
+
/**
|
|
201
|
+
* One review's fields, shared by `latestReviews` and `viewerLatestReview`. The two selections must stay
|
|
202
|
+
* identical: `fromGitHubPullRequest` merges the viewer's review into the capped `latestReviews` window and
|
|
203
|
+
* dedups by `id`, so a field present in only one of them would produce rows that differ by where they came
|
|
204
|
+
* from rather than by what they are.
|
|
205
|
+
*/
|
|
206
|
+
const gqlPullRequestReviewFragment = `
|
|
207
|
+
id
|
|
208
|
+
author {
|
|
209
|
+
login
|
|
210
|
+
avatarUrl(size: $avatarSize)
|
|
211
|
+
url
|
|
212
|
+
}
|
|
213
|
+
state
|
|
214
|
+
commit {
|
|
215
|
+
oid
|
|
216
|
+
}
|
|
217
|
+
`;
|
|
156
218
|
const gqlPullRequestFragment = `
|
|
157
219
|
${gqlPullRequestLiteFragment}
|
|
158
220
|
additions
|
|
@@ -163,6 +225,7 @@ assignees(first: 25) {
|
|
|
163
225
|
url
|
|
164
226
|
}
|
|
165
227
|
}
|
|
228
|
+
changedFiles
|
|
166
229
|
checksUrl
|
|
167
230
|
deletions
|
|
168
231
|
mergeable
|
|
@@ -172,14 +235,12 @@ mergedBy {
|
|
|
172
235
|
reviewDecision
|
|
173
236
|
latestReviews(first: 25) {
|
|
174
237
|
nodes {
|
|
175
|
-
|
|
176
|
-
login
|
|
177
|
-
avatarUrl(size: $avatarSize)
|
|
178
|
-
url
|
|
179
|
-
}
|
|
180
|
-
state
|
|
238
|
+
${gqlPullRequestReviewFragment}
|
|
181
239
|
}
|
|
182
240
|
}
|
|
241
|
+
viewerLatestReview {
|
|
242
|
+
${gqlPullRequestReviewFragment}
|
|
243
|
+
}
|
|
183
244
|
reviewRequests(first: 25) {
|
|
184
245
|
nodes {
|
|
185
246
|
asCodeOwner
|
|
@@ -194,6 +255,7 @@ reviewRequests(first: 25) {
|
|
|
194
255
|
}
|
|
195
256
|
}
|
|
196
257
|
commits(last: 1) {
|
|
258
|
+
totalCount
|
|
197
259
|
nodes {
|
|
198
260
|
commit {
|
|
199
261
|
statusCheckRollup {
|
|
@@ -271,6 +333,7 @@ export class GitHubApi {
|
|
|
271
333
|
try {
|
|
272
334
|
const query = `query getCurrentAccount($avatarSize: Int) {
|
|
273
335
|
viewer {
|
|
336
|
+
databaseId
|
|
274
337
|
name
|
|
275
338
|
email
|
|
276
339
|
login
|
|
@@ -282,7 +345,10 @@ export class GitHubApi {
|
|
|
282
345
|
return undefined;
|
|
283
346
|
return {
|
|
284
347
|
provider: provider,
|
|
285
|
-
id
|
|
348
|
+
// `id` is the provider's own id, as it is for every other provider, and `username` the handle
|
|
349
|
+
// filters and viewer matching key on. Falls back to the login only when GitHub omits the
|
|
350
|
+
// database id, which leaves the two equal rather than leaving `id` empty.
|
|
351
|
+
id: rsp.viewer.databaseId != null ? String(rsp.viewer.databaseId) : rsp.viewer.login,
|
|
286
352
|
name: rsp.viewer.name ?? undefined,
|
|
287
353
|
email: rsp.viewer.email ?? undefined,
|
|
288
354
|
// If we are GitHub Enterprise, we may need to convert the avatar URL since it might require authentication
|
|
@@ -579,6 +645,7 @@ export class GitHubApi {
|
|
|
579
645
|
repository(name: $repo, owner: $owner) {
|
|
580
646
|
pullRequest(number: $number) {
|
|
581
647
|
${gqlPullRequestLiteFragment}
|
|
648
|
+
${gqlPullRequestStackFragmentFor(options)}
|
|
582
649
|
}
|
|
583
650
|
}
|
|
584
651
|
}`;
|
|
@@ -614,6 +681,7 @@ export class GitHubApi {
|
|
|
614
681
|
associatedPullRequests(first: $limit, orderBy: {field: UPDATED_AT, direction: DESC}, states: $include) {
|
|
615
682
|
nodes {
|
|
616
683
|
${gqlPullRequestLiteFragment}
|
|
684
|
+
${gqlPullRequestStackFragmentFor(options)}
|
|
617
685
|
}
|
|
618
686
|
}
|
|
619
687
|
}
|
|
@@ -659,6 +727,7 @@ export class GitHubApi {
|
|
|
659
727
|
associatedPullRequests(first: 2, orderBy: {field: UPDATED_AT, direction: DESC}) {
|
|
660
728
|
nodes {
|
|
661
729
|
${gqlPullRequestLiteFragment}
|
|
730
|
+
${gqlPullRequestStackFragmentFor(options)}
|
|
662
731
|
}
|
|
663
732
|
}
|
|
664
733
|
}
|
|
@@ -1974,6 +2043,17 @@ export class GitHubApi {
|
|
|
1974
2043
|
return promise;
|
|
1975
2044
|
}
|
|
1976
2045
|
async request(provider, token, route, options, scope, cancellation) {
|
|
2046
|
+
return (await this.requestCore(provider, token, route, options, scope, cancellation));
|
|
2047
|
+
}
|
|
2048
|
+
/**
|
|
2049
|
+
* REST call for routes `@octokit/types` doesn't describe yet — currently the stacked-pull-request
|
|
2050
|
+
* merge APIs, which are in public preview and absent from the generated endpoint map. Prefer
|
|
2051
|
+
* `request` for anything typed.
|
|
2052
|
+
*/
|
|
2053
|
+
async requestPreview(provider, token, route, options, scope, cancellation) {
|
|
2054
|
+
return (await this.requestCore(provider, token, route, options, scope, cancellation));
|
|
2055
|
+
}
|
|
2056
|
+
async requestCore(provider, token, route, options, scope, cancellation) {
|
|
1977
2057
|
const { accessToken } = token;
|
|
1978
2058
|
try {
|
|
1979
2059
|
let signal;
|
|
@@ -1986,7 +2066,7 @@ export class GitHubApi {
|
|
|
1986
2066
|
// Retry transient gateway/network failures on idempotent reads only
|
|
1987
2067
|
const method = route.split(' ', 1)[0].toUpperCase();
|
|
1988
2068
|
const retryable = method === 'GET' || method === 'HEAD';
|
|
1989
|
-
return
|
|
2069
|
+
return await this.requestWithRetries(() => this.config.wrapForForcedInsecureSSL(provider?.getIgnoreSSLErrors() ?? false, () => this.getDefaults(accessToken, request)(route, options)), retryable, signal, scope);
|
|
1990
2070
|
}
|
|
1991
2071
|
catch (ex) {
|
|
1992
2072
|
if (ex instanceof RequestError || ex.name === 'AbortError') {
|
|
@@ -2161,14 +2241,21 @@ export class GitHubApi {
|
|
|
2161
2241
|
* One page of the current user's pull requests, filtered by state and optionally by an explicit
|
|
2162
2242
|
* relationship qualifier. Backs the PR sweeps, which drain it page by page.
|
|
2163
2243
|
*
|
|
2164
|
-
* Ordering is part of the contract, not an option: always `sort:updated` (most recently updated first),
|
|
2165
|
-
*
|
|
2244
|
+
* Ordering is part of the contract, not an option: always `sort:updated` (most recently updated first), which is
|
|
2245
|
+
* {@link searchPullRequestsPage}'s DEFAULT rather than its only order — that read takes a `criteria.sort`, this
|
|
2246
|
+
* one does not, because a sweep's recency window is what its page budget is defined against. A caller that stops
|
|
2247
|
+
* before `hasMore` clears — every sweep with a
|
|
2166
2248
|
* page budget — therefore retains a well-defined recency window instead of an arbitrary slice of GitHub's
|
|
2167
2249
|
* relevance ranking.
|
|
2168
2250
|
*/
|
|
2169
2251
|
async searchMyPullRequestsPage(provider, token, options, cancellation) {
|
|
2170
2252
|
const scope = getScopedLogger();
|
|
2171
|
-
|
|
2253
|
+
// The page follows the projection rather than being a separate decision: the full fragment is what GitHub
|
|
2254
|
+
// rejects at 100 nodes (see `defaultPullRequestSearchPageSize`), so every read that selects it pages at the
|
|
2255
|
+
// reduced size, and only the lite shape asks for the maximum. A caller that wants a whole list pages for it
|
|
2256
|
+
// — see `searchMyPullRequests`.
|
|
2257
|
+
const configuredLimit = this.config.getLaunchpadQueryLimit?.() ?? maxPullRequestSearchPageSize;
|
|
2258
|
+
const limit = Math.min(options?.summary === true ? maxPullRequestSearchPageSize : defaultPullRequestSearchPageSize, configuredLimit);
|
|
2172
2259
|
try {
|
|
2173
2260
|
const query = `query searchMyPullRequests(
|
|
2174
2261
|
$search: String!
|
|
@@ -2184,6 +2271,7 @@ export class GitHubApi {
|
|
|
2184
2271
|
nodes {
|
|
2185
2272
|
...on PullRequest {
|
|
2186
2273
|
${options?.summary ? gqlPullRequestLiteFragment : gqlPullRequestFragment}
|
|
2274
|
+
${gqlPullRequestStackFragmentFor(options)}
|
|
2187
2275
|
}
|
|
2188
2276
|
}
|
|
2189
2277
|
}
|
|
@@ -2247,8 +2335,36 @@ export class GitHubApi {
|
|
|
2247
2335
|
throw this.handleException(ex, provider, scope, options?.silent);
|
|
2248
2336
|
}
|
|
2249
2337
|
}
|
|
2338
|
+
/**
|
|
2339
|
+
* The whole list rather than a page: this read has no cursor to hand back (its `IntegrationResult<T[]>` return
|
|
2340
|
+
* has no paging channel at all), so it drains up to {@link maxMyPullRequestSearchPages} pages itself.
|
|
2341
|
+
*
|
|
2342
|
+
* Draining instead of taking one page is what lets the full projection page at the reduced size everywhere
|
|
2343
|
+
* (see the `limit` in {@link searchMyPullRequestsPage}): a single page would otherwise have to ask for 100
|
|
2344
|
+
* nodes of the selection GitHub rejects at that size, purely because this caller cannot resume. Ordering is
|
|
2345
|
+
* `sort:updated`, so the pages compose into a defined window rather than a shifting relevance ranking, and the
|
|
2346
|
+
* drain stops as soon as GitHub reports no next page.
|
|
2347
|
+
*/
|
|
2250
2348
|
async searchMyPullRequests(provider, token, options, cancellation) {
|
|
2251
|
-
|
|
2349
|
+
const values = [];
|
|
2350
|
+
// The searches behind one page can overlap (a PR can be authored by and review-requested from the same
|
|
2351
|
+
// user), and a later page can repeat a row an earlier one already served if the PR was updated mid-drain.
|
|
2352
|
+
const seen = new Set();
|
|
2353
|
+
let cursor;
|
|
2354
|
+
for (let page = 0; page < maxMyPullRequestSearchPages; page++) {
|
|
2355
|
+
const result = await this.searchMyPullRequestsPage(provider, token, { ...options, cursor: cursor }, cancellation);
|
|
2356
|
+
for (const pr of result.values) {
|
|
2357
|
+
if (seen.has(pr.url))
|
|
2358
|
+
continue;
|
|
2359
|
+
seen.add(pr.url);
|
|
2360
|
+
values.push(pr);
|
|
2361
|
+
}
|
|
2362
|
+
// A missing or repeated cursor with `hasMore` would loop on the same page forever.
|
|
2363
|
+
if (!result.hasMore || result.cursor == null || result.cursor === cursor)
|
|
2364
|
+
break;
|
|
2365
|
+
cursor = result.cursor;
|
|
2366
|
+
}
|
|
2367
|
+
return values;
|
|
2252
2368
|
}
|
|
2253
2369
|
/**
|
|
2254
2370
|
* The current user's issues: authored ∪ assigned ∪ mentioned, each its own aliased search behind one composite
|
|
@@ -2431,6 +2547,64 @@ export class GitHubApi {
|
|
|
2431
2547
|
throw this.handleException(ex, provider, scope);
|
|
2432
2548
|
}
|
|
2433
2549
|
}
|
|
2550
|
+
/**
|
|
2551
|
+
* The PR twin of {@link countIssues}: counts pull requests for several scopes in ONE request via aliased
|
|
2552
|
+
* `search` fields selecting only `issueCount` with `first: 0`. Same positional/undefined contract as the issue
|
|
2553
|
+
* count.
|
|
2554
|
+
*
|
|
2555
|
+
* The one difference is states. {@link toGitHubPullRequestSearchFacets} fans a scope's states out into one
|
|
2556
|
+
* `search` each, so this reports the count the SAME way {@link searchPullRequestsPage} reports its total — the
|
|
2557
|
+
* LARGEST facet's `issueCount`, not their sum: the result ceiling applies per search, so the max is what
|
|
2558
|
+
* `exceedsProviderLimit` compares against, and summing would claim a total the read never surfaces. Relationships
|
|
2559
|
+
* are OR-ed and can't be a single count; the facade refuses a multi-relationship scope, so at most one is here.
|
|
2560
|
+
*/
|
|
2561
|
+
async countPullRequests(provider, token, scopes, options, cancellation) {
|
|
2562
|
+
const scope = getScopedLogger();
|
|
2563
|
+
if (scopes.length === 0)
|
|
2564
|
+
return [];
|
|
2565
|
+
// Each scope expands to one query string per state facet (all sharing its single relationship, which the
|
|
2566
|
+
// facade guarantees). A scope's count is the MAX across its facets — mirroring searchPullRequestsPage's
|
|
2567
|
+
// totalCount — so the aliases stay grouped by scope and are reduced after the response.
|
|
2568
|
+
const scopeQueries = scopes.map(s => {
|
|
2569
|
+
const scopeQualifiers = toGitHubIssueSearchScopeQualifiers(s.org, s.repos);
|
|
2570
|
+
return toGitHubPullRequestSearchFacets(s.criteria).map(f => [...scopeQualifiers, ...f.qualifiers].join(' '));
|
|
2571
|
+
});
|
|
2572
|
+
// Aliases are positional and generated (`s${scope}f${facet}`): a caller's key is arbitrary text and would
|
|
2573
|
+
// break the document, so results are reduced back to one count per scope by index.
|
|
2574
|
+
const aliased = scopeQueries.flatMap((queries, si) => queries.map((query, fi) => ({ alias: `s${si}f${fi}`, query: query })));
|
|
2575
|
+
const params = aliased.map(a => `$${a.alias}: String!`).join('\n\t\t\t\t');
|
|
2576
|
+
// `first: 0` is what makes this cheap — `issueCount` alone, no nodes over the wire.
|
|
2577
|
+
const fields = aliased
|
|
2578
|
+
.map(a => `${a.alias}: search(query: $${a.alias}, type: ISSUE, first: 0) { issueCount }`)
|
|
2579
|
+
.join('\n\t\t\t\t');
|
|
2580
|
+
const query = `query countPullRequests(
|
|
2581
|
+
${params}
|
|
2582
|
+
) {
|
|
2583
|
+
${fields}
|
|
2584
|
+
}`;
|
|
2585
|
+
const variables = { baseUrl: options?.baseUrl };
|
|
2586
|
+
for (const a of aliased) {
|
|
2587
|
+
variables[a.alias] = a.query;
|
|
2588
|
+
}
|
|
2589
|
+
try {
|
|
2590
|
+
const rsp = await this.graphql(provider, token, query, variables, scope, cancellation);
|
|
2591
|
+
if (rsp == null)
|
|
2592
|
+
return scopes.map(() => undefined);
|
|
2593
|
+
return scopeQueries.map((queries, si) => {
|
|
2594
|
+
let max;
|
|
2595
|
+
for (let fi = 0; fi < queries.length; fi++) {
|
|
2596
|
+
const count = rsp[`s${si}f${fi}`]?.issueCount;
|
|
2597
|
+
if (count != null) {
|
|
2598
|
+
max = max == null ? count : Math.max(max, count);
|
|
2599
|
+
}
|
|
2600
|
+
}
|
|
2601
|
+
return max;
|
|
2602
|
+
});
|
|
2603
|
+
}
|
|
2604
|
+
catch (ex) {
|
|
2605
|
+
throw this.handleException(ex, provider, scope);
|
|
2606
|
+
}
|
|
2607
|
+
}
|
|
2434
2608
|
/**
|
|
2435
2609
|
* The aliased-search engine behind every GitHub issue search: one GraphQL request carrying N independently
|
|
2436
2610
|
* cursored `search` fields, `@include`-gated so an exhausted or unrequested one costs nothing.
|
|
@@ -2646,8 +2820,11 @@ export class GitHubApi {
|
|
|
2646
2820
|
* every active relationship × state facet, so one HTTP request serves one page even when the logical search is
|
|
2647
2821
|
* a union. The cursor preserves each facet's continuation plus the positional page.
|
|
2648
2822
|
*
|
|
2649
|
-
* Ordering is
|
|
2650
|
-
*
|
|
2823
|
+
* Ordering is `criteria.sort`, defaulting to most-recently-updated-first — the order this read served before it
|
|
2824
|
+
* was expressible. It is requested of the provider AND re-applied to the merged page, because the page is a
|
|
2825
|
+
* union of facets and no per-facet server order describes it. The sort is part of the cursor fingerprint, so
|
|
2826
|
+
* changing it invalidates a threaded cursor exactly as changing the text or the scope does. User text is
|
|
2827
|
+
* sanitized before it reaches the provider query. See {@link toGitHubPullRequestSearchFacets}.
|
|
2651
2828
|
*/
|
|
2652
2829
|
async searchPullRequestsPage(provider, token, options, cancellation) {
|
|
2653
2830
|
const scope = getScopedLogger();
|
|
@@ -2723,6 +2900,7 @@ export class GitHubApi {
|
|
|
2723
2900
|
nodes {
|
|
2724
2901
|
... on PullRequest {
|
|
2725
2902
|
${gqlPullRequestFragment}
|
|
2903
|
+
${gqlPullRequestStackFragmentFor(options)}
|
|
2726
2904
|
}
|
|
2727
2905
|
}
|
|
2728
2906
|
}`);
|
|
@@ -2758,7 +2936,15 @@ export class GitHubApi {
|
|
|
2758
2936
|
}
|
|
2759
2937
|
}
|
|
2760
2938
|
}
|
|
2761
|
-
|
|
2939
|
+
// The PR path re-sorts the merged page rather than trusting the per-facet server order — GitHub's
|
|
2940
|
+
// server-side PR sort has been unreliable (the per-branch path re-sorts for the same reason), and the
|
|
2941
|
+
// union of several facets is unordered regardless. The key was validated against
|
|
2942
|
+
// `githubPullRequestSearchCapabilities.sorts` upstream, so its comparator is always defined for a PR
|
|
2943
|
+
// shape; the guard only guards the unreachable case rather than inventing an order for it.
|
|
2944
|
+
const comparator = getPullRequestComparator(options?.criteria?.sort ?? defaultPullRequestSort);
|
|
2945
|
+
if (comparator != null) {
|
|
2946
|
+
pullRequests.sort(comparator);
|
|
2947
|
+
}
|
|
2762
2948
|
const values = [
|
|
2763
2949
|
...uniqueBy(pullRequests, pr => pr.url, (original, _current) => original),
|
|
2764
2950
|
];
|
|
@@ -2826,6 +3012,7 @@ export class GitHubApi {
|
|
|
2826
3012
|
nodes {
|
|
2827
3013
|
...on PullRequest {
|
|
2828
3014
|
${gqlPullRequestFragment}
|
|
3015
|
+
${gqlPullRequestStackFragmentFor(options)}
|
|
2829
3016
|
}
|
|
2830
3017
|
}
|
|
2831
3018
|
}
|
|
@@ -2868,6 +3055,98 @@ export class GitHubApi {
|
|
|
2868
3055
|
throw this.handleException(ex, provider, scope);
|
|
2869
3056
|
}
|
|
2870
3057
|
}
|
|
3058
|
+
/**
|
|
3059
|
+
* Every stack in the repository, each with its members bottom to top.
|
|
3060
|
+
*
|
|
3061
|
+
* One request regardless of how many pull requests are involved — which is what makes it the right
|
|
3062
|
+
* shape for list surfaces, whose pull requests arrive through the shared providers API and so carry no
|
|
3063
|
+
* stack membership of their own. Callers join the result by pull request number.
|
|
3064
|
+
*
|
|
3065
|
+
* A `404` means the repository isn't enrolled in the stacked-pull-requests preview; that's reported as
|
|
3066
|
+
* `undefined` rather than an error, since "no stacks" and "not available" both mean nothing to show.
|
|
3067
|
+
*/
|
|
3068
|
+
async getRepositoryStacks(provider, token, owner, repo, options, cancellation) {
|
|
3069
|
+
const scope = getScopedLogger();
|
|
3070
|
+
try {
|
|
3071
|
+
const rsp = await this.requestPreview(provider, token, 'GET /repos/{owner}/{repo}/stacks', { owner: owner, repo: repo, baseUrl: options?.baseUrl }, scope, cancellation);
|
|
3072
|
+
return rsp.data;
|
|
3073
|
+
}
|
|
3074
|
+
catch (ex) {
|
|
3075
|
+
if (isCancellationError(ex))
|
|
3076
|
+
throw ex;
|
|
3077
|
+
Logger.warn(scope, `Unable to list stacks for ${owner}/${repo}: ${ex}`);
|
|
3078
|
+
return undefined;
|
|
3079
|
+
}
|
|
3080
|
+
}
|
|
3081
|
+
/**
|
|
3082
|
+
* Merges a stacked pull request, and with it every layer below it.
|
|
3083
|
+
*
|
|
3084
|
+
* Stacks cannot go through `mergePullRequest` — GitHub rejects stacked pull requests on the legacy
|
|
3085
|
+
* synchronous merge endpoints and mutations. The replacement is asynchronous: submit, then poll a
|
|
3086
|
+
* ticket until it reaches a terminal state.
|
|
3087
|
+
*/
|
|
3088
|
+
async mergeStackedPullRequest(provider, token, owner, repo, pullNumber, expectedSourceSha, options, cancellation) {
|
|
3089
|
+
const scope = getScopedLogger();
|
|
3090
|
+
try {
|
|
3091
|
+
let uuid;
|
|
3092
|
+
try {
|
|
3093
|
+
const submitted = await this.requestPreview(provider, token, 'PUT /repos/{owner}/{repo}/pulls/{pull_number}/merge-async', {
|
|
3094
|
+
owner: owner,
|
|
3095
|
+
repo: repo,
|
|
3096
|
+
pull_number: pullNumber,
|
|
3097
|
+
sha: expectedSourceSha,
|
|
3098
|
+
merge_method: options?.mergeMethod,
|
|
3099
|
+
baseUrl: options?.baseUrl,
|
|
3100
|
+
}, scope, cancellation);
|
|
3101
|
+
// Already merged or rejected outright — nothing to poll for. `enqueued` lands via the merge
|
|
3102
|
+
// queue, which can take several merge groups to settle, so it's transitional like `pending`.
|
|
3103
|
+
if (submitted.data.status !== 'pending' && submitted.data.status !== 'enqueued') {
|
|
3104
|
+
if (submitted.data.status === 'failed') {
|
|
3105
|
+
Logger.warn(scope, `Stacked merge refused: ${submitted.data.details?.message ?? 'no reason given'}`);
|
|
3106
|
+
}
|
|
3107
|
+
return submitted.data.status === 'merged';
|
|
3108
|
+
}
|
|
3109
|
+
uuid = submitted.data.details?.uuid;
|
|
3110
|
+
}
|
|
3111
|
+
catch (ex) {
|
|
3112
|
+
// A merge request is already in flight (a retry, or a double-click) — adopt its ticket and
|
|
3113
|
+
// poll that instead of reporting a failure for a merge that is actually running.
|
|
3114
|
+
uuid = getAsyncMergeUuidFromConflict(ex);
|
|
3115
|
+
if (uuid == null)
|
|
3116
|
+
throw ex;
|
|
3117
|
+
}
|
|
3118
|
+
if (uuid == null)
|
|
3119
|
+
return false;
|
|
3120
|
+
// The stack merges server-side one layer at a time, so this can take a while. Poll on a
|
|
3121
|
+
// fixed interval and give up rather than hang forever if the ticket never settles.
|
|
3122
|
+
for (let attempt = 0; attempt < maxAsyncMergePolls; attempt++) {
|
|
3123
|
+
if (cancellation?.aborted)
|
|
3124
|
+
throw new CancellationError();
|
|
3125
|
+
await new Promise(resolve => setTimeout(resolve, asyncMergePollIntervalMs));
|
|
3126
|
+
const polled = await this.requestPreview(provider, token, 'GET /repos/{owner}/{repo}/pulls/{pull_number}/merge-async/{uuid}', {
|
|
3127
|
+
owner: owner,
|
|
3128
|
+
repo: repo,
|
|
3129
|
+
pull_number: pullNumber,
|
|
3130
|
+
uuid: uuid,
|
|
3131
|
+
baseUrl: options?.baseUrl,
|
|
3132
|
+
}, scope, cancellation);
|
|
3133
|
+
if (polled.data.status === 'pending' || polled.data.status === 'enqueued')
|
|
3134
|
+
continue;
|
|
3135
|
+
if (polled.data.status === 'failed') {
|
|
3136
|
+
Logger.warn(scope, `Stacked merge failed: ${polled.data.details?.message ?? 'no reason given'}`);
|
|
3137
|
+
}
|
|
3138
|
+
return polled.data.status === 'merged';
|
|
3139
|
+
}
|
|
3140
|
+
Logger.warn(scope, `Timed out waiting for stacked merge of ${owner}/${repo}#${pullNumber}`);
|
|
3141
|
+
return false;
|
|
3142
|
+
}
|
|
3143
|
+
catch (ex) {
|
|
3144
|
+
if (isCancellationError(ex))
|
|
3145
|
+
throw ex;
|
|
3146
|
+
Logger.error(ex, scope);
|
|
3147
|
+
throw this.handleException(ex, provider, scope);
|
|
3148
|
+
}
|
|
3149
|
+
}
|
|
2871
3150
|
async mergePullRequest(provider, token, nodeId, expectedSourceSha, options, cancellation) {
|
|
2872
3151
|
const scope = getScopedLogger();
|
|
2873
3152
|
let githubMergeStrategy;
|
|
@@ -2903,7 +3182,7 @@ export class GitHubApi {
|
|
|
2903
3182
|
mergeMethod: githubMergeStrategy,
|
|
2904
3183
|
baseUrl: options?.baseUrl,
|
|
2905
3184
|
}, scope, cancellation);
|
|
2906
|
-
return rsp?.pullRequest?.id === nodeId;
|
|
3185
|
+
return rsp?.mergePullRequest?.pullRequest?.id === nodeId;
|
|
2907
3186
|
}
|
|
2908
3187
|
catch (ex) {
|
|
2909
3188
|
throw this.handleException(ex, provider, scope);
|
|
@@ -3205,12 +3484,37 @@ __decorate([
|
|
|
3205
3484
|
__decorate([
|
|
3206
3485
|
trace({ args: (provider, token) => ({ provider: provider.name, token: `<token:${token.microHash}>` }) })
|
|
3207
3486
|
], GitHubApi.prototype, "countIssues", null);
|
|
3487
|
+
__decorate([
|
|
3488
|
+
trace({ args: (provider, token) => ({ provider: provider.name, token: `<token:${token.microHash}>` }) })
|
|
3489
|
+
], GitHubApi.prototype, "countPullRequests", null);
|
|
3208
3490
|
__decorate([
|
|
3209
3491
|
trace({ args: (provider, token) => ({ provider: provider.name, token: `<token:${token.microHash}>` }) })
|
|
3210
3492
|
], GitHubApi.prototype, "searchPullRequestsPage", null);
|
|
3211
3493
|
__decorate([
|
|
3212
3494
|
trace({ args: (provider, token) => ({ provider: provider.name, token: `<token:${token.microHash}>` }) })
|
|
3213
3495
|
], GitHubApi.prototype, "searchPullRequests", null);
|
|
3496
|
+
__decorate([
|
|
3497
|
+
trace({
|
|
3498
|
+
args: (provider, token, owner, repo) => ({
|
|
3499
|
+
provider: provider.name,
|
|
3500
|
+
token: `<token:${token.microHash}>`,
|
|
3501
|
+
owner: owner,
|
|
3502
|
+
repo: repo,
|
|
3503
|
+
}),
|
|
3504
|
+
})
|
|
3505
|
+
], GitHubApi.prototype, "getRepositoryStacks", null);
|
|
3506
|
+
__decorate([
|
|
3507
|
+
trace({
|
|
3508
|
+
args: (provider, token, owner, repo, pullNumber, expectedSourceSha) => ({
|
|
3509
|
+
provider: provider.name,
|
|
3510
|
+
token: `<token:${token.microHash}>`,
|
|
3511
|
+
owner: owner,
|
|
3512
|
+
repo: repo,
|
|
3513
|
+
pullNumber: pullNumber,
|
|
3514
|
+
expectedSourceSha: expectedSourceSha,
|
|
3515
|
+
}),
|
|
3516
|
+
})
|
|
3517
|
+
], GitHubApi.prototype, "mergeStackedPullRequest", null);
|
|
3214
3518
|
__decorate([
|
|
3215
3519
|
trace({
|
|
3216
3520
|
args: (provider, token, nodeId, expectedSourceSha) => ({
|