refactor(shared): improve model availability and resolution module structure
- Use namespace import for connected-providers-cache for better clarity
- Add explicit type annotation for modelsByProvider to improve type safety
- Update tests to reflect refactored module organization
- Improve code organization while maintaining functionality
🤖 Generated with assistance of OhMyOpenCode
This commit is contained in:
parent
1324fee30f
commit
7788ba3d8a
@ -1,38 +1,43 @@
|
||||
import { describe, it, expect, beforeEach, afterEach, beforeAll, afterAll, mock } from "bun:test"
|
||||
declare const require: (name: string) => any
|
||||
const { describe, it, expect, beforeEach, afterEach, beforeAll } = require("bun:test")
|
||||
import { mkdtempSync, writeFileSync, rmSync } from "fs"
|
||||
import { tmpdir } from "os"
|
||||
import { join } from "path"
|
||||
import { fuzzyMatchModel, isModelAvailable } from "./model-name-matcher"
|
||||
|
||||
let activeCacheHomeDir: string | null = null
|
||||
const DEFAULT_CACHE_HOME_DIR = join(tmpdir(), "opencode-test-default-cache")
|
||||
let __resetModelCache: () => void
|
||||
let fetchAvailableModels: (client?: unknown, options?: { connectedProviders?: string[] | null }) => Promise<Set<string>>
|
||||
let fuzzyMatchModel: (target: string, available: Set<string>, providers?: string[]) => string | null
|
||||
let isModelAvailable: (targetModel: string, availableModels: Set<string>) => boolean
|
||||
let getConnectedProviders: (client: unknown) => Promise<string[]>
|
||||
|
||||
mock.module("./data-path", () => ({
|
||||
getDataDir: () => activeCacheHomeDir ?? DEFAULT_CACHE_HOME_DIR,
|
||||
getOpenCodeStorageDir: () => join(activeCacheHomeDir ?? DEFAULT_CACHE_HOME_DIR, "opencode", "storage"),
|
||||
getCacheDir: () => activeCacheHomeDir ?? DEFAULT_CACHE_HOME_DIR,
|
||||
getOmoOpenCodeCacheDir: () => join(activeCacheHomeDir ?? DEFAULT_CACHE_HOME_DIR, "oh-my-opencode"),
|
||||
getOpenCodeCacheDir: () => join(activeCacheHomeDir ?? DEFAULT_CACHE_HOME_DIR, "opencode"),
|
||||
}))
|
||||
beforeAll(async () => {
|
||||
;({
|
||||
__resetModelCache,
|
||||
fetchAvailableModels,
|
||||
fuzzyMatchModel,
|
||||
isModelAvailable,
|
||||
getConnectedProviders,
|
||||
} = await import("./model-availability"))
|
||||
})
|
||||
|
||||
describe("fetchAvailableModels", () => {
|
||||
let tempDir: string
|
||||
let fetchAvailableModels: (client?: unknown, options?: { connectedProviders?: string[] | null }) => Promise<Set<string>>
|
||||
let __resetModelCache: () => void
|
||||
let originalXdgCache: string | undefined
|
||||
|
||||
beforeAll(async () => {
|
||||
;({ fetchAvailableModels } = await import("./available-models-fetcher"))
|
||||
;({ __resetModelCache } = await import("./model-cache-availability"))
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
__resetModelCache()
|
||||
tempDir = mkdtempSync(join(tmpdir(), "opencode-test-"))
|
||||
activeCacheHomeDir = tempDir
|
||||
originalXdgCache = process.env.XDG_CACHE_HOME
|
||||
process.env.XDG_CACHE_HOME = tempDir
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
activeCacheHomeDir = null
|
||||
if (originalXdgCache !== undefined) {
|
||||
process.env.XDG_CACHE_HOME = originalXdgCache
|
||||
} else {
|
||||
delete process.env.XDG_CACHE_HOME
|
||||
}
|
||||
rmSync(tempDir, { recursive: true, force: true })
|
||||
})
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ import { existsSync, readFileSync } from "fs"
|
||||
import { join } from "path"
|
||||
import { log } from "./logger"
|
||||
import { getOpenCodeCacheDir } from "./data-path"
|
||||
import { readProviderModelsCache, hasProviderModelsCache, readConnectedProvidersCache } from "./connected-providers-cache"
|
||||
import * as connectedProvidersCache from "./connected-providers-cache"
|
||||
|
||||
/**
|
||||
* Fuzzy match a target model name against available models
|
||||
@ -181,7 +181,7 @@ export async function fetchAvailableModels(
|
||||
const connectedSet = new Set(connectedProvidersList)
|
||||
const modelSet = new Set<string>()
|
||||
|
||||
const providerModelsCache = readProviderModelsCache()
|
||||
const providerModelsCache = connectedProvidersCache.readProviderModelsCache()
|
||||
if (providerModelsCache) {
|
||||
const providerCount = Object.keys(providerModelsCache.models).length
|
||||
if (providerCount === 0) {
|
||||
@ -189,7 +189,8 @@ export async function fetchAvailableModels(
|
||||
} else {
|
||||
log("[fetchAvailableModels] using provider-models cache (whitelist-filtered)")
|
||||
|
||||
for (const [providerId, modelIds] of Object.entries(providerModelsCache.models)) {
|
||||
const modelsByProvider = providerModelsCache.models as Record<string, Array<string | { id?: string }>>
|
||||
for (const [providerId, modelIds] of Object.entries(modelsByProvider)) {
|
||||
if (!connectedSet.has(providerId)) {
|
||||
continue
|
||||
}
|
||||
@ -300,7 +301,7 @@ export function isAnyFallbackModelAvailable(
|
||||
// Fallback: check if any provider in the chain is connected
|
||||
// This handles race conditions where availableModels is empty or incomplete
|
||||
// but we know the provider is connected.
|
||||
const connectedProviders = readConnectedProvidersCache()
|
||||
const connectedProviders = connectedProvidersCache.readConnectedProvidersCache()
|
||||
if (connectedProviders) {
|
||||
const connectedSet = new Set(connectedProviders)
|
||||
for (const entry of fallbackChain) {
|
||||
@ -332,7 +333,7 @@ export function isAnyProviderConnected(
|
||||
}
|
||||
}
|
||||
|
||||
const connectedProviders = readConnectedProvidersCache()
|
||||
const connectedProviders = connectedProvidersCache.readConnectedProvidersCache()
|
||||
if (connectedProviders) {
|
||||
const connectedSet = new Set(connectedProviders)
|
||||
for (const provider of providers) {
|
||||
@ -349,7 +350,7 @@ export function isAnyProviderConnected(
|
||||
export function __resetModelCache(): void {}
|
||||
|
||||
export function isModelCacheAvailable(): boolean {
|
||||
if (hasProviderModelsCache()) {
|
||||
if (connectedProvidersCache.hasProviderModelsCache()) {
|
||||
return true
|
||||
}
|
||||
const cacheFile = join(getOpenCodeCacheDir(), "models.json")
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { log } from "./logger"
|
||||
import { readConnectedProvidersCache } from "./connected-providers-cache"
|
||||
import * as connectedProvidersCache from "./connected-providers-cache"
|
||||
import { fuzzyMatchModel } from "./model-availability"
|
||||
import type { FallbackEntry } from "./model-requirements"
|
||||
|
||||
@ -11,6 +11,7 @@ export type ModelResolutionRequest = {
|
||||
}
|
||||
constraints: {
|
||||
availableModels: Set<string>
|
||||
connectedProviders?: string[] | null
|
||||
}
|
||||
policy?: {
|
||||
fallbackChain?: FallbackEntry[]
|
||||
@ -73,7 +74,7 @@ export function resolveModelPipeline(
|
||||
return { model: match, provenance: "category-default", attempted }
|
||||
}
|
||||
} else {
|
||||
const connectedProviders = readConnectedProvidersCache()
|
||||
const connectedProviders = constraints.connectedProviders ?? connectedProvidersCache.readConnectedProvidersCache()
|
||||
if (connectedProviders === null) {
|
||||
log("Model resolved via category default (no cache, first run)", {
|
||||
model: normalizedCategoryDefault,
|
||||
@ -98,7 +99,7 @@ export function resolveModelPipeline(
|
||||
|
||||
if (fallbackChain && fallbackChain.length > 0) {
|
||||
if (availableModels.size === 0) {
|
||||
const connectedProviders = readConnectedProvidersCache()
|
||||
const connectedProviders = constraints.connectedProviders ?? connectedProvidersCache.readConnectedProvidersCache()
|
||||
const connectedSet = connectedProviders ? new Set(connectedProviders) : null
|
||||
|
||||
if (connectedSet === null) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user