























@@ -1,17 +1,10 @@
1-import { execFile } from "node:child_process";
21import fs from "node:fs/promises";
32import path from "node:path";
4-import { promisify } from "node:util";
53import { isInboundPathAllowed } from "openclaw/plugin-sdk/media-runtime";
64import { saveMediaBuffer } from "openclaw/plugin-sdk/media-store";
7-import { buildRandomTempFilePath } from "openclaw/plugin-sdk/temp-path";
5+import { loadWebMedia } from "openclaw/plugin-sdk/web-media";
86import type { IMessageAttachment } from "./types.js";
9710-const execFileAsync = promisify(execFile);
11-12-const HEIC_CONVERSION_TIMEOUT_MS = 15_000;
13-const HEIC_CONVERSION_MAX_BUFFER_BYTES = 64 * 1024;
14-158export type StagedIMessageAttachment = {
169path: string;
1710contentType?: string;
@@ -73,43 +66,6 @@ async function resolveAllowedCanonicalAttachmentPath(params: {
7366return canonicalPath;
7467}
756876-async function convertHeicToJpegWithSips(sourcePath: string, maxBytes: number): Promise<Buffer> {
77-const tempPath = buildRandomTempFilePath({
78-prefix: "openclaw-imessage",
79-extension: "jpg",
80-});
81-try {
82-await execFileAsync(
83-"sips",
84-[
85-"-s",
86-"format",
87-"jpeg",
88-"-s",
89-"formatOptions",
90-"90",
91-"-Z",
92-"4096",
93-sourcePath,
94-"--out",
95-tempPath,
96-],
97-{
98-timeout: HEIC_CONVERSION_TIMEOUT_MS,
99-maxBuffer: HEIC_CONVERSION_MAX_BUFFER_BYTES,
100-killSignal: "SIGKILL",
101-},
102-);
103-const stat = await fs.stat(tempPath);
104-if (stat.size > maxBytes) {
105-throw new Error(`converted media exceeds ${Math.round(maxBytes / (1024 * 1024))}MB limit`);
106-}
107-return await fs.readFile(tempPath);
108-} finally {
109-await fs.rm(tempPath, { force: true }).catch(() => {});
110-}
111-}
112-11369async function readAttachmentBuffer(params: {
11470attachmentPath: string;
11571mimeType?: string | null;
@@ -142,11 +98,20 @@ async function readAttachmentBuffer(params: {
1429814399if (isHeicAttachment(params.attachmentPath, params.mimeType)) {
144100try {
145-const convert = params.deps.convertHeicToJpeg ?? convertHeicToJpegWithSips;
101+const convert = params.deps.convertHeicToJpeg;
102+const converted = convert
103+ ? {
104+buffer: await convert(canonicalPath, params.maxBytes),
105+fileName: jpegFilenameForAttachment(params.attachmentPath),
106+}
107+ : await loadWebMedia(canonicalPath, {
108+maxBytes: params.maxBytes,
109+localRoots: [path.dirname(canonicalPath)],
110+});
146111return {
147-buffer: await convert(canonicalPath, params.maxBytes),
112+buffer: converted.buffer,
148113contentType: "image/jpeg",
149-originalFilename: jpegFilenameForAttachment(params.attachmentPath),
114+originalFilename: converted.fileName ?? jpegFilenameForAttachment(params.attachmentPath),
150115};
151116} catch (err) {
152117params.deps.logVerbose?.(
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。