






















@@ -5,10 +5,12 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
55import type { OpenClawConfig } from "../../config/config.js";
66import * as pdfExtractModule from "../../media/pdf-extract.js";
77import * as webMedia from "../../media/web-media.js";
8+import type { AuthProfileStore } from "../auth-profiles/types.js";
89import * as modelAuth from "../model-auth.js";
910import * as modelsConfig from "../models-config.js";
1011import * as modelDiscovery from "../pi-model-discovery.js";
1112import * as pdfNativeProviders from "./pdf-native-providers.js";
13+import * as pdfModelConfigModule from "./pdf-tool.model-config.js";
1214import { resetPdfToolAuthEnv, withTempPdfAgentDir } from "./pdf-tool.test-support.js";
13151416const completeMock = vi.hoisted(() => vi.fn());
@@ -71,6 +73,12 @@ function withPdfModel(primary: string): OpenClawConfig {
7173} as OpenClawConfig;
7274}
737576+function withDefaultModel(primary: string): OpenClawConfig {
77+return {
78+agents: { defaults: { model: { primary } } },
79+} as OpenClawConfig;
80+}
81+7482async function stubPdfToolInfra(
7583agentDir: string,
7684params?: {
@@ -159,6 +167,77 @@ describe("createPdfTool", () => {
159167});
160168});
161169170+it("defers automatic model config resolution during registration (#76644)", async () => {
171+const resolveSpy = vi.spyOn(pdfModelConfigModule, "resolvePdfModelConfigForTool");
172+const cfg = withDefaultModel("openai/gpt-5.4");
173+const authProfileStore = {
174+version: 1,
175+profiles: {
176+"anthropic:default": {
177+type: "api_key",
178+provider: "anthropic",
179+key: "test-key",
180+},
181+},
182+} satisfies AuthProfileStore;
183+const createTool = await loadCreatePdfTool();
184+await withTempPdfAgentDir(async (agentDir) => {
185+expect(
186+createTool({
187+config: cfg,
188+ agentDir,
189+ authProfileStore,
190+deferAutoModelResolution: true,
191+})?.name,
192+).toBe("pdf");
193+expect(resolveSpy).not.toHaveBeenCalled();
194+});
195+resolveSpy.mockRestore();
196+});
197+198+it("keeps explicit model config resolution eager even when automatic resolution is deferred", async () => {
199+const resolveSpy = vi.spyOn(pdfModelConfigModule, "resolvePdfModelConfigForTool");
200+const createTool = await loadCreatePdfTool();
201+await withTempPdfAgentDir(async (agentDir) => {
202+expect(
203+createTool({
204+config: withPdfModel(ANTHROPIC_PDF_MODEL),
205+ agentDir,
206+deferAutoModelResolution: true,
207+})?.name,
208+).toBe("pdf");
209+expect(resolveSpy).toHaveBeenCalledTimes(1);
210+});
211+resolveSpy.mockRestore();
212+});
213+214+it("resolves deferred model config on execution before loading PDFs", async () => {
215+const resolveSpy = vi
216+.spyOn(pdfModelConfigModule, "resolvePdfModelConfigForTool")
217+.mockReturnValue(null);
218+const loadSpy = vi.spyOn(webMedia, "loadWebMediaRaw");
219+const createTool = await loadCreatePdfTool();
220+const cfg = withDefaultModel("openai/gpt-5.4");
221+await withTempPdfAgentDir(async (agentDir) => {
222+const tool = requirePdfTool(
223+createTool({
224+config: cfg,
225+ agentDir,
226+deferAutoModelResolution: true,
227+}),
228+);
229+await expect(
230+tool.execute("t1", {
231+prompt: "summarize",
232+pdf: "/tmp/doc.pdf",
233+}),
234+).rejects.toThrow("No PDF model configured.");
235+});
236+expect(resolveSpy).toHaveBeenCalledTimes(1);
237+expect(loadSpy).not.toHaveBeenCalled();
238+resolveSpy.mockRestore();
239+});
240+162241it("rejects when no pdf input provided", async () => {
163242await withConfiguredPdfTool(async (tool) => {
164243await expect(tool.execute("t1", { prompt: "test" })).rejects.toThrow("pdf required");
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。