feat: check provider connectivity instead of specific model for hephaestus availability

Hephaestus now appears when any of its providers (openai, github-copilot, opencode) is
connected, rather than requiring the exact gpt-5.2-codex model. This allows users with
newer codex models (e.g., gpt-5.3-codex) to use Hephaestus without manual config overrides.

- Add requiresProvider field to ModelRequirement type
- Add isAnyProviderConnected() helper in model-availability
- Update hephaestus config from requiresModel to requiresProvider
- Update cli model-fallback to handle requiresProvider checks
This commit is contained in:
YeonGyu-Kim
2026-02-06 10:42:46 +09:00
parent 04576c306c
commit b8f15affdb
7 changed files with 100 additions and 22 deletions
+6 -6
View File
@@ -409,7 +409,7 @@ describe("generateModelConfig", () => {
})
describe("Hephaestus agent special cases", () => {
test("Hephaestus is created when OpenAI is available (has gpt-5.2-codex)", () => {
test("Hephaestus is created when OpenAI is available (openai provider connected)", () => {
// #given
const config = createConfig({ hasOpenAI: true })
@@ -421,7 +421,7 @@ describe("generateModelConfig", () => {
expect(result.agents?.hephaestus?.variant).toBe("medium")
})
test("Hephaestus is created when Copilot is available (has gpt-5.2-codex)", () => {
test("Hephaestus is created when Copilot is available (github-copilot provider connected)", () => {
// #given
const config = createConfig({ hasCopilot: true })
@@ -433,7 +433,7 @@ describe("generateModelConfig", () => {
expect(result.agents?.hephaestus?.variant).toBe("medium")
})
test("Hephaestus is created when OpenCode Zen is available (has gpt-5.2-codex)", () => {
test("Hephaestus is created when OpenCode Zen is available (opencode provider connected)", () => {
// #given
const config = createConfig({ hasOpencodeZen: true })
@@ -445,7 +445,7 @@ describe("generateModelConfig", () => {
expect(result.agents?.hephaestus?.variant).toBe("medium")
})
test("Hephaestus is omitted when only Claude is available (no gpt-5.2-codex)", () => {
test("Hephaestus is omitted when only Claude is available (no required provider connected)", () => {
// #given
const config = createConfig({ hasClaude: true })
@@ -456,7 +456,7 @@ describe("generateModelConfig", () => {
expect(result.agents?.hephaestus).toBeUndefined()
})
test("Hephaestus is omitted when only Gemini is available (no gpt-5.2-codex)", () => {
test("Hephaestus is omitted when only Gemini is available (no required provider connected)", () => {
// #given
const config = createConfig({ hasGemini: true })
@@ -467,7 +467,7 @@ describe("generateModelConfig", () => {
expect(result.agents?.hephaestus).toBeUndefined()
})
test("Hephaestus is omitted when only ZAI is available (no gpt-5.2-codex)", () => {
test("Hephaestus is omitted when only ZAI is available (no required provider connected)", () => {
// #given
const config = createConfig({ hasZaiCodingPlan: true })
+13
View File
@@ -122,6 +122,13 @@ function isRequiredModelAvailable(
return matchingEntry.providers.some((provider) => isProviderAvailable(provider, avail))
}
function isRequiredProviderAvailable(
requiredProviders: string[],
avail: ProviderAvailability
): boolean {
return requiredProviders.some((provider) => isProviderAvailable(provider, avail))
}
export function generateModelConfig(config: InstallConfig): GeneratedOmoConfig {
const avail = toProviderAvailability(config)
const hasAnyProvider =
@@ -185,6 +192,9 @@ export function generateModelConfig(config: InstallConfig): GeneratedOmoConfig {
if (req.requiresModel && !isRequiredModelAvailable(req.requiresModel, req.fallbackChain, avail)) {
continue
}
if (req.requiresProvider && !isRequiredProviderAvailable(req.requiresProvider, avail)) {
continue
}
const resolved = resolveModelFromChain(req.fallbackChain, avail)
if (resolved) {
@@ -205,6 +215,9 @@ export function generateModelConfig(config: InstallConfig): GeneratedOmoConfig {
if (req.requiresModel && !isRequiredModelAvailable(req.requiresModel, req.fallbackChain, avail)) {
continue
}
if (req.requiresProvider && !isRequiredProviderAvailable(req.requiresProvider, avail)) {
continue
}
const resolved = resolveModelFromChain(fallbackChain, avail)
if (resolved) {