docs: document image and pdf tool tests

This commit is contained in:
Peter Steinberger
2026-06-04 16:38:27 -04:00
parent d5ce1edf7e
commit ea9f791a68
7 changed files with 29 additions and 0 deletions
@@ -1,3 +1,5 @@
// Regression tests for custom image providers whose credentials live in
// models.json rather than environment variables or auth profiles.
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
@@ -147,6 +149,8 @@ describe("image custom provider auth regression", () => {
});
it("executes deferred image tool discovery with config-backed auth and runtime key resolution", async () => {
// This covers the production deferred-discovery path: registration can
// avoid auth work, but execution still resolves the config-backed key.
await withEmptyAgentDir(async (agentDir) => {
const cfg = createUserReportedConfig();
const auth = await getApiKeyForModel({
@@ -1,3 +1,4 @@
// Live Ollama image tool smoke test for providerless local vision-model config.
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
@@ -12,6 +13,8 @@ const OLLAMA_BASE_URL =
const OLLAMA_IMAGE_MODEL = process.env.OPENCLAW_LIVE_OLLAMA_IMAGE_MODEL?.trim() || "qwen2.5vl:7b";
function resolveLiveNumCtx(): number {
// Ollama vision models can fail with tiny context windows; clamp live smoke
// config to a usable minimum while still letting operators override it.
const parsed = Number.parseInt(process.env.OPENCLAW_LIVE_OLLAMA_IMAGE_NUM_CTX ?? "2048", 10);
return Number.isFinite(parsed) ? Math.max(512, parsed) : 2048;
}
@@ -1,3 +1,5 @@
// Live image provider tests verify real provider calls downscale large local
// images before sending them to OpenAI or Anthropic.
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
@@ -80,6 +82,8 @@ function createLargeCenterRedPng(size: number): Buffer {
}
function readJpegDimensions(buffer: Buffer): { width: number; height: number } {
// The provider hook receives JPEG bytes after optimization; parsing SOF
// markers keeps the downscale proof independent from image libraries.
let offset = 2;
while (offset + 9 < buffer.length) {
if (buffer[offset] !== 0xff) {
+6
View File
@@ -1,3 +1,5 @@
// Image tool tests cover model routing, provider auth, path safety, inbound
// media refs, data URLs, response validation, and compression policy.
import fsSync from "node:fs";
import fs from "node:fs/promises";
import os from "node:os";
@@ -23,6 +25,8 @@ import { testing, createImageTool, resolveImageModelConfigForTool } from "./imag
import { resolveMediaToolInboundRoots } from "./media-tool-shared.js";
function jsonRoundTrip<T>(value: T): T {
// Anthropic rejects union-heavy schemas, so schema snapshots must survive the
// same JSON serialization path used for model-facing tool definitions.
const serialized = JSON.stringify(value);
return JSON.parse(serialized) as T;
}
@@ -305,6 +309,8 @@ function createLargeColorBlockPng(size: number): Buffer {
}
function readJpegDimensions(buffer: Buffer): { width: number; height: number } {
// The tests inspect JPEG SOF markers directly so resize assertions do not
// depend on an external decoder.
let offset = 2;
while (offset + 9 < buffer.length) {
if (buffer[offset] !== 0xff) {
@@ -1,3 +1,5 @@
// Model catalog document support tests keep PDF routing tied to declared input
// capabilities.
import { describe, expect, it } from "vitest";
import { modelSupportsDocument } from "../model-catalog.js";
@@ -1,3 +1,5 @@
// Shared PDF tool test helpers provide isolated agent dirs and scrub provider
// auth variables for deterministic model-resolution tests.
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
+8
View File
@@ -1,3 +1,5 @@
// PDF tool tests cover model discovery, input validation, managed inbound refs,
// native document providers, extraction fallback, and model-facing schema.
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
@@ -116,6 +118,8 @@ async function stubPdfToolInfra(
modelFound?: boolean;
},
) {
// Keep PDF tool tests focused on orchestration; provider discovery, auth, and
// remote media loading are replaced with narrow spies at the module boundary.
const loadSpy = vi.spyOn(webMedia, "loadWebMediaRaw");
if (params?.mockLoad !== false) {
loadSpy.mockResolvedValue(FAKE_PDF_MEDIA as never);
@@ -156,6 +160,8 @@ async function stubPdfToolInfra(
async function withManagedInboundPdf(
run: (params: { stateDir: string; mediaId: string; mediaPath: string }) => Promise<void>,
) {
// Managed inbound PDFs live under state and may be addressed by claim-check
// IDs or absolute paths even when workspace-only policy is active.
const stateDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-pdf-managed-inbound-"));
const inboundDir = path.join(stateDir, "media", "inbound");
const mediaId = "claim-check-test.pdf";
@@ -483,6 +489,8 @@ describe("createPdfTool", () => {
});
it("uses native PDF path without eager extraction", async () => {
// Document-capable providers receive the PDF bytes directly; extraction is
// reserved for text-only model paths.
await withTempPdfAgentDir(async (agentDir) => {
const workspaceDir = path.join(agentDir, "workspace");
await stubPdfToolInfra(agentDir, { provider: "anthropic", input: ["text", "document"] });