compiler: inject missing model pricing from models.dev at compile time#43003
Conversation
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
|
There was a problem hiding this comment.
Pull request overview
Adds a compile-time fallback that injects missing model pricing into GH_AW_INFO_MODEL_COSTS by downloading and querying the models.dev catalog, so runtime cost accounting doesn’t rely on a live catalog fetch when the embedded models.json lacks a model.
Changes:
- Adds a
Compiler-injectedmodelPricingResolvercallback and wires it up from the CLI compile path. - Implements compile-time resolution/merge logic to extend
WorkflowData.ModelCostsonly when pricing is missing. - Adds a
sync.Once-cached models.dev catalog downloader/parser plus unit tests for both CLI and workflow layers.
Show a summary per file
| File | Description |
|---|---|
| pkg/workflow/workflow_builder.go | Calls the compiler’s pricing resolver after assembling the frontmatter ModelCosts overlay. |
| pkg/workflow/compiler_types.go | Adds modelPricingResolver and a setter to inject pricing resolution without circular imports. |
| pkg/workflow/compiler_model_pricing.go | New pricing resolution + merge helpers for injecting missing per-token costs into ModelCosts. |
| pkg/workflow/compiler_model_pricing_test.go | Unit tests covering provider resolution, merge behavior, and resolver integration. |
| pkg/cli/models_dev_sync.go | sync.Once download/parse of models.dev/catalog.json into a normalized per-token pricing cache. |
| pkg/cli/models_dev_sync_test.go | Unit tests for parsing and lookup logic against a local test server. |
| pkg/cli/model_costs.go | Adds FindOrFetchModelPricing to short-circuit embedded-catalog models and otherwise query models.dev. |
| pkg/cli/compile_compiler_setup.go | Registers FindOrFetchModelPricing as the compiler’s resolver during CLI compilation. |
Review details
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 8/8 changed files
- Comments generated: 2
- Review effort level: Low
| provider := resolveEngineProviderForPricing(engineConfig) | ||
| model := strings.ToLower(strings.TrimSpace(engineConfig.Model)) | ||
|
|
| // Reset the sync.Once and cache so we can inject a test server. | ||
| modelsDevOnce = sync.Once{} | ||
| modelsDevCache = nil |
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Implemented in commit 7cf566f.
|
|
@copilot please run the Run: https://github.com/github/gh-aw/actions/runs/28606537165
|
Ran a PR-finisher pass with no additional code changes required. Maintainer summary:
Still blocking merge:
|
|
@copilot please run the Run: https://github.com/github/gh-aw/actions/runs/28611171544
|
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
…er-handling-models Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Completed. Addressed remaining review feedback and refreshed the branch from Code updates landed in:
Local checks are green on current HEAD after refresh:
PR is maintainer-ready from the agent side; CI on this updated head still needs maintainer-triggered rerun/approval. |
|
@copilot refactor models.dev support into separate package modelsdev to clearly separate the core functionality of this feature into a new package. |
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Done in I refactored the models.dev catalog fetch/parse/cache/lookup logic into a new |
|
@copilot use syncutil helper to cache catalog |
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Implemented in Switched |
|
@copilot run pr-finisher skill Fix https://github.com/github/gh-aw/actions/runs/28620919434/job/84877643669 |
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
|
Hey One thing would help get this across the finish line:
If you would like a hand splitting it up, you can assign this prompt to your coding agent:
|
Fixed in I reproduced the failing
Validation rerun locally passed:
|
…er-handling-models Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Models absent from the embedded
models.jsoncatalog produce no pricing data in compiledlock.yml, causing the AWF proxy to mark themunknown_model_ai_credits=trueat runtime. This PR makes the compiler fetch missing pricing fromhttps://models.dev/catalog.json(once per process) and embed it inGH_AW_INFO_MODEL_COSTSso cost accounting works without a live catalog download in the agent job.Approach
Dependency injection avoids the
pkg/cli→pkg/workflowcircular import: the pricing resolver is afunc(ctx, provider, model)field onCompiler, set by the cli at compile time. WASM builds are safe since the field is never populated there.Key changes
pkg/cli/models_dev_sync.go—sync.Oncedownload ofmodels.dev/catalog.json; normalizes per-million → per-tokenfloat64;modelsDevCatalogURLandmodelsDevHTTPClientFactoryarevarfor testabilitypkg/cli/model_costs.go—FindOrFetchModelPricing: short-circuits with(nil, false)for models already in the embedded catalog (runtime already has them), falls through to models.dev for unknownspkg/workflow/compiler_types.go—modelPricingResolverfield +SetModelPricingResolversetterpkg/workflow/compiler_model_pricing.go—resolveModelPricingIfMissing(skips if frontmatter overlay already covers the model),resolveEngineProviderForPricing(LLMProvider → InlineProviderID → engine-ID heuristic),mergeModelPricingIntoModelCosts(shallow-clone; prices serialized as%gstrings matching the models.json schema)pkg/workflow/workflow_builder.go— callsresolveModelPricingIfMissingafter the frontmatterModelCostsoverlay is assembledpkg/cli/compile_compiler_setup.go— registersFindOrFetchModelPricingas the resolver increateAndConfigureCompilerBehavior
(nil, false)— runtime models.json already has itGH_AW_INFO_MODEL_COSTS