Gate task providers by availability (#2189)

* Gate task providers by availability

Implement provider availability gating documented in docs/task-provider-availability.md.

* Remove task provider availability design doc

* Restore task source after provider availability checks

- Keep saved GitLab/Linear defaults from being lost while provider checks hydrate
- Ignore stale Linear status responses after connect or workspace changes

* fix: address review findings
This commit is contained in:
Jinjing
2026-05-17 19:27:44 -07:00
committed by GitHub
parent 8057cbdf78
commit d88b62f115
17 changed files with 622 additions and 136 deletions
+23 -1
View File
@@ -1,5 +1,9 @@
import { describe, expect, it } from 'vitest'
import { normalizeVisibleTaskProviders, resolveVisibleTaskProvider } from './task-providers'
import {
filterAvailableTaskProviders,
normalizeVisibleTaskProviders,
resolveVisibleTaskProvider
} from './task-providers'
describe('task providers', () => {
it('normalizes provider lists while preserving supported order', () => {
@@ -16,4 +20,22 @@ describe('task providers', () => {
it('resolves hidden preferred providers to the first visible provider', () => {
expect(resolveVisibleTaskProvider('github', ['linear'])).toBe('linear')
})
it('filters runtime-unavailable providers without changing preference normalization', () => {
expect(
filterAvailableTaskProviders(['github', 'gitlab', 'linear'], {
gitlabInstalled: false,
linearConnected: true
})
).toEqual(['github', 'linear'])
})
it('falls back to GitHub when every preferred provider is unavailable', () => {
expect(
filterAvailableTaskProviders(['gitlab', 'linear'], {
gitlabInstalled: false,
linearConnected: false
})
).toEqual(['github'])
})
})
+22
View File
@@ -24,6 +24,28 @@ export function normalizeVisibleTaskProviders(value: unknown): TaskProvider[] {
return normalized.length > 0 ? normalized : [...TASK_PROVIDERS]
}
export type TaskProviderAvailability = {
gitlabInstalled: boolean
linearConnected: boolean
}
export function filterAvailableTaskProviders(
visibleProviders: readonly TaskProvider[],
availability: TaskProviderAvailability
): TaskProvider[] {
const available = visibleProviders.filter((provider) => {
if (provider === 'github') {
return true
}
if (provider === 'gitlab') {
return availability.gitlabInstalled
}
return availability.linearConnected
})
return available.length > 0 ? available : ['github']
}
export function resolveVisibleTaskProvider(
preferred: TaskProvider | null | undefined,
visibleProviders: readonly TaskProvider[]