vidspotai-shared 1.0.80 → 1.0.82-dev.0

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.
Files changed (31) hide show
  1. package/lib/globals/aiModels/enums.d.ts +5 -0
  2. package/lib/globals/aiModels/enums.d.ts.map +1 -1
  3. package/lib/globals/aiModels/enums.js +12 -1
  4. package/lib/globals/aiModels/providers/alibaba.d.ts.map +1 -1
  5. package/lib/globals/aiModels/providers/alibaba.js +159 -39
  6. package/lib/globals/aiModels/providers/google.d.ts.map +1 -1
  7. package/lib/globals/aiModels/providers/google.js +12 -3
  8. package/lib/services/aiGen/aiGenFactory.service.d.ts +4 -1
  9. package/lib/services/aiGen/aiGenFactory.service.d.ts.map +1 -1
  10. package/lib/services/aiGen/aiGenFactory.service.js +13 -1
  11. package/lib/services/aiGen/index.d.ts +1 -0
  12. package/lib/services/aiGen/index.d.ts.map +1 -1
  13. package/lib/services/aiGen/index.js +1 -0
  14. package/lib/services/aiGen/providers/alibaba/alibaba.d.ts +34 -7
  15. package/lib/services/aiGen/providers/alibaba/alibaba.d.ts.map +1 -1
  16. package/lib/services/aiGen/providers/alibaba/alibaba.js +193 -75
  17. package/lib/services/aiGen/providers/google/google.service.d.ts +1 -0
  18. package/lib/services/aiGen/providers/google/google.service.d.ts.map +1 -1
  19. package/lib/services/aiGen/providers/google/google.service.js +66 -1
  20. package/lib/services/aiGen/providers/pixverse/pixverse.service.d.ts.map +1 -1
  21. package/lib/services/aiGen/providers/pixverse/pixverse.service.js +71 -40
  22. package/lib/services/aiGen/transientRetry.d.ts +35 -0
  23. package/lib/services/aiGen/transientRetry.d.ts.map +1 -0
  24. package/lib/services/aiGen/transientRetry.js +106 -0
  25. package/package.json +1 -1
  26. package/lib/services/aiGen/providers/azure/azure.service.d.ts +0 -14
  27. package/lib/services/aiGen/providers/azure/azure.service.d.ts.map +0 -1
  28. package/lib/services/aiGen/providers/azure/azure.service.js +0 -108
  29. package/lib/services/aiGen/providers/azure/index.d.ts +0 -2
  30. package/lib/services/aiGen/providers/azure/index.d.ts.map +0 -1
  31. package/lib/services/aiGen/providers/azure/index.js +0 -17
@@ -0,0 +1,35 @@
1
+ /**
2
+ * True when an error from `fetch()` / SDK call is a transient network failure
3
+ * worth retrying. False for application-layer errors (4xx, validation, etc.).
4
+ */
5
+ export declare function isTransientFetchError(err: unknown): boolean;
6
+ /**
7
+ * Marker thrown by callers when they detect a transient HTTP response (5xx /
8
+ * 429 / opt-in 404) and want `withTransientRetry` to retry it. Caller is
9
+ * responsible for the classification — this util is response-shape agnostic.
10
+ */
11
+ export declare class TransientHttpError extends Error {
12
+ readonly isTransientHttpError = true;
13
+ readonly status: number;
14
+ constructor(status: number, message: string);
15
+ }
16
+ export interface TransientRetryOptions {
17
+ /** Max attempts including the first try. Defaults to 3. */
18
+ maxAttempts?: number;
19
+ /** Base backoff in ms; doubled each retry. Defaults to 1000 (1s → 2s → 4s). */
20
+ baseBackoffMs?: number;
21
+ /** Logger function for warn-level retry notices. */
22
+ onRetry?: (info: {
23
+ attempt: number;
24
+ maxAttempts: number;
25
+ backoffMs: number;
26
+ err: Error;
27
+ }) => void;
28
+ }
29
+ /**
30
+ * Wraps `fn` with retry on transient errors. UserFacingError ALWAYS short-
31
+ * circuits (no retry, no logging — caller's responsibility to log appropriately).
32
+ * Non-transient errors short-circuit on the first attempt.
33
+ */
34
+ export declare function withTransientRetry<T>(label: string, fn: () => Promise<T>, opts?: TransientRetryOptions): Promise<T>;
35
+ //# sourceMappingURL=transientRetry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transientRetry.d.ts","sourceRoot":"","sources":["../../../src/services/aiGen/transientRetry.ts"],"names":[],"mappings":"AAwCA;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAQ3D;AAED;;;;GAIG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,oBAAoB,QAAQ;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBACZ,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAK5C;AAED,MAAM,WAAW,qBAAqB;IACpC,2DAA2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+EAA+E;IAC/E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oDAAoD;IACpD,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,KAAK,CAAA;KAAE,KAAK,IAAI,CAAC;CACnG;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,CAAC,EACxC,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,IAAI,GAAE,qBAA0B,GAC/B,OAAO,CAAC,CAAC,CAAC,CA2BZ"}
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ // Shared transient-error retry primitive for provider service calls.
3
+ //
4
+ // Background: every provider (Google, PixVerse, Alibaba, ...) makes outbound
5
+ // HTTP/SDK calls that can drop on transient network failures (TCP resets,
6
+ // undici fetch hiccups, upstream 5xx, CloudFlare edge 404 misroutes, etc.).
7
+ // Before this util each provider classified transient errors inline or not at
8
+ // all, so the same edge hiccup that retried OK on Google would fail-fast on
9
+ // PixVerse — fan-out inconsistency that bit us with the 2026-06-06 PixVerse
10
+ // 404 (the request body was valid, the account had a real account-level
11
+ // problem, but the response shape was an HTML "404 page not found" from the
12
+ // edge layer — a one-shot we'd have absorbed silently with a retry).
13
+ //
14
+ // Policy:
15
+ // - retry on undici "fetch failed" + the network-code allowlist below
16
+ // - retry on HTTP 5xx + 429 + 404 (404 ONLY when the URL is known-good and the
17
+ // caller opted in via `retryHttp4xx404`; otherwise 4xx is permanent)
18
+ // - never retry UserFacingError — those are deterministic by construction
19
+ // (content moderation, validation, missing input) and a retry just burns
20
+ // a provider credit for the same outcome
21
+ //
22
+ // Backoff: exponential 1s → 2s → 4s by default. Override via `backoffMs`.
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.TransientHttpError = void 0;
25
+ exports.isTransientFetchError = isTransientFetchError;
26
+ exports.withTransientRetry = withTransientRetry;
27
+ const errors_1 = require("../../utils/errors");
28
+ // Codes from undici / Node net layer that indicate a transient network failure
29
+ // (request never reached server, or server hung up mid-flight). Retrying these
30
+ // is safe at the API layer for our use cases.
31
+ const TRANSIENT_NETWORK_CODES = new Set([
32
+ "ECONNRESET",
33
+ "ECONNREFUSED",
34
+ "ETIMEDOUT",
35
+ "ENOTFOUND",
36
+ "EAI_AGAIN",
37
+ "EPIPE",
38
+ "UND_ERR_SOCKET",
39
+ "UND_ERR_CONNECT_TIMEOUT",
40
+ "UND_ERR_HEADERS_TIMEOUT",
41
+ "UND_ERR_BODY_TIMEOUT",
42
+ ]);
43
+ /**
44
+ * True when an error from `fetch()` / SDK call is a transient network failure
45
+ * worth retrying. False for application-layer errors (4xx, validation, etc.).
46
+ */
47
+ function isTransientFetchError(err) {
48
+ if (!err)
49
+ return false;
50
+ const e = err;
51
+ // undici wraps low-level errors as `TypeError: fetch failed` with the real
52
+ // reason on `err.cause`. Treat that exact shape as transient.
53
+ if (e.message === "fetch failed")
54
+ return true;
55
+ const code = e.code ?? e.cause?.code;
56
+ return !!code && TRANSIENT_NETWORK_CODES.has(code);
57
+ }
58
+ /**
59
+ * Marker thrown by callers when they detect a transient HTTP response (5xx /
60
+ * 429 / opt-in 404) and want `withTransientRetry` to retry it. Caller is
61
+ * responsible for the classification — this util is response-shape agnostic.
62
+ */
63
+ class TransientHttpError extends Error {
64
+ constructor(status, message) {
65
+ super(message);
66
+ this.isTransientHttpError = true;
67
+ this.name = "TransientHttpError";
68
+ this.status = status;
69
+ }
70
+ }
71
+ exports.TransientHttpError = TransientHttpError;
72
+ /**
73
+ * Wraps `fn` with retry on transient errors. UserFacingError ALWAYS short-
74
+ * circuits (no retry, no logging — caller's responsibility to log appropriately).
75
+ * Non-transient errors short-circuit on the first attempt.
76
+ */
77
+ async function withTransientRetry(label, fn, opts = {}) {
78
+ const maxAttempts = opts.maxAttempts ?? 3;
79
+ const baseBackoffMs = opts.baseBackoffMs ?? 1000;
80
+ let lastErr;
81
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
82
+ try {
83
+ return await fn();
84
+ }
85
+ catch (err) {
86
+ lastErr = err;
87
+ // UserFacingError is by-construction deterministic — never retry.
88
+ if (err instanceof errors_1.UserFacingError)
89
+ throw err;
90
+ const transient = isTransientFetchError(err) ||
91
+ (err instanceof TransientHttpError);
92
+ if (!transient || attempt === maxAttempts)
93
+ throw err;
94
+ const backoffMs = baseBackoffMs * 2 ** (attempt - 1);
95
+ opts.onRetry?.({
96
+ attempt,
97
+ maxAttempts,
98
+ backoffMs,
99
+ err: err,
100
+ });
101
+ void label; // label is for tracing in caller's onRetry; intentionally unused here
102
+ await new Promise((r) => setTimeout(r, backoffMs));
103
+ }
104
+ }
105
+ throw lastErr;
106
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vidspotai-shared",
3
- "version": "1.0.80",
3
+ "version": "1.0.82-dev.0",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "exports": {
@@ -1,14 +0,0 @@
1
- import { BaseAiGenProviderService } from "../baseAiGenProvider.service";
2
- import { CreditUsageParams, VideoGenerationParams, VideoGenerationResult, VideoStatusParams, VideoStatusResult } from "../types";
3
- export declare class AzureService extends BaseAiGenProviderService {
4
- private readonly baseUrl;
5
- private readonly apiKey;
6
- private readonly apiVersion;
7
- private readonly timeout;
8
- constructor();
9
- private request;
10
- generateVideo(params: VideoGenerationParams): Promise<VideoGenerationResult>;
11
- checkVideoStatus({ task, outputFilename, outputFilePath, }: VideoStatusParams): Promise<VideoStatusResult>;
12
- getCreditUsed({ modelKey, dimensions, duration, multiClip, }: CreditUsageParams): number;
13
- }
14
- //# sourceMappingURL=azure.service.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"azure.service.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/azure/azure.service.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,UAAU,CAAC;AAElB,qBAAa,YAAa,SAAQ,wBAAwB;IACxD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IACxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;;YAiBnB,OAAO;IAwBf,aAAa,CACjB,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,qBAAqB,CAAC;IA6B3B,gBAAgB,CAAC,EACrB,IAAI,EACJ,cAAc,EACd,cAAyB,GAC1B,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAgDjD,aAAa,CAAC,EACZ,QAAQ,EACR,UAAsB,EACtB,QAAY,EACZ,SAAiB,GAClB,EAAE,iBAAiB,GAAG,MAAM;CAS9B"}
@@ -1,108 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.AzureService = void 0;
7
- const axios_1 = __importDefault(require("axios"));
8
- const aiModels_1 = require("../../../../globals/aiModels");
9
- const types_1 = require("../../../../globals/types");
10
- const firebase_1 = require("../../../../libs/firebase");
11
- const helpers_1 = require("../../../../utils/helpers");
12
- const logger_1 = require("../../../../utils/logger");
13
- const helpers_2 = require("../../helpers");
14
- const baseAiGenProvider_service_1 = require("../baseAiGenProvider.service");
15
- class AzureService extends baseAiGenProvider_service_1.BaseAiGenProviderService {
16
- constructor() {
17
- super();
18
- this.apiVersion = "preview";
19
- this.timeout = 60000; // 60 seconds
20
- if (!process.env.AZURE_OPENAI_ENDPOINT ||
21
- !process.env.AZURE_OPENAI_API_KEY) {
22
- throw new Error("Missing AZURE_OPENAI_ENDPOINT or AZURE_OPENAI_API_KEY in environment variables");
23
- }
24
- this.baseUrl = process.env.AZURE_OPENAI_ENDPOINT;
25
- this.apiKey = process.env.AZURE_OPENAI_API_KEY;
26
- }
27
- async request(endpoint, method, body) {
28
- const url = `${this.baseUrl}${endpoint}${endpoint.includes("?") ? "&" : "?"}api-version=${this.apiVersion}`;
29
- const config = {
30
- method,
31
- url,
32
- headers: {
33
- "api-key": this.apiKey,
34
- "Content-Type": "application/json",
35
- },
36
- timeout: this.timeout,
37
- data: body,
38
- };
39
- const res = await axios_1.default.request(config);
40
- return res.data;
41
- }
42
- async generateVideo(params) {
43
- (0, helpers_2.validateParams)(params);
44
- const modelId = aiModels_1.aiModelConfigs[params.modelKey]?.modelId || "sora";
45
- const body = {
46
- prompt: params.prompt,
47
- width: params.dimensions?.split("x")[0]
48
- ? parseInt(params.dimensions.split("x")[0] ?? "480", 10)
49
- : 480,
50
- height: params.dimensions?.split("x")[1]
51
- ? parseInt(params.dimensions.split("x")[1] ?? "480", 10)
52
- : 480,
53
- n_seconds: params.duration || 5,
54
- model: modelId,
55
- };
56
- const job = await this.request(`/openai/v1/video/generations/jobs?`, "POST", body);
57
- return {
58
- task: job.id,
59
- status: types_1.EVideoSceneStatus.TRIGGERED,
60
- };
61
- }
62
- async checkVideoStatus({ task, outputFilename, outputFilePath = "videos", }) {
63
- const result = await this.request(`/openai/v1/video/generations/jobs/${task}?`, "GET");
64
- if (result.status === "succeeded") {
65
- if (!result.generations || !(result.generations.length > 0)) {
66
- return {
67
- status: types_1.EVideoSceneStatus.FAILED,
68
- errorMessage: "No video returned from API",
69
- };
70
- }
71
- const generationId = result.generations[0].id;
72
- const videoUrl = `${this.baseUrl}/openai/v1/video/generations/${generationId}/content/video?api-version=${this.apiVersion}`;
73
- const videoResp = await axios_1.default.get(videoUrl, {
74
- headers: { "api-key": this.apiKey },
75
- responseType: "arraybuffer",
76
- timeout: this.timeout,
77
- });
78
- if (!videoResp.data)
79
- throw new Error("No video data received from Azure API");
80
- const filePath = `${outputFilePath}/${outputFilename}.mp4`;
81
- const file = (0, firebase_1.getBucket)().file(filePath);
82
- const buffer = Buffer.from(videoResp.data);
83
- await file.save(buffer, { contentType: "video/mp4" });
84
- const [signedUrl] = await file.getSignedUrl({
85
- action: "read",
86
- expires: "03-09-2491",
87
- });
88
- return { videoUrl: signedUrl, status: types_1.EVideoSceneStatus.COMPLETED };
89
- }
90
- else if (result.status === "failed") {
91
- return {
92
- status: types_1.EVideoSceneStatus.FAILED,
93
- errorMessage: `Task failed: ${result.failure_reason || "unknown"}`,
94
- };
95
- }
96
- return { status: types_1.EVideoSceneStatus.PENDING };
97
- }
98
- getCreditUsed({ modelKey, dimensions = "480x480", duration = 5, multiClip = false, }) {
99
- const modelConfig = aiModels_1.aiModelConfigs[modelKey];
100
- const cost = modelConfig.cost?.table?.[dimensions]?.[duration];
101
- if (cost === undefined || cost === null) {
102
- logger_1.logger.warn(`Azure getCreditUsed: no cost entry for modelKey="${modelKey}" dimensions="${dimensions}" duration=${duration} — returning fallback`, { modelKey, dimensions, duration });
103
- return (0, helpers_1.getCreditsFromCost)(1.0, !multiClip);
104
- }
105
- return (0, helpers_1.getCreditsFromCost)(cost, !multiClip);
106
- }
107
- }
108
- exports.AzureService = AzureService;
@@ -1,2 +0,0 @@
1
- export * from "./azure.service";
2
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/services/aiGen/providers/azure/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC"}
@@ -1,17 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./azure.service"), exports);