Skip to content

Commit aadd57c

Browse files
fix(pdf): reject empty parsed page ranges (#97698)
1 parent e2dd5a0 commit aadd57c

3 files changed

Lines changed: 29 additions & 1 deletion

File tree

src/agents/tools/pdf-tool.helpers.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ describe("parsePageRange", () => {
6262
expect(parsePageRange("1-100", 5)).toEqual([1, 2, 3, 4, 5]);
6363
});
6464

65+
it("throws when no requested pages are within maxPages", () => {
66+
expect(() => parsePageRange("999", 20)).toThrow('No PDF pages matched requested range "999"');
67+
});
68+
6569
it("deduplicates and sorts", () => {
6670
expect(parsePageRange("5,3,1,3,5", 20)).toEqual([1, 3, 5]);
6771
});

src/agents/tools/pdf-tool.helpers.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,11 @@ export function parsePageRange(range: string, maxPages: number): number[] {
7474
}
7575
}
7676
}
77-
return Array.from(pages).toSorted((a, b) => a - b);
77+
const parsedPages = Array.from(pages).toSorted((a, b) => a - b);
78+
if (parsedPages.length === 0) {
79+
throw new Error(`No PDF pages matched requested range "${range}"`);
80+
}
81+
return parsedPages;
7882
}
7983

8084
/** Converts a provider assistant message into PDF text or throws a model-labelled failure. */

src/agents/tools/pdf-tool.test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,26 @@ describe("createPdfTool", () => {
548548
});
549549
});
550550

551+
it("rejects explicit page ranges that resolve to no pages before native PDF analysis", async () => {
552+
await withTempPdfAgentDir(async (agentDir) => {
553+
await stubPdfToolInfra(agentDir, { provider: "anthropic", input: ["text", "document"] });
554+
const nativeSpy = vi
555+
.spyOn(pdfNativeProviders, "anthropicAnalyzePdf")
556+
.mockResolvedValue("native summary");
557+
const cfg = withPdfModel(ANTHROPIC_PDF_MODEL);
558+
const tool = requirePdfTool((await loadCreatePdfTool())({ config: cfg, agentDir }));
559+
560+
await expect(
561+
tool.execute("t1", {
562+
prompt: "summarize",
563+
pdf: "/tmp/doc.pdf",
564+
pages: "999",
565+
}),
566+
).rejects.toThrow('No PDF pages matched requested range "999"');
567+
expect(nativeSpy).not.toHaveBeenCalled();
568+
});
569+
});
570+
551571
it("rejects password parameter for native PDF providers", async () => {
552572
await withTempPdfAgentDir(async (agentDir) => {
553573
await stubPdfToolInfra(agentDir, { provider: "anthropic", input: ["text", "document"] });

0 commit comments

Comments
 (0)