feat(commands): add /models and fix /model listing UX
This commit is contained in:
@@ -169,8 +169,9 @@ export async function maybeHandleModelDirectiveInfo(params: {
|
||||
const rawDirective = params.directives.rawModelDirective?.trim();
|
||||
const directive = rawDirective?.toLowerCase();
|
||||
const wantsStatus = directive === "status";
|
||||
const wantsList = !rawDirective || directive === "list";
|
||||
if (!wantsList && !wantsStatus) return undefined;
|
||||
const wantsSummary = !rawDirective;
|
||||
const wantsLegacyList = directive === "list";
|
||||
if (!wantsSummary && !wantsStatus && !wantsLegacyList) return undefined;
|
||||
|
||||
if (params.directives.rawModelProfile) {
|
||||
return { text: "Auth profile override requires a model selection." };
|
||||
@@ -184,16 +185,28 @@ export async function maybeHandleModelDirectiveInfo(params: {
|
||||
allowedModelCatalog: params.allowedModelCatalog,
|
||||
});
|
||||
|
||||
if (wantsList) {
|
||||
const items = buildModelPickerItems(pickerCatalog);
|
||||
if (items.length === 0) return { text: "No models available." };
|
||||
if (wantsLegacyList) {
|
||||
return {
|
||||
text: [
|
||||
"Model listing moved.",
|
||||
"",
|
||||
"Use: /models (providers) or /models <provider> (models)",
|
||||
"Switch: /model <provider/model>",
|
||||
].join("\n"),
|
||||
};
|
||||
}
|
||||
|
||||
if (wantsSummary) {
|
||||
const current = `${params.provider}/${params.model}`;
|
||||
const lines: string[] = [`Current: ${current}`, "Pick: /model <#> or /model <provider/model>"];
|
||||
for (const [idx, item] of items.entries()) {
|
||||
lines.push(`${idx + 1}) ${item.provider}/${item.model}`);
|
||||
}
|
||||
lines.push("", "More: /model status");
|
||||
return { text: lines.join("\n") };
|
||||
return {
|
||||
text: [
|
||||
`Current: ${current}`,
|
||||
"",
|
||||
"Switch: /model <provider/model>",
|
||||
"Browse: /models (providers) or /models <provider> (models)",
|
||||
"More: /model status",
|
||||
].join("\n"),
|
||||
};
|
||||
}
|
||||
|
||||
const modelsPath = `${params.agentDir}/models.json`;
|
||||
@@ -285,31 +298,36 @@ export function resolveModelSelectionFromDirective(params: {
|
||||
let modelSelection: ModelDirectiveSelection | undefined;
|
||||
|
||||
if (/^[0-9]+$/.test(raw)) {
|
||||
const pickerCatalog = buildModelPickerCatalog({
|
||||
cfg: params.cfg,
|
||||
defaultProvider: params.defaultProvider,
|
||||
defaultModel: params.defaultModel,
|
||||
aliasIndex: params.aliasIndex,
|
||||
allowedModelCatalog: params.allowedModelCatalog,
|
||||
});
|
||||
const items = buildModelPickerItems(pickerCatalog);
|
||||
const index = Number.parseInt(raw, 10) - 1;
|
||||
const item = Number.isFinite(index) ? items[index] : undefined;
|
||||
if (!item) {
|
||||
return {
|
||||
errorText: `Invalid model selection "${raw}". Use /model to list.`,
|
||||
return {
|
||||
errorText: [
|
||||
"Numeric model selection is not supported in chat.",
|
||||
"",
|
||||
"Browse: /models or /models <provider>",
|
||||
"Switch: /model <provider/model>",
|
||||
].join("\n"),
|
||||
};
|
||||
}
|
||||
|
||||
const explicit = resolveModelRefFromString({
|
||||
raw,
|
||||
defaultProvider: params.defaultProvider,
|
||||
aliasIndex: params.aliasIndex,
|
||||
});
|
||||
if (explicit) {
|
||||
const explicitKey = modelKey(explicit.ref.provider, explicit.ref.model);
|
||||
if (params.allowedModelKeys.size === 0 || params.allowedModelKeys.has(explicitKey)) {
|
||||
modelSelection = {
|
||||
provider: explicit.ref.provider,
|
||||
model: explicit.ref.model,
|
||||
isDefault:
|
||||
explicit.ref.provider === params.defaultProvider &&
|
||||
explicit.ref.model === params.defaultModel,
|
||||
...(explicit.alias ? { alias: explicit.alias } : {}),
|
||||
};
|
||||
}
|
||||
const key = `${item.provider}/${item.model}`;
|
||||
const aliases = params.aliasIndex.byKey.get(key);
|
||||
const alias = aliases && aliases.length > 0 ? aliases[0] : undefined;
|
||||
modelSelection = {
|
||||
provider: item.provider,
|
||||
model: item.model,
|
||||
isDefault: item.provider === params.defaultProvider && item.model === params.defaultModel,
|
||||
...(alias ? { alias } : {}),
|
||||
};
|
||||
} else {
|
||||
}
|
||||
|
||||
if (!modelSelection) {
|
||||
const resolved = resolveModelDirectiveSelection({
|
||||
raw,
|
||||
defaultProvider: params.defaultProvider,
|
||||
@@ -317,10 +335,24 @@ export function resolveModelSelectionFromDirective(params: {
|
||||
aliasIndex: params.aliasIndex,
|
||||
allowedModelKeys: params.allowedModelKeys,
|
||||
});
|
||||
|
||||
if (resolved.error) {
|
||||
return { errorText: resolved.error };
|
||||
}
|
||||
modelSelection = resolved.selection;
|
||||
|
||||
if (resolved.selection) {
|
||||
const suggestion = `${resolved.selection.provider}/${resolved.selection.model}`;
|
||||
return {
|
||||
errorText: [
|
||||
`Unrecognized model: ${raw}`,
|
||||
"",
|
||||
`Did you mean: ${suggestion}`,
|
||||
`Try: /model ${suggestion}`,
|
||||
"",
|
||||
"Browse: /models or /models <provider>",
|
||||
].join("\n"),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
let profileOverride: string | undefined;
|
||||
|
||||
Reference in New Issue
Block a user