fix(models): handle out-of-range pages

This commit is contained in:
Vignesh Natarajan
2026-01-21 12:54:02 -08:00
parent 41d56c06b9
commit 310f916675
2 changed files with 36 additions and 6 deletions

View File

@@ -74,11 +74,20 @@ describe("/models command", () => {
const result = await handleCommands(params);
expect(result.shouldContinue).toBe(false);
expect(result.reply?.text).toContain("Models (anthropic)");
expect(result.reply?.text).toContain("page 1/");
expect(result.reply?.text).toContain("anthropic/claude-opus-4-5");
expect(result.reply?.text).toContain("Switch: /model <provider/model>");
expect(result.reply?.text).toContain("All: /models anthropic all");
});
it("errors on out-of-range pages", async () => {
const params = buildParams("/models anthropic 4", cfg);
const result = await handleCommands(params);
expect(result.shouldContinue).toBe(false);
expect(result.reply?.text).toContain("Page out of range");
expect(result.reply?.text).toContain("valid: 1-");
});
it("handles unknown providers", async () => {
const params = buildParams("/models not-a-provider", cfg);
const result = await handleCommands(params);

View File

@@ -143,23 +143,44 @@ export const handleModelsCommand: CommandHandler = async (params, allowTextComma
const models = [...(byProvider.get(provider) ?? new Set<string>())].sort();
const total = models.length;
if (total === 0) {
const lines: string[] = [
`Models (${provider}) — none`,
"",
"Browse: /models",
"Switch: /model <provider/model>",
];
return { reply: { text: lines.join("\n") }, shouldContinue: false };
}
const effectivePageSize = all ? total : pageSize;
const startIndex = (page - 1) * effectivePageSize;
const pageCount = effectivePageSize > 0 ? Math.ceil(total / effectivePageSize) : 1;
const safePage = all ? 1 : Math.max(1, Math.min(page, pageCount));
if (!all && page !== safePage) {
const lines: string[] = [
`Page out of range: ${page} (valid: 1-${pageCount})`,
"",
`Try: /models ${provider} ${safePage}`,
`All: /models ${provider} all`,
];
return { reply: { text: lines.join("\n") }, shouldContinue: false };
}
const startIndex = (safePage - 1) * effectivePageSize;
const endIndexExclusive = Math.min(total, startIndex + effectivePageSize);
const pageModels = models.slice(startIndex, endIndexExclusive);
const header = `Models (${provider}) — showing ${startIndex + 1}-${endIndexExclusive} of ${total}`;
const header = `Models (${provider}) — showing ${startIndex + 1}-${endIndexExclusive} of ${total} (page ${safePage}/${pageCount})`;
const lines: string[] = [header];
for (const id of pageModels) {
lines.push(`- ${provider}/${id}`);
}
const pageCount = effectivePageSize > 0 ? Math.ceil(total / effectivePageSize) : 1;
lines.push("", "Switch: /model <provider/model>");
if (!all && page < pageCount) {
lines.push(`More: /models ${provider} ${page + 1}`);
if (!all && safePage < pageCount) {
lines.push(`More: /models ${provider} ${safePage + 1}`);
}
if (!all) {
lines.push(`All: /models ${provider} all`);