Skip to content

modelPickerOrder: complete-picker (bare native id) ordering is implemented and documented, but PUT /api/subagent-models rejects it #6337

Closed as not planned

Description

@arikon

Summary

The complete-picker ordering feature is implemented in the catalog engine and documented, but the only supported write path rejects the input it requires.

modelPickerOrder supports ordering the complete picker when the array includes a bare native id (e.g. gpt-5.6-sol). This is implemented in applyFullModelPickerOrder (src/codex/catalog/build-entries.ts) and documented in docs-site/src/content/docs/guides/model-ordering.md ("To order the complete picker, include a bare native id", with a worked example modelPickerOrder: ["gpt-5.6-sol", "opencode-go/glm-5.3"]).

However, PUT /api/subagent-models validates every pickerOrder entry against visible routed slugs only and rejects bare native ids:

// src/server/management/agent-settings-routes.ts
const visible = new Set(filterCatalogVisibleModels(models, config).map(catalogModelSlug).filter(slug => slug.includes("/")));
if (pickerOrder.some(model => !visible.has(model))) {
  return jsonResponse({ error: "pickerOrder must contain each visible routed model at most once" }, 400);
}

tests/routing/subagent-roster-retention.test.ts even pins { pickerOrder: ["gpt-5.5"] } as an invalid body, so the rejection appears intentional at the API layer. The dashboard follows suit: once a saved order contains a native id, the custom-order editor locks with the nativeLocked message and cannot edit or re-save it.

The result is a documented feature that cannot be created or edited through any supported path. Config hand-edits work (the engine honors them on the next catalog converge), but they bypass the API's ownership, staleness and rebase protections, and a running proxy must be restarted to pick the change up.

Reproduction

On opencodex 2.74.0 (bundled macOS app CLI) with any routed provider configured:

TOKEN=$(cat ~/.opencodex/admin-api-token)
PORT=$(jq -r .port ~/.opencodex/config.json)
curl -s -X PUT http://127.0.0.1:$PORT/api/subagent-models \
  -H "X-OpenCodex-API-Key: $TOKEN" -H 'Content-Type: application/json' \
  -d '{"pickerOrder":["gpt-5.5"]}'
# -> {"error":"pickerOrder must contain each visible routed model at most once"}

curl -s -X PUT http://127.0.0.1:$PORT/api/subagent-models \
  -H "X-OpenCodex-API-Key: $TOKEN" -H 'Content-Type: application/json' \
  -d '{"pickerOrder":["eliza-openrouter/z-ai-glm-5.3"]}'
# -> 200 ok (routed-only lists are accepted)

Expected: a bare id that names a visible native catalog row (present in nativeModelRows(config) / NATIVE_OPENAI_MODELS) should be accepted for complete-picker ordering, matching the documented behavior and the engine implementation.

Observed on the live proxy at 2.74.0; the validation matches current dev (6eec1265c lineage). Related history: #1649 introduced modelPickerOrder, #3774/#3801 added dashboard presets; both left native-id handling outstanding.

Version

2.74.0

Operating system

macOS (observed on the bundled OpenCodex.app CLI; the route is platform-independent)

Activity

  1. github-actions commented on Sep 30, 2026

    @github-actions
    Contributor

    Issue closed: use an issue template

    Thanks for taking the time to submit this issue. It was closed automatically because it was not opened with a recognized issue template (Bug report, Feature request, Documentation, or Provider compatibility). Freeform and API-opened issues cannot skip this check.

    • This looks like a bug report but it does not use the Bug report template headings (for example Description/Log entry instead of Summary).

    Please edit the issue to add:

    • Use the Bug report template, or edit this issue to include: Client or integration, Summary, Reproduction, Version, and Operating system.
    • Retitling with [Bug]: and applying the bug label alone is not enough without those section headings filled in.

    See the Contributing guide for details.

    Once the report passes the automated checks, it will be reopened automatically unless a maintainer has changed its state.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions