From 0a8f6a326ef220e499c2fd5aaf14bba61ed05a68 Mon Sep 17 00:00:00 2001 From: JUN Date: Wed, 11 Nov 2026 08:14:14 +0900 Subject: [PATCH 1/5] feat(aliases): opt-in per-provider alias templates #7705, as approved: a provider may set aliasTemplate (for example "{providerAlias}-{modelBasename}") to name every model that has no manual or built-in alias. Aliases are derived at resolution time and never written to config, so a newly discovered model gets its alias immediately and removing the template removes them. Only the literal {providerAlias} and {modelBasename} placeholders exist and the basename is required. Manual > Builtin > Template. A candidate is skipped, never renamed, when it is invalid, uses a reserved prefix, or matches anything already claimed (native ids, provider aliases, built-in alias names, provider names, other providers' manual aliases, combo ids and aliases); colliding candidates are both skipped so the result is roster-order invariant. effectiveModelAliases/resolveModelAlias take an optional providerName that all seven callers pass. PUT /api/providers/{provider}/alias-template validates, saves and previews; GET /api/aliases lists templates and template-sourced rows; ocx alias template set|rm|show; an invalid hand-edited template is dropped with a warning at load. Closes #7705 --- .../src/content/docs/guides/model-routing.md | 6 + docs-site/src/content/docs/reference/cli.md | 2 +- .../docs/reference/configuration/providers.md | 2 +- scripts/test-layout/layout-providers.json | 1 + .../ocx/references/01_management_surface.md | 18 ++- .../references/01_surface_providers-models.md | 52 ++++++- src/cli/alias.ts | 39 ++++- src/cli/capabilities-provider-models.ts | 16 ++ src/clients/config-export/alias-selectors.ts | 2 +- src/codex/catalog/routed-gather.ts | 2 +- src/config/load-degrade.ts | 9 +- src/config/schema/leaf-validators.ts | 2 + src/providers/alias-template.ts | 48 ++++++ src/providers/default-aliases.ts | 116 +++++++++++--- src/providers/model-rename-fields.ts | 1 + src/router.ts | 4 +- src/server/auth-cors.ts | 1 + src/server/index/serve-options.ts | 1 + src/server/management/model-routes.ts | 43 +++++- .../management/provider-completion-test.ts | 8 +- src/server/management/route-registry.ts | 1 + src/types/provider.ts | 6 + tests/cli/cli-alias-json.test.ts | 33 ++++ .../codex-convergence-contract.test.ts | 9 +- tests/fixtures/test-layout-expected.json | 2 +- .../providers/provider-alias-template.test.ts | 143 ++++++++++++++++++ tests/server/alias-management-api.test.ts | 23 +++ 27 files changed, 544 insertions(+), 46 deletions(-) create mode 100644 src/providers/alias-template.ts create mode 100644 tests/providers/provider-alias-template.test.ts diff --git a/docs-site/src/content/docs/guides/model-routing.md b/docs-site/src/content/docs/guides/model-routing.md index 772a078eb74..ce2456eca37 100644 --- a/docs-site/src/content/docs/guides/model-routing.md +++ b/docs-site/src/content/docs/guides/model-routing.md @@ -67,6 +67,12 @@ through to one another. 8. **Default provider** — if nothing matched, the id is sent to `config.defaultProvider` unchanged. (If no default provider is configured, or it is disabled, routing throws.) +## Model alias templates + +`aliasTemplate` (opt-in, per provider) names every model of that provider that has no manual or built-in alias, for example `"aliasTemplate": "{providerAlias}-{modelBasename}"` on a provider whose alias is `CC` turns `reflection/beam:free` into `CC-beam-free`. Only two literal placeholders exist: `{providerAlias}` (the provider's alias; a template that uses it does nothing for a provider without one) and `{modelBasename}` (the last `/` segment of the model id with `:` written as `-`), and `{modelBasename}` is required. The aliases are derived whenever models are resolved and are never written to the config, so a new model gets its alias as soon as it is discovered and removing the template removes them at once. + +Manual aliases win, then built-in ones, then the template. A generated name is skipped, never renamed, when it is not a valid alias, starts with a reserved prefix (`gpt-`, `o1-`, `o3-`, `o4-`, `codex-`), or matches anything already claimed: a native model id or alias of the provider, a built-in alias name, a provider name or alias, another provider's manual alias, or a combo id or alias. When two models produce the same name, both are skipped, so the result does not depend on the order models are listed. A bare template alias that another provider's template also produced is ambiguous like any other alias; the `/` form still works. Set it with `ocx alias template set