fix: correct camera snap mime mapping
This commit is contained in:
@@ -76,6 +76,7 @@
|
|||||||
- macOS: log health refresh failures and recovery to make gateway issues easier to diagnose.
|
- macOS: log health refresh failures and recovery to make gateway issues easier to diagnose.
|
||||||
- macOS codesign: skip hardened runtime for ad-hoc signing and avoid empty options args (#70) — thanks @petter-b
|
- macOS codesign: skip hardened runtime for ad-hoc signing and avoid empty options args (#70) — thanks @petter-b
|
||||||
- macOS codesign: include camera entitlement so permission prompts work in the menu bar app.
|
- macOS codesign: include camera entitlement so permission prompts work in the menu bar app.
|
||||||
|
- Agent tools: map `camera.snap` JPEG payloads to `image/jpeg` to avoid MIME mismatch errors.
|
||||||
- macOS packaging: move rpath config into swift build for reliability (#69) — thanks @petter-b
|
- macOS packaging: move rpath config into swift build for reliability (#69) — thanks @petter-b
|
||||||
- macOS: prioritize main bundle for device resources to prevent crash (#73) — thanks @petter-b
|
- macOS: prioritize main bundle for device resources to prevent crash (#73) — thanks @petter-b
|
||||||
- macOS remote: route settings through gateway config and avoid local config reads in remote mode.
|
- macOS remote: route settings through gateway config and avoid local config reads in remote mode.
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ import { parseDurationMs } from "../cli/parse-duration.js";
|
|||||||
import { loadConfig } from "../config/config.js";
|
import { loadConfig } from "../config/config.js";
|
||||||
import { reactMessageDiscord } from "../discord/send.js";
|
import { reactMessageDiscord } from "../discord/send.js";
|
||||||
import { callGateway } from "../gateway/call.js";
|
import { callGateway } from "../gateway/call.js";
|
||||||
import { detectMime } from "../media/mime.js";
|
import { detectMime, imageMimeFromFormat } from "../media/mime.js";
|
||||||
import { sanitizeToolResultImages } from "./tool-images.js";
|
import { sanitizeToolResultImages } from "./tool-images.js";
|
||||||
|
|
||||||
// biome-ignore lint/suspicious/noExplicitAny: TypeBox schema type from pi-ai uses a different module instance.
|
// biome-ignore lint/suspicious/noExplicitAny: TypeBox schema type from pi-ai uses a different module instance.
|
||||||
@@ -875,7 +875,7 @@ function createCanvasTool(): AnyAgentTool {
|
|||||||
});
|
});
|
||||||
await writeBase64ToFile(filePath, payload.base64);
|
await writeBase64ToFile(filePath, payload.base64);
|
||||||
const mimeType =
|
const mimeType =
|
||||||
payload.format === "jpeg" ? "image/jpeg" : "image/png";
|
imageMimeFromFormat(payload.format) ?? "image/png";
|
||||||
return await imageResult({
|
return await imageResult({
|
||||||
label: "canvas:snapshot",
|
label: "canvas:snapshot",
|
||||||
path: filePath,
|
path: filePath,
|
||||||
@@ -1141,7 +1141,8 @@ function createNodesTool(): AnyAgentTool {
|
|||||||
content.push({
|
content.push({
|
||||||
type: "image",
|
type: "image",
|
||||||
data: payload.base64,
|
data: payload.base64,
|
||||||
mimeType: payload.format === "jpeg" ? "image/jpeg" : "image/png",
|
mimeType:
|
||||||
|
imageMimeFromFormat(payload.format) ?? "image/png",
|
||||||
});
|
});
|
||||||
details.push({
|
details.push({
|
||||||
facing,
|
facing,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import JSZip from "jszip";
|
import JSZip from "jszip";
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
import { detectMime } from "./mime.js";
|
import { detectMime, imageMimeFromFormat } from "./mime.js";
|
||||||
|
|
||||||
async function makeOoxmlZip(opts: {
|
async function makeOoxmlZip(opts: {
|
||||||
mainMime: string;
|
mainMime: string;
|
||||||
@@ -17,6 +17,15 @@ async function makeOoxmlZip(opts: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe("mime detection", () => {
|
describe("mime detection", () => {
|
||||||
|
it("maps common image formats to mime types", () => {
|
||||||
|
expect(imageMimeFromFormat("jpg")).toBe("image/jpeg");
|
||||||
|
expect(imageMimeFromFormat("jpeg")).toBe("image/jpeg");
|
||||||
|
expect(imageMimeFromFormat("png")).toBe("image/png");
|
||||||
|
expect(imageMimeFromFormat("webp")).toBe("image/webp");
|
||||||
|
expect(imageMimeFromFormat("gif")).toBe("image/gif");
|
||||||
|
expect(imageMimeFromFormat("unknown")).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
it("detects docx from buffer", async () => {
|
it("detects docx from buffer", async () => {
|
||||||
const buf = await makeOoxmlZip({
|
const buf = await makeOoxmlZip({
|
||||||
mainMime:
|
mainMime:
|
||||||
|
|||||||
@@ -107,6 +107,25 @@ export function extensionForMime(mime?: string | null): string | undefined {
|
|||||||
return EXT_BY_MIME[mime.toLowerCase()];
|
return EXT_BY_MIME[mime.toLowerCase()];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function imageMimeFromFormat(
|
||||||
|
format?: string | null,
|
||||||
|
): string | undefined {
|
||||||
|
if (!format) return undefined;
|
||||||
|
switch (format.toLowerCase()) {
|
||||||
|
case "jpg":
|
||||||
|
case "jpeg":
|
||||||
|
return "image/jpeg";
|
||||||
|
case "png":
|
||||||
|
return "image/png";
|
||||||
|
case "webp":
|
||||||
|
return "image/webp";
|
||||||
|
case "gif":
|
||||||
|
return "image/gif";
|
||||||
|
default:
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function kindFromMime(mime?: string | null): MediaKind {
|
export function kindFromMime(mime?: string | null): MediaKind {
|
||||||
return mediaKindFromMime(mime);
|
return mediaKindFromMime(mime);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user