Files
9router/open-sse/translator/concerns/image.js
T
decoluaandCursor d3f61aac2f refactor(open-sse): translator DRY + schema enums, bug fixes, dead code cleanup
- Bug B1-B7: media UI m.kind||m.type, serviceKinds, gemini mediaPriority, schema kind, models/info lookup by kind
- Dead code D1-D6: safeParseJSON, drop PROVIDER_ENDPOINTS, orphan fetcher, GITHUB_CONFIG derive, getProviderConfig internal, legacy kiro file
- Translator concerns: toOpenAIUsage, toOpenAIFinish (gemini/kiro/ollama + fix kiro tool finish), thinking effort maps
- Reorg helpers/ → concerns/ (logic) + formats/ (per-format) + schema/ (pure enums: roles/blocks/finishReasons/defaults)
- Wire ~280 hardcoded role/block/finish/default literals to schema enums across 20+ files
- collapseTextParts + extractTextContent dedup
- Normalize translator fn names to openaiToXRequest / xToOpenAIResponse
- Golden tests lock behavior; 0 regression (byte-for-byte providers/alias, 26=26 known fails)

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 18:49:38 +07:00

49 lines
1.7 KiB
JavaScript

// Build a base64 data URI from mime + base64 payload
export function encodeDataUri(mimeType, base64) {
return `data:${mimeType};base64,${base64}`;
}
// Parse a base64 data URI → { mimeType, base64 }, or null if not a data URI.
// [\s\S] tolerates newlines inside the base64 payload.
const DATA_URI_RE = /^data:([^;]+);base64,([\s\S]+)$/;
export function parseDataUri(url) {
if (typeof url !== "string") return null;
const m = url.match(DATA_URI_RE);
return m ? { mimeType: m[1], base64: m[2] } : null;
}
/**
* Fetch a remote image URL and return it as a base64 data URI.
* Used when upstream providers (Codex, etc.) require inline base64 images
* instead of remote URLs they cannot fetch.
* Returns null if fetch fails.
*
* @param {string} imageUrl - HTTP(S) URL of the image
* @param {object} options - { signal, timeoutMs }
* @returns {Promise<{url: string, mimeType: string}|null>}
*/
export async function fetchImageAsBase64(imageUrl, options = {}) {
const { signal, timeoutMs = 10000 } = options;
if (!imageUrl || (!imageUrl.startsWith("http://") && !imageUrl.startsWith("https://"))) {
return null;
}
const controller = new AbortController();
const timeout = signal ? null : setTimeout(() => controller.abort(), timeoutMs);
const fetchSignal = signal || controller.signal;
try {
const response = await fetch(imageUrl, { signal: fetchSignal });
if (!response.ok) return null;
const mimeType = response.headers.get("Content-Type") || "image/jpeg";
const arrayBuffer = await response.arrayBuffer();
const base64 = Buffer.from(arrayBuffer).toString("base64");
return { url: `data:${mimeType};base64,${base64}`, mimeType };
} catch {
return null;
} finally {
if (timeout) clearTimeout(timeout);
}
}