Skip to content

feat(sync): add safe NanoGPT model catalog sync - #3342

Merged
rekram1-node merged 5 commits into
anomalyco:devfrom
huggix:codex/nanogpt-sync-review-fixes
Jul 29, 2026
Merged

feat(sync): add safe NanoGPT model catalog sync#3342
rekram1-node merged 5 commits into
anomalyco:devfrom
huggix:codex/nanogpt-sync-review-fixes

Conversation

@huggix

@huggix huggix commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Summary

This supersedes #2891 with the sync implementation separated from generated catalog data, addressing the automated review feedback.

  • add NanoGPT as an automated aggregator sync source
  • consume verified reasoning_efforts rather than inferring controls from IDs
  • preserve existing prices when source pricing is null and omit modality-dependent token prices
  • refresh limit.input from the source context length
  • factor known variants through canonical base_model metadata
  • use the normal stale-entry deletion behavior
  • never propagate NanoGPT's internal providers field
  • leave generated model files to the existing hourly automation

Safety and compatibility

  • NanoGPT's source change is additive and limited to the detailed catalog response
  • no provider identifiers are written to models.dev output
  • missing pricing is never converted to zero
  • fixed-reasoning models do not receive invented toggles
  • open-weight metadata is sourced explicitly or inherited from canonical metadata

Evidence

  • Models endpoint documents the public /api/v1/models?detailed=true catalog and its detailed pricing, limits, and capability fields.
  • Live detailed catalog is the authoritative per-model source for the optional reasoning_efforts arrays consumed by this sync.
  • Chat Completions reasoning effort documents the request values represented by those arrays: none, minimal, low, medium, high, and xhigh.
  • Model suffixes documents thinking and budget aliases normalized before canonical base_model lookup.

Verification

  • bun test packages/core/test/sync.test.ts — 50 passing
  • bun validate
  • live dry run on 2026-07-20 — 57 created, 544 updated, 59 stale removed, 14 unchanged
  • generated-output audit — no provider fields, no invalid input limits, and no inferred toggle controls

@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [medium] [possible mistake] packages/core/src/sync/providers/nano-gpt.ts:272,288 - Check: resolveNanoGptBaseModel only strips the :thinking suffix and only resolves canonical base models for IDs that carry an org prefix (plus the zai-org/, TEE/, and explicit alias cases). Why: providers/nano-gpt/provider.toml documents three NanoGPT model-ID variants — :thinking, legacy -thinking, and Anthropic :<number> budgets — but the code only strips :thinking. Existing catalog entries such as claude-haiku-4-5-20251001-thinking and claude-sonnet-4-5-20250929-thinking (legacy -thinking) have matching models/anthropic/*.toml metadata, as do unprefixed IDs like gemini-2.5-pro (models/google/gemini-2.5-pro.toml) and qwen3.5-27b (models/alibaba/qwen3.5-27b.toml). For every one of these, resolveCanonicalBaseModel returns undefined because there is no / or the suffix is not stripped, so the sync writes a full inline definition instead of using base_model. That conflicts with the AGENTS.md "New models" blocker: "Must use base_model when a models/ metadata entry exists." Action: Either extend resolveNanoGptBaseModel to strip legacy -thinking and :<number> suffixes and to discover canonical metadata for unprefixed IDs (e.g., by probing known provider directories), or confirm that the live ?detailed=true API always returns org-prefixed, :thinking-only IDs for models with matching models/ entries so the legacy/unprefixed existing files are removed as stale rather than rewritten inline.

  • [low] [possible mistake] PR body — Check: Citations for the NanoGPT catalog API and the reasoning_efforts field. Why: The sync consumes reasoning_efforts as the verified source for reasoning_options and depends on the ?detailed=true endpoint shape, but the PR body does not link to the API reference or model documentation that proves the field exists and maps to the documented reasoning_effort request values (none, minimal, low, medium, high, xhigh). providers/nano-gpt/provider.toml already cites the docs, but the PR body itself states nothing about what each citation supports, so the reasoning-option mapping cannot be reviewed from the PR alone. Action: Add an "Evidence" section to the PR body citing the NanoGPT API reference for the detailed=true catalog response and the reasoning_efforts field, stating exactly what each link proves.

@rekram1-node

Copy link
Copy Markdown
Collaborator

plz address review

@huggix
huggix force-pushed the codex/nanogpt-sync-review-fixes branch from 313016e to 4df632f Compare July 24, 2026 12:44
@huggix

huggix commented Jul 24, 2026

Copy link
Copy Markdown
Contributor Author

Addressed both review items in 4df632f:

  • canonical lookup now normalizes legacy -thinking and Anthropic :<number> budget suffixes, then deterministically probes canonical metadata for unprefixed IDs
  • regression coverage includes the cited Claude, Gemini, and Qwen examples
  • generated-output verification confirms those entries now serialize with base_model
  • the PR body now includes an Evidence section linking the detailed catalog, live reasoning_efforts source, reasoning-effort semantics, and suffix documentation

The validation/SDK workflow is green; the refreshed automated review is still running.

@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [high] [violation] packages/core/src/sync/providers/nano-gpt.ts:237 - Check: Provider models must use base_model when matching models/ metadata exists. Why: TEE/ handling only rewrites deepseek/qwen/glm. Other TEE IDs (e.g. TEE/kimi-k2.5, TEE/gpt-oss-120b, TEE/gemma-4-31b-it) fall through still prefixed with TEE/, and if (direct !== undefined || normalized.includes("/")) return direct then skips the unprefixed resolver. Canonical entries such as moonshotai/kimi-k2.5, openai/gpt-oss-120b, and google/gemma-4-31b-it are never linked, so sync keeps full duplicated provider-agnostic fields. Action: After stripping TEE/, resolve the remainder through the same alias/canonical/unprefixed path used for bare IDs (not only deepseek/qwen/glm), and add tests for those TEE models.
  • [high] [violation] packages/core/src/sync/providers/nano-gpt.ts:96 - Check: base_model must point at the matching models/<provider>/<model>.toml entry. Why: "xiaomi/mimo-v2.5-pro-ultraspeed": "xiaomi/mimo-v2.5-pro" forces the wrong canonical model even though models/xiaomi/mimo-v2.5-pro-ultraspeed.toml already exists (different name, dates, weights). Without the alias, resolveCanonicalBaseModel("xiaomi/mimo-v2.5-pro-ultraspeed") would select the correct metadata. Action: Remove this alias (or retarget it to xiaomi/mimo-v2.5-pro-ultraspeed) and cover it in the base-model tests.
  • [medium] [violation] packages/core/src/sync/providers/nano-gpt.ts:226 - Check: Variant model IDs should factor against canonical metadata after stripping NanoGPT suffixes. Why: Suffix cleanup only removes a trailing :\d+ and one final :thinking/-thinking. Catalog IDs such as anthropic/claude-opus-4.6:thinking:low (and :medium/:high/:max) keep the extra effort suffix, so canonical resolution misses anthropic/claude-opus-4-6 and emits full inline copies. Action: Strip chained NanoGPT variant suffixes (at least :thinking:<effort> and repeated thinking markers) before alias/canonical lookup, with tests for those IDs.

@github-actions

Copy link
Copy Markdown
Contributor

Action items

  • [high] [violation] packages/core/src/sync/providers/nano-gpt.ts:146 - Check: Sync must preserve hand-authored provider fields when the API is not authoritative (sync.md). Why: preserveExistingOverrides is only true when existing.base_model === baseModel. On first factoring of the many full NanoGPT TOMLs (no base_model yet), API-absent fields fall through to undefined and inherit canonical metadata instead of keeping local overrides. That drops provider-specific values such as reasoning, tool_call, structured_output, limits, and modalities whenever the detailed payload omits them—e.g. providers/nano-gpt/models/anthropic/claude-sonnet-4.6.toml (reasoning = false, limit.output = 128_000, structured_output = true) against models/anthropic/claude-sonnet-4-6.toml (reasoning = true, output = 64_000, no structured_output). Action: When the source does not authoritatively set a field, fall back to existing for any local model (not only already-factored ones)—same pattern as DeepInfra/LLM Gateway. Keep the stricter “don’t copy full-definition junk into a new factor” behavior only for fields you intentionally want to re-inherit (e.g. description), and add a first-factor test that API-silent reasoning/limit.output/structured_output retain the existing provider overrides.

@github-actions

Copy link
Copy Markdown
Contributor

No actionable findings.

@huggix
huggix force-pushed the codex/nanogpt-sync-review-fixes branch from 9da548f to 9ec41e1 Compare July 25, 2026 05:59
@github-actions

Copy link
Copy Markdown
Contributor

No actionable findings.

@huggix

huggix commented Jul 25, 2026

Copy link
Copy Markdown
Contributor Author

@rekram1-node Thanks for the ping. conflicts should be closed now.

@huggix

huggix commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

@rekram1-node Could you let me know if there is anything else we can do from our side?

@rekram1-node
rekram1-node merged commit bddb089 into anomalyco:dev Jul 29, 2026
2 checks passed
@jonaspm

jonaspm commented Aug 5, 2026

Copy link
Copy Markdown

wohoo!! congratulations and AWESOME work! @huggix

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants