




















@@ -51,6 +51,11 @@ type ArtifactCollectionOptions = {
5151downloadArtifactId?: string;
5252};
535354+type ArtifactBase64Payload = {
55+data?: string;
56+sizeBytes: number;
57+};
58+5459type ResolvedArtifactSession = {
5560sessionKey: string;
5661agentId?: string;
@@ -155,40 +160,85 @@ function base64FromDataUrl(value: string): string | undefined {
155160if (!metadata.includes(";base64")) {
156161return undefined;
157162}
158-return trimmed.slice(commaIndex + 1).replace(/\s+/g, "");
163+return trimmed.slice(commaIndex + 1);
159164}
160165161166function isBase64Whitespace(value: string): boolean {
162167return value === " " || value === "\n" || value === "\r" || value === "\t";
163168}
164169165-function estimateBase64Size(value: string | undefined): number | undefined {
170+function isArtifactBase64DataChar(value: string): boolean {
171+const code = value.charCodeAt(0);
172+return (
173+(code >= 0x41 && code <= 0x5a) ||
174+(code >= 0x61 && code <= 0x7a) ||
175+(code >= 0x30 && code <= 0x39) ||
176+value === "+" ||
177+value === "/" ||
178+value === "-" ||
179+value === "_"
180+);
181+}
182+183+function normalizeArtifactBase64Char(value: string): string {
184+if (value === "-") {
185+return "+";
186+}
187+if (value === "_") {
188+return "/";
189+}
190+return value;
191+}
192+193+function readArtifactBase64Payload(
194+value: string | undefined,
195+opts: { includeData: boolean },
196+): ArtifactBase64Payload | undefined {
166197if (!value) {
167198return undefined;
168199}
169200let encodedLength = 0;
170201let padding = 0;
202+let sawPadding = false;
203+let data = opts.includeData ? "" : undefined;
171204for (const char of value) {
172-if (!char || isBase64Whitespace(char)) {
173-continue;
174-}
175-encodedLength += 1;
176-}
177-for (let index = value.length - 1; index >= 0 && padding < 2; index -= 1) {
178-const char = value[index];
179-if (!char || isBase64Whitespace(char)) {
205+if (isBase64Whitespace(char)) {
180206continue;
181207}
182208if (char === "=") {
183209padding += 1;
210+if (padding > 2) {
211+return undefined;
212+}
213+sawPadding = true;
214+encodedLength += 1;
215+if (data !== undefined) {
216+data += char;
217+}
184218continue;
185219}
186-break;
220+if (sawPadding || !isArtifactBase64DataChar(char)) {
221+return undefined;
222+}
223+encodedLength += 1;
224+if (data !== undefined) {
225+data += normalizeArtifactBase64Char(char);
226+}
187227}
188228if (encodedLength === 0) {
189229return undefined;
190230}
191-return Math.max(0, Math.floor((encodedLength * 3) / 4) - padding);
231+const remainder = encodedLength % 4;
232+if ((padding > 0 && remainder !== 0) || remainder === 1) {
233+return undefined;
234+}
235+if (data !== undefined && padding === 0 && remainder > 0) {
236+data += "=".repeat(4 - remainder);
237+}
238+return {
239+ ...(data !== undefined ? { data } : {}),
240+sizeBytes: Math.max(0, Math.floor((encodedLength * 3) / 4) - padding),
241+};
192242}
193243194244function mediaUrlValue(value: unknown): string | undefined {
@@ -274,10 +324,14 @@ function resolveBlockDownload(
274324const dataUrl = [url, sourceUrl, imageUrl, audioUrl, data, content, sourceData].find(
275325(value) => typeof value === "string" && /^data:/i.test(value),
276326);
277-const base64FromDetectedDataUrl = dataUrl ? base64FromDataUrl(dataUrl) : undefined;
278-const directBase64 = [data, sourceData, content].find(
279-(value) => typeof value === "string" && !/^data:/i.test(value),
327+const base64FromDetectedDataUrl = readArtifactBase64Payload(
328+ dataUrl ? base64FromDataUrl(dataUrl) : undefined,
329+opts,
280330);
331+const directBase64 = [data, sourceData, content]
332+.filter((value): value is string => typeof value === "string" && !/^data:/i.test(value))
333+.map((value) => readArtifactBase64Payload(value, opts))
334+.find((value): value is ArtifactBase64Payload => value !== undefined);
281335const base64 = base64FromDetectedDataUrl ?? directBase64;
282336const remoteUrl = [url, sourceUrl, imageUrl, audioUrl].find(
283337(value) => typeof value === "string" && isSafeDownloadUrl(value),
@@ -292,9 +346,14 @@ function resolveBlockDownload(
292346const sizeBytes =
293347typeof explicitSize === "number" && Number.isFinite(explicitSize) && explicitSize >= 0
294348 ? Math.floor(explicitSize)
295- : estimateBase64Size(base64);
349+ : base64?.sizeBytes;
296350if (base64) {
297-return { mode: "bytes", ...(opts.includeData ? { data: base64 } : {}), mimeType, sizeBytes };
351+return {
352+mode: "bytes",
353+ ...(base64.data ? { data: base64.data } : {}),
354+ mimeType,
355+ sizeBytes,
356+};
298357}
299358if (remoteUrl) {
300359return { mode: "url", url: remoteUrl, mimeType, sizeBytes };
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。