Skip to content

Commit 41c855f

Browse files
ndemiancclaude
andcommitted
redesign(ai): name-only Cloud model picker — drop the per-row debug detail
The gateway model picker showed three technical fields per model: the raw id (anthropic/claude-opus-5), the context size, and a "N× credits · NK ctx · ≈N turns left" second line. For someone who just wants to pick Opus 5 that buried the name in noise and made every row a tall two-line block. Each row is now a single, name-forward line: the friendly name + the active check, and a lock + "coming soon" on staged models. The plan and remaining credits still live in the picker's placeholder, so the one number that matters isn't lost. Reads like the Cursor / Claude Code pickers. - dropped: description=id, the ctx/multiplier/turns detail line, and fmtTurns (now unused). matchOnDescription is off, so typing filters by model name only. - staged rows carry _name — the "coming soon" toast used to read the model name out of description, which is now literally the string "coming soon". It's a native QuickPick, so the font follows the app UI font (can't be set per-picker); the single-line rows are what make the name read large and clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent a0850f4 commit 41c855f

1 file changed

Lines changed: 18 additions & 31 deletions

File tree

extensions/levelcode-ai/extension.js

Lines changed: 18 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,18 +1169,13 @@ async function openLegal(target) {
11691169
await vscode.env.openExternal(vscode.Uri.parse('https://levelcode.ai' + path));
11701170
}
11711171

1172-
/** Human "≈ turns left" formatting (e.g. 8044 → "8k", 375 → "375"). */
1173-
function fmtTurns(n) {
1174-
n = Number(n) || 0;
1175-
return n >= 1000 ? (Math.round(n / 100) / 10) + 'k' : String(n);
1176-
}
1177-
11781172
/**
11791173
* The LevelCode Cloud model menu (gateway mode, signed in). Fetches the plan's roster from the backend
1180-
* (GET /account/models): LIVE models (confirmed price) are selectable with their credit multiplier +
1181-
* ≈ turns-left on the remaining budget; STAGED models (frontier, assumption-priced) are shown 🔒 as
1182-
* "coming soon"; the free tier surfaces an Upgrade CTA. The backend re-checks entitlement, so a
1183-
* client selection can never over-reach the plan.
1174+
* (GET /account/models): LIVE models (confirmed price) are selectable; STAGED models (frontier,
1175+
* assumption-priced) are shown 🔒 as "coming soon"; the free tier surfaces an Upgrade CTA. Rows are
1176+
* deliberately NAME-ONLY — the id, context, credit multiplier and ≈turns-left were debug detail that
1177+
* buried the model name, so they were dropped (the plan + remaining credits stay in the placeholder).
1178+
* The backend re-checks entitlement, so a client selection can never over-reach the plan.
11841179
*/
11851180
async function pickCloudModel() {
11861181
const roster = await fetchCloudRoster();
@@ -1195,46 +1190,38 @@ async function pickCloudModel() {
11951190
const items = [{ label: 'LevelCode Cloud · ' + plan, kind: vscode.QuickPickItemKind.Separator }];
11961191
// Auto (paid only): the gateway picks the cheapest engine per turn — free margin for the user.
11971192
if (paid) {
1198-
items.push({
1199-
label: (active === GATEWAY_AUTO_MODEL ? '$(check) ' : '') + '$(sparkle) ' + GATEWAY_AUTO_LABEL,
1200-
description: GATEWAY_AUTO_MODEL,
1201-
detail: 'Routes each turn to the best-value engine · saves credits',
1202-
_cloud: GATEWAY_AUTO_MODEL
1203-
});
1193+
items.push({ label: (active === GATEWAY_AUTO_MODEL ? '$(check) ' : '') + '$(sparkle) ' + GATEWAY_AUTO_LABEL, _cloud: GATEWAY_AUTO_MODEL });
12041194
}
12051195
if (models.length) {
12061196
for (const m of models) {
1207-
const ctxK = Math.round((m.context || 0) / 1000) + 'K ctx';
12081197
if (m.live) {
1209-
const turns = (m.turns_left != null) ? ' · ≈' + fmtTurns(m.turns_left) + ' turns left' : '';
1210-
items.push({
1211-
label: (m.id === active ? '$(check) ' : '') + m.label,
1212-
description: m.id,
1213-
detail: m.multiplier + '× credits · ' + ctxK + turns,
1214-
_cloud: m.id
1215-
});
1198+
// Name only — the model name is the whole point of the row. id/ctx/multiplier/turns removed.
1199+
items.push({ label: (m.id === active ? '$(check) ' : '') + m.label, _cloud: m.id });
12161200
} else {
1217-
items.push({ label: '$(lock) ' + m.label, description: m.id, detail: m.multiplier + '× credits · ' + ctxK + ' · coming soon', _soon: true });
1201+
// Staged: not selectable yet — "coming soon" is the one kept hint; _name backs the info toast.
1202+
items.push({ label: '$(lock) ' + m.label, description: 'coming soon', _soon: true, _name: m.label });
12181203
}
12191204
}
12201205
} else {
12211206
// Offline / roster unavailable — minimal fallback so the menu still works.
1222-
items.push({ label: (active === GATEWAY_FREE_MODEL ? '$(check) ' : '') + GATEWAY_FREE_LABEL, description: GATEWAY_FREE_MODEL, _cloud: GATEWAY_FREE_MODEL });
1223-
if (paid) { items.push({ label: (active === GATEWAY_PRO_MODEL ? '$(check) ' : '') + GATEWAY_PRO_LABEL, description: GATEWAY_PRO_MODEL, _cloud: GATEWAY_PRO_MODEL }); }
1207+
items.push({ label: (active === GATEWAY_FREE_MODEL ? '$(check) ' : '') + GATEWAY_FREE_LABEL, _cloud: GATEWAY_FREE_MODEL });
1208+
if (paid) { items.push({ label: (active === GATEWAY_PRO_MODEL ? '$(check) ' : '') + GATEWAY_PRO_LABEL, _cloud: GATEWAY_PRO_MODEL }); }
12241209
}
12251210
if (!paid) {
1226-
items.push({ label: '$(rocket) Upgrade to Pro', description: 'Kimi K2.7 Code + the full model roster', _upgrade: true });
1211+
items.push({ label: '$(rocket) Upgrade to Pro', description: 'unlock the full roster', _upgrade: true });
12271212
}
12281213
items.push({ label: 'Other', kind: vscode.QuickPickItemKind.Separator });
1229-
items.push({ label: '$(key) Use my own key (BYOK)…', description: 'Turn off the metered gateway in settings', _action: 'byokSettings' });
1214+
items.push({ label: '$(key) Use my own key (BYOK)…', description: 'turn off the metered gateway', _action: 'byokSettings' });
12301215

1216+
// Name-forward filtering: match the label only (no hidden id/description matching), so typing "opus"
1217+
// narrows to the Opus rows and nothing else.
12311218
const pick = await vscode.window.showQuickPick(items, {
12321219
placeHolder: 'LevelCode Cloud model · Plan: ' + plan + credits,
1233-
matchOnDescription: true
1220+
matchOnDescription: false
12341221
});
12351222
if (!pick) { return; }
12361223
if (pick._upgrade) { await openUpgrade(); return; }
1237-
if (pick._soon) { vscode.window.showInformationMessage('LevelCode Cloud: ' + (pick.description || 'that model') + ' is coming soon — pricing is being finalized.'); return; }
1224+
if (pick._soon) { vscode.window.showInformationMessage('LevelCode Cloud: ' + (pick._name || 'that model') + ' is coming soon — pricing is being finalized.'); return; }
12381225
if (pick._action === 'byokSettings') { vscode.commands.executeCommand('workbench.action.openSettings', 'levelcode.ai.providerMode'); return; }
12391226
if (pick._cloud) {
12401227
await aiConfig().update('cloudModel', pick._cloud, vscode.ConfigurationTarget.Global);

0 commit comments

Comments
 (0)