@umituz/web-ai 1.0.2 → 1.0.3
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.
- package/dist/{text-generation.service-CcYQM6Ch.d.ts → cancellation-error-CKcZRhFg.d.ts} +64 -1
- package/dist/{text-generation.service-BQO3Tvz2.d.cts → cancellation-error-DwHrDKBz.d.cts} +64 -1
- package/dist/content/index.cjs +798 -27
- package/dist/content/index.cjs.map +1 -1
- package/dist/content/index.js +798 -27
- package/dist/content/index.js.map +1 -1
- package/dist/hooks/index.cjs +922 -31
- package/dist/hooks/index.cjs.map +1 -1
- package/dist/hooks/index.d.cts +38 -2
- package/dist/hooks/index.d.ts +38 -2
- package/dist/hooks/index.js +919 -32
- package/dist/hooks/index.js.map +1 -1
- package/dist/index.cjs +809 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +800 -28
- package/dist/index.js.map +1 -1
- package/dist/providers/index.cjs +809 -27
- package/dist/providers/index.cjs.map +1 -1
- package/dist/providers/index.d.cts +43 -3
- package/dist/providers/index.d.ts +43 -3
- package/dist/providers/index.js +800 -28
- package/dist/providers/index.js.map +1 -1
- package/package.json +6 -1
package/dist/index.cjs
CHANGED
|
@@ -2917,39 +2917,811 @@ function createFalProvider(config) {
|
|
|
2917
2917
|
return new FalProvider(config);
|
|
2918
2918
|
}
|
|
2919
2919
|
|
|
2920
|
-
// src/providers/pruna/
|
|
2921
|
-
var
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2920
|
+
// src/providers/pruna/client/core/constants/limits.ts
|
|
2921
|
+
var DEFAULT_ASPECT_RATIO = "16:9";
|
|
2922
|
+
var P_VIDEO_DEFAULTS = {
|
|
2923
|
+
duration: 5,
|
|
2924
|
+
resolution: "720p",
|
|
2925
|
+
fps: 24,
|
|
2926
|
+
draft: false,
|
|
2927
|
+
promptUpsampling: true
|
|
2928
|
+
};
|
|
2929
|
+
var POLL_DEFAULTS = {
|
|
2930
|
+
intervalMs: 3e3,
|
|
2931
|
+
maxAttempts: 120,
|
|
2932
|
+
maxIntervalMs: 1e4,
|
|
2933
|
+
backoffBase: 1.5,
|
|
2934
|
+
jitterPercent: 0.1
|
|
2935
|
+
};
|
|
2936
|
+
var DEFAULT_DEDUPLICATOR_TTL_MS = 3e4;
|
|
2937
|
+
var DEDUPLICATOR_CLEANUP_GRACE_MS = 100;
|
|
2938
|
+
|
|
2939
|
+
// src/providers/pruna/client/core/constants/network.ts
|
|
2940
|
+
var HTTPS_PREFIX = "https://";
|
|
2941
|
+
var HTTP_PREFIX = "http://";
|
|
2942
|
+
var BASE64_MARKER = "base64,";
|
|
2943
|
+
var PRUNA_BASE_URL = "https://api.pruna.ai";
|
|
2944
|
+
var PRUNA_PREDICTIONS_URL = `${PRUNA_BASE_URL}/v1/predictions`;
|
|
2945
|
+
var PRUNA_FILES_URL = `${PRUNA_BASE_URL}/v1/files`;
|
|
2946
|
+
var AUTH_FAILURE_STATUSES = [401, 403];
|
|
2947
|
+
var MIN_API_KEY_LENGTH = 1;
|
|
2948
|
+
var MAX_API_KEY_LENGTH = 256;
|
|
2949
|
+
|
|
2950
|
+
// src/providers/pruna/client/core/constants/mime-types.ts
|
|
2951
|
+
var MIME_PNG = "image/png";
|
|
2952
|
+
var MIME_JPEG = "image/jpeg";
|
|
2953
|
+
var MIME_WEBP = "image/webp";
|
|
2954
|
+
var DEFAULT_IMAGE_MIME = MIME_PNG;
|
|
2955
|
+
var MIME_FILE_EXTENSION = {
|
|
2956
|
+
[MIME_PNG]: "png",
|
|
2957
|
+
[MIME_JPEG]: "jpg",
|
|
2958
|
+
[MIME_WEBP]: "webp"
|
|
2959
|
+
};
|
|
2960
|
+
var IMAGE_SIGNATURES = {
|
|
2961
|
+
PNG: [137, 80],
|
|
2962
|
+
JPEG: [255, 216],
|
|
2963
|
+
WEBP_RIFF: [82, 73]
|
|
2964
|
+
};
|
|
2965
|
+
|
|
2966
|
+
// src/providers/pruna/client/core/errors/cancellation-error.ts
|
|
2967
|
+
var CANCELLATION_MESSAGE = "Request cancelled by user";
|
|
2968
|
+
var CancellationError = class extends Error {
|
|
2969
|
+
constructor(message = CANCELLATION_MESSAGE) {
|
|
2970
|
+
super(message);
|
|
2971
|
+
this.name = "CancellationError";
|
|
2926
2972
|
}
|
|
2927
|
-
|
|
2973
|
+
};
|
|
2974
|
+
|
|
2975
|
+
// src/providers/pruna/client/core/errors/authentication-error.ts
|
|
2976
|
+
var AUTHENTICATION_MESSAGE = "Authentication failed. Please check your API key.";
|
|
2977
|
+
var AuthenticationError = class extends Error {
|
|
2978
|
+
constructor(message = AUTHENTICATION_MESSAGE) {
|
|
2979
|
+
super(message);
|
|
2980
|
+
this.name = "AuthenticationError";
|
|
2981
|
+
}
|
|
2982
|
+
};
|
|
2983
|
+
|
|
2984
|
+
// src/providers/pruna/client/core/errors/timeout-error.ts
|
|
2985
|
+
var TIMEOUT_MESSAGE = "Generation timed out. Maximum polling attempts reached.";
|
|
2986
|
+
var TimeoutError = class extends Error {
|
|
2987
|
+
constructor(message = TIMEOUT_MESSAGE) {
|
|
2988
|
+
super(message);
|
|
2989
|
+
this.name = "TimeoutError";
|
|
2990
|
+
}
|
|
2991
|
+
};
|
|
2992
|
+
|
|
2993
|
+
// src/providers/pruna/client/core/errors/validation-error.ts
|
|
2994
|
+
var ValidationError = class extends Error {
|
|
2995
|
+
field;
|
|
2996
|
+
reason;
|
|
2997
|
+
receivedValue;
|
|
2998
|
+
constructor(context) {
|
|
2999
|
+
super(`Invalid ${context.field}: ${context.reason}`);
|
|
3000
|
+
this.name = "ValidationError";
|
|
3001
|
+
this.field = context.field;
|
|
3002
|
+
this.reason = context.reason;
|
|
3003
|
+
this.receivedValue = context.receivedValue;
|
|
3004
|
+
}
|
|
3005
|
+
};
|
|
3006
|
+
|
|
3007
|
+
// src/providers/pruna/client/core/utils/base64.ts
|
|
3008
|
+
var globalScope = globalThis;
|
|
3009
|
+
var hasBuffer = typeof globalScope.Buffer?.from === "function";
|
|
3010
|
+
function base64ToBytes(raw) {
|
|
3011
|
+
if (hasBuffer) {
|
|
3012
|
+
const bufferFactory = globalScope.Buffer;
|
|
3013
|
+
if (!bufferFactory) {
|
|
3014
|
+
throw new Error("Buffer unavailable despite detection flag");
|
|
3015
|
+
}
|
|
3016
|
+
const buf = bufferFactory.from(raw, "base64");
|
|
3017
|
+
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
|
|
3018
|
+
}
|
|
3019
|
+
const decoded = atob(raw);
|
|
3020
|
+
return Uint8Array.from(decoded, (char) => char.charCodeAt(0));
|
|
2928
3021
|
}
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
if (
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
3022
|
+
|
|
3023
|
+
// src/providers/pruna/client/core/utils/mime-detector.ts
|
|
3024
|
+
var MIN_SIGNATURE_BYTES = 2;
|
|
3025
|
+
function matchesSignature(bytes, signature) {
|
|
3026
|
+
if (bytes.length < signature.length) return false;
|
|
3027
|
+
return signature.every((value, index) => bytes[index] === value);
|
|
3028
|
+
}
|
|
3029
|
+
function detectImageMime(bytes) {
|
|
3030
|
+
if (bytes.length < MIN_SIGNATURE_BYTES) return DEFAULT_IMAGE_MIME;
|
|
3031
|
+
if (matchesSignature(bytes, IMAGE_SIGNATURES.PNG)) return MIME_PNG;
|
|
3032
|
+
if (matchesSignature(bytes, IMAGE_SIGNATURES.JPEG)) return MIME_JPEG;
|
|
3033
|
+
if (matchesSignature(bytes, IMAGE_SIGNATURES.WEBP_RIFF)) return MIME_WEBP;
|
|
3034
|
+
return DEFAULT_IMAGE_MIME;
|
|
3035
|
+
}
|
|
3036
|
+
|
|
3037
|
+
// src/providers/pruna/client/core/utils/api-error-parser.ts
|
|
3038
|
+
async function parseApiError(response, fallback) {
|
|
3039
|
+
const payload = await response.json().catch(() => ({ message: response.statusText }));
|
|
3040
|
+
const message = payload.message ?? `${fallback}: ${response.status}`;
|
|
3041
|
+
const error = new Error(message);
|
|
3042
|
+
error.statusCode = response.status;
|
|
3043
|
+
return error;
|
|
3044
|
+
}
|
|
3045
|
+
|
|
3046
|
+
// src/providers/pruna/client/core/protocol/http-status.ts
|
|
3047
|
+
function isAuthFailureStatus(status) {
|
|
3048
|
+
return AUTH_FAILURE_STATUSES.includes(status);
|
|
3049
|
+
}
|
|
3050
|
+
|
|
3051
|
+
// src/providers/pruna/client/core/protocol/job-status.ts
|
|
3052
|
+
var TERMINAL_SUCCESS_STATUSES = ["succeeded", "completed"];
|
|
3053
|
+
var TERMINAL_FAILURE_STATUSES = ["failed"];
|
|
3054
|
+
function isTerminalSuccessStatus(status) {
|
|
3055
|
+
if (!status) return false;
|
|
3056
|
+
return TERMINAL_SUCCESS_STATUSES.includes(status);
|
|
3057
|
+
}
|
|
3058
|
+
function isTerminalFailureStatus(status) {
|
|
3059
|
+
if (!status) return false;
|
|
3060
|
+
return TERMINAL_FAILURE_STATUSES.includes(status);
|
|
3061
|
+
}
|
|
3062
|
+
|
|
3063
|
+
// src/providers/pruna/client/core/protocol/abort-signal-classifier.ts
|
|
3064
|
+
function isAbortError(err) {
|
|
3065
|
+
if (err instanceof DOMException && err.code === DOMException.ABORT_ERR) return true;
|
|
3066
|
+
if (err instanceof Error && err.name === "AbortError") return true;
|
|
3067
|
+
return false;
|
|
3068
|
+
}
|
|
3069
|
+
|
|
3070
|
+
// src/providers/pruna/client/core/protocol/pruna-url-builder.ts
|
|
3071
|
+
function isAbsoluteHttpUrl(value) {
|
|
3072
|
+
return value.startsWith(HTTPS_PREFIX) || value.startsWith(HTTP_PREFIX);
|
|
3073
|
+
}
|
|
3074
|
+
function isHttpsUrl(value) {
|
|
3075
|
+
return value.startsWith(HTTPS_PREFIX);
|
|
3076
|
+
}
|
|
3077
|
+
function buildPrunaApiUrl(pathOrUrl) {
|
|
3078
|
+
if (isAbsoluteHttpUrl(pathOrUrl)) return pathOrUrl;
|
|
3079
|
+
return `${PRUNA_BASE_URL}${pathOrUrl}`;
|
|
3080
|
+
}
|
|
3081
|
+
function buildFileUrlById(fileId) {
|
|
3082
|
+
return `${PRUNA_FILES_URL}/${fileId}`;
|
|
3083
|
+
}
|
|
3084
|
+
|
|
3085
|
+
// src/providers/pruna/client/core/math/exponential-backoff.ts
|
|
3086
|
+
function calculateExponentialBackoff2(inputs) {
|
|
3087
|
+
const {
|
|
3088
|
+
attempt,
|
|
3089
|
+
baseIntervalMs,
|
|
3090
|
+
maxIntervalMs = POLL_DEFAULTS.maxIntervalMs,
|
|
3091
|
+
jitterPercent = POLL_DEFAULTS.jitterPercent,
|
|
3092
|
+
growthBase = POLL_DEFAULTS.backoffBase
|
|
3093
|
+
} = inputs;
|
|
3094
|
+
const safeAttempt = Math.max(0, attempt);
|
|
3095
|
+
const safeBase = Math.max(0, baseIntervalMs);
|
|
3096
|
+
const exponentialDelay = Math.min(safeBase * Math.pow(growthBase, safeAttempt), maxIntervalMs);
|
|
3097
|
+
const jitter = exponentialDelay * jitterPercent * Math.random();
|
|
3098
|
+
return exponentialDelay + jitter;
|
|
3099
|
+
}
|
|
3100
|
+
|
|
3101
|
+
// src/providers/pruna/client/core/utils/uri-resolver.ts
|
|
3102
|
+
var uriCache = /* @__PURE__ */ new WeakMap();
|
|
3103
|
+
function stripBase64Prefix(image) {
|
|
3104
|
+
if (isHttpsUrl(image)) return image;
|
|
3105
|
+
const base64Index = image.indexOf(BASE64_MARKER);
|
|
3106
|
+
return base64Index !== -1 ? image.slice(base64Index + BASE64_MARKER.length) : image;
|
|
3107
|
+
}
|
|
3108
|
+
function readOutput(output) {
|
|
3109
|
+
if (typeof output === "string") return output;
|
|
3110
|
+
if (Array.isArray(output) && output.length > 0) return output[0] ?? null;
|
|
3111
|
+
if (output !== null && typeof output === "object" && "url" in output) {
|
|
3112
|
+
return output.url;
|
|
3113
|
+
}
|
|
3114
|
+
return null;
|
|
3115
|
+
}
|
|
3116
|
+
function extractUri(data) {
|
|
3117
|
+
const cached = uriCache.get(data);
|
|
3118
|
+
if (cached !== void 0) return cached;
|
|
3119
|
+
if (!isTerminalSuccessStatus(data.status)) {
|
|
3120
|
+
uriCache.set(data, null);
|
|
3121
|
+
return null;
|
|
3122
|
+
}
|
|
3123
|
+
const result = data.generation_url ?? readOutput(data.output) ?? data.video_url ?? data.data ?? null;
|
|
3124
|
+
uriCache.set(data, result);
|
|
3125
|
+
return result;
|
|
3126
|
+
}
|
|
3127
|
+
function resolveUri(uri) {
|
|
3128
|
+
return uri.startsWith("/") ? `${PRUNA_BASE_URL}${uri}` : uri;
|
|
3129
|
+
}
|
|
3130
|
+
|
|
3131
|
+
// src/providers/pruna/client/core/services/pruna-client.service.ts
|
|
3132
|
+
function buildFileExtension(mime) {
|
|
3133
|
+
return MIME_FILE_EXTENSION[mime] ?? "bin";
|
|
3134
|
+
}
|
|
3135
|
+
async function uploadImage(base64OrUrl, apiKey, onProgress) {
|
|
3136
|
+
if (isHttpsUrl(base64OrUrl)) return base64OrUrl;
|
|
3137
|
+
if (base64OrUrl.startsWith(HTTP_PREFIX)) {
|
|
3138
|
+
throw new Error("Only HTTPS URLs are supported for security.");
|
|
3139
|
+
}
|
|
3140
|
+
onProgress?.("uploading");
|
|
3141
|
+
const raw = stripBase64Prefix(base64OrUrl);
|
|
3142
|
+
let bytes;
|
|
3143
|
+
try {
|
|
3144
|
+
bytes = base64ToBytes(raw);
|
|
3145
|
+
} catch {
|
|
3146
|
+
throw new Error("Invalid image format. Provide base64 or a valid HTTPS URL.");
|
|
3147
|
+
}
|
|
3148
|
+
const mime = detectImageMime(bytes);
|
|
3149
|
+
const buffer = bytes.buffer.slice(
|
|
3150
|
+
bytes.byteOffset,
|
|
3151
|
+
bytes.byteOffset + bytes.byteLength
|
|
3152
|
+
);
|
|
3153
|
+
const blob = new Blob([buffer], { type: mime });
|
|
3154
|
+
const formData = new FormData();
|
|
3155
|
+
formData.append("content", blob, `upload.${buildFileExtension(mime)}`);
|
|
3156
|
+
const res = await fetch(PRUNA_FILES_URL, {
|
|
3157
|
+
method: "POST",
|
|
3158
|
+
headers: { apikey: apiKey },
|
|
3159
|
+
body: formData
|
|
3160
|
+
});
|
|
3161
|
+
if (!res.ok) {
|
|
3162
|
+
throw await parseApiError(res, "File upload error");
|
|
3163
|
+
}
|
|
3164
|
+
const data = await res.json();
|
|
3165
|
+
return data.urls?.get ?? buildFileUrlById(data.id ?? "");
|
|
3166
|
+
}
|
|
3167
|
+
async function submitPrediction(model, input, apiKey, signal, onProgress) {
|
|
3168
|
+
onProgress?.("predicting");
|
|
3169
|
+
const res = await fetch(PRUNA_PREDICTIONS_URL, {
|
|
3170
|
+
method: "POST",
|
|
3171
|
+
headers: {
|
|
3172
|
+
apikey: apiKey,
|
|
3173
|
+
Model: model,
|
|
3174
|
+
"Try-Sync": "true",
|
|
3175
|
+
"Content-Type": "application/json"
|
|
3176
|
+
},
|
|
3177
|
+
body: JSON.stringify({ input }),
|
|
3178
|
+
signal
|
|
3179
|
+
});
|
|
3180
|
+
if (!res.ok) {
|
|
3181
|
+
throw await parseApiError(res, "API error");
|
|
3182
|
+
}
|
|
3183
|
+
return res.json();
|
|
3184
|
+
}
|
|
3185
|
+
var GenerationFailedError = class extends Error {
|
|
3186
|
+
constructor(message) {
|
|
3187
|
+
super(message);
|
|
3188
|
+
this.name = "GenerationFailedError";
|
|
3189
|
+
}
|
|
3190
|
+
};
|
|
3191
|
+
async function attemptPoll(fullUrl, apiKey, signal) {
|
|
3192
|
+
let res;
|
|
3193
|
+
try {
|
|
3194
|
+
res = await fetch(fullUrl, { headers: { apikey: apiKey }, signal });
|
|
3195
|
+
} catch (err) {
|
|
3196
|
+
if (isAbortError(err)) throw new CancellationError();
|
|
3197
|
+
return { outcome: "transient-failure" };
|
|
3198
|
+
}
|
|
3199
|
+
if (!res.ok) {
|
|
3200
|
+
if (isAuthFailureStatus(res.status)) throw new AuthenticationError();
|
|
3201
|
+
return { outcome: "transient-failure" };
|
|
3202
|
+
}
|
|
3203
|
+
let data;
|
|
3204
|
+
try {
|
|
3205
|
+
data = await res.json();
|
|
3206
|
+
} catch {
|
|
3207
|
+
return { outcome: "transient-failure" };
|
|
3208
|
+
}
|
|
3209
|
+
if (isTerminalSuccessStatus(data.status)) {
|
|
3210
|
+
const uri = extractUri(data);
|
|
3211
|
+
if (uri) return { outcome: "succeeded", uri: resolveUri(uri) };
|
|
3212
|
+
return { outcome: "transient-failure" };
|
|
3213
|
+
}
|
|
3214
|
+
if (isTerminalFailureStatus(data.status)) {
|
|
3215
|
+
throw new GenerationFailedError(data.error ?? "Generation failed during processing.");
|
|
3216
|
+
}
|
|
3217
|
+
return { outcome: "continue" };
|
|
3218
|
+
}
|
|
3219
|
+
async function pollForResult(pollUrl, apiKey, maxAttempts = POLL_DEFAULTS.maxAttempts, intervalMs = POLL_DEFAULTS.intervalMs, signal, onProgress) {
|
|
3220
|
+
const fullUrl = isAbsoluteHttpUrl(pollUrl) ? pollUrl : buildPrunaApiUrl(pollUrl);
|
|
3221
|
+
const controller = new AbortController();
|
|
3222
|
+
const onExternalAbort = () => controller.abort();
|
|
3223
|
+
signal?.addEventListener("abort", onExternalAbort);
|
|
3224
|
+
try {
|
|
3225
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
3226
|
+
if (signal?.aborted) throw new CancellationError();
|
|
3227
|
+
const delay = calculateExponentialBackoff2({ attempt: i, baseIntervalMs: intervalMs });
|
|
3228
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
3229
|
+
if (signal?.aborted) throw new CancellationError();
|
|
3230
|
+
onProgress?.("polling", i + 1);
|
|
3231
|
+
const result = await attemptPoll(fullUrl, apiKey, controller.signal);
|
|
3232
|
+
if (result.outcome === "succeeded" && result.uri) {
|
|
3233
|
+
return result.uri;
|
|
3234
|
+
}
|
|
3235
|
+
}
|
|
3236
|
+
throw new TimeoutError();
|
|
3237
|
+
} finally {
|
|
3238
|
+
signal?.removeEventListener("abort", onExternalAbort);
|
|
3239
|
+
controller.abort();
|
|
3240
|
+
}
|
|
3241
|
+
}
|
|
3242
|
+
|
|
3243
|
+
// src/providers/pruna/client/core/math/comparison-hash.ts
|
|
3244
|
+
function sortKeysDeep(value) {
|
|
3245
|
+
if (Array.isArray(value)) {
|
|
3246
|
+
return value.map(sortKeysDeep);
|
|
3247
|
+
}
|
|
3248
|
+
if (value !== null && typeof value === "object") {
|
|
3249
|
+
const record = value;
|
|
3250
|
+
return Object.keys(record).sort().reduce((acc, key) => {
|
|
3251
|
+
acc[key] = sortKeysDeep(record[key]);
|
|
3252
|
+
return acc;
|
|
3253
|
+
}, {});
|
|
3254
|
+
}
|
|
3255
|
+
return value;
|
|
3256
|
+
}
|
|
3257
|
+
function hashValue(value) {
|
|
3258
|
+
if (value === null || typeof value !== "object") {
|
|
3259
|
+
return String(value);
|
|
3260
|
+
}
|
|
3261
|
+
try {
|
|
3262
|
+
return JSON.stringify(sortKeysDeep(value));
|
|
3263
|
+
} catch {
|
|
3264
|
+
return String(value);
|
|
3265
|
+
}
|
|
3266
|
+
}
|
|
3267
|
+
function compositeHash(...values) {
|
|
3268
|
+
return values.map(hashValue).join("|");
|
|
3269
|
+
}
|
|
3270
|
+
|
|
3271
|
+
// src/providers/pruna/client/core/math/cache-key-derivation.ts
|
|
3272
|
+
function deriveGenerationCacheKey(apiKey, input) {
|
|
3273
|
+
return `${apiKey}:${compositeHash(input)}`;
|
|
3274
|
+
}
|
|
3275
|
+
|
|
3276
|
+
// src/providers/pruna/client/core/validation/api-key-validator.ts
|
|
3277
|
+
function assertValidApiKey(apiKey) {
|
|
3278
|
+
if (typeof apiKey !== "string") {
|
|
3279
|
+
throw new ValidationError({
|
|
3280
|
+
field: "apiKey",
|
|
3281
|
+
reason: "must be a string",
|
|
3282
|
+
receivedValue: typeof apiKey
|
|
3283
|
+
});
|
|
3284
|
+
}
|
|
3285
|
+
if (apiKey.length < MIN_API_KEY_LENGTH) {
|
|
3286
|
+
throw new ValidationError({
|
|
3287
|
+
field: "apiKey",
|
|
3288
|
+
reason: "must not be empty",
|
|
3289
|
+
receivedValue: apiKey
|
|
3290
|
+
});
|
|
3291
|
+
}
|
|
3292
|
+
if (apiKey.length > MAX_API_KEY_LENGTH) {
|
|
3293
|
+
throw new ValidationError({
|
|
3294
|
+
field: "apiKey",
|
|
3295
|
+
reason: `exceeds maximum length of ${MAX_API_KEY_LENGTH}`,
|
|
3296
|
+
receivedValue: apiKey.length
|
|
3297
|
+
});
|
|
3298
|
+
}
|
|
3299
|
+
}
|
|
3300
|
+
|
|
3301
|
+
// src/providers/pruna/client/core/validation/image-source-validator.ts
|
|
3302
|
+
function classifyImageSource(source) {
|
|
3303
|
+
if (source.startsWith(HTTPS_PREFIX)) return "https-url";
|
|
3304
|
+
if (source.startsWith(HTTP_PREFIX)) return "http-url";
|
|
3305
|
+
if (source.includes(BASE64_MARKER) || /^[A-Za-z0-9+/=]+$/.test(source)) return "base64";
|
|
3306
|
+
return "unknown";
|
|
3307
|
+
}
|
|
3308
|
+
function assertSecureImageSource(image, fieldName = "image") {
|
|
3309
|
+
if (typeof image !== "string") {
|
|
3310
|
+
throw new ValidationError({
|
|
3311
|
+
field: fieldName,
|
|
3312
|
+
reason: "must be a string",
|
|
3313
|
+
receivedValue: typeof image
|
|
3314
|
+
});
|
|
3315
|
+
}
|
|
3316
|
+
const kind = classifyImageSource(image);
|
|
3317
|
+
if (kind === "http-url") {
|
|
3318
|
+
throw new ValidationError({
|
|
3319
|
+
field: fieldName,
|
|
3320
|
+
reason: "HTTP URLs are not supported; use HTTPS or a base64 data URI",
|
|
3321
|
+
receivedValue: image
|
|
3322
|
+
});
|
|
3323
|
+
}
|
|
3324
|
+
if (kind === "unknown") {
|
|
3325
|
+
throw new ValidationError({
|
|
3326
|
+
field: fieldName,
|
|
3327
|
+
reason: "must be an HTTPS URL or a base64 data URI",
|
|
3328
|
+
receivedValue: typeof image
|
|
3329
|
+
});
|
|
3330
|
+
}
|
|
3331
|
+
}
|
|
3332
|
+
|
|
3333
|
+
// src/providers/pruna/client/core/validation/aspect-ratio-validator.ts
|
|
3334
|
+
var SUPPORTED_ASPECT_RATIOS = [
|
|
3335
|
+
"16:9",
|
|
3336
|
+
"9:16",
|
|
3337
|
+
"1:1",
|
|
3338
|
+
"4:3",
|
|
3339
|
+
"3:4",
|
|
3340
|
+
"3:2",
|
|
3341
|
+
"2:3"
|
|
3342
|
+
];
|
|
3343
|
+
function isSupportedAspectRatio(value) {
|
|
3344
|
+
return typeof value === "string" && SUPPORTED_ASPECT_RATIOS.includes(value);
|
|
3345
|
+
}
|
|
3346
|
+
function assertValidAspectRatio(value, fieldName = "aspect_ratio") {
|
|
3347
|
+
if (value === void 0 || value === null) return;
|
|
3348
|
+
if (!isSupportedAspectRatio(value)) {
|
|
3349
|
+
throw new ValidationError({
|
|
3350
|
+
field: fieldName,
|
|
3351
|
+
reason: `must be one of ${SUPPORTED_ASPECT_RATIOS.join(", ")}`,
|
|
3352
|
+
receivedValue: value
|
|
3353
|
+
});
|
|
3354
|
+
}
|
|
3355
|
+
}
|
|
3356
|
+
|
|
3357
|
+
// src/providers/pruna/client/core/validation/resolution-validator.ts
|
|
3358
|
+
var SUPPORTED_RESOLUTIONS = ["720p", "1080p"];
|
|
3359
|
+
function isSupportedResolution(value) {
|
|
3360
|
+
return typeof value === "string" && SUPPORTED_RESOLUTIONS.includes(value);
|
|
3361
|
+
}
|
|
3362
|
+
function assertValidResolution(value, fieldName = "resolution") {
|
|
3363
|
+
if (value === void 0 || value === null) return;
|
|
3364
|
+
if (!isSupportedResolution(value)) {
|
|
3365
|
+
throw new ValidationError({
|
|
3366
|
+
field: fieldName,
|
|
3367
|
+
reason: `must be one of ${SUPPORTED_RESOLUTIONS.join(", ")}`,
|
|
3368
|
+
receivedValue: value
|
|
3369
|
+
});
|
|
3370
|
+
}
|
|
3371
|
+
}
|
|
3372
|
+
|
|
3373
|
+
// src/providers/pruna/client/core/validation/duration-validator.ts
|
|
3374
|
+
var MIN_VIDEO_DURATION_SECONDS = 1;
|
|
3375
|
+
var MAX_VIDEO_DURATION_SECONDS = 30;
|
|
3376
|
+
function isValidDuration(value) {
|
|
3377
|
+
return typeof value === "number" && Number.isFinite(value) && value >= MIN_VIDEO_DURATION_SECONDS && value <= MAX_VIDEO_DURATION_SECONDS && Number.isInteger(value);
|
|
3378
|
+
}
|
|
3379
|
+
function assertValidDuration(value, fieldName = "duration") {
|
|
3380
|
+
if (value === void 0 || value === null) return;
|
|
3381
|
+
if (!isValidDuration(value)) {
|
|
3382
|
+
throw new ValidationError({
|
|
3383
|
+
field: fieldName,
|
|
3384
|
+
reason: `must be an integer between ${MIN_VIDEO_DURATION_SECONDS} and ${MAX_VIDEO_DURATION_SECONDS} seconds`,
|
|
3385
|
+
receivedValue: value
|
|
3386
|
+
});
|
|
3387
|
+
}
|
|
3388
|
+
}
|
|
3389
|
+
|
|
3390
|
+
// src/providers/pruna/client/core/validation/prompt-validator.ts
|
|
3391
|
+
var MIN_PROMPT_LENGTH = 1;
|
|
3392
|
+
var MAX_PROMPT_LENGTH = 4e3;
|
|
3393
|
+
function assertValidPrompt(value, fieldName = "prompt") {
|
|
3394
|
+
if (typeof value !== "string") {
|
|
3395
|
+
throw new ValidationError({
|
|
3396
|
+
field: fieldName,
|
|
3397
|
+
reason: "must be a string",
|
|
3398
|
+
receivedValue: typeof value
|
|
3399
|
+
});
|
|
3400
|
+
}
|
|
3401
|
+
if (value.trim().length < MIN_PROMPT_LENGTH) {
|
|
3402
|
+
throw new ValidationError({
|
|
3403
|
+
field: fieldName,
|
|
3404
|
+
reason: "must not be empty or whitespace-only",
|
|
3405
|
+
receivedValue: value
|
|
3406
|
+
});
|
|
3407
|
+
}
|
|
3408
|
+
if (value.length > MAX_PROMPT_LENGTH) {
|
|
3409
|
+
throw new ValidationError({
|
|
3410
|
+
field: fieldName,
|
|
3411
|
+
reason: `exceeds maximum length of ${MAX_PROMPT_LENGTH} characters`,
|
|
3412
|
+
receivedValue: value.length
|
|
3413
|
+
});
|
|
3414
|
+
}
|
|
3415
|
+
}
|
|
3416
|
+
|
|
3417
|
+
// src/providers/pruna/client/core/validation/seed-validator.ts
|
|
3418
|
+
var MIN_SEED = -2147483648;
|
|
3419
|
+
var MAX_SEED = 2147483647;
|
|
3420
|
+
function isValidSeed(value) {
|
|
3421
|
+
return typeof value === "number" && Number.isFinite(value) && Number.isInteger(value) && value >= MIN_SEED && value <= MAX_SEED;
|
|
3422
|
+
}
|
|
3423
|
+
function assertValidSeed(value, fieldName = "seed") {
|
|
3424
|
+
if (value === void 0 || value === null) return;
|
|
3425
|
+
if (!isValidSeed(value)) {
|
|
3426
|
+
throw new ValidationError({
|
|
3427
|
+
field: fieldName,
|
|
3428
|
+
reason: `must be an integer in [${MIN_SEED}, ${MAX_SEED}]`,
|
|
3429
|
+
receivedValue: value
|
|
3430
|
+
});
|
|
3431
|
+
}
|
|
3432
|
+
}
|
|
3433
|
+
|
|
3434
|
+
// src/providers/pruna/client/core/protocol/input-type-guard.ts
|
|
3435
|
+
function isTextToImageInput(input) {
|
|
3436
|
+
return input.model === "p-image";
|
|
3437
|
+
}
|
|
3438
|
+
function isImageToImageInput(input) {
|
|
3439
|
+
return input.model === "p-image-edit";
|
|
3440
|
+
}
|
|
3441
|
+
function isImageToVideoInput(input) {
|
|
3442
|
+
return input.model === "p-video";
|
|
3443
|
+
}
|
|
3444
|
+
|
|
3445
|
+
// src/providers/pruna/client/core/utils/request-deduplicator.ts
|
|
3446
|
+
var RequestDeduplicator2 = class {
|
|
3447
|
+
pendingRequests = /* @__PURE__ */ new Map();
|
|
3448
|
+
ttl;
|
|
3449
|
+
constructor(ttl = DEFAULT_DEDUPLICATOR_TTL_MS) {
|
|
3450
|
+
this.ttl = ttl;
|
|
3451
|
+
}
|
|
3452
|
+
execute(key, fn) {
|
|
3453
|
+
const existing = this.pendingRequests.get(key);
|
|
3454
|
+
if (existing) {
|
|
3455
|
+
if (Date.now() - existing.timestamp < this.ttl) {
|
|
3456
|
+
return existing.promise;
|
|
3457
|
+
}
|
|
3458
|
+
this.pendingRequests.delete(key);
|
|
3459
|
+
}
|
|
3460
|
+
const promise = fn().finally(() => {
|
|
3461
|
+
setTimeout(() => {
|
|
3462
|
+
this.pendingRequests.delete(key);
|
|
3463
|
+
}, DEDUPLICATOR_CLEANUP_GRACE_MS);
|
|
3464
|
+
});
|
|
3465
|
+
this.pendingRequests.set(key, { promise, timestamp: Date.now() });
|
|
3466
|
+
return promise;
|
|
3467
|
+
}
|
|
3468
|
+
clear() {
|
|
3469
|
+
this.pendingRequests.clear();
|
|
3470
|
+
}
|
|
3471
|
+
size() {
|
|
3472
|
+
this.purgeExpired();
|
|
3473
|
+
return this.pendingRequests.size;
|
|
3474
|
+
}
|
|
3475
|
+
purgeExpired() {
|
|
3476
|
+
const now = Date.now();
|
|
3477
|
+
for (const [key, value] of this.pendingRequests) {
|
|
3478
|
+
if (now - value.timestamp >= this.ttl) {
|
|
3479
|
+
this.pendingRequests.delete(key);
|
|
3480
|
+
}
|
|
3481
|
+
}
|
|
3482
|
+
}
|
|
3483
|
+
};
|
|
3484
|
+
var globalDeduplicator = new RequestDeduplicator2();
|
|
3485
|
+
|
|
3486
|
+
// src/providers/pruna/client/generation/builders/text-to-image.builder.ts
|
|
3487
|
+
var TextToImageInputBuilder = class {
|
|
3488
|
+
model = "p-image";
|
|
3489
|
+
build(input, _context) {
|
|
3490
|
+
const payload = {
|
|
3491
|
+
prompt: input.prompt,
|
|
3492
|
+
aspect_ratio: input.aspect_ratio ?? DEFAULT_ASPECT_RATIO
|
|
2944
3493
|
};
|
|
2945
|
-
|
|
3494
|
+
if (input.seed !== void 0) {
|
|
3495
|
+
payload.seed = input.seed;
|
|
3496
|
+
}
|
|
3497
|
+
return Promise.resolve(payload);
|
|
2946
3498
|
}
|
|
2947
|
-
|
|
3499
|
+
};
|
|
3500
|
+
|
|
3501
|
+
// src/providers/pruna/client/generation/builders/image-to-image.builder.ts
|
|
3502
|
+
var ImageToImageInputBuilder = class {
|
|
3503
|
+
model = "p-image-edit";
|
|
3504
|
+
build(input, _context) {
|
|
3505
|
+
const payload = {
|
|
3506
|
+
images: [stripBase64Prefix(input.image)],
|
|
3507
|
+
prompt: input.prompt,
|
|
3508
|
+
aspect_ratio: input.aspect_ratio ?? DEFAULT_ASPECT_RATIO
|
|
3509
|
+
};
|
|
3510
|
+
if (input.seed !== void 0) {
|
|
3511
|
+
payload.seed = input.seed;
|
|
3512
|
+
}
|
|
3513
|
+
return Promise.resolve(payload);
|
|
3514
|
+
}
|
|
3515
|
+
};
|
|
3516
|
+
|
|
3517
|
+
// src/providers/pruna/client/generation/builders/image-to-video.builder.ts
|
|
3518
|
+
var ImageToVideoInputBuilder = class {
|
|
3519
|
+
model = "p-video";
|
|
3520
|
+
async build(input, context) {
|
|
3521
|
+
if (context.signal?.aborted) {
|
|
3522
|
+
throw new CancellationError();
|
|
3523
|
+
}
|
|
3524
|
+
const fileUrl = await uploadImage(
|
|
3525
|
+
input.image,
|
|
3526
|
+
context.apiKey,
|
|
3527
|
+
context.onProgress
|
|
3528
|
+
);
|
|
3529
|
+
return {
|
|
3530
|
+
image: fileUrl,
|
|
3531
|
+
prompt: input.prompt,
|
|
3532
|
+
duration: input.duration ?? P_VIDEO_DEFAULTS.duration,
|
|
3533
|
+
resolution: input.resolution ?? P_VIDEO_DEFAULTS.resolution,
|
|
3534
|
+
fps: P_VIDEO_DEFAULTS.fps,
|
|
3535
|
+
draft: input.draft ?? P_VIDEO_DEFAULTS.draft,
|
|
3536
|
+
aspect_ratio: input.aspect_ratio ?? DEFAULT_ASPECT_RATIO,
|
|
3537
|
+
prompt_upsampling: P_VIDEO_DEFAULTS.promptUpsampling
|
|
3538
|
+
};
|
|
3539
|
+
}
|
|
3540
|
+
};
|
|
3541
|
+
|
|
3542
|
+
// src/providers/pruna/client/generation/builders/model-input-builder.ts
|
|
3543
|
+
var ModelInputBuilderRegistry = class {
|
|
3544
|
+
builders = /* @__PURE__ */ new Map();
|
|
3545
|
+
register(builder) {
|
|
3546
|
+
this.builders.set(builder.model, builder);
|
|
3547
|
+
return this;
|
|
3548
|
+
}
|
|
3549
|
+
resolve(model) {
|
|
3550
|
+
const builder = this.builders.get(model);
|
|
3551
|
+
if (!builder) {
|
|
3552
|
+
throw new Error(`No input builder registered for model: ${model}`);
|
|
3553
|
+
}
|
|
3554
|
+
return builder;
|
|
3555
|
+
}
|
|
3556
|
+
};
|
|
3557
|
+
|
|
3558
|
+
// src/providers/pruna/client/generation/builders/builder-factory.ts
|
|
3559
|
+
function createDefaultBuilderRegistry() {
|
|
3560
|
+
return new ModelInputBuilderRegistry().register(new TextToImageInputBuilder()).register(new ImageToImageInputBuilder()).register(new ImageToVideoInputBuilder());
|
|
3561
|
+
}
|
|
3562
|
+
|
|
3563
|
+
// src/providers/pruna/client/generation/services/generation.service.ts
|
|
3564
|
+
var builderRegistry = createDefaultBuilderRegistry();
|
|
3565
|
+
function validateGenerateInput(input) {
|
|
3566
|
+
assertValidPrompt(input.prompt, `${input.model}.prompt`);
|
|
3567
|
+
assertValidAspectRatio(input.aspect_ratio, `${input.model}.aspect_ratio`);
|
|
3568
|
+
if (isTextToImageInput(input)) {
|
|
3569
|
+
assertValidSeed(input.seed, `${input.model}.seed`);
|
|
3570
|
+
} else if (isImageToImageInput(input)) {
|
|
3571
|
+
assertSecureImageSource(input.image, `${input.model}.image`);
|
|
3572
|
+
assertValidSeed(input.seed, `${input.model}.seed`);
|
|
3573
|
+
} else if (isImageToVideoInput(input)) {
|
|
3574
|
+
assertSecureImageSource(input.image, `${input.model}.image`);
|
|
3575
|
+
assertValidDuration(input.duration, `${input.model}.duration`);
|
|
3576
|
+
assertValidResolution(input.resolution, `${input.model}.resolution`);
|
|
3577
|
+
}
|
|
3578
|
+
}
|
|
3579
|
+
async function generate(apiKey, input, options = {}) {
|
|
3580
|
+
assertValidApiKey(apiKey);
|
|
3581
|
+
validateGenerateInput(input);
|
|
3582
|
+
const { signal, onProgress, useCache = true } = options;
|
|
3583
|
+
if (useCache) {
|
|
3584
|
+
const cacheKey = deriveGenerationCacheKey(apiKey, input);
|
|
3585
|
+
return globalDeduplicator.execute(
|
|
3586
|
+
cacheKey,
|
|
3587
|
+
() => generateInternal(apiKey, input, { signal, onProgress })
|
|
3588
|
+
);
|
|
3589
|
+
}
|
|
3590
|
+
return generateInternal(apiKey, input, { signal, onProgress });
|
|
3591
|
+
}
|
|
3592
|
+
async function generateInternal(apiKey, input, options) {
|
|
3593
|
+
const { signal, onProgress } = options;
|
|
3594
|
+
const builder = builderRegistry.resolve(input.model);
|
|
3595
|
+
const modelInput = await builder.build(input, { apiKey, signal, onProgress });
|
|
3596
|
+
const response = await submitPrediction(input.model, modelInput, apiKey, signal, onProgress);
|
|
3597
|
+
const syncUri = extractUri(response);
|
|
3598
|
+
if (syncUri) {
|
|
3599
|
+
return { url: resolveUri(syncUri), model: input.model };
|
|
3600
|
+
}
|
|
3601
|
+
const pollUrl = response.get_url ?? response.status_url;
|
|
2948
3602
|
if (!pollUrl) {
|
|
2949
|
-
throw new Error("Pruna
|
|
3603
|
+
throw new Error("Pruna API returned no result and no polling URL.");
|
|
3604
|
+
}
|
|
3605
|
+
const url = await pollForResult(
|
|
3606
|
+
pollUrl,
|
|
3607
|
+
apiKey,
|
|
3608
|
+
POLL_DEFAULTS.maxAttempts,
|
|
3609
|
+
POLL_DEFAULTS.intervalMs,
|
|
3610
|
+
signal,
|
|
3611
|
+
onProgress
|
|
3612
|
+
);
|
|
3613
|
+
return { url, model: input.model };
|
|
3614
|
+
}
|
|
3615
|
+
async function generateImageThenVideo(apiKey, input, options = {}) {
|
|
3616
|
+
assertValidApiKey(apiKey);
|
|
3617
|
+
assertValidPrompt(input.prompt, "text-to-video.prompt");
|
|
3618
|
+
assertValidAspectRatio(input.aspect_ratio, "text-to-video.aspect_ratio");
|
|
3619
|
+
assertValidDuration(input.duration, "text-to-video.duration");
|
|
3620
|
+
assertValidResolution(input.resolution, "text-to-video.resolution");
|
|
3621
|
+
const { signal, onProgress } = options;
|
|
3622
|
+
const aspectRatio = input.aspect_ratio ?? DEFAULT_ASPECT_RATIO;
|
|
3623
|
+
onProgress?.("predicting", 1);
|
|
3624
|
+
const imageResult = await generate(
|
|
3625
|
+
apiKey,
|
|
3626
|
+
{ model: "p-image", prompt: input.prompt, aspect_ratio: aspectRatio },
|
|
3627
|
+
{ signal }
|
|
3628
|
+
);
|
|
3629
|
+
onProgress?.("predicting", 2);
|
|
3630
|
+
return generate(
|
|
3631
|
+
apiKey,
|
|
3632
|
+
{
|
|
3633
|
+
model: "p-video",
|
|
3634
|
+
prompt: input.prompt,
|
|
3635
|
+
image: imageResult.url,
|
|
3636
|
+
duration: input.duration ?? P_VIDEO_DEFAULTS.duration,
|
|
3637
|
+
resolution: input.resolution ?? P_VIDEO_DEFAULTS.resolution,
|
|
3638
|
+
aspect_ratio: aspectRatio,
|
|
3639
|
+
draft: input.draft ?? P_VIDEO_DEFAULTS.draft
|
|
3640
|
+
},
|
|
3641
|
+
{ signal, onProgress }
|
|
3642
|
+
);
|
|
3643
|
+
}
|
|
3644
|
+
|
|
3645
|
+
// src/providers/pruna/pruna-generate.ts
|
|
3646
|
+
async function* generateWithPruna(request, apiKey, signal, onProgress) {
|
|
3647
|
+
const stages = [];
|
|
3648
|
+
let notify = null;
|
|
3649
|
+
let done = false;
|
|
3650
|
+
const wake = () => {
|
|
3651
|
+
const fn = notify;
|
|
3652
|
+
if (fn) {
|
|
3653
|
+
notify = null;
|
|
3654
|
+
fn();
|
|
3655
|
+
}
|
|
3656
|
+
};
|
|
3657
|
+
const handleProgress = (stage) => {
|
|
3658
|
+
stages.push({ stage });
|
|
3659
|
+
onProgress?.(stage);
|
|
3660
|
+
wake();
|
|
3661
|
+
};
|
|
3662
|
+
const promise = (async () => {
|
|
3663
|
+
try {
|
|
3664
|
+
const model = request.model ?? (request.image ? "p-image-edit" : "p-image");
|
|
3665
|
+
if (model === "p-video" && !request.image && request.prompt) {
|
|
3666
|
+
const videoRes = await generateImageThenVideo(
|
|
3667
|
+
apiKey,
|
|
3668
|
+
{
|
|
3669
|
+
prompt: request.prompt,
|
|
3670
|
+
duration: request.duration ?? 5,
|
|
3671
|
+
aspect_ratio: request.aspectRatio ?? request.aspect_ratio ?? "16:9"
|
|
3672
|
+
},
|
|
3673
|
+
{ signal, onProgress: handleProgress }
|
|
3674
|
+
);
|
|
3675
|
+
stages.push({
|
|
3676
|
+
stage: "polling",
|
|
3677
|
+
result: { url: videoRes.url, model: "p-video" }
|
|
3678
|
+
});
|
|
3679
|
+
return;
|
|
3680
|
+
}
|
|
3681
|
+
const input = {
|
|
3682
|
+
model,
|
|
3683
|
+
prompt: request.prompt ?? "",
|
|
3684
|
+
aspect_ratio: request.aspectRatio ?? request.aspect_ratio ?? "1:1",
|
|
3685
|
+
...request.image ? { image: request.image } : {},
|
|
3686
|
+
...request.duration ? { duration: request.duration } : {},
|
|
3687
|
+
...request.resolution ? { resolution: request.resolution } : {},
|
|
3688
|
+
...request.seed !== void 0 ? { seed: request.seed } : {}
|
|
3689
|
+
};
|
|
3690
|
+
const res = await generate(apiKey, input, {
|
|
3691
|
+
signal,
|
|
3692
|
+
onProgress: handleProgress
|
|
3693
|
+
});
|
|
3694
|
+
stages.push({
|
|
3695
|
+
stage: "polling",
|
|
3696
|
+
result: { url: res.url, model: res.model }
|
|
3697
|
+
});
|
|
3698
|
+
} catch (err) {
|
|
3699
|
+
stages.push({
|
|
3700
|
+
stage: "processing",
|
|
3701
|
+
error: err instanceof Error ? err : new Error(String(err))
|
|
3702
|
+
});
|
|
3703
|
+
} finally {
|
|
3704
|
+
done = true;
|
|
3705
|
+
wake();
|
|
3706
|
+
}
|
|
3707
|
+
})();
|
|
3708
|
+
while (!done || stages.length > 0) {
|
|
3709
|
+
if (stages.length === 0 && !done) {
|
|
3710
|
+
await new Promise((resolve) => {
|
|
3711
|
+
notify = resolve;
|
|
3712
|
+
});
|
|
3713
|
+
notify = null;
|
|
3714
|
+
}
|
|
3715
|
+
while (stages.length > 0) {
|
|
3716
|
+
const nextStage = stages.shift();
|
|
3717
|
+
if (!nextStage) continue;
|
|
3718
|
+
yield nextStage;
|
|
3719
|
+
if (nextStage.error) {
|
|
3720
|
+
throw nextStage.error;
|
|
3721
|
+
}
|
|
3722
|
+
}
|
|
2950
3723
|
}
|
|
2951
|
-
|
|
2952
|
-
yield { stage: "polling", result: { url: resultUrl, model: modelId } };
|
|
3724
|
+
await promise;
|
|
2953
3725
|
}
|
|
2954
3726
|
|
|
2955
3727
|
// src/providers/pruna/pruna.provider.ts
|
|
@@ -3595,8 +4367,10 @@ exports.API_ENDPOINTS = API_ENDPOINTS;
|
|
|
3595
4367
|
exports.AnthropicHttpTransport = AnthropicHttpTransport;
|
|
3596
4368
|
exports.AnthropicProvider = AnthropicProvider;
|
|
3597
4369
|
exports.AnthropicRequestBuilder = AnthropicRequestBuilder;
|
|
4370
|
+
exports.AuthenticationError = AuthenticationError;
|
|
3598
4371
|
exports.BaseProvider = BaseProvider;
|
|
3599
4372
|
exports.CacheManager = CacheManager;
|
|
4373
|
+
exports.CancellationError = CancellationError;
|
|
3600
4374
|
exports.ChatIdGenerator = ChatIdGenerator;
|
|
3601
4375
|
exports.ChatService = ChatService;
|
|
3602
4376
|
exports.CompositeExecutor = CompositeExecutor;
|
|
@@ -3619,6 +4393,7 @@ exports.GEMINI_TIERS = GEMINI_TIERS;
|
|
|
3619
4393
|
exports.GROQ_MODELS = GROQ_MODELS;
|
|
3620
4394
|
exports.GROQ_TIERS = GROQ_TIERS;
|
|
3621
4395
|
exports.GeminiProvider = GeminiProvider;
|
|
4396
|
+
exports.GenerationFailedError = GenerationFailedError;
|
|
3622
4397
|
exports.GroqChatRequestBuilder = GroqChatRequestBuilder;
|
|
3623
4398
|
exports.GroqConfigStore = GroqConfigStore;
|
|
3624
4399
|
exports.GroqError = GroqError;
|
|
@@ -3646,7 +4421,9 @@ exports.TEXT_TIERS = TEXT_TIERS;
|
|
|
3646
4421
|
exports.TIMEOUTS = TIMEOUTS;
|
|
3647
4422
|
exports.TextGenerationService = TextGenerationService;
|
|
3648
4423
|
exports.ThrottleManager = ThrottleManager;
|
|
4424
|
+
exports.TimeoutError = TimeoutError;
|
|
3649
4425
|
exports.USER_FRIENDLY_ERROR_MESSAGES = USER_FRIENDLY_ERROR_MESSAGES;
|
|
4426
|
+
exports.ValidationError = ValidationError;
|
|
3650
4427
|
exports.asObjectArray = asObjectArray;
|
|
3651
4428
|
exports.asRecord = asRecord;
|
|
3652
4429
|
exports.asStringArray = asStringArray;
|
|
@@ -3685,6 +4462,8 @@ exports.extractTextFromMessages = extractTextFromMessages;
|
|
|
3685
4462
|
exports.extractTokenUsage = extractTokenUsage;
|
|
3686
4463
|
exports.formatErrorForLogging = formatErrorForLogging;
|
|
3687
4464
|
exports.formatMessagesForDisplay = formatMessagesForDisplay;
|
|
4465
|
+
exports.generateImageThenVideo = generateImageThenVideo;
|
|
4466
|
+
exports.generatePruna = generate;
|
|
3688
4467
|
exports.generateWithPruna = generateWithPruna;
|
|
3689
4468
|
exports.getProvider = getProvider;
|
|
3690
4469
|
exports.isAuthErrorType = isAuthErrorType;
|
|
@@ -3700,6 +4479,7 @@ exports.mergeTierOverrides = mergeTierOverrides;
|
|
|
3700
4479
|
exports.messageFormatter = messageFormatter;
|
|
3701
4480
|
exports.normalizeSseChunk = normalizeSseChunk;
|
|
3702
4481
|
exports.oneOfCatalog = oneOfCatalog;
|
|
4482
|
+
exports.pollForResult = pollForResult;
|
|
3703
4483
|
exports.promptToMessages = promptToMessages;
|
|
3704
4484
|
exports.repairCommonJsonDefects = repairCommonJsonDefects;
|
|
3705
4485
|
exports.requestDeduplicator = requestDeduplicator;
|
|
@@ -3711,9 +4491,11 @@ exports.resolveUserFriendlyErrorMessage = resolveUserFriendlyErrorMessage;
|
|
|
3711
4491
|
exports.resolveUserFriendlyMessage = resolveUserFriendlyMessage;
|
|
3712
4492
|
exports.retryManager = retryManager;
|
|
3713
4493
|
exports.splitSseLines = splitSseLines;
|
|
4494
|
+
exports.submitPrediction = submitPrediction;
|
|
3714
4495
|
exports.throttle = throttle;
|
|
3715
4496
|
exports.throttleManager = throttleManager;
|
|
3716
4497
|
exports.toGroqMessages = toGroqMessages;
|
|
4498
|
+
exports.uploadImage = uploadImage;
|
|
3717
4499
|
exports.validateApiKey = validateApiKey;
|
|
3718
4500
|
exports.withRetry = withRetry;
|
|
3719
4501
|
//# sourceMappingURL=index.cjs.map
|