refactor(model-core): inject bundled capabilities snapshot from harness

- remove bundled snapshot dependency on src/generated in model-core

- make shared harness provide runtime bundled snapshot

- update guardrail and capability tests to pass explicit snapshot

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
YeonGyu-Kim
2026-05-21 11:36:26 +09:00
parent 2462d7af29
commit e15461febc
8 changed files with 63 additions and 39 deletions
@@ -1,11 +1,12 @@
import { describe, expect, test } from "bun:test" import { describe, expect, test } from "bun:test"
import { getBundledModelCapabilitiesSnapshot, getModelCapabilities } from "./model-capabilities" import { getBundledModelCapabilitiesSnapshot, getModelCapabilities } from "./model-capabilities"
import bundledModelCapabilitiesSnapshotJson from "./generated/model-capabilities.generated.json"
describe("bundled model capabilities snapshot", () => { describe("bundled model capabilities snapshot", () => {
test("keeps GPT-4.1 OpenAI variants marked as supporting tool calls", () => { test("keeps GPT-4.1 OpenAI variants marked as supporting tool calls", () => {
// given // given
const bundledSnapshot = getBundledModelCapabilitiesSnapshot() const bundledSnapshot = getBundledModelCapabilitiesSnapshot(bundledModelCapabilitiesSnapshotJson)
const modelIDs = [ const modelIDs = [
"openai/gpt-4.1", "openai/gpt-4.1",
"openai/gpt-4.1-mini", "openai/gpt-4.1-mini",
@@ -2,6 +2,7 @@ import type { ModelCapabilitiesSnapshot } from "./model-capabilities"
import { afterEach, describe, expect, test, spyOn } from "bun:test" import { afterEach, describe, expect, test, spyOn } from "bun:test"
import * as connectedProvidersCache from "./connected-providers-cache" import * as connectedProvidersCache from "./connected-providers-cache"
import { getModelCapabilities, getBundledModelCapabilitiesSnapshot } from "./model-capabilities" import { getModelCapabilities, getBundledModelCapabilitiesSnapshot } from "./model-capabilities"
import bundledModelCapabilitiesSnapshotJson from "./generated/model-capabilities.generated.json"
import { AGENT_MODEL_REQUIREMENTS, CATEGORY_MODEL_REQUIREMENTS } from "./model-requirements" import { AGENT_MODEL_REQUIREMENTS, CATEGORY_MODEL_REQUIREMENTS } from "./model-requirements"
describe("getModelCapabilities", () => { describe("getModelCapabilities", () => {
@@ -402,7 +403,7 @@ describe("getModelCapabilities", () => {
}) })
test("keeps every built-in OmO requirement model snapshot-backed", () => { test("keeps every built-in OmO requirement model snapshot-backed", () => {
const bundledSnapshot = getBundledModelCapabilitiesSnapshot() const bundledSnapshot = getBundledModelCapabilitiesSnapshot(bundledModelCapabilitiesSnapshotJson)
const requirementModels = new Set<string>() const requirementModels = new Set<string>()
for (const requirement of Object.values(AGENT_MODEL_REQUIREMENTS)) { for (const requirement of Object.values(AGENT_MODEL_REQUIREMENTS)) {
@@ -1,24 +1,14 @@
import bundledModelCapabilitiesSnapshotJson from "../../../../src/generated/model-capabilities.generated.json"
import { SUPPLEMENTAL_MODEL_CAPABILITIES } from "./supplemental-entries" import { SUPPLEMENTAL_MODEL_CAPABILITIES } from "./supplemental-entries"
import type { ModelCapabilitiesSnapshot } from "./types" import type { ModelCapabilitiesSnapshot } from "./types"
function normalizeSnapshot( export function getBundledModelCapabilitiesSnapshot(
snapshot: ModelCapabilitiesSnapshot | typeof bundledModelCapabilitiesSnapshotJson, snapshotJson: ModelCapabilitiesSnapshot,
): ModelCapabilitiesSnapshot { ): ModelCapabilitiesSnapshot {
return snapshot as ModelCapabilitiesSnapshot return {
} ...snapshotJson,
models: {
const normalizedBundledSnapshot = normalizeSnapshot(bundledModelCapabilitiesSnapshotJson) ...snapshotJson.models,
...SUPPLEMENTAL_MODEL_CAPABILITIES,
const bundledModelCapabilitiesSnapshot: ModelCapabilitiesSnapshot = { },
...normalizedBundledSnapshot, }
models: {
...normalizedBundledSnapshot.models,
...SUPPLEMENTAL_MODEL_CAPABILITIES,
},
}
export function getBundledModelCapabilitiesSnapshot(): ModelCapabilitiesSnapshot {
return bundledModelCapabilitiesSnapshot
} }
@@ -1,8 +1,6 @@
import { resolveModelIDAlias } from "../model-capability-aliases" import { resolveModelIDAlias } from "../model-capability-aliases"
import { detectHeuristicModelFamily } from "../model-capability-heuristics" import { detectHeuristicModelFamily } from "../model-capability-heuristics"
import type { ProviderCache } from "../provider-cache"
import { getBundledModelCapabilitiesSnapshot } from "./bundled-snapshot"
import { import {
readRuntimeModel, readRuntimeModel,
readRuntimeModelLimitOutput, readRuntimeModelLimitOutput,
@@ -38,9 +36,9 @@ export function getModelCapabilities(input: GetModelCapabilitiesInput): ModelCap
input.runtimeModel ?? input.providerCache?.findProviderModelMetadata(input.providerID, input.modelID), input.runtimeModel ?? input.providerCache?.findProviderModelMetadata(input.providerID, input.modelID),
) )
const runtimeSnapshot = input.runtimeSnapshot const runtimeSnapshot = input.runtimeSnapshot
const bundledSnapshot = input.bundledSnapshot ?? getBundledModelCapabilitiesSnapshot() const bundledSnapshot = input.bundledSnapshot
const snapshotEntry = runtimeSnapshot?.models?.[canonicalization.canonicalModelID] const snapshotEntry = runtimeSnapshot?.models?.[canonicalization.canonicalModelID]
?? bundledSnapshot.models[canonicalization.canonicalModelID] ?? bundledSnapshot?.models?.[canonicalization.canonicalModelID]
const heuristicFamily = detectHeuristicModelFamily(canonicalization.canonicalModelID) const heuristicFamily = detectHeuristicModelFamily(canonicalization.canonicalModelID)
const runtimeVariants = readRuntimeModelVariants(runtimeModel) const runtimeVariants = readRuntimeModelVariants(runtimeModel)
@@ -55,7 +53,7 @@ export function getModelCapabilities(input: GetModelCapabilitiesInput): ModelCap
const snapshotSource: ModelCapabilitiesDiagnostics["snapshot"]["source"] = const snapshotSource: ModelCapabilitiesDiagnostics["snapshot"]["source"] =
runtimeSnapshot?.models?.[canonicalization.canonicalModelID] runtimeSnapshot?.models?.[canonicalization.canonicalModelID]
? "runtime-snapshot" ? "runtime-snapshot"
: bundledSnapshot.models[canonicalization.canonicalModelID] : bundledSnapshot?.models?.[canonicalization.canonicalModelID]
? "bundled-snapshot" ? "bundled-snapshot"
: "none" : "none"
const familySource: ModelCapabilitiesDiagnostics["family"]["source"] = const familySource: ModelCapabilitiesDiagnostics["family"]["source"] =
@@ -2,6 +2,7 @@ import { describe, expect, test } from "bun:test"
import type { ModelCapabilitiesSnapshot } from "./model-capabilities" import type { ModelCapabilitiesSnapshot } from "./model-capabilities"
import { getBundledModelCapabilitiesSnapshot } from "./model-capabilities" import { getBundledModelCapabilitiesSnapshot } from "./model-capabilities"
import bundledModelCapabilitiesSnapshotJson from "./generated/model-capabilities.generated.json"
import { import {
collectModelCapabilityGuardrailIssues, collectModelCapabilityGuardrailIssues,
getBuiltInRequirementModelIDs, getBuiltInRequirementModelIDs,
@@ -9,7 +10,9 @@ import {
describe("model-capability-guardrails", () => { describe("model-capability-guardrails", () => {
test("keeps the current alias registry and built-in requirements aligned with the bundled snapshot", () => { test("keeps the current alias registry and built-in requirements aligned with the bundled snapshot", () => {
const issues = collectModelCapabilityGuardrailIssues() const issues = collectModelCapabilityGuardrailIssues({
snapshot: getBundledModelCapabilitiesSnapshot(bundledModelCapabilitiesSnapshotJson),
})
expect(issues).toEqual([]) expect(issues).toEqual([])
}) })
@@ -25,7 +28,7 @@ describe("model-capability-guardrails", () => {
}) })
test("flags exact aliases whose canonical target disappears from the snapshot", () => { test("flags exact aliases whose canonical target disappears from the snapshot", () => {
const bundledSnapshot = getBundledModelCapabilitiesSnapshot() const bundledSnapshot = getBundledModelCapabilitiesSnapshot(bundledModelCapabilitiesSnapshotJson)
const brokenSnapshot: ModelCapabilitiesSnapshot = { const brokenSnapshot: ModelCapabilitiesSnapshot = {
...bundledSnapshot, ...bundledSnapshot,
models: Object.fromEntries( models: Object.fromEntries(
@@ -48,7 +51,7 @@ describe("model-capability-guardrails", () => {
}) })
test("flags pattern aliases when models.dev gains a canonical entry for the alias itself", () => { test("flags pattern aliases when models.dev gains a canonical entry for the alias itself", () => {
const bundledSnapshot = getBundledModelCapabilitiesSnapshot() const bundledSnapshot = getBundledModelCapabilitiesSnapshot(bundledModelCapabilitiesSnapshotJson)
const aliasCollisionSnapshot: ModelCapabilitiesSnapshot = { const aliasCollisionSnapshot: ModelCapabilitiesSnapshot = {
...bundledSnapshot, ...bundledSnapshot,
models: { models: {
@@ -76,7 +79,7 @@ describe("model-capability-guardrails", () => {
}) })
test("flags exact aliases when models.dev gains a canonical entry for the alias itself", () => { test("flags exact aliases when models.dev gains a canonical entry for the alias itself", () => {
const bundledSnapshot = getBundledModelCapabilitiesSnapshot() const bundledSnapshot = getBundledModelCapabilitiesSnapshot(bundledModelCapabilitiesSnapshotJson)
const aliasCollisionSnapshot: ModelCapabilitiesSnapshot = { const aliasCollisionSnapshot: ModelCapabilitiesSnapshot = {
...bundledSnapshot, ...bundledSnapshot,
models: { models: {
@@ -105,6 +108,7 @@ describe("model-capability-guardrails", () => {
test("flags built-in requirement models that rely on aliases instead of canonical IDs", () => { test("flags built-in requirement models that rely on aliases instead of canonical IDs", () => {
const issues = collectModelCapabilityGuardrailIssues({ const issues = collectModelCapabilityGuardrailIssues({
snapshot: getBundledModelCapabilitiesSnapshot(bundledModelCapabilitiesSnapshotJson),
requirementModelIDs: ["gemini-3.1-pro-high"], requirementModelIDs: ["gemini-3.1-pro-high"],
}) })
@@ -1,5 +1,4 @@
import type { ModelCapabilitiesSnapshot } from "./model-capabilities" import type { ModelCapabilitiesSnapshot } from "./model-capabilities"
import { getBundledModelCapabilitiesSnapshot } from "./model-capabilities"
import { import {
getExactModelIDAliasRules, getExactModelIDAliasRules,
getPatternModelIDAliasRules, getPatternModelIDAliasRules,
@@ -45,6 +44,7 @@ export type ModelCapabilityGuardrailIssue =
type CollectModelCapabilityGuardrailIssuesInput = { type CollectModelCapabilityGuardrailIssuesInput = {
snapshot?: ModelCapabilitiesSnapshot snapshot?: ModelCapabilitiesSnapshot
loadBundledSnapshot?: () => ModelCapabilitiesSnapshot
requirementModelIDs?: Iterable<string> requirementModelIDs?: Iterable<string>
} }
@@ -73,7 +73,10 @@ export function getBuiltInRequirementModelIDs(): string[] {
export function collectModelCapabilityGuardrailIssues( export function collectModelCapabilityGuardrailIssues(
input: CollectModelCapabilityGuardrailIssuesInput = {}, input: CollectModelCapabilityGuardrailIssuesInput = {},
): ModelCapabilityGuardrailIssue[] { ): ModelCapabilityGuardrailIssue[] {
const snapshot = input.snapshot ?? getBundledModelCapabilitiesSnapshot() const snapshot = input.snapshot ?? input.loadBundledSnapshot?.()
if (!snapshot) {
return []
}
const snapshotModelIDs = new Set( const snapshotModelIDs = new Set(
Object.keys(snapshot.models).map((modelID) => normalizeLookupModelID(modelID)), Object.keys(snapshot.models).map((modelID) => normalizeLookupModelID(modelID)),
) )
+13 -3
View File
@@ -1,15 +1,25 @@
import { import {
getBundledModelCapabilitiesSnapshot, getBundledModelCapabilitiesSnapshot,
getModelCapabilities as getModelCapabilitiesFromCore, getModelCapabilities as getModelCapabilitiesFromCore,
} from "@oh-my-opencode/model-core" } from "@oh-my-opencode/model-core"
import type { GetModelCapabilitiesInput, ModelCapabilities } from "@oh-my-opencode/model-core" import type { GetModelCapabilitiesInput, ModelCapabilities } from "@oh-my-opencode/model-core"
import * as connectedProvidersCache from "../connected-providers-cache" import * as connectedProvidersCache from "../connected-providers-cache"
import bundledModelCapabilitiesSnapshotJson from "../../generated/model-capabilities.generated.json"
export { getBundledModelCapabilitiesSnapshot } export function getBundledModelCapabilitiesSnapshotForRuntime() {
return getBundledModelCapabilitiesSnapshot(bundledModelCapabilitiesSnapshotJson)
}
export function getBundledModelCapabilitiesSnapshotForShared(): ReturnType<typeof getBundledModelCapabilitiesSnapshotForRuntime> {
return getBundledModelCapabilitiesSnapshotForRuntime()
}
export { getBundledModelCapabilitiesSnapshotForShared as getBundledModelCapabilitiesSnapshot }
export function getModelCapabilities(input: GetModelCapabilitiesInput): ModelCapabilities { export function getModelCapabilities(input: GetModelCapabilitiesInput): ModelCapabilities {
return getModelCapabilitiesFromCore({ return getModelCapabilitiesFromCore({
...input, ...input,
bundledSnapshot: input.bundledSnapshot ?? getBundledModelCapabilitiesSnapshotForRuntime(),
providerCache: input.providerCache ?? connectedProvidersCache, providerCache: input.providerCache ?? connectedProvidersCache,
}) })
} }
+21 -4
View File
@@ -1,5 +1,22 @@
export type { ModelCapabilityGuardrailIssue } from "@oh-my-opencode/model-core" import {
export { collectModelCapabilityGuardrailIssues as collectModelCapabilityGuardrailIssuesFromCore,
getBuiltInRequirementModelIDs, getBuiltInRequirementModelIDs,
collectModelCapabilityGuardrailIssues,
} from "@oh-my-opencode/model-core" } from "@oh-my-opencode/model-core"
import type {
ModelCapabilityGuardrailIssue,
ModelCapabilitiesSnapshot,
} from "@oh-my-opencode/model-core"
import { getBundledModelCapabilitiesSnapshotForRuntime } from "./model-capabilities"
export { getBuiltInRequirementModelIDs }
export type { ModelCapabilityGuardrailIssue }
export function collectModelCapabilityGuardrailIssues(input: {
snapshot?: ModelCapabilitiesSnapshot
requirementModelIDs?: Iterable<string>
} = {}): ModelCapabilityGuardrailIssue[] {
return collectModelCapabilityGuardrailIssuesFromCore({
...input,
snapshot: input.snapshot ?? getBundledModelCapabilitiesSnapshotForRuntime(),
})
}