@@ -4,21 +4,19 @@ import { randomUUID } from "node:crypto";
|
4 | 4 | import fs from "node:fs/promises"; |
5 | 5 | import type { IncomingMessage, ServerResponse } from "node:http"; |
6 | 6 | import path from "node:path"; |
7 | | -import { isPassThroughRemoteMediaSource } from "@openclaw/media-core/media-source-url"; |
8 | 7 | import { resolveDefaultAgentId } from "../agents/agent-scope-config.js"; |
9 | 8 | import { getRuntimeConfig } from "../config/config.js"; |
10 | 9 | import { resolveStateDir } from "../config/paths.js"; |
11 | 10 | import { readLocalFileSafely } from "../infra/fs-safe.js"; |
12 | 11 | import { tryReadJson, writeJson } from "../infra/json-files.js"; |
13 | | -import { safeFileURLToPath } from "../infra/local-file-access.js"; |
14 | 12 | import { assertLocalMediaAllowed } from "../media/local-media-access.js"; |
| 13 | +import { resolveLocalMediaPath } from "../media/local-media-path.js"; |
15 | 14 | import { |
16 | 15 | createImageProcessor, |
17 | 16 | getImageMetadata, |
18 | 17 | readImageProbeFromHeader, |
19 | 18 | } from "../media/media-services.js"; |
20 | 19 | import { MEDIA_MAX_BYTES, saveMediaBuffer, saveMediaSource } from "../media/store.js"; |
21 | | -import { resolveUserPath } from "../utils.js"; |
22 | 20 | import type { AuthRateLimiter } from "./auth-rate-limit.js"; |
23 | 21 | import type { ResolvedGatewayAuth } from "./auth.js"; |
24 | 22 | import { sendJson, sendMethodNotAllowed, sendMissingScopeForbidden } from "./http-common.js"; |
@@ -35,8 +33,6 @@ const OUTGOING_IMAGE_ROUTE_PREFIX = "/api/chat/media/outgoing";
|
35 | 33 | const DEFAULT_TRANSIENT_OUTGOING_IMAGE_TTL_MS = 15 * 60 * 1000; |
36 | 34 | const MANAGED_OUTGOING_ATTACHMENT_ID_RE = |
37 | 35 | /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; |
38 | | -const DATA_URL_RE = /^data:/i; |
39 | | -const WINDOWS_DRIVE_RE = /^[A-Za-z]:[\\/]/; |
40 | 36 | |
41 | 37 | export const DEFAULT_MANAGED_IMAGE_ATTACHMENT_LIMITS = { |
42 | 38 | maxBytes: 12 * 1024 * 1024, |
@@ -274,27 +270,6 @@ function deriveAltText(source: string, index: number) {
|
274 | 270 | return localName || fallback; |
275 | 271 | } |
276 | 272 | |
277 | | -function resolveLocalMediaPath(source: string): string | undefined { |
278 | | -const trimmed = source.trim(); |
279 | | -if (!trimmed || isPassThroughRemoteMediaSource(trimmed) || DATA_URL_RE.test(trimmed)) { |
280 | | -return undefined; |
281 | | -} |
282 | | -if (trimmed.startsWith("file://")) { |
283 | | -try { |
284 | | -return safeFileURLToPath(trimmed); |
285 | | -} catch { |
286 | | -return undefined; |
287 | | -} |
288 | | -} |
289 | | -if (trimmed.startsWith("~")) { |
290 | | -return resolveUserPath(trimmed); |
291 | | -} |
292 | | -if (path.isAbsolute(trimmed) || WINDOWS_DRIVE_RE.test(trimmed)) { |
293 | | -return path.resolve(trimmed); |
294 | | -} |
295 | | -return undefined; |
296 | | -} |
297 | | - |
298 | 273 | function parseImageDataUrl( |
299 | 274 | source: string, |
300 | 275 | alt: string, |
|