@agimon-ai/po-author 0.0.0-alpha.71 → 0.0.0-alpha.73
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -958,6 +958,7 @@ const VIDEO_MIMES = {
|
|
|
958
958
|
const IMAGE_SAVE_MAX_BYTES = 33554432;
|
|
959
959
|
const PDF_MAX_BYTES = 33554432;
|
|
960
960
|
const VIDEO_MAX_BYTES = 134217728;
|
|
961
|
+
const READ_CHUNK_BYTES = 1048576;
|
|
961
962
|
const extensionOf = (path) => path.toLowerCase().split("/").at(-1)?.split(".").slice(1).at(-1) ?? "";
|
|
962
963
|
/** Reuse the native decoder's supported image paths for canvas-specific host layout. */
|
|
963
964
|
function authorNativeIsImage(path) {
|
|
@@ -1078,49 +1079,74 @@ async function loadAuthorFile(sessionId, path, signal) {
|
|
|
1078
1079
|
if (format !== void 0) return await loadStructuredFile(sessionId, path, format, signal);
|
|
1079
1080
|
const artifact = path.startsWith(AUTHOR_ARTIFACT_PREFIX);
|
|
1080
1081
|
const query = { path: artifact ? path.slice(9) : path };
|
|
1081
|
-
const
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1082
|
+
const load = async (headers) => {
|
|
1083
|
+
if (signal.aborted) throw new Error("Opening was cancelled.");
|
|
1084
|
+
const result = artifact ? await artifactFiles.session(sessionId).content({
|
|
1085
|
+
query,
|
|
1086
|
+
headers,
|
|
1087
|
+
signal
|
|
1088
|
+
}) : await sessionFiles.session(sessionId).file({
|
|
1089
|
+
query,
|
|
1090
|
+
headers,
|
|
1091
|
+
signal
|
|
1092
|
+
});
|
|
1093
|
+
const response = result.response;
|
|
1094
|
+
if (result.status === 412) throw new Error("This file changed. Reopen it.");
|
|
1095
|
+
const empty = result.status === 416 && response?.headers.get("content-range") === "bytes */0";
|
|
1096
|
+
if (!result.ok && !empty) throw new Error(result.error || "This file could not be read.");
|
|
1097
|
+
if (!response) throw new Error("This file could not be read.");
|
|
1098
|
+
return response;
|
|
1099
|
+
};
|
|
1100
|
+
const response = await load({ Range: `bytes=0-1048575` });
|
|
1091
1101
|
const extension = extensionOf(query.path);
|
|
1092
1102
|
const mediaMime = extension === "pdf" ? "application/pdf" : VIDEO_MIMES[extension];
|
|
1093
1103
|
const limit = extension === "pdf" ? PDF_MAX_BYTES : mediaMime ? VIDEO_MAX_BYTES : MAX_FILE_BYTES;
|
|
1094
1104
|
if (Number(response.headers.get("content-length") ?? 0) > limit) throw new Error("This file is too large to open here.");
|
|
1095
1105
|
const mimeType = (response.headers.get("content-type")?.split(";")[0]?.trim() ?? "").toLowerCase();
|
|
1096
1106
|
const sourceSha256 = response.headers.get("X-File-SHA256") ?? void 0;
|
|
1097
|
-
|
|
1098
|
-
|
|
1107
|
+
let bytes;
|
|
1108
|
+
if (response.status === 206) {
|
|
1109
|
+
const range = /^bytes 0-(\d+)\/(\d+)$/.exec(response.headers.get("content-range") ?? "");
|
|
1110
|
+
const size = range ? Number(range[2]) : NaN;
|
|
1111
|
+
const version = response.headers.get("etag");
|
|
1112
|
+
if (!Number.isSafeInteger(size) || size < 1 || !version || version.startsWith("W/")) throw new Error("This file returned an invalid range or version.");
|
|
1113
|
+
if (size > limit) throw new Error("This file is too large to open here.");
|
|
1114
|
+
if (Number(range[1]) !== Math.min(READ_CHUNK_BYTES, size) - 1) throw new Error("This file returned an invalid range.");
|
|
1115
|
+
bytes = new Uint8Array(size);
|
|
1116
|
+
let part = response;
|
|
1117
|
+
for (let offset = 0; offset < size; offset += READ_CHUNK_BYTES) {
|
|
1118
|
+
const end = Math.min(offset + READ_CHUNK_BYTES, size) - 1;
|
|
1119
|
+
if (offset > 0) part = await load({
|
|
1120
|
+
Range: `bytes=${offset}-${end}`,
|
|
1121
|
+
"If-Match": version
|
|
1122
|
+
});
|
|
1123
|
+
if (part.status !== 206 || part.headers.get("etag") !== version || part.headers.get("content-range") !== `bytes ${offset}-${end}/${size}`) throw new Error("This file changed or returned an invalid range.");
|
|
1124
|
+
const chunk = new Uint8Array(await part.arrayBuffer());
|
|
1125
|
+
if (signal.aborted) throw new Error("Opening was cancelled.");
|
|
1126
|
+
if (chunk.byteLength !== end - offset + 1) throw new Error("This file response is incomplete.");
|
|
1127
|
+
bytes.set(chunk, offset);
|
|
1128
|
+
}
|
|
1129
|
+
} else {
|
|
1130
|
+
bytes = new Uint8Array(await response.arrayBuffer());
|
|
1099
1131
|
if (signal.aborted) throw new Error("Opening was cancelled.");
|
|
1132
|
+
if (response.status === 416 && bytes.byteLength !== 0) throw new Error("This file response is incomplete.");
|
|
1100
1133
|
if (bytes.byteLength > limit) throw new Error("This file is too large to open here.");
|
|
1101
|
-
return {
|
|
1102
|
-
kind: extension === "pdf" ? "pdf" : "video",
|
|
1103
|
-
bytes,
|
|
1104
|
-
mimeType: mediaMime,
|
|
1105
|
-
...sourceSha256 === void 0 ? {} : { sourceSha256 }
|
|
1106
|
-
};
|
|
1107
|
-
}
|
|
1108
|
-
if (IMAGE_TYPES.has(mimeType)) {
|
|
1109
|
-
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
1110
|
-
if (signal.aborted) throw new Error("Opening was cancelled.");
|
|
1111
|
-
if (bytes.byteLength > MAX_FILE_BYTES) throw new Error("This file is too large to open here.");
|
|
1112
|
-
return {
|
|
1113
|
-
kind: "image",
|
|
1114
|
-
data: encodeBase64(bytes),
|
|
1115
|
-
mimeType,
|
|
1116
|
-
...sourceSha256 === void 0 ? {} : { sourceSha256 }
|
|
1117
|
-
};
|
|
1118
1134
|
}
|
|
1135
|
+
if (mediaMime !== void 0) return {
|
|
1136
|
+
kind: extension === "pdf" ? "pdf" : "video",
|
|
1137
|
+
bytes,
|
|
1138
|
+
mimeType: mediaMime,
|
|
1139
|
+
...sourceSha256 === void 0 ? {} : { sourceSha256 }
|
|
1140
|
+
};
|
|
1141
|
+
if (IMAGE_TYPES.has(mimeType)) return {
|
|
1142
|
+
kind: "image",
|
|
1143
|
+
data: encodeBase64(bytes),
|
|
1144
|
+
mimeType,
|
|
1145
|
+
...sourceSha256 === void 0 ? {} : { sourceSha256 }
|
|
1146
|
+
};
|
|
1119
1147
|
if (mimeType.startsWith("text/") || mimeType === "application/json" || TEXT_EXTENSIONS.has(extension)) {
|
|
1120
|
-
const text =
|
|
1121
|
-
if (signal.aborted) throw new Error("Opening was cancelled.");
|
|
1148
|
+
const text = new TextDecoder().decode(bytes);
|
|
1122
1149
|
if (new Blob([text]).size > MAX_FILE_BYTES) throw new Error("This file is too large to open here.");
|
|
1123
|
-
const sourceSha256 = response.headers.get("X-File-SHA256") ?? void 0;
|
|
1124
1150
|
return {
|
|
1125
1151
|
kind: "text",
|
|
1126
1152
|
text,
|