Files
openclaw/src/media/parse.ts

51 lines
1.5 KiB
TypeScript

// Shared helpers for parsing MEDIA tokens from command/stdout text.
// Allow optional wrapping backticks and punctuation after the token; capture the core token.
export const MEDIA_TOKEN_RE = /\bMEDIA:\s*`?([^\s`]+)`?/i;
export function normalizeMediaSource(src: string) {
return src.startsWith("file://") ? src.replace("file://", "") : src;
}
function cleanCandidate(raw: string) {
return raw.replace(/^[`"'[{(]+/, "").replace(/[`"'\\})\],]+$/, "");
}
function isValidMedia(candidate: string) {
if (!candidate) return false;
if (candidate.length > 1024) return false;
if (/\s/.test(candidate)) return false;
return /^https?:\/\//i.test(candidate) || candidate.startsWith("/") || candidate.startsWith("./");
}
export function splitMediaFromOutput(raw: string): {
text: string;
mediaUrl?: string;
} {
const trimmedRaw = raw.trim();
const match = MEDIA_TOKEN_RE.exec(trimmedRaw);
if (!match?.[1]) return { text: trimmedRaw };
const candidate = normalizeMediaSource(cleanCandidate(match[1]));
const mediaUrl = isValidMedia(candidate) ? candidate : undefined;
const cleanedText =
mediaUrl
? trimmedRaw
.replace(match[0], "")
.replace(/[ \t]+\n/g, "\n")
.replace(/[ \t]{2,}/g, " ")
.replace(/\n{2,}/g, "\n")
.trim()
: trimmedRaw
.split("\n")
.filter((line) => !MEDIA_TOKEN_RE.test(line))
.join("\n")
.replace(/[ \t]+\n/g, "\n")
.replace(/[ \t]{2,}/g, " ")
.replace(/\n{2,}/g, "\n")
.trim();
return mediaUrl ? { text: cleanedText, mediaUrl } : { text: cleanedText };
}