openclaw / src /media-understanding /attachments.normalize.test.ts
SaylorTwift's picture
SaylorTwift HF Staff
Add files using upload-large-folder tool
253e783 verified
Raw History Blame Contribute Delete
11.2 kB
// Attachment path normalization tests cover file URL host checks and Windows
// network path rejection.
import os from "node:os";
import path from "node:path";
import { pathToFileURL } from "node:url";
import { describe, expect, it } from "vitest";
import { withMockedPlatform } from "../test-utils/vitest-spies.js";
import {
normalizeAttachmentPath,
normalizeAttachments,
resolveAttachmentKind,
} from "./attachments.normalize.js";
import { selectAttachments } from "./attachments.select.js";
describe("normalizeAttachmentPath", () => {
it("allows localhost file URLs", () => {
const localPath = path.join(os.tmpdir(), "photo.png");
const fileUrl = pathToFileURL(localPath);
fileUrl.hostname = "localhost";
expect(normalizeAttachmentPath(fileUrl.href)).toBe(localPath);
});
it("recognizes file URL schemes case-insensitively", () => {
const localPath = path.join(os.tmpdir(), "photo with space.png");
const fileUrl = pathToFileURL(localPath).href.replace(/^file:/u, "FILE:");
expect(normalizeAttachmentPath(fileUrl)).toBe(localPath);
});
it("rejects remote-host file URLs", () => {
expect(normalizeAttachmentPath("file://attacker/share/photo.png")).toBeUndefined();
expect(normalizeAttachmentPath("FILE://attacker/share/photo.png")).toBeUndefined();
});
it("rejects Windows network paths", () => {
withMockedPlatform("win32", () => {
expect(normalizeAttachmentPath("\\\\attacker\\share\\photo.png")).toBeUndefined();
});
});
});
describe("normalizeAttachments", () => {
it("preserves original fact indexes when empty slots are not materializable", () => {
expect(
normalizeAttachments({
media: [
{},
{ path: "/tmp/voice.ogg", contentType: "audio/ogg" },
{ url: "https://example.test/photo.jpg", contentType: "image/jpeg" },
],
}).map((attachment) => attachment.index),
).toEqual([1, 2]);
});
it("normalizes ordered facts", () => {
expect(
normalizeAttachments({
media: [
{ path: " /tmp/voice.ogg ", contentType: " audio/ogg ", transcribed: true },
{ url: "https://example.test/photo.jpg", kind: "image" },
],
}),
).toEqual([
{
path: "/tmp/voice.ogg",
url: undefined,
mime: "audio/ogg",
kind: "audio",
index: 0,
alreadyTranscribed: true,
},
{
path: undefined,
url: "https://example.test/photo.jpg",
mime: undefined,
kind: "image",
index: 1,
alreadyTranscribed: false,
},
]);
});
it("uses staged fact paths at the attachment consumer", () => {
expect(
normalizeAttachments({
media: [
{
path: "/tmp/staged/voice.ogg",
url: "/tmp/staged/voice.ogg",
contentType: "audio/ogg",
workspaceDir: "/tmp/staged",
},
],
}),
).toEqual([
expect.objectContaining({
path: "/tmp/staged/voice.ogg",
url: "/tmp/staged/voice.ogg",
workspaceDir: "/tmp/staged",
}),
]);
});
it("preserves authoritative media kinds without inventing MIME metadata", () => {
expect(
normalizeAttachments({
media: [{ url: "https://cdn.example.test/download?token=fixture", kind: "image" }],
}),
).toEqual([
{
path: undefined,
url: "https://cdn.example.test/download?token=fixture",
mime: undefined,
kind: "image",
index: 0,
alreadyTranscribed: false,
},
]);
});
it("distinguishes an explicit document from generic binary MIME inference", () => {
const attachments = normalizeAttachments({
media: [
{ path: "/tmp/upload.avif", contentType: "application/octet-stream" },
{
path: "/tmp/report.png",
contentType: "application/octet-stream",
kind: "document",
},
],
});
expect(attachments.map(({ kind }) => kind)).toEqual([undefined, "document"]);
expect(attachments.map(resolveAttachmentKind)).toEqual(["image", "unknown"]);
});
it("omits optional attachment fields when canonical facts do not declare them", () => {
const [attachment] = normalizeAttachments({
media: [{ path: "/tmp/photo.png", contentType: "application/octet-stream" }],
});
expect(attachment).toEqual({
path: "/tmp/photo.png",
url: undefined,
mime: "application/octet-stream",
index: 0,
alreadyTranscribed: false,
});
});
it.each([
{ fileName: "photo.png", capability: "image", contentType: "application/octet-stream" },
{ fileName: "voice.ogg", capability: "audio", contentType: undefined },
{ fileName: "clip.mp4", capability: "video", contentType: "application/octet-stream" },
{ fileName: "scan.TIFF", capability: "image", contentType: "binary/octet-stream" },
] as const)(
"selects opaque-source $fileName for its $capability provider",
({ fileName, capability, contentType }) => {
const attachments = normalizeAttachments({
media: [
{
url: "https://cdn.example.test/download/opaque",
fileName,
contentType,
},
],
});
expect(attachments.map(resolveAttachmentKind)).toEqual([capability]);
expect(selectAttachments({ capability, attachments }).selected).toEqual(attachments);
},
);
it.each([
{
name: "filename-only SVG",
fact: { fileName: "diagram.svg", contentType: "application/octet-stream" },
},
{
name: "authoritative document kind",
fact: { fileName: "photo.png", kind: "document" as const },
},
{
name: "authoritative document MIME",
fact: { fileName: "photo.png", contentType: "application/pdf" },
},
])("does not select $name for image understanding", ({ fact }) => {
const attachments = normalizeAttachments({
media: [{ url: "https://cdn.example.test/download/opaque", ...fact }],
});
expect(selectAttachments({ capability: "image", attachments }).selected).toEqual([]);
});
it.each([
["audio", "ogg", undefined],
["audio", "ogg", "photo.png"],
["video", "mp4", undefined],
["video", "mp4", "photo.png"],
] as const)(
"selects the %s .%s URL with display filename %s",
(capability, extension, fileName) => {
const attachments = normalizeAttachments({
media: [
{
path: "/tmp/opaque",
url: `https://cdn.example.test/download/media.${extension}`,
fileName,
contentType: "application/octet-stream",
},
],
});
expect(selectAttachments({ capability, attachments }).selected).toEqual(attachments);
expect(selectAttachments({ capability: "image", attachments }).selected).toEqual([]);
},
);
});
describe("resolveAttachmentKind", () => {
it.each([
{ source: "/tmp/photo.avif", expected: "image" },
{ source: "/tmp/photo.HEIC", expected: "image" },
{ source: "/tmp/photo.heif", expected: "image" },
{ source: "/tmp/scan.tif", expected: "image" },
{ source: "/tmp/scan.TIFF", expected: "image" },
{ source: "/tmp/clip.flv", expected: "video" },
{ source: "/tmp/clip.m4v", expected: "video" },
{ source: "/tmp/clip.wmv", expected: "video" },
{ source: "/tmp/voice.aiff", expected: "audio" },
{ source: "https://cdn.example.test/photo%2EHEIC?download=1", expected: "image" },
] as const)(
"classifies $source as $expected from canonical media metadata",
({ source, expected }) => {
expect(resolveAttachmentKind({ path: source, index: 0 })).toBe(expected);
},
);
it.each(["image", "audio", "video"] as const)(
"preserves an authoritative %s kind for an extensionless URL",
(kind) => {
expect(
resolveAttachmentKind({ url: "https://cdn.example.test/download", kind, index: 0 }),
).toBe(kind);
},
);
it.each([
{ mime: undefined, expected: "image" },
{ mime: "image/webp", expected: "image" },
{ mime: "audio/ogg", expected: "image" },
] as const)(
"treats sticker facts as authoritative image media with MIME $mime",
({ mime, expected }) => {
expect(
resolveAttachmentKind({
url: "https://cdn.example.test/sticker",
kind: "sticker",
mime,
index: 0,
}),
).toBe(expected);
},
);
it("does not let the unknown category mask a concrete audio MIME", () => {
expect(
resolveAttachmentKind({
url: "https://cdn.example.test/download",
kind: "unknown",
mime: "audio/ogg",
index: 0,
}),
).toBe("audio");
});
it.each([
{ source: "/tmp/report.png", mime: undefined },
{ source: "/tmp/report.png", mime: "application/pdf" },
{ source: "/tmp/report.png", mime: "application/octet-stream" },
{ source: "/tmp/report.png", mime: "image/png" },
{ source: "/tmp/report.ogg", mime: "audio/ogg" },
{ source: "/tmp/report.mp4", mime: "video/mp4" },
{ source: "/tmp/report.tiff", mime: undefined },
])("keeps explicit documents authoritative for $source and MIME $mime", ({ source, mime }) => {
expect(resolveAttachmentKind({ path: source, kind: "document", mime, index: 0 })).toBe(
"unknown",
);
});
it.each([undefined, "application/octet-stream"] as const)(
"infers an unknown-kind image from its canonical filename with MIME %s",
(mime) => {
expect(
resolveAttachmentKind({ path: "/tmp/upload.png", kind: "unknown", mime, index: 0 }),
).toBe("image");
},
);
it.each(["application/pdf", "application/zip", "text/plain", "application/json"] as const)(
"never infers an image over authoritative non-image MIME %s",
(mime) => {
expect(
resolveAttachmentKind({ path: "/tmp/report.png", kind: "unknown", mime, index: 0 }),
).toBe("unknown");
expect(resolveAttachmentKind({ path: "/tmp/report.png", mime, index: 0 })).toBe("unknown");
},
);
it("prefers the authoritative kind over conflicting MIME and filename hints", () => {
expect(
resolveAttachmentKind({
path: "/tmp/video.mp4",
mime: "video/mp4",
kind: "image",
index: 0,
}),
).toBe("image");
});
it("preserves explicit MIME precedence over a conflicting filename", () => {
expect(resolveAttachmentKind({ path: "/tmp/video.mp4", mime: "image/heic", index: 0 })).toBe(
"image",
);
});
it("keeps filename-only SVG out of raster image understanding", () => {
expect(resolveAttachmentKind({ path: "/tmp/diagram.svg", index: 0 })).toBe("unknown");
});
it("preserves explicitly identified SVG images", () => {
expect(
resolveAttachmentKind({ path: "/tmp/diagram.svg", mime: "image/svg+xml", index: 0 }),
).toBe("image");
});
it("falls back to canonical filename metadata when the declared MIME is not media", () => {
expect(
resolveAttachmentKind({
path: "/tmp/photo.avif",
mime: "application/octet-stream",
index: 0,
}),
).toBe("image");
});
});