Repository navigation
cmux NEXT model menu: every row names its effort, each agent tab lists current versions with older ones under Legacy #30054
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
fa2da85
fef693f
4840703
7e2491a
256941b
ba65507
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -54,9 +54,29 @@ function newer(a: Model, b: Model): boolean { | |||||
| return variant(b) && !variant(a); | ||||||
| } | ||||||
|
|
||||||
| /** `a` is a strictly older version than `b`. A variant of the same version is not, nor is a model | ||||||
| * whose name and id carry no version (a bare alias). A snapshot date is no version part, so | ||||||
| * `claude-opus-4-5` is not older than its dated snapshot `claude-opus-4-5-20251101`. */ | ||||||
| function olderVersion(a: Model, b: Model): boolean { | ||||||
| const release = (model: Model) => version(model).filter((part) => part < 100_000); | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: Prompt for AI agents |
||||||
| const left = release(a); | ||||||
| const right = release(b); | ||||||
| if (left.length === 0 || right.length === 0) return false; | ||||||
| for (let index = 0; index < Math.max(left.length, right.length); index++) { | ||||||
| const difference = (left[index] ?? 0) - (right[index] ?? 0); | ||||||
| if (difference) return difference < 0; | ||||||
| } | ||||||
| return false; | ||||||
| } | ||||||
|
|
||||||
| /** One product line: the declared family and the version-stripped id together, so a harness whose | ||||||
| * families are whole vendors ("OpenAI", "Google") never folds one product line under another. */ | ||||||
| const lineKey = (model: Model) => `${familyKey(model)}\u0000${familyKey({ ...model, family: undefined })}`; | ||||||
|
|
||||||
| export function relevantModelSections<T extends Model>( | ||||||
| models: readonly T[], | ||||||
| top: readonly string[] | undefined, | ||||||
| running?: string, | ||||||
| ): { shown: T[]; more: T[] } { | ||||||
| const available = (model: T) => (model.offers ?? [model]).some((offer) => !offer.unavailable); | ||||||
| const chosen = new Set<T>(); | ||||||
|
|
@@ -67,6 +87,25 @@ export function relevantModelSections<T extends Model>( | |||||
| ); | ||||||
| if (model && available(model)) chosen.add(model); | ||||||
| } | ||||||
| // A harness that reports its whole live list (Codex: every GPT generation) would otherwise | ||||||
| // list its tab flat while one that reports a short menu (Claude Code) folds the rest under | ||||||
| // Legacy models (https://github.com/manaflow-ai/cmux/issues/29915). A menu model of a declared | ||||||
| // catalog family whose product line the same menu also lists at a newer version folds, so every | ||||||
| // tab shows its lines' current versions. Context variants of one version stay, inferred families | ||||||
| // never fold, and the chat's running model keeps its row: folding never hides the live choice. | ||||||
| const isRunning = (model: T) => | ||||||
| !!running && (model.offers ?? [model]).some((offer) => offer.id === running || offer.release === running); | ||||||
| const newest = new Map<string, T>(); | ||||||
| for (const model of chosen) { | ||||||
| if (!model.family) continue; | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: A versionless model that shares a product line with versioned models can become the line's Prompt for AI agents
Suggested change
|
||||||
| const key = lineKey(model); | ||||||
| const previous = newest.get(key); | ||||||
| if (!previous || olderVersion(previous, model)) newest.set(key, model); | ||||||
| } | ||||||
| for (const model of chosen) { | ||||||
| const lead = model.family ? newest.get(lineKey(model)) : undefined; | ||||||
| if (lead && olderVersion(model, lead) && !isRunning(model)) chosen.delete(model); | ||||||
| } | ||||||
| } else { | ||||||
| const families = new Map<string, T>(); | ||||||
| for (const model of models) { | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2: Effort-capable models without
defaultEffortstill have no recommended choice, soshownstays undefined and the effort trigger remains hidden at rest. Derive and display the actual landing level for these rows so every supported model names its effort.Prompt for AI agents