@gitkraken/core-gitlens 0.5.110 → 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 +16 -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 +38 -2
- package/dist/git/models/pullRequest.d.ts.map +1 -1
- package/dist/git/models/pullRequest.js +12 -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 +14 -1
- package/dist/git/utils/pullRequest.utils.d.ts.map +1 -1
- package/dist/git/utils/pullRequest.utils.js +31 -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 +55 -0
- package/dist/plus/git-github/api/github.d.ts.map +1 -1
- package/dist/plus/git-github/api/github.js +177 -4
- package/dist/plus/git-github/api/github.js.map +1 -1
- package/dist/plus/git-github/models.d.ts +16 -0
- package/dist/plus/git-github/models.d.ts.map +1 -1
- package/dist/plus/git-github/models.js +29 -3
- 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/models/gitHostIntegration.d.ts +6 -3
- package/dist/plus/integrations/models/gitHostIntegration.d.ts.map +1 -1
- package/dist/plus/integrations/models/gitHostIntegration.js +12 -2
- package/dist/plus/integrations/models/gitHostIntegration.js.map +1 -1
- package/dist/plus/integrations/models/integration.d.ts +3 -1
- 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/providers/accounts.d.ts.map +1 -1
- package/dist/plus/integrations/providers/accounts.js +4 -0
- package/dist/plus/integrations/providers/accounts.js.map +1 -1
- 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 +14 -2
- package/dist/plus/integrations/providers/github.d.ts.map +1 -1
- package/dist/plus/integrations/providers/github.js +55 -3
- package/dist/plus/integrations/providers/github.js.map +1 -1
- package/dist/plus/integrations/providers/gitlab.d.ts.map +1 -1
- package/dist/plus/integrations/providers/gitlab.js.map +1 -1
- package/dist/plus/integrations/providers/models.d.ts.map +1 -1
- package/dist/plus/integrations/providers/models.js +30 -4
- package/dist/plus/integrations/providers/models.js.map +1 -1
- 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/drains.d.ts.map +1 -1
- package/dist/plus/integrations/reads/drains.js +7 -4
- package/dist/plus/integrations/reads/drains.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/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/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 +33 -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 +36 -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 +291 -7
- package/src/plus/git-github/models.ts +48 -2
- 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/models/gitHostIntegration.ts +25 -2
- package/src/plus/integrations/models/integration.ts +23 -13
- package/src/plus/integrations/providers/accounts.ts +4 -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 +85 -1
- package/src/plus/integrations/providers/gitlab.ts +2 -10
- package/src/plus/integrations/providers/models.ts +36 -4
- package/src/plus/integrations/reads/broaden.ts +6 -1
- package/src/plus/integrations/reads/drains.ts +7 -4
- 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/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
|
@@ -8,9 +8,14 @@ import { OpenAICompatibleProviderBase } from './openAICompatibleProviderBase.js'
|
|
|
8
8
|
|
|
9
9
|
type GitKrakenModel = AIModel<typeof provider.id>;
|
|
10
10
|
|
|
11
|
+
/** Opt-out flag the models endpoint reports in `disabledAttributes` for models whose upstream
|
|
12
|
+
* translation doesn't cover native structured outputs */
|
|
13
|
+
const structuredOutputAttribute = 'structured_output';
|
|
14
|
+
|
|
11
15
|
export class GitKrakenProvider extends OpenAICompatibleProviderBase<typeof provider.id> {
|
|
12
16
|
readonly id = provider.id;
|
|
13
17
|
readonly name = provider.name;
|
|
18
|
+
readonly supportsTools = true;
|
|
14
19
|
protected readonly descriptor = provider;
|
|
15
20
|
protected readonly config = {};
|
|
16
21
|
|
|
@@ -47,6 +52,7 @@ export class GitKrakenProvider extends OpenAICompatibleProviderBase<typeof provi
|
|
|
47
52
|
preferred: boolean;
|
|
48
53
|
maxInputTokens: number;
|
|
49
54
|
maxOutputTokens: number;
|
|
55
|
+
disabledAttributes?: string[];
|
|
50
56
|
consumptionRateLabel?: string;
|
|
51
57
|
}[];
|
|
52
58
|
error?: null;
|
|
@@ -67,6 +73,10 @@ export class GitKrakenProvider extends OpenAICompatibleProviderBase<typeof provi
|
|
|
67
73
|
default: m.preferred,
|
|
68
74
|
temperature: null,
|
|
69
75
|
consumptionRateLabel: m.consumptionRateLabel,
|
|
76
|
+
// The backend owns the per-upstream `response_format` translation, so it's the
|
|
77
|
+
// authority on which models it covers. A schema an upstream's converter still
|
|
78
|
+
// rejects is recovered per-request via isResponseFormatRejection below
|
|
79
|
+
supportsStructuredOutputs: !m.disabledAttributes?.includes(structuredOutputAttribute),
|
|
70
80
|
}) satisfies GitKrakenModel,
|
|
71
81
|
);
|
|
72
82
|
return models;
|
|
@@ -84,6 +94,31 @@ export class GitKrakenProvider extends OpenAICompatibleProviderBase<typeof provi
|
|
|
84
94
|
return 'chat/completions';
|
|
85
95
|
}
|
|
86
96
|
|
|
97
|
+
protected override isToolsRejection(status: number, message: string | undefined): boolean {
|
|
98
|
+
if (super.isToolsRejection(status, message)) return true;
|
|
99
|
+
if (message == null) return false;
|
|
100
|
+
|
|
101
|
+
// The backend forwards an upstream refusal as its own envelope carrying only "upstream AI provider
|
|
102
|
+
// error (<provider> HTTP 400)", naming neither "tool" nor "function" — so the base's text match can
|
|
103
|
+
// never fire here. Treat any wrapped upstream 400 as a candidate and let the retry decide: `tools`
|
|
104
|
+
// is the only field a tool-using request sends that a plain completion doesn't, the probe costs one
|
|
105
|
+
// request, and the caller latches the rejection only when dropping tools actually fixes it. A
|
|
106
|
+
// misread therefore self-corrects — the same bargain `isResponseFormatRejection` below makes.
|
|
107
|
+
return getWrappedUpstreamStatus(message) === 400;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
protected override isResponseFormatRejection(status: number, body: string): boolean {
|
|
111
|
+
if (super.isResponseFormatRejection(status, body)) return true;
|
|
112
|
+
|
|
113
|
+
// The backend wraps upstream schema rejections in its own envelope, carrying only the upstream
|
|
114
|
+
// status (e.g. its Gemini schema converter mangles null-union types → Gemini 400s). Match on the
|
|
115
|
+
// wrapper, NOT the envelope code — that varies by backend (500.1 on prod, 400.1 seen on staging),
|
|
116
|
+
// and keying off it means the probe silently stops firing. A non-schema upstream 400 also matches,
|
|
117
|
+
// which is fine: the strip-and-resend probe is cheap and rejection is only memoized when the
|
|
118
|
+
// resend succeeds, so misclassification self-corrects.
|
|
119
|
+
return getWrappedUpstreamStatus(body) === 400;
|
|
120
|
+
}
|
|
121
|
+
|
|
87
122
|
protected override getHeaders<TAction extends AIActionType>(
|
|
88
123
|
action: TAction,
|
|
89
124
|
apiKey: string,
|
|
@@ -107,17 +142,27 @@ export class GitKrakenProvider extends OpenAICompatibleProviderBase<typeof provi
|
|
|
107
142
|
_model: AIModel<typeof provider.id>,
|
|
108
143
|
retries: number,
|
|
109
144
|
maxInputTokens: number,
|
|
110
|
-
|
|
145
|
+
body?: string,
|
|
146
|
+
sentTools?: boolean,
|
|
147
|
+
): Promise<{ retry: true; maxInputTokens: number; withoutTools?: boolean }> {
|
|
111
148
|
type ErrorResponse = {
|
|
112
149
|
error?: { code: string; message: string; data?: any };
|
|
113
150
|
};
|
|
114
151
|
|
|
115
152
|
let json;
|
|
116
153
|
try {
|
|
117
|
-
json = (await rsp.json()) as ErrorResponse | undefined;
|
|
154
|
+
json = (body != null ? JSON.parse(body) : await rsp.json()) as ErrorResponse | undefined;
|
|
118
155
|
} catch {}
|
|
119
156
|
|
|
157
|
+
// The backend's own prose says only "upstream AI provider error (<provider> HTTP <status>)" and
|
|
158
|
+
// puts the provider's actual complaint in `data`. Dropping it (as every branch but the
|
|
159
|
+
// entitlement one did) leaves nothing naming a cause, so a request the upstream rejected is
|
|
160
|
+
// indistinguishable from any other 400 — and the only way to find out is to guess.
|
|
120
161
|
let message = json?.error?.message || rsp.statusText;
|
|
162
|
+
const detail = formatErrorData(json?.error?.data);
|
|
163
|
+
if (detail != null) {
|
|
164
|
+
message += `; ${detail}`;
|
|
165
|
+
}
|
|
121
166
|
|
|
122
167
|
let status: string | number;
|
|
123
168
|
let code: string | number;
|
|
@@ -126,6 +171,33 @@ export class GitKrakenProvider extends OpenAICompatibleProviderBase<typeof provi
|
|
|
126
171
|
status = status ? parseInt(status, 10) : rsp.status;
|
|
127
172
|
code = code ? parseInt(code, 10) : 0;
|
|
128
173
|
|
|
174
|
+
// Classify a wrapped upstream failure by the status it carries, not by the envelope's own code:
|
|
175
|
+
// prod reports these as 500.1, but staging has been seen using 400.1, and keying off the outer
|
|
176
|
+
// code means an upstream rate limit arrives as a bare Error with no reason — so no "Switch
|
|
177
|
+
// Model" action and no retry, just an opaque message.
|
|
178
|
+
const upstreamStatus = getWrappedUpstreamStatus(message);
|
|
179
|
+
if (upstreamStatus != null) {
|
|
180
|
+
const wrapped = new Error(`(${this.name}) ${status}.${code}: ${message}`);
|
|
181
|
+
switch (upstreamStatus) {
|
|
182
|
+
case 429:
|
|
183
|
+
throw new AIError(AIErrorReason.RateLimitExceeded, wrapped);
|
|
184
|
+
case 413:
|
|
185
|
+
throw new AIError(AIErrorReason.RequestTooLarge, wrapped);
|
|
186
|
+
case 401:
|
|
187
|
+
case 403:
|
|
188
|
+
throw new AIError(AIErrorReason.Unauthorized, wrapped);
|
|
189
|
+
// Anything else is the upstream refusing the request itself. There's nothing to recover
|
|
190
|
+
// automatically, so fall through and surface it with the detail folded in above.
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Recover a tools rejection BEFORE the switch below. This override owns the 400 case and throws,
|
|
195
|
+
// so it never reaches `super.handleFetchFailure` — which is the only place the base's
|
|
196
|
+
// retry-without-tools fallback lives, leaving it unreachable for this provider.
|
|
197
|
+
if (sentTools && this.isToolsRejection(status, message)) {
|
|
198
|
+
return { retry: true, maxInputTokens: maxInputTokens, withoutTools: true };
|
|
199
|
+
}
|
|
200
|
+
|
|
129
201
|
switch (status) {
|
|
130
202
|
case 400: // Bad Request
|
|
131
203
|
// CodeValidation = "400.1"
|
|
@@ -201,9 +273,12 @@ export class GitKrakenProvider extends OpenAICompatibleProviderBase<typeof provi
|
|
|
201
273
|
case 499:
|
|
202
274
|
// CodeRequestCanceled = "499.1"
|
|
203
275
|
throw new Error(`(${this.name}) ${status}.${code}: ${message}`);
|
|
204
|
-
case 500:
|
|
276
|
+
case 500: {
|
|
205
277
|
// CodeServerError = "500.1"
|
|
278
|
+
// Wrapped upstream failures are classified above, before this switch — the backend has
|
|
279
|
+
// used more than one envelope code for them, so that can't key off `status`.
|
|
206
280
|
throw new Error(`(${this.name}) ${status}.${code}: ${message}`);
|
|
281
|
+
}
|
|
207
282
|
case 503:
|
|
208
283
|
// CodeServiceUnavailable = "503.1"
|
|
209
284
|
|
|
@@ -222,3 +297,51 @@ export class GitKrakenProvider extends OpenAICompatibleProviderBase<typeof provi
|
|
|
222
297
|
}
|
|
223
298
|
}
|
|
224
299
|
}
|
|
300
|
+
|
|
301
|
+
/** Max characters of `error.data` folded into a message — enough to name a cause, bounded so a large
|
|
302
|
+
* payload can't dominate a notification or a log line. */
|
|
303
|
+
const maxErrorDetailLength = 500;
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Renders the backend's `error.data` as a short detail string. This is where the upstream provider's
|
|
307
|
+
* own complaint arrives, so it's the difference between "upstream AI provider error (OpenAI HTTP 400)"
|
|
308
|
+
* and knowing which field it rejected.
|
|
309
|
+
*
|
|
310
|
+
* Strings pass through; objects are JSON-encoded. A common shape is the upstream's own error envelope,
|
|
311
|
+
* so a nested `message` is preferred when present rather than dumping the whole object.
|
|
312
|
+
*/
|
|
313
|
+
function formatErrorData(data: unknown): string | undefined {
|
|
314
|
+
if (data == null) return undefined;
|
|
315
|
+
|
|
316
|
+
let text: string | undefined;
|
|
317
|
+
if (typeof data === 'string') {
|
|
318
|
+
text = data;
|
|
319
|
+
} else if (typeof data === 'object') {
|
|
320
|
+
const nested =
|
|
321
|
+
(data as { error?: { message?: unknown }; message?: unknown }).error?.message ??
|
|
322
|
+
(data as { message?: unknown }).message;
|
|
323
|
+
if (typeof nested === 'string' && nested) {
|
|
324
|
+
text = nested;
|
|
325
|
+
} else {
|
|
326
|
+
try {
|
|
327
|
+
text = JSON.stringify(data);
|
|
328
|
+
} catch {
|
|
329
|
+
return undefined;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
} else if (typeof data === 'number' || typeof data === 'boolean') {
|
|
333
|
+
text = String(data);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
text = text?.trim();
|
|
337
|
+
if (!text || text === '{}' || text === 'null') return undefined;
|
|
338
|
+
|
|
339
|
+
return text.length > maxErrorDetailLength ? `${text.slice(0, maxErrorDetailLength)}…` : text;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/** Extracts the upstream HTTP status from the backend's upstream-error prose wrapper. The envelope code
|
|
343
|
+
* varies (500.1 on prod, 400.1 seen on staging), so callers must key off this, not the outer code. */
|
|
344
|
+
function getWrappedUpstreamStatus(text: string): number | undefined {
|
|
345
|
+
const status = /upstream ai provider error[\s\S]*?http (\d{3})/i.exec(text)?.[1];
|
|
346
|
+
return status != null ? parseInt(status, 10) : undefined;
|
|
347
|
+
}
|
|
@@ -55,4 +55,10 @@ export class HuggingFaceProvider extends OpenAICompatibleProviderBase<typeof pro
|
|
|
55
55
|
protected getUrl(_model: AIModel<typeof provider.id>): string {
|
|
56
56
|
return 'https://router.huggingface.co/v1/chat/completions';
|
|
57
57
|
}
|
|
58
|
+
|
|
59
|
+
// Router support varies by partner provider with no capability metadata and auto-routing —
|
|
60
|
+
// the prompt-described JSON fallback is the only reliable path
|
|
61
|
+
protected override supportsResponseFormat(_model: AIModel<typeof provider.id>): boolean {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
58
64
|
}
|
|
@@ -8,10 +8,17 @@ type MistralModel = AIModel<typeof provider.id>;
|
|
|
8
8
|
const models: MistralModel[] = [
|
|
9
9
|
{
|
|
10
10
|
id: 'mistral-medium-latest',
|
|
11
|
-
name: 'Mistral Medium',
|
|
12
|
-
maxTokens: { input:
|
|
11
|
+
name: 'Mistral Medium 3.5',
|
|
12
|
+
maxTokens: { input: 262144, output: 4096 },
|
|
13
13
|
provider: provider,
|
|
14
14
|
},
|
|
15
|
+
{
|
|
16
|
+
id: 'mistral-medium-3-5',
|
|
17
|
+
name: 'Mistral Medium 3.5',
|
|
18
|
+
maxTokens: { input: 262144, output: 4096 },
|
|
19
|
+
provider: provider,
|
|
20
|
+
hidden: true,
|
|
21
|
+
},
|
|
15
22
|
{
|
|
16
23
|
id: 'mistral-medium-2505',
|
|
17
24
|
name: 'Mistral Medium',
|
|
@@ -20,24 +27,44 @@ const models: MistralModel[] = [
|
|
|
20
27
|
hidden: true,
|
|
21
28
|
},
|
|
22
29
|
{
|
|
23
|
-
id: '
|
|
24
|
-
name: '
|
|
30
|
+
id: 'zai-glm-5-2',
|
|
31
|
+
name: 'GLM 5.2',
|
|
32
|
+
maxTokens: { input: 1000000, output: 128000 },
|
|
33
|
+
provider: provider,
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: 'mistral-small-latest',
|
|
37
|
+
name: 'Mistral Small 4',
|
|
25
38
|
maxTokens: { input: 262144, output: 4096 },
|
|
26
39
|
provider: provider,
|
|
27
40
|
default: true,
|
|
28
41
|
},
|
|
29
42
|
{
|
|
30
|
-
id: '
|
|
31
|
-
name: '
|
|
43
|
+
id: 'mistral-small-2603',
|
|
44
|
+
name: 'Mistral Small 4',
|
|
32
45
|
maxTokens: { input: 262144, output: 4096 },
|
|
33
46
|
provider: provider,
|
|
34
47
|
hidden: true,
|
|
35
48
|
},
|
|
36
49
|
{
|
|
37
|
-
id: 'mistral-
|
|
38
|
-
name: 'Mistral
|
|
50
|
+
id: 'mistral-small-2503',
|
|
51
|
+
name: 'Mistral Small',
|
|
39
52
|
maxTokens: { input: 131072, output: 4096 },
|
|
40
53
|
provider: provider,
|
|
54
|
+
hidden: true,
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
id: 'mistral-large-latest',
|
|
58
|
+
name: 'Mistral Large 3',
|
|
59
|
+
maxTokens: { input: 262144, output: 4096 },
|
|
60
|
+
provider: provider,
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
id: 'mistral-large-2512',
|
|
64
|
+
name: 'Mistral Large 3',
|
|
65
|
+
maxTokens: { input: 262144, output: 4096 },
|
|
66
|
+
provider: provider,
|
|
67
|
+
hidden: true,
|
|
41
68
|
},
|
|
42
69
|
{
|
|
43
70
|
id: 'mistral-large-2411',
|
|
@@ -47,27 +74,74 @@ const models: MistralModel[] = [
|
|
|
47
74
|
hidden: true,
|
|
48
75
|
},
|
|
49
76
|
{
|
|
50
|
-
id: '
|
|
51
|
-
name: '
|
|
77
|
+
id: 'ministral-14b-latest',
|
|
78
|
+
name: 'Ministral 3 14B',
|
|
79
|
+
maxTokens: { input: 262144, output: 4096 },
|
|
80
|
+
provider: provider,
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
id: 'ministral-14b-2512',
|
|
84
|
+
name: 'Ministral 3 14B',
|
|
85
|
+
maxTokens: { input: 262144, output: 4096 },
|
|
86
|
+
provider: provider,
|
|
87
|
+
hidden: true,
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
id: 'ministral-8b-latest',
|
|
91
|
+
name: 'Ministral 3 8B',
|
|
92
|
+
maxTokens: { input: 262144, output: 4096 },
|
|
93
|
+
provider: provider,
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
id: 'ministral-8b-2512',
|
|
97
|
+
name: 'Ministral 3 8B',
|
|
98
|
+
maxTokens: { input: 262144, output: 4096 },
|
|
99
|
+
provider: provider,
|
|
100
|
+
hidden: true,
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
id: 'ministral-3b-latest',
|
|
104
|
+
name: 'Ministral 3 3B',
|
|
105
|
+
maxTokens: { input: 262144, output: 4096 },
|
|
106
|
+
provider: provider,
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
id: 'ministral-3b-2512',
|
|
110
|
+
name: 'Ministral 3 3B',
|
|
111
|
+
maxTokens: { input: 262144, output: 4096 },
|
|
112
|
+
provider: provider,
|
|
113
|
+
hidden: true,
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
id: 'codestral-latest',
|
|
117
|
+
name: 'Codestral',
|
|
52
118
|
maxTokens: { input: 131072, output: 4096 },
|
|
53
119
|
provider: provider,
|
|
54
120
|
},
|
|
55
121
|
{
|
|
56
|
-
id: '
|
|
57
|
-
name: '
|
|
122
|
+
id: 'codestral-2508',
|
|
123
|
+
name: 'Codestral',
|
|
58
124
|
maxTokens: { input: 131072, output: 4096 },
|
|
59
125
|
provider: provider,
|
|
60
126
|
hidden: true,
|
|
61
127
|
},
|
|
62
128
|
{
|
|
63
|
-
id: '
|
|
64
|
-
name: '
|
|
129
|
+
id: 'codestral-2501',
|
|
130
|
+
name: 'Codestral',
|
|
131
|
+
maxTokens: { input: 262144, output: 4096 },
|
|
132
|
+
provider: provider,
|
|
133
|
+
hidden: true,
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
id: 'devstral-small-latest',
|
|
137
|
+
name: 'Devstral Small',
|
|
65
138
|
maxTokens: { input: 131072, output: 4096 },
|
|
66
139
|
provider: provider,
|
|
140
|
+
hidden: true,
|
|
67
141
|
},
|
|
68
142
|
{
|
|
69
|
-
id: '
|
|
70
|
-
name: '
|
|
143
|
+
id: 'devstral-small-2505',
|
|
144
|
+
name: 'Devstral Small',
|
|
71
145
|
maxTokens: { input: 131072, output: 4096 },
|
|
72
146
|
provider: provider,
|
|
73
147
|
hidden: true,
|
|
@@ -77,6 +151,7 @@ const models: MistralModel[] = [
|
|
|
77
151
|
export class MistralProvider extends OpenAICompatibleProviderBase<typeof provider.id> {
|
|
78
152
|
readonly id = provider.id;
|
|
79
153
|
readonly name = provider.name;
|
|
154
|
+
readonly supportsTools = true;
|
|
80
155
|
protected readonly descriptor = provider;
|
|
81
156
|
protected readonly config = {
|
|
82
157
|
keyUrl: 'https://console.mistral.ai/api-keys',
|
|
@@ -111,11 +186,13 @@ export class MistralProvider extends OpenAICompatibleProviderBase<typeof provide
|
|
|
111
186
|
model: AIModel<typeof provider.id>,
|
|
112
187
|
retries: number,
|
|
113
188
|
maxInputTokens: number,
|
|
114
|
-
|
|
189
|
+
body?: string,
|
|
190
|
+
sentTools?: boolean,
|
|
191
|
+
): Promise<{ retry: true; maxInputTokens: number; withoutTools?: boolean }> {
|
|
115
192
|
if (rsp.status !== 404 && rsp.status !== 429) {
|
|
116
193
|
let json;
|
|
117
194
|
try {
|
|
118
|
-
json = (await rsp.json()) as MistralError | undefined;
|
|
195
|
+
json = (body != null ? JSON.parse(body) : await rsp.json()) as MistralError | undefined;
|
|
119
196
|
} catch {}
|
|
120
197
|
|
|
121
198
|
debugger;
|
|
@@ -137,10 +214,16 @@ export class MistralProvider extends OpenAICompatibleProviderBase<typeof provide
|
|
|
137
214
|
}
|
|
138
215
|
}
|
|
139
216
|
|
|
217
|
+
// This override throws for every non-404/429 status, so the base class's tools-rejection
|
|
218
|
+
// recovery would never run for Mistral — check it here to keep the text-only fallback
|
|
219
|
+
if (sentTools && this.isToolsRejection(rsp.status, message)) {
|
|
220
|
+
return { retry: true, maxInputTokens: maxInputTokens, withoutTools: true };
|
|
221
|
+
}
|
|
222
|
+
|
|
140
223
|
throw new Error(`(${this.name}) ${rsp.status}: ${message || rsp.statusText}`);
|
|
141
224
|
}
|
|
142
225
|
|
|
143
|
-
return super.handleFetchFailure(rsp, action, model, retries, maxInputTokens);
|
|
226
|
+
return super.handleFetchFailure(rsp, action, model, retries, maxInputTokens, body, sentTools);
|
|
144
227
|
}
|
|
145
228
|
}
|
|
146
229
|
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import { uuid } from '../../../utils/crypto.js';
|
|
2
|
+
import { Logger } from '../../../utils/logger.js';
|
|
2
3
|
import { ollamaProviderDescriptor as provider } from '../constants.js';
|
|
3
4
|
import type { AIActionType, AIModel } from '../models/model.js';
|
|
4
|
-
import type {
|
|
5
|
+
import type {
|
|
6
|
+
AIChatMessage,
|
|
7
|
+
AIChatMessageRole,
|
|
8
|
+
AIProviderResponse,
|
|
9
|
+
AIResponseFormat,
|
|
10
|
+
JSONSchema,
|
|
11
|
+
} from '../models/provider.js';
|
|
5
12
|
import { OpenAICompatibleProviderBase } from './openAICompatibleProviderBase.js';
|
|
6
13
|
|
|
7
14
|
type OllamaModel = AIModel<typeof provider.id>;
|
|
@@ -122,6 +129,11 @@ export class OllamaProvider extends OpenAICompatibleProviderBase<typeof provider
|
|
|
122
129
|
return url ? `${url}/api/chat` : undefined;
|
|
123
130
|
}
|
|
124
131
|
|
|
132
|
+
// Ollama < 0.5.0 rejects a schema-valued `format` (accepts only 'json')
|
|
133
|
+
protected override isResponseFormatRejection(status: number, body: string): boolean {
|
|
134
|
+
return status === 400 && /format/i.test(body);
|
|
135
|
+
}
|
|
136
|
+
|
|
125
137
|
protected override getHeaders<TAction extends AIActionType>(
|
|
126
138
|
_action: TAction,
|
|
127
139
|
_apiKey: string,
|
|
@@ -138,8 +150,9 @@ export class OllamaProvider extends OpenAICompatibleProviderBase<typeof provider
|
|
|
138
150
|
action: TAction,
|
|
139
151
|
model: AIModel<typeof provider.id>,
|
|
140
152
|
apiKey: string,
|
|
141
|
-
messages: (maxInputTokens: number, retries: number) => Promise<AIChatMessage[]>,
|
|
153
|
+
messages: (maxInputTokens: number, retries: number) => Promise<AIChatMessage<AIChatMessageRole>[]>,
|
|
142
154
|
modelOptions?: { outputTokens?: number; temperature?: number },
|
|
155
|
+
responseFormat?: AIResponseFormat,
|
|
143
156
|
signal?: AbortSignal,
|
|
144
157
|
): Promise<AIProviderResponse<void>> {
|
|
145
158
|
let retries = 0;
|
|
@@ -158,10 +171,19 @@ export class OllamaProvider extends OpenAICompatibleProviderBase<typeof provider
|
|
|
158
171
|
// Ensure temperature is within valid range for Ollama (0.0-1.0)
|
|
159
172
|
const temperature = Math.min(Math.max(modelOptions?.temperature ?? 0.7, 0), 1);
|
|
160
173
|
|
|
174
|
+
const format =
|
|
175
|
+
responseFormat != null &&
|
|
176
|
+
!this.isResponseFormatSessionRejected(model, responseFormat) &&
|
|
177
|
+
this.supportsResponseFormat(model)
|
|
178
|
+
? responseFormat.schema
|
|
179
|
+
: undefined;
|
|
180
|
+
|
|
161
181
|
const request: OllamaChatRequest = {
|
|
162
182
|
model: model.id,
|
|
163
183
|
messages: ollamaMessages,
|
|
164
184
|
stream: false,
|
|
185
|
+
// Ollama takes the bare JSON schema (grammar-constrained sampling, any model)
|
|
186
|
+
format: format,
|
|
165
187
|
options: {
|
|
166
188
|
temperature: temperature,
|
|
167
189
|
// Add num_predict if outputTokens is specified
|
|
@@ -169,9 +191,34 @@ export class OllamaProvider extends OpenAICompatibleProviderBase<typeof provider
|
|
|
169
191
|
},
|
|
170
192
|
};
|
|
171
193
|
|
|
172
|
-
|
|
194
|
+
let rsp = await this.fetchCore(action, model, apiKey, request, signal);
|
|
195
|
+
let errorBody: string | undefined;
|
|
196
|
+
if (!rsp.ok && rsp.status === 400 && request.format != null) {
|
|
197
|
+
// If the schema-valued format was rejected (Ollama < 0.5.0 accepts only 'json'),
|
|
198
|
+
// resend the same request without it — the prompt still describes the JSON
|
|
199
|
+
// Leave it `undefined` (not '') when the read fails, so `handleFetchFailure` falls
|
|
200
|
+
// back to reading the still-unconsumed response instead of parsing an empty string
|
|
201
|
+
errorBody = await rsp
|
|
202
|
+
.clone()
|
|
203
|
+
.text()
|
|
204
|
+
.catch(() => undefined);
|
|
205
|
+
if (this.isResponseFormatRejection(rsp.status, errorBody ?? '')) {
|
|
206
|
+
Logger.warn(
|
|
207
|
+
`(${this.name}) ${model.id}: native response format was rejected (${rsp.status}); retrying without it`,
|
|
208
|
+
);
|
|
209
|
+
const rejected = responseFormat;
|
|
210
|
+
responseFormat = undefined;
|
|
211
|
+
delete request.format;
|
|
212
|
+
rsp = await this.fetchCore(action, model, apiKey, request, signal);
|
|
213
|
+
errorBody = undefined;
|
|
214
|
+
if (rsp.ok && rejected != null) {
|
|
215
|
+
this.rememberResponseFormatRejection(model, rejected);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
173
220
|
if (!rsp.ok) {
|
|
174
|
-
const result = await this.handleFetchFailure(rsp, action, model, retries, maxInputTokens);
|
|
221
|
+
const result = await this.handleFetchFailure(rsp, action, model, retries, maxInputTokens, errorBody);
|
|
175
222
|
if (result.retry) {
|
|
176
223
|
maxInputTokens = result.maxInputTokens;
|
|
177
224
|
retries++;
|
|
@@ -190,6 +237,7 @@ export class OllamaProvider extends OpenAICompatibleProviderBase<typeof provider
|
|
|
190
237
|
return {
|
|
191
238
|
id: uuid(),
|
|
192
239
|
content: data.message.content,
|
|
240
|
+
finishReason: data.done_reason === 'length' ? 'length' : undefined,
|
|
193
241
|
model: model,
|
|
194
242
|
usage: {
|
|
195
243
|
promptTokens: data.prompt_eval_count ?? 0,
|
|
@@ -216,6 +264,8 @@ interface OllamaChatRequest {
|
|
|
216
264
|
content: string;
|
|
217
265
|
}>;
|
|
218
266
|
stream: boolean;
|
|
267
|
+
/** 'json' for JSON mode, or a JSON schema object for structured output (Ollama ≥0.5.0) */
|
|
268
|
+
format?: 'json' | JSONSchema;
|
|
219
269
|
options?: {
|
|
220
270
|
temperature?: number;
|
|
221
271
|
top_p?: number;
|
|
@@ -232,6 +282,7 @@ interface OllamaChatResponse {
|
|
|
232
282
|
content: string;
|
|
233
283
|
};
|
|
234
284
|
done: boolean;
|
|
285
|
+
done_reason?: string;
|
|
235
286
|
total_duration?: number;
|
|
236
287
|
load_duration?: number;
|
|
237
288
|
prompt_eval_count?: number;
|
|
@@ -27,6 +27,11 @@ export class OpenAICompatibleProvider extends OpenAICompatibleProviderBase<typeo
|
|
|
27
27
|
return cfg.url || undefined;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
// Unknown user-configured backend — fall back to prompt-described JSON
|
|
31
|
+
protected override supportsResponseFormat(_model: AIModel<typeof provider.id>): boolean {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
|
|
30
35
|
private async getOrPromptBaseUrl(silent: boolean, hasApiKey: boolean): Promise<string | undefined> {
|
|
31
36
|
const orgConf = this.context.getProviderConfig(this.id);
|
|
32
37
|
if (!orgConf.enabled) return undefined;
|