@umituz/web-ai 1.0.3 → 1.0.5
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/{AIErrors-B2ogd1PB.d.ts → AIErrors-CLjXRty-.d.ts} +99 -92
- package/dist/{AIErrors-C5EasV_c.d.cts → AIErrors-DjZXUiLT.d.cts} +99 -92
- package/dist/{cancellation-error-DwHrDKBz.d.cts → cancellation-error-Cj7fJyCg.d.cts} +3 -3
- package/dist/{cancellation-error-CKcZRhFg.d.ts → cancellation-error-CkMn5Kft.d.ts} +3 -3
- package/dist/chat/index.cjs.map +1 -1
- package/dist/chat/index.d.cts +3 -3
- package/dist/chat/index.d.ts +3 -3
- package/dist/chat/index.js.map +1 -1
- package/dist/{chat.service-CL1qtYxe.d.cts → chat.service-9M-KpLo-.d.cts} +1 -1
- package/dist/{chat.service-q05GnhEm.d.ts → chat.service-B4FLFxR1.d.ts} +1 -1
- package/dist/content/index.cjs +1047 -490
- package/dist/content/index.cjs.map +1 -1
- package/dist/content/index.d.cts +165 -219
- package/dist/content/index.d.ts +165 -219
- package/dist/content/index.js +983 -491
- package/dist/content/index.js.map +1 -1
- package/dist/{create-ai-9PW752z8.d.ts → create-ai-0eZFFqTw.d.ts} +1 -1
- package/dist/{create-ai-CXYKPK6G.d.cts → create-ai-BrKR_5fQ.d.cts} +1 -1
- package/dist/hooks/index.cjs +66 -8
- package/dist/hooks/index.cjs.map +1 -1
- package/dist/hooks/index.d.cts +21 -11
- package/dist/hooks/index.d.ts +21 -11
- package/dist/hooks/index.js +65 -9
- package/dist/hooks/index.js.map +1 -1
- package/dist/index-BUVULo3h.d.ts +177 -0
- package/dist/index-BulSkB2L.d.cts +177 -0
- package/dist/index.cjs +1800 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -5
- package/dist/index.d.ts +8 -5
- package/dist/index.js +1757 -15
- package/dist/index.js.map +1 -1
- package/dist/{provider.factory-DfDfk0dK.d.ts → provider.factory-BwPnqSEU.d.ts} +3 -1
- package/dist/{provider.factory-BxsfK4WW.d.cts → provider.factory-DyfJtR8M.d.cts} +3 -1
- package/dist/providers/index.cjs +9 -0
- package/dist/providers/index.cjs.map +1 -1
- package/dist/providers/index.d.cts +10 -8
- package/dist/providers/index.d.ts +10 -8
- package/dist/providers/index.js +7 -1
- package/dist/providers/index.js.map +1 -1
- package/dist/requestQueue-CkJ6Xc9K.d.cts +261 -0
- package/dist/requestQueue-CvxWxC-z.d.ts +261 -0
- package/dist/wizard/index.d.cts +2 -86
- package/dist/wizard/index.d.ts +2 -86
- package/package.json +16 -1
- package/dist/ContentGeneration-B6iK2B33.d.cts +0 -93
- package/dist/ContentGeneration-B6iK2B33.d.ts +0 -93
package/dist/index.js
CHANGED
|
@@ -1082,6 +1082,26 @@ function isMediaProvider(provider) {
|
|
|
1082
1082
|
return provider.capabilities.includes("image") || provider.capabilities.includes("video");
|
|
1083
1083
|
}
|
|
1084
1084
|
|
|
1085
|
+
// src/content/domain/errors/AIErrors.ts
|
|
1086
|
+
var ValidationError = class extends AIError {
|
|
1087
|
+
constructor(message) {
|
|
1088
|
+
super(message, "VALIDATION_ERROR");
|
|
1089
|
+
this.name = "ValidationError";
|
|
1090
|
+
}
|
|
1091
|
+
};
|
|
1092
|
+
var ProviderUnavailableError = class extends AIError {
|
|
1093
|
+
constructor(providerId) {
|
|
1094
|
+
super(`Provider ${providerId} is not available`, "PROVIDER_UNAVAILABLE");
|
|
1095
|
+
this.name = "ProviderUnavailableError";
|
|
1096
|
+
}
|
|
1097
|
+
};
|
|
1098
|
+
var ProviderQuotaExhaustedError = class extends AIError {
|
|
1099
|
+
constructor(providerId) {
|
|
1100
|
+
super(`Provider ${providerId} quota exhausted`, "PROVIDER_QUOTA_EXHAUSTED");
|
|
1101
|
+
this.name = "ProviderQuotaExhaustedError";
|
|
1102
|
+
}
|
|
1103
|
+
};
|
|
1104
|
+
|
|
1085
1105
|
// src/content/domain/limits/ProviderTimingConfig.ts
|
|
1086
1106
|
var ProviderTimingConfig = {
|
|
1087
1107
|
DEFAULT_TIMEOUT_MS: 3e4,
|
|
@@ -1424,6 +1444,9 @@ var ProviderFactory = class {
|
|
|
1424
1444
|
);
|
|
1425
1445
|
}
|
|
1426
1446
|
};
|
|
1447
|
+
function createProviderFactory(config) {
|
|
1448
|
+
return new ProviderFactory(config);
|
|
1449
|
+
}
|
|
1427
1450
|
|
|
1428
1451
|
// src/providers/anthropic/anthropic.constants.ts
|
|
1429
1452
|
var ANTHROPIC_MODELS = {
|
|
@@ -2453,6 +2476,9 @@ function toGroqMessages(messages, systemPrompt) {
|
|
|
2453
2476
|
}
|
|
2454
2477
|
return wire;
|
|
2455
2478
|
}
|
|
2479
|
+
function createGroqProvider(config) {
|
|
2480
|
+
return new GroqProvider(config);
|
|
2481
|
+
}
|
|
2456
2482
|
function findLastIndex2(items, predicate) {
|
|
2457
2483
|
for (let i = items.length - 1; i >= 0; i--) {
|
|
2458
2484
|
if (predicate(items[i])) return i;
|
|
@@ -2719,6 +2745,128 @@ function createGeminiProvider(config) {
|
|
|
2719
2745
|
return new GeminiProvider(config);
|
|
2720
2746
|
}
|
|
2721
2747
|
|
|
2748
|
+
// src/content/domain/predicates/KeywordProminenceClassifier.ts
|
|
2749
|
+
var HIGH_DENSITY_THRESHOLD = 2;
|
|
2750
|
+
var MEDIUM_DENSITY_THRESHOLD = 1;
|
|
2751
|
+
function classifyKeywordProminence(densityPercent) {
|
|
2752
|
+
if (densityPercent > HIGH_DENSITY_THRESHOLD) return "high";
|
|
2753
|
+
if (densityPercent > MEDIUM_DENSITY_THRESHOLD) return "medium";
|
|
2754
|
+
return "low";
|
|
2755
|
+
}
|
|
2756
|
+
function isUnderutilizedKeyword(densityPercent) {
|
|
2757
|
+
return densityPercent < 1;
|
|
2758
|
+
}
|
|
2759
|
+
|
|
2760
|
+
// src/content/domain/types/index.ts
|
|
2761
|
+
var PLATFORM_SPECS = {
|
|
2762
|
+
twitter: {
|
|
2763
|
+
maxLength: 280,
|
|
2764
|
+
style: "concise, engaging, thread-friendly",
|
|
2765
|
+
emojiSupport: true,
|
|
2766
|
+
hashtagSupport: true,
|
|
2767
|
+
imageSupport: true,
|
|
2768
|
+
videoSupport: true,
|
|
2769
|
+
maxHashtags: 5
|
|
2770
|
+
},
|
|
2771
|
+
linkedin: {
|
|
2772
|
+
maxLength: 3e3,
|
|
2773
|
+
style: "professional, insightful, industry-focused",
|
|
2774
|
+
emojiSupport: true,
|
|
2775
|
+
hashtagSupport: true,
|
|
2776
|
+
imageSupport: true,
|
|
2777
|
+
videoSupport: true,
|
|
2778
|
+
maxHashtags: 5
|
|
2779
|
+
},
|
|
2780
|
+
instagram: {
|
|
2781
|
+
maxLength: 2200,
|
|
2782
|
+
style: "visual, engaging, emoji-rich",
|
|
2783
|
+
emojiSupport: true,
|
|
2784
|
+
hashtagSupport: true,
|
|
2785
|
+
imageSupport: true,
|
|
2786
|
+
videoSupport: true,
|
|
2787
|
+
maxHashtags: 30
|
|
2788
|
+
},
|
|
2789
|
+
threads: {
|
|
2790
|
+
maxLength: 500,
|
|
2791
|
+
style: "conversational, community-driven",
|
|
2792
|
+
emojiSupport: true,
|
|
2793
|
+
hashtagSupport: true,
|
|
2794
|
+
imageSupport: true,
|
|
2795
|
+
videoSupport: true,
|
|
2796
|
+
maxHashtags: 5
|
|
2797
|
+
},
|
|
2798
|
+
tiktok: {
|
|
2799
|
+
maxLength: 150,
|
|
2800
|
+
style: "catchy, trending, short-form",
|
|
2801
|
+
emojiSupport: true,
|
|
2802
|
+
hashtagSupport: true,
|
|
2803
|
+
imageSupport: false,
|
|
2804
|
+
videoSupport: true,
|
|
2805
|
+
maxHashtags: 5
|
|
2806
|
+
},
|
|
2807
|
+
facebook: {
|
|
2808
|
+
maxLength: 63206,
|
|
2809
|
+
style: "conversational, engaging, shareable",
|
|
2810
|
+
emojiSupport: true,
|
|
2811
|
+
hashtagSupport: true,
|
|
2812
|
+
imageSupport: true,
|
|
2813
|
+
videoSupport: true,
|
|
2814
|
+
maxHashtags: 5
|
|
2815
|
+
}
|
|
2816
|
+
};
|
|
2817
|
+
|
|
2818
|
+
// src/content/domain/predicates/HashtagPriorityRanker.ts
|
|
2819
|
+
var DEFAULT_HASHTAG_BUDGET = Number.MAX_SAFE_INTEGER;
|
|
2820
|
+
function resolveHashtagBudget(platform) {
|
|
2821
|
+
return PLATFORM_SPECS[platform]?.maxHashtags ?? DEFAULT_HASHTAG_BUDGET;
|
|
2822
|
+
}
|
|
2823
|
+
function rankAndTrimHashtags(hashtags, budget) {
|
|
2824
|
+
if (hashtags.length <= budget) return [...hashtags];
|
|
2825
|
+
return [...hashtags].sort((a, b) => b.length - a.length).slice(0, budget);
|
|
2826
|
+
}
|
|
2827
|
+
|
|
2828
|
+
// src/content/domain/predicates/QualityRecommenderByRatio.ts
|
|
2829
|
+
var WIDE_RATIOS = /* @__PURE__ */ new Set(["16:9", "4:3"]);
|
|
2830
|
+
function recommendQualityForAspectRatio(ratio) {
|
|
2831
|
+
return WIDE_RATIOS.has(ratio) ? "hd" : "standard";
|
|
2832
|
+
}
|
|
2833
|
+
|
|
2834
|
+
// src/content/domain/predicates/PlatformSpecResolver.ts
|
|
2835
|
+
var FALLBACK_SPEC = {
|
|
2836
|
+
maxLength: 280,
|
|
2837
|
+
style: "concise, engaging, audience-friendly",
|
|
2838
|
+
emojiSupport: true,
|
|
2839
|
+
hashtagSupport: true,
|
|
2840
|
+
imageSupport: true,
|
|
2841
|
+
videoSupport: true,
|
|
2842
|
+
maxHashtags: 5
|
|
2843
|
+
};
|
|
2844
|
+
function resolvePlatformSpec(platform) {
|
|
2845
|
+
return PLATFORM_SPECS[platform] ?? FALLBACK_SPEC;
|
|
2846
|
+
}
|
|
2847
|
+
function resolveMaxContentLength(platform, override) {
|
|
2848
|
+
return override ?? resolvePlatformSpec(platform).maxLength;
|
|
2849
|
+
}
|
|
2850
|
+
|
|
2851
|
+
// src/content/domain/predicates/ScoreRangeGuard.ts
|
|
2852
|
+
var SCORE_MIN = 0;
|
|
2853
|
+
var SCORE_MAX = 100;
|
|
2854
|
+
var SCORE_FALLBACK = 50;
|
|
2855
|
+
var CONFIDENCE_MIN = 0;
|
|
2856
|
+
var CONFIDENCE_MAX = 1;
|
|
2857
|
+
var CONFIDENCE_FALLBACK = 0.5;
|
|
2858
|
+
function clampScoreToValidRange(score, fallback = SCORE_FALLBACK) {
|
|
2859
|
+
if (!Number.isFinite(score)) return fallback;
|
|
2860
|
+
return Math.max(SCORE_MIN, Math.min(SCORE_MAX, score));
|
|
2861
|
+
}
|
|
2862
|
+
function clampConfidenceToValidRange(confidence, fallback = CONFIDENCE_FALLBACK) {
|
|
2863
|
+
if (!Number.isFinite(confidence)) return fallback;
|
|
2864
|
+
return Math.max(CONFIDENCE_MIN, Math.min(CONFIDENCE_MAX, confidence));
|
|
2865
|
+
}
|
|
2866
|
+
|
|
2867
|
+
// src/content/domain/predicates/AbTestConfidence.ts
|
|
2868
|
+
var AB_TEST_DEFAULT_CONFIDENCE = 0.7;
|
|
2869
|
+
|
|
2722
2870
|
// src/content/domain/predicates/FalImageRenderingOptions.ts
|
|
2723
2871
|
var FAL_FORMAT_TO_IMAGE_SIZE = {
|
|
2724
2872
|
square: "square_hd",
|
|
@@ -2989,7 +3137,7 @@ var TimeoutError = class extends Error {
|
|
|
2989
3137
|
};
|
|
2990
3138
|
|
|
2991
3139
|
// src/providers/pruna/client/core/errors/validation-error.ts
|
|
2992
|
-
var
|
|
3140
|
+
var ValidationError2 = class extends Error {
|
|
2993
3141
|
field;
|
|
2994
3142
|
reason;
|
|
2995
3143
|
receivedValue;
|
|
@@ -3274,21 +3422,21 @@ function deriveGenerationCacheKey(apiKey, input) {
|
|
|
3274
3422
|
// src/providers/pruna/client/core/validation/api-key-validator.ts
|
|
3275
3423
|
function assertValidApiKey(apiKey) {
|
|
3276
3424
|
if (typeof apiKey !== "string") {
|
|
3277
|
-
throw new
|
|
3425
|
+
throw new ValidationError2({
|
|
3278
3426
|
field: "apiKey",
|
|
3279
3427
|
reason: "must be a string",
|
|
3280
3428
|
receivedValue: typeof apiKey
|
|
3281
3429
|
});
|
|
3282
3430
|
}
|
|
3283
3431
|
if (apiKey.length < MIN_API_KEY_LENGTH) {
|
|
3284
|
-
throw new
|
|
3432
|
+
throw new ValidationError2({
|
|
3285
3433
|
field: "apiKey",
|
|
3286
3434
|
reason: "must not be empty",
|
|
3287
3435
|
receivedValue: apiKey
|
|
3288
3436
|
});
|
|
3289
3437
|
}
|
|
3290
3438
|
if (apiKey.length > MAX_API_KEY_LENGTH) {
|
|
3291
|
-
throw new
|
|
3439
|
+
throw new ValidationError2({
|
|
3292
3440
|
field: "apiKey",
|
|
3293
3441
|
reason: `exceeds maximum length of ${MAX_API_KEY_LENGTH}`,
|
|
3294
3442
|
receivedValue: apiKey.length
|
|
@@ -3305,7 +3453,7 @@ function classifyImageSource(source) {
|
|
|
3305
3453
|
}
|
|
3306
3454
|
function assertSecureImageSource(image, fieldName = "image") {
|
|
3307
3455
|
if (typeof image !== "string") {
|
|
3308
|
-
throw new
|
|
3456
|
+
throw new ValidationError2({
|
|
3309
3457
|
field: fieldName,
|
|
3310
3458
|
reason: "must be a string",
|
|
3311
3459
|
receivedValue: typeof image
|
|
@@ -3313,14 +3461,14 @@ function assertSecureImageSource(image, fieldName = "image") {
|
|
|
3313
3461
|
}
|
|
3314
3462
|
const kind = classifyImageSource(image);
|
|
3315
3463
|
if (kind === "http-url") {
|
|
3316
|
-
throw new
|
|
3464
|
+
throw new ValidationError2({
|
|
3317
3465
|
field: fieldName,
|
|
3318
3466
|
reason: "HTTP URLs are not supported; use HTTPS or a base64 data URI",
|
|
3319
3467
|
receivedValue: image
|
|
3320
3468
|
});
|
|
3321
3469
|
}
|
|
3322
3470
|
if (kind === "unknown") {
|
|
3323
|
-
throw new
|
|
3471
|
+
throw new ValidationError2({
|
|
3324
3472
|
field: fieldName,
|
|
3325
3473
|
reason: "must be an HTTPS URL or a base64 data URI",
|
|
3326
3474
|
receivedValue: typeof image
|
|
@@ -3344,7 +3492,7 @@ function isSupportedAspectRatio(value) {
|
|
|
3344
3492
|
function assertValidAspectRatio(value, fieldName = "aspect_ratio") {
|
|
3345
3493
|
if (value === void 0 || value === null) return;
|
|
3346
3494
|
if (!isSupportedAspectRatio(value)) {
|
|
3347
|
-
throw new
|
|
3495
|
+
throw new ValidationError2({
|
|
3348
3496
|
field: fieldName,
|
|
3349
3497
|
reason: `must be one of ${SUPPORTED_ASPECT_RATIOS.join(", ")}`,
|
|
3350
3498
|
receivedValue: value
|
|
@@ -3360,7 +3508,7 @@ function isSupportedResolution(value) {
|
|
|
3360
3508
|
function assertValidResolution(value, fieldName = "resolution") {
|
|
3361
3509
|
if (value === void 0 || value === null) return;
|
|
3362
3510
|
if (!isSupportedResolution(value)) {
|
|
3363
|
-
throw new
|
|
3511
|
+
throw new ValidationError2({
|
|
3364
3512
|
field: fieldName,
|
|
3365
3513
|
reason: `must be one of ${SUPPORTED_RESOLUTIONS.join(", ")}`,
|
|
3366
3514
|
receivedValue: value
|
|
@@ -3377,7 +3525,7 @@ function isValidDuration(value) {
|
|
|
3377
3525
|
function assertValidDuration(value, fieldName = "duration") {
|
|
3378
3526
|
if (value === void 0 || value === null) return;
|
|
3379
3527
|
if (!isValidDuration(value)) {
|
|
3380
|
-
throw new
|
|
3528
|
+
throw new ValidationError2({
|
|
3381
3529
|
field: fieldName,
|
|
3382
3530
|
reason: `must be an integer between ${MIN_VIDEO_DURATION_SECONDS} and ${MAX_VIDEO_DURATION_SECONDS} seconds`,
|
|
3383
3531
|
receivedValue: value
|
|
@@ -3390,21 +3538,21 @@ var MIN_PROMPT_LENGTH = 1;
|
|
|
3390
3538
|
var MAX_PROMPT_LENGTH = 4e3;
|
|
3391
3539
|
function assertValidPrompt(value, fieldName = "prompt") {
|
|
3392
3540
|
if (typeof value !== "string") {
|
|
3393
|
-
throw new
|
|
3541
|
+
throw new ValidationError2({
|
|
3394
3542
|
field: fieldName,
|
|
3395
3543
|
reason: "must be a string",
|
|
3396
3544
|
receivedValue: typeof value
|
|
3397
3545
|
});
|
|
3398
3546
|
}
|
|
3399
3547
|
if (value.trim().length < MIN_PROMPT_LENGTH) {
|
|
3400
|
-
throw new
|
|
3548
|
+
throw new ValidationError2({
|
|
3401
3549
|
field: fieldName,
|
|
3402
3550
|
reason: "must not be empty or whitespace-only",
|
|
3403
3551
|
receivedValue: value
|
|
3404
3552
|
});
|
|
3405
3553
|
}
|
|
3406
3554
|
if (value.length > MAX_PROMPT_LENGTH) {
|
|
3407
|
-
throw new
|
|
3555
|
+
throw new ValidationError2({
|
|
3408
3556
|
field: fieldName,
|
|
3409
3557
|
reason: `exceeds maximum length of ${MAX_PROMPT_LENGTH} characters`,
|
|
3410
3558
|
receivedValue: value.length
|
|
@@ -3421,7 +3569,7 @@ function isValidSeed(value) {
|
|
|
3421
3569
|
function assertValidSeed(value, fieldName = "seed") {
|
|
3422
3570
|
if (value === void 0 || value === null) return;
|
|
3423
3571
|
if (!isValidSeed(value)) {
|
|
3424
|
-
throw new
|
|
3572
|
+
throw new ValidationError2({
|
|
3425
3573
|
field: fieldName,
|
|
3426
3574
|
reason: `must be an integer in [${MIN_SEED}, ${MAX_SEED}]`,
|
|
3427
3575
|
receivedValue: value
|
|
@@ -4355,6 +4503,1600 @@ function resetProvider() {
|
|
|
4355
4503
|
container = null;
|
|
4356
4504
|
}
|
|
4357
4505
|
|
|
4358
|
-
|
|
4506
|
+
// src/content/domain/calculations/ContentCreditCost.ts
|
|
4507
|
+
var CREDIT_COSTS = {
|
|
4508
|
+
"text-to-image": { standard: 1, hd: 2, "4k": 4 },
|
|
4509
|
+
"image-to-image": { standard: 1, hd: 2, "4k": 4 },
|
|
4510
|
+
"image-to-video": { standard: 3, hd: 5, "4k": 8 },
|
|
4511
|
+
"text-to-video": { standard: 5, hd: 8, "4k": 12 }
|
|
4512
|
+
};
|
|
4513
|
+
var DEFAULT_CREDIT_COST = 0;
|
|
4514
|
+
function toQualityTier(quality) {
|
|
4515
|
+
if (quality === "4k") return "4k";
|
|
4516
|
+
if (quality === "hd" || quality === "1080p") return "hd";
|
|
4517
|
+
return "standard";
|
|
4518
|
+
}
|
|
4519
|
+
function calculateContentCreditCost(type, quality = "standard") {
|
|
4520
|
+
const tierCosts = CREDIT_COSTS[type];
|
|
4521
|
+
if (!tierCosts) return DEFAULT_CREDIT_COST;
|
|
4522
|
+
return tierCosts[toQualityTier(quality)] ?? tierCosts.standard;
|
|
4523
|
+
}
|
|
4524
|
+
|
|
4525
|
+
// src/content/domain/limits/ImageFormatOptions.ts
|
|
4526
|
+
var ASPECT_RATIO_OPTIONS = [
|
|
4527
|
+
{ value: "1:1", label: "Square", width: 1024, height: 1024 },
|
|
4528
|
+
{ value: "16:9", label: "Landscape", width: 1920, height: 1080 },
|
|
4529
|
+
{ value: "9:16", label: "Portrait", width: 1080, height: 1920 },
|
|
4530
|
+
{ value: "4:3", label: "Standard", width: 1440, height: 1080 },
|
|
4531
|
+
{ value: "3:4", label: "Tall", width: 1080, height: 1440 }
|
|
4532
|
+
];
|
|
4533
|
+
var IMAGE_QUALITY_OPTIONS = [
|
|
4534
|
+
{ value: "standard", label: "Standard", description: "1024x1024, good quality", resolution: "1024x1024" },
|
|
4535
|
+
{ value: "hd", label: "HD", description: "1920x1080, high quality", resolution: "1920x1080" },
|
|
4536
|
+
{ value: "4k", label: "4K", description: "3840x2160, ultra quality", resolution: "3840x2160" }
|
|
4537
|
+
];
|
|
4538
|
+
var VIDEO_QUALITY_OPTIONS = [
|
|
4539
|
+
{ value: "720p", label: "720p HD", resolution: "1280x720" },
|
|
4540
|
+
{ value: "1080p", label: "1080p Full HD", resolution: "1920x1080" },
|
|
4541
|
+
{ value: "4k", label: "4K Ultra HD", resolution: "3840x2160" }
|
|
4542
|
+
];
|
|
4543
|
+
var VIDEO_DURATION_OPTIONS_SECONDS = [2, 3, 4, 5, 6, 7, 8, 9, 10];
|
|
4544
|
+
var MOTION_OPTIONS = [
|
|
4545
|
+
{ value: "slow", label: "Slow", description: "Gentle movement" },
|
|
4546
|
+
{ value: "medium", label: "Medium", description: "Balanced motion" },
|
|
4547
|
+
{ value: "fast", label: "Fast", description: "Dynamic movement" }
|
|
4548
|
+
];
|
|
4549
|
+
var STYLE_PRESETS = [
|
|
4550
|
+
{ value: "realistic", label: "Realistic", promptFragment: "realistic, photograph, detailed" },
|
|
4551
|
+
{ value: "artistic", label: "Artistic", promptFragment: "artistic, painting, creative" },
|
|
4552
|
+
{ value: "anime", label: "Anime", promptFragment: "anime style, manga, vibrant colors" },
|
|
4553
|
+
{ value: "cinematic", label: "Cinematic", promptFragment: "cinematic, movie scene, dramatic lighting" },
|
|
4554
|
+
{ value: "vintage", label: "Vintage", promptFragment: "vintage, retro, film grain" },
|
|
4555
|
+
{ value: "fantasy", label: "Fantasy", promptFragment: "fantasy, magical, ethereal" },
|
|
4556
|
+
{ value: "minimalist", label: "Minimalist", promptFragment: "minimalist, clean, simple" },
|
|
4557
|
+
{ value: "abstract", label: "Abstract", promptFragment: "abstract, geometric, artistic" }
|
|
4558
|
+
];
|
|
4559
|
+
|
|
4560
|
+
// src/content/domain/calculations/AspectRatioDimensions.ts
|
|
4561
|
+
var FALLBACK_DIMENSIONS = { width: 1024, height: 1024 };
|
|
4562
|
+
function resolveDimensionsForAspectRatio(ratio) {
|
|
4563
|
+
const match = ASPECT_RATIO_OPTIONS.find((option) => option.value === ratio);
|
|
4564
|
+
return match ? { width: match.width, height: match.height } : FALLBACK_DIMENSIONS;
|
|
4565
|
+
}
|
|
4566
|
+
|
|
4567
|
+
// src/content/domain/constants/GenerationConstants.ts
|
|
4568
|
+
var ASPECT_RATIO_VALUES = ASPECT_RATIO_OPTIONS.map((o) => o.value);
|
|
4569
|
+
var IMAGE_QUALITY_VALUES = IMAGE_QUALITY_OPTIONS.map((o) => o.value);
|
|
4570
|
+
var VIDEO_QUALITY_VALUES = VIDEO_QUALITY_OPTIONS.map((o) => o.value);
|
|
4571
|
+
var VIDEO_DURATION_OPTIONS = VIDEO_DURATION_OPTIONS_SECONDS;
|
|
4572
|
+
var getDimensionsForAspectRatio = resolveDimensionsForAspectRatio;
|
|
4573
|
+
var getRecommendedQuality = recommendQualityForAspectRatio;
|
|
4574
|
+
|
|
4575
|
+
// src/content/domain/limits/ValidationLimits.ts
|
|
4576
|
+
var ValidationLimits = {
|
|
4577
|
+
TOPIC: {
|
|
4578
|
+
MIN: 1,
|
|
4579
|
+
MAX: 500
|
|
4580
|
+
},
|
|
4581
|
+
CONTENT: {
|
|
4582
|
+
MIN: 1,
|
|
4583
|
+
MAX: 1e4
|
|
4584
|
+
},
|
|
4585
|
+
KEYWORD: {
|
|
4586
|
+
MAX_COUNT: 20,
|
|
4587
|
+
MAX_LENGTH: 50
|
|
4588
|
+
},
|
|
4589
|
+
DURATION_SECONDS: {
|
|
4590
|
+
MIN: 10,
|
|
4591
|
+
MAX: 600
|
|
4592
|
+
},
|
|
4593
|
+
CALENDAR_DAYS: {
|
|
4594
|
+
MIN: 1,
|
|
4595
|
+
MAX: 90
|
|
4596
|
+
},
|
|
4597
|
+
HASHTAG_COUNT: {
|
|
4598
|
+
MIN: 1,
|
|
4599
|
+
MAX: 50
|
|
4600
|
+
},
|
|
4601
|
+
SEO_CONTENT_PREVIEW: 500,
|
|
4602
|
+
BLOG_PROMPT_PREVIEW: 1e3,
|
|
4603
|
+
AB_VARIANT_CONTENT_PREVIEW: 200
|
|
4604
|
+
};
|
|
4605
|
+
|
|
4606
|
+
// src/content/domain/limits/SpeechPaceConfig.ts
|
|
4607
|
+
var SpeechPaceConfig = {
|
|
4608
|
+
WORDS_PER_SECOND: 2.5,
|
|
4609
|
+
TOKENS_PER_SECOND: 10,
|
|
4610
|
+
JSON_TOKEN_OVERHEAD: 500,
|
|
4611
|
+
TOKENS_PER_CALENDAR_DAY: 150
|
|
4612
|
+
};
|
|
4613
|
+
|
|
4614
|
+
// src/content/domain/calculations/SpeechPaceEstimate.ts
|
|
4615
|
+
function estimateWordCountForDuration(durationSeconds) {
|
|
4616
|
+
return Math.floor(durationSeconds * SpeechPaceConfig.WORDS_PER_SECOND);
|
|
4617
|
+
}
|
|
4618
|
+
function estimateTokenBudgetForDuration(durationSeconds) {
|
|
4619
|
+
return durationSeconds * SpeechPaceConfig.TOKENS_PER_SECOND + SpeechPaceConfig.JSON_TOKEN_OVERHEAD;
|
|
4620
|
+
}
|
|
4621
|
+
function estimateTokenBudgetForCalendarDays(days) {
|
|
4622
|
+
return days * SpeechPaceConfig.TOKENS_PER_CALENDAR_DAY + SpeechPaceConfig.JSON_TOKEN_OVERHEAD;
|
|
4623
|
+
}
|
|
4624
|
+
|
|
4625
|
+
// src/content/domain/calculations/SeoKeywordDensity.ts
|
|
4626
|
+
function countKeywordOccurrences(content, keyword) {
|
|
4627
|
+
if (!keyword) return 0;
|
|
4628
|
+
const escaped = keyword.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
4629
|
+
const matches = content.match(new RegExp(escaped, "gi"));
|
|
4630
|
+
return matches ? matches.length : 0;
|
|
4631
|
+
}
|
|
4632
|
+
function countWordsInContent(content) {
|
|
4633
|
+
const tokens = content.split(/\s+/).filter(Boolean);
|
|
4634
|
+
return tokens.length || 1;
|
|
4635
|
+
}
|
|
4636
|
+
function calculateKeywordDensity(content, keyword) {
|
|
4637
|
+
const totalWords = countWordsInContent(content);
|
|
4638
|
+
const occurrences = countKeywordOccurrences(content, keyword);
|
|
4639
|
+
return occurrences / totalWords * 100;
|
|
4640
|
+
}
|
|
4641
|
+
|
|
4642
|
+
// src/content/domain/calculations/AbTestImprovementRatio.ts
|
|
4643
|
+
function calculateImprovementPercentage(scoreA, scoreB) {
|
|
4644
|
+
const higher = Math.max(scoreA, scoreB);
|
|
4645
|
+
const lower = Math.min(scoreA, scoreB);
|
|
4646
|
+
if (lower <= 0) {
|
|
4647
|
+
return "100";
|
|
4648
|
+
}
|
|
4649
|
+
const delta = (higher / lower - 1) * 100;
|
|
4650
|
+
return Math.abs(delta).toFixed(0);
|
|
4651
|
+
}
|
|
4652
|
+
function selectHigherScoreVariantId(scoreA, scoreB, idA = "A", idB = "B") {
|
|
4653
|
+
return scoreA > scoreB ? idA : idB;
|
|
4654
|
+
}
|
|
4655
|
+
|
|
4656
|
+
// src/content/domain/calculations/ContentCalendarDateOffset.ts
|
|
4657
|
+
var ONE_DAY_MS = 24 * 60 * 60 * 1e3;
|
|
4658
|
+
function resolveCalendarEntryDate(dayIndex, baseTimestamp = Date.now()) {
|
|
4659
|
+
return new Date(baseTimestamp + (dayIndex - 1) * ONE_DAY_MS);
|
|
4660
|
+
}
|
|
4661
|
+
|
|
4662
|
+
// src/content/domain/validation/TopicTextValidator.ts
|
|
4663
|
+
function validateTopicText(topic) {
|
|
4664
|
+
if (typeof topic !== "string" || topic.trim().length < ValidationLimits.TOPIC.MIN) {
|
|
4665
|
+
throw new ValidationError("Topic cannot be empty");
|
|
4666
|
+
}
|
|
4667
|
+
const trimmed = topic.trim();
|
|
4668
|
+
if (trimmed.length > ValidationLimits.TOPIC.MAX) {
|
|
4669
|
+
throw new ValidationError(`Topic exceeds maximum length of ${ValidationLimits.TOPIC.MAX} characters`);
|
|
4670
|
+
}
|
|
4671
|
+
return trimmed;
|
|
4672
|
+
}
|
|
4673
|
+
|
|
4674
|
+
// src/content/domain/validation/ContentBodyValidator.ts
|
|
4675
|
+
function validateContentBody(content) {
|
|
4676
|
+
if (typeof content !== "string" || content.trim().length < ValidationLimits.CONTENT.MIN) {
|
|
4677
|
+
throw new ValidationError("Content cannot be empty");
|
|
4678
|
+
}
|
|
4679
|
+
const trimmed = content.trim();
|
|
4680
|
+
if (trimmed.length > ValidationLimits.CONTENT.MAX) {
|
|
4681
|
+
throw new ValidationError(`Content exceeds maximum length of ${ValidationLimits.CONTENT.MAX} characters`);
|
|
4682
|
+
}
|
|
4683
|
+
return trimmed;
|
|
4684
|
+
}
|
|
4685
|
+
function truncateForSeoPreview(content) {
|
|
4686
|
+
return content.substring(0, ValidationLimits.SEO_CONTENT_PREVIEW);
|
|
4687
|
+
}
|
|
4688
|
+
function truncateForBlogPromptPreview(content) {
|
|
4689
|
+
return content.substring(0, ValidationLimits.BLOG_PROMPT_PREVIEW);
|
|
4690
|
+
}
|
|
4691
|
+
function truncateForAbVariantPreview(content) {
|
|
4692
|
+
return content.substring(0, ValidationLimits.AB_VARIANT_CONTENT_PREVIEW);
|
|
4693
|
+
}
|
|
4694
|
+
|
|
4695
|
+
// src/content/domain/validation/KeywordListValidator.ts
|
|
4696
|
+
function validateKeywordList(keywords) {
|
|
4697
|
+
if (!Array.isArray(keywords)) {
|
|
4698
|
+
throw new ValidationError("Keywords must be an array");
|
|
4699
|
+
}
|
|
4700
|
+
if (keywords.length > ValidationLimits.KEYWORD.MAX_COUNT) {
|
|
4701
|
+
throw new ValidationError(`Cannot process more than ${ValidationLimits.KEYWORD.MAX_COUNT} keywords`);
|
|
4702
|
+
}
|
|
4703
|
+
return keywords.filter((k) => typeof k === "string" && k.trim().length > 0).map((keyword) => {
|
|
4704
|
+
const trimmed = keyword.trim();
|
|
4705
|
+
if (trimmed.length > ValidationLimits.KEYWORD.MAX_LENGTH) {
|
|
4706
|
+
const preview = trimmed.substring(0, 20);
|
|
4707
|
+
throw new ValidationError(
|
|
4708
|
+
`Keyword "${preview}..." exceeds maximum length of ${ValidationLimits.KEYWORD.MAX_LENGTH} characters`
|
|
4709
|
+
);
|
|
4710
|
+
}
|
|
4711
|
+
return trimmed;
|
|
4712
|
+
});
|
|
4713
|
+
}
|
|
4714
|
+
|
|
4715
|
+
// src/content/domain/validation/DurationSecondsValidator.ts
|
|
4716
|
+
function validateDurationSeconds(duration) {
|
|
4717
|
+
if (!Number.isFinite(duration)) {
|
|
4718
|
+
throw new ValidationError(
|
|
4719
|
+
`Duration must be between ${ValidationLimits.DURATION_SECONDS.MIN} and ${ValidationLimits.DURATION_SECONDS.MAX} seconds`
|
|
4720
|
+
);
|
|
4721
|
+
}
|
|
4722
|
+
if (duration < ValidationLimits.DURATION_SECONDS.MIN || duration > ValidationLimits.DURATION_SECONDS.MAX) {
|
|
4723
|
+
throw new ValidationError(
|
|
4724
|
+
`Duration must be between ${ValidationLimits.DURATION_SECONDS.MIN} and ${ValidationLimits.DURATION_SECONDS.MAX} seconds`
|
|
4725
|
+
);
|
|
4726
|
+
}
|
|
4727
|
+
return duration;
|
|
4728
|
+
}
|
|
4729
|
+
|
|
4730
|
+
// src/content/domain/validation/CalendarDaysValidator.ts
|
|
4731
|
+
function validateCalendarDays(days) {
|
|
4732
|
+
if (!Number.isFinite(days)) {
|
|
4733
|
+
throw new ValidationError(
|
|
4734
|
+
`Days must be between ${ValidationLimits.CALENDAR_DAYS.MIN} and ${ValidationLimits.CALENDAR_DAYS.MAX}`
|
|
4735
|
+
);
|
|
4736
|
+
}
|
|
4737
|
+
if (days < ValidationLimits.CALENDAR_DAYS.MIN || days > ValidationLimits.CALENDAR_DAYS.MAX) {
|
|
4738
|
+
throw new ValidationError(
|
|
4739
|
+
`Days must be between ${ValidationLimits.CALENDAR_DAYS.MIN} and ${ValidationLimits.CALENDAR_DAYS.MAX}`
|
|
4740
|
+
);
|
|
4741
|
+
}
|
|
4742
|
+
return days;
|
|
4743
|
+
}
|
|
4744
|
+
|
|
4745
|
+
// src/content/domain/validation/HashtagCountValidator.ts
|
|
4746
|
+
function validateHashtagCount(count) {
|
|
4747
|
+
if (!Number.isFinite(count)) {
|
|
4748
|
+
throw new ValidationError(
|
|
4749
|
+
`Hashtag count must be between ${ValidationLimits.HASHTAG_COUNT.MIN} and ${ValidationLimits.HASHTAG_COUNT.MAX}`
|
|
4750
|
+
);
|
|
4751
|
+
}
|
|
4752
|
+
if (count < ValidationLimits.HASHTAG_COUNT.MIN || count > ValidationLimits.HASHTAG_COUNT.MAX) {
|
|
4753
|
+
throw new ValidationError(
|
|
4754
|
+
`Hashtag count must be between ${ValidationLimits.HASHTAG_COUNT.MIN} and ${ValidationLimits.HASHTAG_COUNT.MAX}`
|
|
4755
|
+
);
|
|
4756
|
+
}
|
|
4757
|
+
return Math.floor(count);
|
|
4758
|
+
}
|
|
4759
|
+
|
|
4760
|
+
// src/content/domain/utils/IdGenerator.ts
|
|
4761
|
+
function generateId(prefix) {
|
|
4762
|
+
const id = typeof crypto !== "undefined" && typeof crypto.randomUUID === "function" ? crypto.randomUUID() : `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 11)}`;
|
|
4763
|
+
return prefix ? `${prefix}-${id}` : id;
|
|
4764
|
+
}
|
|
4765
|
+
|
|
4766
|
+
// src/content/application/prompts/PromptBuilder.ts
|
|
4767
|
+
var PromptBuilder = class {
|
|
4768
|
+
static blogPost(input) {
|
|
4769
|
+
return `
|
|
4770
|
+
As an expert SEO Content Strategist and Copywriter, generate a high-quality, comprehensive blog post.
|
|
4771
|
+
|
|
4772
|
+
TOPIC: ${input.topic}
|
|
4773
|
+
TYPE: ${input.blogType}
|
|
4774
|
+
KEYWORDS: ${input.keywords.join(", ")}
|
|
4775
|
+
TONE: ${input.tone}
|
|
4776
|
+
TARGET AUDIENCE: ${input.targetAudience}
|
|
4777
|
+
WORD COUNT: ${input.wordCount}
|
|
4778
|
+
LANGUAGE: ${input.language || "English"}
|
|
4779
|
+
|
|
4780
|
+
OPTIMIZATION REQUIREMENTS:
|
|
4781
|
+
- SEO Optimization: ${input.seoOptimization ? "ON (Include semantic keywords, LSI, and proper H1-H3 structure)" : "OFF"}
|
|
4782
|
+
- Include Schema Markup: ${input.includeSchema ? "ON (Generate JSON-LD for this blog type)" : "OFF"}
|
|
4783
|
+
- Image Suggestions: ${input.includeImages ? "ON (Provide DALL-E/Midjourney style prompts for contextually relevant images)" : "OFF"}
|
|
4784
|
+
|
|
4785
|
+
RESPONSE FORMAT (STRICT JSON ONLY):
|
|
4786
|
+
{
|
|
4787
|
+
"title": "Compelling, Click-worthy Title",
|
|
4788
|
+
"content": "Full markdown-formatted blog content with headers",
|
|
4789
|
+
"metaDescription": "SEO-optimized description (150-160 chars)",
|
|
4790
|
+
"seoScore": 0-100,
|
|
4791
|
+
"readabilityScore": 0-100,
|
|
4792
|
+
"keywords": ["list", "of", "optimized", "keywords"],
|
|
4793
|
+
"performance": {
|
|
4794
|
+
"readingTime": minutes (number),
|
|
4795
|
+
"shareability": 0-10 (number),
|
|
4796
|
+
"seoRank": 0-10 (number)
|
|
4797
|
+
},
|
|
4798
|
+
"schemaMarkup": "JSON-LD string (if requested)",
|
|
4799
|
+
"imagePrompts": ["Prompt 1", "Prompt 2"] (if requested)
|
|
4800
|
+
}
|
|
4801
|
+
`;
|
|
4802
|
+
}
|
|
4803
|
+
static socialPost(input) {
|
|
4804
|
+
return `
|
|
4805
|
+
Write a ${input.tone} social media post about: ${input.topic}
|
|
4806
|
+
|
|
4807
|
+
Platform: ${input.platform}
|
|
4808
|
+
Style: ${input.style}
|
|
4809
|
+
Maximum length: ${input.maxLength} characters
|
|
4810
|
+
${input.includeHashtags ? "Include relevant hashtags" : "No hashtags"}
|
|
4811
|
+
${input.includeCallToAction ? "Include a call-to-action" : ""}
|
|
4812
|
+
|
|
4813
|
+
Requirements:
|
|
4814
|
+
- Platform-optimized formatting
|
|
4815
|
+
- Engaging hook in first sentence
|
|
4816
|
+
- Natural, conversational tone
|
|
4817
|
+
- Platform-appropriate emoji usage
|
|
4818
|
+
|
|
4819
|
+
Generate the post in JSON format:
|
|
4820
|
+
{
|
|
4821
|
+
"content": "The post content",
|
|
4822
|
+
"hashtags": ["hashtag1", "hashtag2"],
|
|
4823
|
+
"emojis": ["emoji1", "emoji2"],
|
|
4824
|
+
"estimatedEngagement": 0-100
|
|
4825
|
+
}
|
|
4826
|
+
`;
|
|
4827
|
+
}
|
|
4828
|
+
static videoScript(input) {
|
|
4829
|
+
return `
|
|
4830
|
+
Create a ${input.tone} video script about: ${input.topic}
|
|
4831
|
+
|
|
4832
|
+
Duration: ${input.duration} seconds
|
|
4833
|
+
Target Audience: ${input.targetAudience}
|
|
4834
|
+
Include Visual Cues: ${input.includeVisuals ? "Yes" : "No"}
|
|
4835
|
+
Include CTA: ${input.includeCallToAction ? "Yes" : "No"}
|
|
4836
|
+
|
|
4837
|
+
Approximate word count: ${estimateWordCountForDuration(input.duration)} words
|
|
4838
|
+
|
|
4839
|
+
Generate in JSON format:
|
|
4840
|
+
{
|
|
4841
|
+
"script": "Full script with dialogue and narration",
|
|
4842
|
+
"visualCues": ["Visual cue 1", "Visual cue 2"],
|
|
4843
|
+
"callToAction": "Call to action text (if requested)",
|
|
4844
|
+
"estimatedEngagement": 0-100
|
|
4845
|
+
}
|
|
4846
|
+
`;
|
|
4847
|
+
}
|
|
4848
|
+
static voiceScript(input) {
|
|
4849
|
+
return `
|
|
4850
|
+
Create a ${input.emotion} voice script about: ${input.topic}
|
|
4851
|
+
|
|
4852
|
+
Duration: ${input.duration} seconds
|
|
4853
|
+
Emotion: ${input.emotion}
|
|
4854
|
+
|
|
4855
|
+
The script should:
|
|
4856
|
+
- Evoke the specified emotion
|
|
4857
|
+
- Be suitable for voice recording with emotion control
|
|
4858
|
+
- Include natural speech patterns
|
|
4859
|
+
- Have appropriate pacing for the emotion
|
|
4860
|
+
- Include emotional cues in brackets where needed
|
|
4861
|
+
|
|
4862
|
+
Approximate word count: ${estimateWordCountForDuration(input.duration)} words
|
|
4863
|
+
|
|
4864
|
+
Generate in JSON format:
|
|
4865
|
+
{
|
|
4866
|
+
"script": "Full script with emotional cues",
|
|
4867
|
+
"visualCues": ["Visual cue 1", "Visual cue 2"],
|
|
4868
|
+
"estimatedEngagement": 0-100
|
|
4869
|
+
}
|
|
4870
|
+
`;
|
|
4871
|
+
}
|
|
4872
|
+
static contentCalendar(niche, days) {
|
|
4873
|
+
return `
|
|
4874
|
+
Generate a ${days}-day content calendar for: ${niche}
|
|
4875
|
+
|
|
4876
|
+
For each day, provide:
|
|
4877
|
+
- Topic
|
|
4878
|
+
- Content type (blog, video, social, email, caption, script)
|
|
4879
|
+
- Best platform for this content
|
|
4880
|
+
- Brief description
|
|
4881
|
+
- Estimated engagement (0-100)
|
|
4882
|
+
- Priority level (high, medium, low)
|
|
4883
|
+
|
|
4884
|
+
Format as JSON array:
|
|
4885
|
+
[
|
|
4886
|
+
{
|
|
4887
|
+
"day": 1,
|
|
4888
|
+
"topic": "...",
|
|
4889
|
+
"contentType": "blog|video|social|email|caption|script",
|
|
4890
|
+
"platform": "twitter|linkedin|instagram|threads|tiktok|facebook",
|
|
4891
|
+
"description": "...",
|
|
4892
|
+
"estimatedEngagement": 0-100,
|
|
4893
|
+
"priority": "high|medium|low"
|
|
4894
|
+
}
|
|
4895
|
+
]
|
|
4896
|
+
|
|
4897
|
+
Requirements:
|
|
4898
|
+
- Mix of content types across platforms
|
|
4899
|
+
- Platform-appropriate suggestions
|
|
4900
|
+
- Engaging, varied topics
|
|
4901
|
+
- Realistic posting schedule
|
|
4902
|
+
`;
|
|
4903
|
+
}
|
|
4904
|
+
static sentiment(content) {
|
|
4905
|
+
return `
|
|
4906
|
+
Analyze the sentiment of this social media post:
|
|
4907
|
+
|
|
4908
|
+
"${content}"
|
|
4909
|
+
|
|
4910
|
+
Provide analysis in JSON format:
|
|
4911
|
+
{
|
|
4912
|
+
"sentiment": "positive|neutral|negative",
|
|
4913
|
+
"confidence": 0-1,
|
|
4914
|
+
"emotions": [
|
|
4915
|
+
{"emotion": "happy|excited|calm|sad|angry|surprised|fearful|disgusted|neutral", "score": 0-1}
|
|
4916
|
+
]
|
|
4917
|
+
}
|
|
4918
|
+
|
|
4919
|
+
Return only the JSON:
|
|
4920
|
+
`;
|
|
4921
|
+
}
|
|
4922
|
+
static contentAnalysis(content) {
|
|
4923
|
+
return `
|
|
4924
|
+
Analyze this content:
|
|
4925
|
+
|
|
4926
|
+
"${content}"
|
|
4927
|
+
|
|
4928
|
+
Provide analysis in JSON format:
|
|
4929
|
+
{
|
|
4930
|
+
"keywords": ["keyword1", "keyword2", ...],
|
|
4931
|
+
"entities": ["entity1", "entity2", ...],
|
|
4932
|
+
"suggestedImprovements": ["suggestion1", ...],
|
|
4933
|
+
"readabilityScore": 0-100,
|
|
4934
|
+
"estimatedEngagement": 0-100
|
|
4935
|
+
}
|
|
4936
|
+
|
|
4937
|
+
Return only the JSON:
|
|
4938
|
+
`;
|
|
4939
|
+
}
|
|
4940
|
+
static seoOptimization(content, keywords) {
|
|
4941
|
+
return `
|
|
4942
|
+
Optimize this content for SEO:
|
|
4943
|
+
|
|
4944
|
+
Content: "${content}"
|
|
4945
|
+
Keywords: ${keywords.join(", ")}
|
|
4946
|
+
|
|
4947
|
+
Tasks:
|
|
4948
|
+
1. Incorporate keywords naturally
|
|
4949
|
+
2. Improve engagement potential
|
|
4950
|
+
3. Add relevant call-to-action if appropriate
|
|
4951
|
+
4. Optimize for readability
|
|
4952
|
+
5. Enhance heading structure
|
|
4953
|
+
|
|
4954
|
+
Return JSON:
|
|
4955
|
+
{
|
|
4956
|
+
"optimized": "...",
|
|
4957
|
+
"score": 0-100,
|
|
4958
|
+
"suggestions": ["suggestion1", ...],
|
|
4959
|
+
"addedKeywords": ["keyword1", ...],
|
|
4960
|
+
"removedFillerWords": number,
|
|
4961
|
+
"readabilityImprovements": ["improvement1", ...],
|
|
4962
|
+
"metaDescription": "SEO-optimized meta description",
|
|
4963
|
+
"titleSuggestions": ["title1", ...]
|
|
4964
|
+
}
|
|
4965
|
+
|
|
4966
|
+
Return only the JSON:
|
|
4967
|
+
`;
|
|
4968
|
+
}
|
|
4969
|
+
static seoScore(content, keywords) {
|
|
4970
|
+
return `
|
|
4971
|
+
Calculate SEO score for this content:
|
|
4972
|
+
|
|
4973
|
+
Content: "${content}"
|
|
4974
|
+
Keywords: ${keywords.join(", ")}
|
|
4975
|
+
|
|
4976
|
+
Provide breakdown in JSON:
|
|
4977
|
+
{
|
|
4978
|
+
"keywordDensity": 0-100,
|
|
4979
|
+
"readabilityScore": 0-100,
|
|
4980
|
+
"titleOptimization": 0-100,
|
|
4981
|
+
"metaDescription": 0-100,
|
|
4982
|
+
"headingStructure": 0-100,
|
|
4983
|
+
"internalLinking": 0-100,
|
|
4984
|
+
"overall": 0-100
|
|
4985
|
+
}
|
|
4986
|
+
|
|
4987
|
+
Return only the JSON:
|
|
4988
|
+
`;
|
|
4989
|
+
}
|
|
4990
|
+
static abTestVariant(input) {
|
|
4991
|
+
return `
|
|
4992
|
+
Predict performance for this content variant:
|
|
4993
|
+
|
|
4994
|
+
Content: "${input.content}"
|
|
4995
|
+
Content Type: ${input.contentType}
|
|
4996
|
+
Tone: ${input.tone}
|
|
4997
|
+
Target Audience: ${input.targetAudience}
|
|
4998
|
+
Platform: ${input.platform}
|
|
4999
|
+
Goals: ${input.goals.join(", ")}
|
|
5000
|
+
|
|
5001
|
+
Provide prediction in JSON:
|
|
5002
|
+
{
|
|
5003
|
+
"predictedEngagement": 0-100,
|
|
5004
|
+
"predictedCTR": 0-100,
|
|
5005
|
+
"predictedConversions": 0-100,
|
|
5006
|
+
"confidence": 0-1,
|
|
5007
|
+
"reasoning": "...",
|
|
5008
|
+
"strengths": ["strength1", ...],
|
|
5009
|
+
"weaknesses": ["weakness1", ...],
|
|
5010
|
+
"suggestions": ["suggestion1", ...]
|
|
5011
|
+
}
|
|
5012
|
+
|
|
5013
|
+
Return only the JSON:
|
|
5014
|
+
`;
|
|
5015
|
+
}
|
|
5016
|
+
static hashtags(content, count) {
|
|
5017
|
+
return `
|
|
5018
|
+
Generate ${count} relevant hashtags for this content:
|
|
5019
|
+
|
|
5020
|
+
"${content}"
|
|
5021
|
+
|
|
5022
|
+
Requirements:
|
|
5023
|
+
- Mix of popular and niche hashtags
|
|
5024
|
+
- Industry-specific when possible
|
|
5025
|
+
- Trending if relevant
|
|
5026
|
+
- No duplicated words
|
|
5027
|
+
- Format: #hashtag (one per line)
|
|
5028
|
+
|
|
5029
|
+
Return only the hashtags:
|
|
5030
|
+
`;
|
|
5031
|
+
}
|
|
5032
|
+
static imagePrompt(description, style) {
|
|
5033
|
+
return `
|
|
5034
|
+
Generate a detailed AI image generation prompt for:
|
|
5035
|
+
|
|
5036
|
+
Description: ${description}
|
|
5037
|
+
Style: ${style || "realistic"}
|
|
5038
|
+
|
|
5039
|
+
Create a detailed, descriptive prompt that includes:
|
|
5040
|
+
- Subject details
|
|
5041
|
+
- Mood and atmosphere
|
|
5042
|
+
- Lighting
|
|
5043
|
+
- Composition
|
|
5044
|
+
- Art style reference
|
|
5045
|
+
- Technical specifications (aspect ratio, quality)
|
|
5046
|
+
|
|
5047
|
+
The prompt should be optimized for models like Midjourney, DALL-E, or Stable Diffusion.
|
|
5048
|
+
|
|
5049
|
+
Generate the prompt:
|
|
5050
|
+
`;
|
|
5051
|
+
}
|
|
5052
|
+
static blogImagePrompts(blogContent) {
|
|
5053
|
+
return `
|
|
5054
|
+
Analyze this blog content and generate 3-5 detailed image prompts for illustrative images:
|
|
5055
|
+
|
|
5056
|
+
Blog Content: "${blogContent}"
|
|
5057
|
+
|
|
5058
|
+
For each image prompt, provide:
|
|
5059
|
+
- Subject description
|
|
5060
|
+
- Mood and atmosphere
|
|
5061
|
+
- Style reference
|
|
5062
|
+
- Composition details
|
|
5063
|
+
- Technical specs
|
|
5064
|
+
|
|
5065
|
+
Return as JSON array:
|
|
5066
|
+
["prompt1", "prompt2", "prompt3", ...]
|
|
5067
|
+
|
|
5068
|
+
Return only the JSON:
|
|
5069
|
+
`;
|
|
5070
|
+
}
|
|
5071
|
+
static maxTokensForDuration(durationSeconds) {
|
|
5072
|
+
return estimateTokenBudgetForDuration(durationSeconds);
|
|
5073
|
+
}
|
|
5074
|
+
};
|
|
5075
|
+
|
|
5076
|
+
// src/content/application/services/BlogService.ts
|
|
5077
|
+
var BlogService = class {
|
|
5078
|
+
constructor(executor) {
|
|
5079
|
+
this.executor = executor;
|
|
5080
|
+
}
|
|
5081
|
+
executor;
|
|
5082
|
+
async generateBlogPost(request) {
|
|
5083
|
+
const topic = validateTopicText(request.topic);
|
|
5084
|
+
const keywords = validateKeywordList(request.targetKeywords);
|
|
5085
|
+
const prompt = PromptBuilder.blogPost({
|
|
5086
|
+
topic,
|
|
5087
|
+
blogType: request.blogType,
|
|
5088
|
+
keywords,
|
|
5089
|
+
tone: request.tone,
|
|
5090
|
+
targetAudience: request.targetAudience,
|
|
5091
|
+
wordCount: request.wordCount,
|
|
5092
|
+
language: request.language,
|
|
5093
|
+
seoOptimization: request.seoOptimization,
|
|
5094
|
+
includeSchema: request.includeSchema,
|
|
5095
|
+
includeImages: request.includeImages
|
|
5096
|
+
});
|
|
5097
|
+
const parsed = await this.executor.runJson(
|
|
5098
|
+
prompt,
|
|
5099
|
+
{},
|
|
5100
|
+
{ maxTokens: request.wordCount * 2, temperature: 0.7 }
|
|
5101
|
+
);
|
|
5102
|
+
return {
|
|
5103
|
+
id: generateId("blog"),
|
|
5104
|
+
...parsed,
|
|
5105
|
+
blogType: request.blogType,
|
|
5106
|
+
tone: request.tone,
|
|
5107
|
+
wordCount: request.wordCount,
|
|
5108
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5109
|
+
};
|
|
5110
|
+
}
|
|
5111
|
+
};
|
|
5112
|
+
|
|
5113
|
+
// src/content/infrastructure/utils/requestQueue.ts
|
|
5114
|
+
var RequestPriority = /* @__PURE__ */ ((RequestPriority2) => {
|
|
5115
|
+
RequestPriority2[RequestPriority2["LOW"] = 0] = "LOW";
|
|
5116
|
+
RequestPriority2[RequestPriority2["NORMAL"] = 1] = "NORMAL";
|
|
5117
|
+
RequestPriority2[RequestPriority2["HIGH"] = 2] = "HIGH";
|
|
5118
|
+
RequestPriority2[RequestPriority2["URGENT"] = 3] = "URGENT";
|
|
5119
|
+
return RequestPriority2;
|
|
5120
|
+
})(RequestPriority || {});
|
|
5121
|
+
async function batchRequest(requests, options = {}) {
|
|
5122
|
+
const {
|
|
5123
|
+
concurrency = 3,
|
|
5124
|
+
stopOnError = false
|
|
5125
|
+
} = options;
|
|
5126
|
+
const results = [];
|
|
5127
|
+
const errors = [];
|
|
5128
|
+
for (let i = 0; i < requests.length; i += concurrency) {
|
|
5129
|
+
const batch = requests.slice(i, i + concurrency);
|
|
5130
|
+
const batchResults = await Promise.allSettled(
|
|
5131
|
+
batch.map((fn) => fn())
|
|
5132
|
+
);
|
|
5133
|
+
for (const result of batchResults) {
|
|
5134
|
+
if (result.status === "fulfilled") {
|
|
5135
|
+
results.push(result.value);
|
|
5136
|
+
} else {
|
|
5137
|
+
errors.push(result.reason);
|
|
5138
|
+
if (stopOnError) {
|
|
5139
|
+
throw new Error(
|
|
5140
|
+
`Batch request failed: ${errors[0].message}`
|
|
5141
|
+
);
|
|
5142
|
+
}
|
|
5143
|
+
}
|
|
5144
|
+
}
|
|
5145
|
+
}
|
|
5146
|
+
if (errors.length > 0 && !stopOnError) {
|
|
5147
|
+
console.warn(`${errors.length} requests failed in batch`);
|
|
5148
|
+
}
|
|
5149
|
+
return results;
|
|
5150
|
+
}
|
|
5151
|
+
|
|
5152
|
+
// src/content/application/services/SocialService.ts
|
|
5153
|
+
var MULTI_PLATFORMS = [
|
|
5154
|
+
"twitter",
|
|
5155
|
+
"linkedin",
|
|
5156
|
+
"instagram",
|
|
5157
|
+
"threads",
|
|
5158
|
+
"tiktok"
|
|
5159
|
+
];
|
|
5160
|
+
var DEFAULT_SOCIAL_RESULT = {
|
|
5161
|
+
content: "",
|
|
5162
|
+
platform: "twitter",
|
|
5163
|
+
hashtags: [],
|
|
5164
|
+
emojis: [],
|
|
5165
|
+
characterCount: 0,
|
|
5166
|
+
estimatedEngagement: 0
|
|
5167
|
+
};
|
|
5168
|
+
var SocialService = class {
|
|
5169
|
+
constructor(executor) {
|
|
5170
|
+
this.executor = executor;
|
|
5171
|
+
}
|
|
5172
|
+
executor;
|
|
5173
|
+
async generateSocialContent(request) {
|
|
5174
|
+
const topic = validateTopicText(request.topic);
|
|
5175
|
+
const spec = resolvePlatformSpec(request.platform);
|
|
5176
|
+
const maxLength = resolveMaxContentLength(request.platform, request.maxLength);
|
|
5177
|
+
const prompt = PromptBuilder.socialPost({
|
|
5178
|
+
topic,
|
|
5179
|
+
platform: request.platform,
|
|
5180
|
+
tone: request.tone,
|
|
5181
|
+
style: spec.style,
|
|
5182
|
+
maxLength,
|
|
5183
|
+
includeHashtags: request.hashtags !== false,
|
|
5184
|
+
includeCallToAction: Boolean(request.includeCallToAction)
|
|
5185
|
+
});
|
|
5186
|
+
const parsed = await this.executor.runJson(
|
|
5187
|
+
prompt,
|
|
5188
|
+
{ ...DEFAULT_SOCIAL_RESULT, platform: request.platform },
|
|
5189
|
+
{ maxTokens: 500, temperature: 0.8 }
|
|
5190
|
+
);
|
|
5191
|
+
return {
|
|
5192
|
+
...parsed,
|
|
5193
|
+
platform: request.platform,
|
|
5194
|
+
characterCount: parsed.content?.length ?? 0
|
|
5195
|
+
};
|
|
5196
|
+
}
|
|
5197
|
+
async generateForAllPlatforms(topic, tone) {
|
|
5198
|
+
const requests = MULTI_PLATFORMS.map(
|
|
5199
|
+
(platform) => () => this.generateSocialContent({ topic, platform, tone })
|
|
5200
|
+
);
|
|
5201
|
+
try {
|
|
5202
|
+
return await batchRequest(requests, { concurrency: 2, stopOnError: false });
|
|
5203
|
+
} catch (error) {
|
|
5204
|
+
console.warn("Batch execution failed, falling back to sequential:", error);
|
|
5205
|
+
const results = [];
|
|
5206
|
+
for (const platform of MULTI_PLATFORMS) {
|
|
5207
|
+
try {
|
|
5208
|
+
results.push(await this.generateSocialContent({ topic, platform, tone }));
|
|
5209
|
+
} catch (err) {
|
|
5210
|
+
console.error(`Failed to generate for ${platform}:`, err);
|
|
5211
|
+
}
|
|
5212
|
+
}
|
|
5213
|
+
return results;
|
|
5214
|
+
}
|
|
5215
|
+
}
|
|
5216
|
+
async generateHashtags(content, count) {
|
|
5217
|
+
const validated = validateHashtagCount(count);
|
|
5218
|
+
const prompt = PromptBuilder.hashtags(content, validated);
|
|
5219
|
+
const response = await this.executor.runText(prompt, { maxTokens: 200, temperature: 0.7 });
|
|
5220
|
+
const hashtags = response.match(/#[\w-]+/g) || [];
|
|
5221
|
+
return hashtags.slice(0, validated);
|
|
5222
|
+
}
|
|
5223
|
+
optimizeHashtags(hashtags, platform) {
|
|
5224
|
+
const budget = resolveHashtagBudget(platform);
|
|
5225
|
+
return rankAndTrimHashtags(hashtags, budget);
|
|
5226
|
+
}
|
|
5227
|
+
};
|
|
5228
|
+
|
|
5229
|
+
// src/content/application/services/VideoScriptService.ts
|
|
5230
|
+
var buildScriptResult = (parsed, duration) => {
|
|
5231
|
+
const script = parsed.script ?? "";
|
|
5232
|
+
if (!script) {
|
|
5233
|
+
throw new Error("AI response missing script field");
|
|
5234
|
+
}
|
|
5235
|
+
const wordCount = script.trim().length === 0 ? 0 : script.trim().split(/\s+/).length;
|
|
5236
|
+
return {
|
|
5237
|
+
...parsed,
|
|
5238
|
+
script,
|
|
5239
|
+
duration,
|
|
5240
|
+
wordCount
|
|
5241
|
+
};
|
|
5242
|
+
};
|
|
5243
|
+
var VideoScriptService = class {
|
|
5244
|
+
constructor(executor) {
|
|
5245
|
+
this.executor = executor;
|
|
5246
|
+
}
|
|
5247
|
+
executor;
|
|
5248
|
+
async generateVideoScript(request) {
|
|
5249
|
+
const topic = validateTopicText(request.topic);
|
|
5250
|
+
const duration = validateDurationSeconds(request.duration);
|
|
5251
|
+
const prompt = PromptBuilder.videoScript({
|
|
5252
|
+
topic,
|
|
5253
|
+
tone: request.tone,
|
|
5254
|
+
duration,
|
|
5255
|
+
targetAudience: request.targetAudience,
|
|
5256
|
+
includeVisuals: request.includeVisuals,
|
|
5257
|
+
includeCallToAction: request.includeCallToAction
|
|
5258
|
+
});
|
|
5259
|
+
const parsed = await this.executor.runJson(
|
|
5260
|
+
prompt,
|
|
5261
|
+
{ script: "", visualCues: [], duration, wordCount: 0, estimatedEngagement: 0 },
|
|
5262
|
+
{ maxTokens: estimateTokenBudgetForDuration(duration), temperature: 0.8 }
|
|
5263
|
+
);
|
|
5264
|
+
return buildScriptResult(parsed, duration);
|
|
5265
|
+
}
|
|
5266
|
+
async generateVoiceScript(topic, emotion, duration) {
|
|
5267
|
+
const validatedTopic = validateTopicText(topic);
|
|
5268
|
+
const validatedDuration = validateDurationSeconds(duration);
|
|
5269
|
+
const prompt = PromptBuilder.voiceScript({
|
|
5270
|
+
topic: validatedTopic,
|
|
5271
|
+
emotion,
|
|
5272
|
+
duration: validatedDuration
|
|
5273
|
+
});
|
|
5274
|
+
const parsed = await this.executor.runJson(
|
|
5275
|
+
prompt,
|
|
5276
|
+
{ script: "", visualCues: [], duration: validatedDuration, wordCount: 0, estimatedEngagement: 0 },
|
|
5277
|
+
{ maxTokens: estimateTokenBudgetForDuration(validatedDuration), temperature: 0.8 }
|
|
5278
|
+
);
|
|
5279
|
+
return buildScriptResult(parsed, validatedDuration);
|
|
5280
|
+
}
|
|
5281
|
+
};
|
|
5282
|
+
|
|
5283
|
+
// src/content/application/services/AnalysisService.ts
|
|
5284
|
+
var DEFAULT_SENTIMENT = {
|
|
5285
|
+
sentiment: "neutral",
|
|
5286
|
+
confidence: 0.5,
|
|
5287
|
+
emotions: []
|
|
5288
|
+
};
|
|
5289
|
+
var DEFAULT_ANALYSIS = {
|
|
5290
|
+
sentiment: DEFAULT_SENTIMENT,
|
|
5291
|
+
keywords: [],
|
|
5292
|
+
entities: [],
|
|
5293
|
+
suggestedImprovements: [],
|
|
5294
|
+
readabilityScore: 50,
|
|
5295
|
+
estimatedEngagement: 50
|
|
5296
|
+
};
|
|
5297
|
+
var AnalysisService = class {
|
|
5298
|
+
constructor(executor) {
|
|
5299
|
+
this.executor = executor;
|
|
5300
|
+
}
|
|
5301
|
+
executor;
|
|
5302
|
+
async analyzeSentiment(content) {
|
|
5303
|
+
const validated = validateContentBody(content);
|
|
5304
|
+
const prompt = PromptBuilder.sentiment(validated);
|
|
5305
|
+
const result = await this.executor.runJson(
|
|
5306
|
+
prompt,
|
|
5307
|
+
DEFAULT_SENTIMENT,
|
|
5308
|
+
{ maxTokens: 200, temperature: 0.3 }
|
|
5309
|
+
);
|
|
5310
|
+
return {
|
|
5311
|
+
...result,
|
|
5312
|
+
confidence: clampConfidenceToValidRange(result.confidence)
|
|
5313
|
+
};
|
|
5314
|
+
}
|
|
5315
|
+
async analyzeContent(request) {
|
|
5316
|
+
const validated = validateContentBody(request.content);
|
|
5317
|
+
const sentimentResult = await this.analyzeSentiment(validated);
|
|
5318
|
+
const prompt = PromptBuilder.contentAnalysis(validated);
|
|
5319
|
+
const parsed = await this.executor.runJson(
|
|
5320
|
+
prompt,
|
|
5321
|
+
{ ...DEFAULT_ANALYSIS, sentiment: sentimentResult },
|
|
5322
|
+
{ maxTokens: 300, temperature: 0.5 }
|
|
5323
|
+
);
|
|
5324
|
+
return {
|
|
5325
|
+
sentiment: sentimentResult,
|
|
5326
|
+
keywords: parsed.keywords ?? [],
|
|
5327
|
+
entities: parsed.entities ?? [],
|
|
5328
|
+
suggestedImprovements: parsed.suggestedImprovements ?? [],
|
|
5329
|
+
readabilityScore: clampScoreToValidRange(parsed.readabilityScore),
|
|
5330
|
+
estimatedEngagement: clampScoreToValidRange(parsed.estimatedEngagement)
|
|
5331
|
+
};
|
|
5332
|
+
}
|
|
5333
|
+
};
|
|
5334
|
+
|
|
5335
|
+
// src/content/application/services/SeoService.ts
|
|
5336
|
+
var DEFAULT_SEO_SCORE = {
|
|
5337
|
+
keywordDensity: 50,
|
|
5338
|
+
readabilityScore: 50,
|
|
5339
|
+
titleOptimization: 50,
|
|
5340
|
+
metaDescription: 50,
|
|
5341
|
+
headingStructure: 50,
|
|
5342
|
+
internalLinking: 50,
|
|
5343
|
+
overall: 50
|
|
5344
|
+
};
|
|
5345
|
+
var UNDERUTILIZED_SUGGESTION = "Consider using this keyword more frequently";
|
|
5346
|
+
var SeoService = class {
|
|
5347
|
+
constructor(executor) {
|
|
5348
|
+
this.executor = executor;
|
|
5349
|
+
}
|
|
5350
|
+
executor;
|
|
5351
|
+
async optimizeSEO(request) {
|
|
5352
|
+
const content = validateContentBody(request.content);
|
|
5353
|
+
const keywords = validateKeywordList(request.keywords);
|
|
5354
|
+
const prompt = PromptBuilder.seoOptimization(content, keywords);
|
|
5355
|
+
const result = await this.executor.runJson(
|
|
5356
|
+
prompt,
|
|
5357
|
+
{
|
|
5358
|
+
optimized: content,
|
|
5359
|
+
score: 50,
|
|
5360
|
+
suggestions: [],
|
|
5361
|
+
addedKeywords: [],
|
|
5362
|
+
removedFillerWords: 0,
|
|
5363
|
+
readabilityImprovements: []
|
|
5364
|
+
},
|
|
5365
|
+
{ maxTokens: 1e3, temperature: 0.7 }
|
|
5366
|
+
);
|
|
5367
|
+
return {
|
|
5368
|
+
...result,
|
|
5369
|
+
score: clampScoreToValidRange(result.score)
|
|
5370
|
+
};
|
|
5371
|
+
}
|
|
5372
|
+
async calculateSEOScore(content, keywords) {
|
|
5373
|
+
const validatedContent = validateContentBody(content);
|
|
5374
|
+
const validatedKeywords = validateKeywordList(keywords);
|
|
5375
|
+
const prompt = PromptBuilder.seoOptimization(
|
|
5376
|
+
truncateForSeoPreview(validatedContent),
|
|
5377
|
+
validatedKeywords
|
|
5378
|
+
);
|
|
5379
|
+
const result = await this.executor.runJson(
|
|
5380
|
+
prompt,
|
|
5381
|
+
DEFAULT_SEO_SCORE,
|
|
5382
|
+
{ maxTokens: 200, temperature: 0.3 }
|
|
5383
|
+
);
|
|
5384
|
+
return {
|
|
5385
|
+
keywordDensity: clampScoreToValidRange(result.keywordDensity),
|
|
5386
|
+
readabilityScore: clampScoreToValidRange(result.readabilityScore),
|
|
5387
|
+
titleOptimization: clampScoreToValidRange(result.titleOptimization),
|
|
5388
|
+
metaDescription: clampScoreToValidRange(result.metaDescription),
|
|
5389
|
+
headingStructure: clampScoreToValidRange(result.headingStructure),
|
|
5390
|
+
internalLinking: clampScoreToValidRange(result.internalLinking),
|
|
5391
|
+
overall: clampScoreToValidRange(result.overall)
|
|
5392
|
+
};
|
|
5393
|
+
}
|
|
5394
|
+
analyzeKeywords(content, keywords) {
|
|
5395
|
+
const validatedContent = validateContentBody(content);
|
|
5396
|
+
const validatedKeywords = validateKeywordList(keywords);
|
|
5397
|
+
return validatedKeywords.map((keyword) => {
|
|
5398
|
+
const count = countKeywordOccurrences(validatedContent, keyword);
|
|
5399
|
+
const density = calculateKeywordDensity(validatedContent, keyword);
|
|
5400
|
+
return {
|
|
5401
|
+
keyword,
|
|
5402
|
+
count,
|
|
5403
|
+
density,
|
|
5404
|
+
prominence: classifyKeywordProminence(density),
|
|
5405
|
+
suggestions: isUnderutilizedKeyword(density) ? [UNDERUTILIZED_SUGGESTION] : []
|
|
5406
|
+
};
|
|
5407
|
+
});
|
|
5408
|
+
}
|
|
5409
|
+
};
|
|
5410
|
+
|
|
5411
|
+
// src/content/application/services/ABTestService.ts
|
|
5412
|
+
var DEFAULT_PREDICTION = {
|
|
5413
|
+
variantId: "",
|
|
5414
|
+
predictedEngagement: 0,
|
|
5415
|
+
predictedCTR: 0,
|
|
5416
|
+
predictedConversions: 0,
|
|
5417
|
+
confidence: 0,
|
|
5418
|
+
reasoning: "",
|
|
5419
|
+
strengths: [],
|
|
5420
|
+
weaknesses: [],
|
|
5421
|
+
suggestions: []
|
|
5422
|
+
};
|
|
5423
|
+
var VARIANT_A_ID = "A";
|
|
5424
|
+
var VARIANT_B_ID = "B";
|
|
5425
|
+
var FALLBACK_ENGAGEMENT = 50;
|
|
5426
|
+
var DEFAULT_RECOMMENDATIONS = [
|
|
5427
|
+
"Test with larger audience",
|
|
5428
|
+
"Monitor click-through rates"
|
|
5429
|
+
];
|
|
5430
|
+
var ABTestService = class {
|
|
5431
|
+
constructor(executor) {
|
|
5432
|
+
this.executor = executor;
|
|
5433
|
+
}
|
|
5434
|
+
executor;
|
|
5435
|
+
async predictABTest(request) {
|
|
5436
|
+
const predictions = [];
|
|
5437
|
+
for (const variant of request.variants) {
|
|
5438
|
+
const prompt = PromptBuilder.abTestVariant({
|
|
5439
|
+
content: truncateForAbVariantPreview(variant.content),
|
|
5440
|
+
contentType: variant.contentType,
|
|
5441
|
+
tone: variant.tone,
|
|
5442
|
+
targetAudience: request.targetAudience,
|
|
5443
|
+
platform: request.platform,
|
|
5444
|
+
goals: request.goals
|
|
5445
|
+
});
|
|
5446
|
+
const parsed = await this.executor.runJson(
|
|
5447
|
+
prompt,
|
|
5448
|
+
{ ...DEFAULT_PREDICTION, variantId: variant.id },
|
|
5449
|
+
{ maxTokens: 300, temperature: 0.5 }
|
|
5450
|
+
);
|
|
5451
|
+
predictions.push({
|
|
5452
|
+
variantId: variant.id,
|
|
5453
|
+
predictedEngagement: clampScoreToValidRange(parsed.predictedEngagement),
|
|
5454
|
+
predictedCTR: clampScoreToValidRange(parsed.predictedCTR),
|
|
5455
|
+
predictedConversions: clampScoreToValidRange(parsed.predictedConversions),
|
|
5456
|
+
confidence: clampConfidenceToValidRange(parsed.confidence),
|
|
5457
|
+
reasoning: parsed.reasoning ?? "",
|
|
5458
|
+
strengths: parsed.strengths ?? [],
|
|
5459
|
+
weaknesses: parsed.weaknesses ?? [],
|
|
5460
|
+
suggestions: parsed.suggestions ?? []
|
|
5461
|
+
});
|
|
5462
|
+
}
|
|
5463
|
+
return predictions;
|
|
5464
|
+
}
|
|
5465
|
+
async compareVariants(variantA, variantB) {
|
|
5466
|
+
const predictions = await this.predictABTest({
|
|
5467
|
+
variants: [
|
|
5468
|
+
{ id: VARIANT_A_ID, content: variantA, contentType: "social", tone: "casual" },
|
|
5469
|
+
{ id: VARIANT_B_ID, content: variantB, contentType: "social", tone: "casual" }
|
|
5470
|
+
],
|
|
5471
|
+
targetAudience: "general",
|
|
5472
|
+
platform: "twitter",
|
|
5473
|
+
goals: ["engagement", "clicks"]
|
|
5474
|
+
});
|
|
5475
|
+
const scoreA = predictions[0]?.predictedEngagement ?? FALLBACK_ENGAGEMENT;
|
|
5476
|
+
const scoreB = predictions[1]?.predictedEngagement ?? FALLBACK_ENGAGEMENT;
|
|
5477
|
+
const isTie = scoreA === scoreB;
|
|
5478
|
+
const winner = selectHigherScoreVariantId(scoreA, scoreB, VARIANT_A_ID, VARIANT_B_ID);
|
|
5479
|
+
const improvement = calculateImprovementPercentage(scoreA, scoreB);
|
|
5480
|
+
return {
|
|
5481
|
+
winner,
|
|
5482
|
+
confidence: AB_TEST_DEFAULT_CONFIDENCE,
|
|
5483
|
+
improvement: isTie ? "0%" : `+${improvement}% engagement`,
|
|
5484
|
+
reasoning: isTie ? "Both variants have equal predicted engagement" : winner === VARIANT_A_ID ? "Variant A has more engaging content" : "Variant B has more engaging content",
|
|
5485
|
+
recommendations: [...DEFAULT_RECOMMENDATIONS]
|
|
5486
|
+
};
|
|
5487
|
+
}
|
|
5488
|
+
};
|
|
5489
|
+
|
|
5490
|
+
// src/content/application/services/ImagePromptService.ts
|
|
5491
|
+
var ImagePromptService = class {
|
|
5492
|
+
constructor(executor) {
|
|
5493
|
+
this.executor = executor;
|
|
5494
|
+
}
|
|
5495
|
+
executor;
|
|
5496
|
+
async generateImagePrompt(description, style) {
|
|
5497
|
+
const validated = validateTopicText(description);
|
|
5498
|
+
const prompt = PromptBuilder.imagePrompt(validated, style);
|
|
5499
|
+
return this.executor.runText(prompt, { maxTokens: 300, temperature: 0.8 });
|
|
5500
|
+
}
|
|
5501
|
+
async generateImagePromptsForBlog(blogContent) {
|
|
5502
|
+
const truncated = truncateForBlogPromptPreview(validateContentBody(blogContent));
|
|
5503
|
+
const prompt = PromptBuilder.blogImagePrompts(truncated);
|
|
5504
|
+
const prompts = await this.executor.runJson(prompt, [], {
|
|
5505
|
+
maxTokens: 500,
|
|
5506
|
+
temperature: 0.8
|
|
5507
|
+
});
|
|
5508
|
+
return Array.isArray(prompts) ? prompts : [];
|
|
5509
|
+
}
|
|
5510
|
+
};
|
|
5511
|
+
|
|
5512
|
+
// src/content/application/services/ContentCalendarService.ts
|
|
5513
|
+
var toCalendarEntry = (item) => ({
|
|
5514
|
+
date: resolveCalendarEntryDate(item.day),
|
|
5515
|
+
topic: item.topic,
|
|
5516
|
+
contentType: item.contentType,
|
|
5517
|
+
platform: item.platform,
|
|
5518
|
+
description: item.description,
|
|
5519
|
+
estimatedEngagement: item.estimatedEngagement,
|
|
5520
|
+
priority: item.priority
|
|
5521
|
+
});
|
|
5522
|
+
var ContentCalendarService = class {
|
|
5523
|
+
constructor(executor) {
|
|
5524
|
+
this.executor = executor;
|
|
5525
|
+
}
|
|
5526
|
+
executor;
|
|
5527
|
+
async generateContentCalendar(niche, days) {
|
|
5528
|
+
const validatedNiche = validateTopicText(niche);
|
|
5529
|
+
const validatedDays = validateCalendarDays(days);
|
|
5530
|
+
const prompt = PromptBuilder.contentCalendar(validatedNiche, validatedDays);
|
|
5531
|
+
const data = await this.executor.runJson(
|
|
5532
|
+
prompt,
|
|
5533
|
+
[],
|
|
5534
|
+
{
|
|
5535
|
+
maxTokens: estimateTokenBudgetForCalendarDays(validatedDays),
|
|
5536
|
+
temperature: 0.8
|
|
5537
|
+
}
|
|
5538
|
+
);
|
|
5539
|
+
const items = Array.isArray(data) ? data : Array.isArray(data?.calendar) ? data.calendar : Array.isArray(data?.entries) ? data.entries : [];
|
|
5540
|
+
return items.map(toCalendarEntry);
|
|
5541
|
+
}
|
|
5542
|
+
};
|
|
5543
|
+
|
|
5544
|
+
// src/content/application/services/ProviderServices.ts
|
|
5545
|
+
var wrapProviderError = (operation, error) => {
|
|
5546
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
5547
|
+
return new AIError(`${operation} failed: ${message}`, "PROVIDER_ERROR", error);
|
|
5548
|
+
};
|
|
5549
|
+
var ensureFactory = (factory, operation) => {
|
|
5550
|
+
if (factory.getAllProviders().length === 0) {
|
|
5551
|
+
throw new AIError(
|
|
5552
|
+
`${operation} failed: No providers are registered. Provide a ProviderConfig with at least one enabled provider when constructing AIContentService.`,
|
|
5553
|
+
"PROVIDER_UNAVAILABLE"
|
|
5554
|
+
);
|
|
5555
|
+
}
|
|
5556
|
+
};
|
|
5557
|
+
var MediaGenerationService = class {
|
|
5558
|
+
constructor(providerFactory) {
|
|
5559
|
+
this.providerFactory = providerFactory;
|
|
5560
|
+
}
|
|
5561
|
+
providerFactory;
|
|
5562
|
+
generateImage(request) {
|
|
5563
|
+
ensureFactory(this.providerFactory, "Image generation");
|
|
5564
|
+
return this.providerFactory.generateImage(request).catch((err) => {
|
|
5565
|
+
throw wrapProviderError("Image generation", err);
|
|
5566
|
+
});
|
|
5567
|
+
}
|
|
5568
|
+
generateVideo(request) {
|
|
5569
|
+
ensureFactory(this.providerFactory, "Video generation");
|
|
5570
|
+
return this.providerFactory.generateVideo(request).catch((err) => {
|
|
5571
|
+
throw wrapProviderError("Video generation", err);
|
|
5572
|
+
});
|
|
5573
|
+
}
|
|
5574
|
+
convertImageToVideo(request) {
|
|
5575
|
+
ensureFactory(this.providerFactory, "Image-to-video conversion");
|
|
5576
|
+
return this.providerFactory.imageToVideo(request).catch((err) => {
|
|
5577
|
+
throw wrapProviderError("Image-to-video conversion", err);
|
|
5578
|
+
});
|
|
5579
|
+
}
|
|
5580
|
+
transformVideo(request) {
|
|
5581
|
+
ensureFactory(this.providerFactory, "Video-to-video transformation");
|
|
5582
|
+
return this.providerFactory.videoToVideo(request).catch((err) => {
|
|
5583
|
+
throw wrapProviderError("Video-to-video transformation", err);
|
|
5584
|
+
});
|
|
5585
|
+
}
|
|
5586
|
+
};
|
|
5587
|
+
|
|
5588
|
+
// src/content/infrastructure/utils/jsonParser.ts
|
|
5589
|
+
function repairCommonJsonDefects2(text) {
|
|
5590
|
+
return text.replace(/(:\s*-?\d+(?:\.\d+)?)\s*"/g, "$1").replace(/(:\s*"[^"]*")"/g, "$1");
|
|
5591
|
+
}
|
|
5592
|
+
function safeJSONParse(text, fallback, onError) {
|
|
5593
|
+
try {
|
|
5594
|
+
return JSON.parse(text);
|
|
5595
|
+
} catch (error) {
|
|
5596
|
+
try {
|
|
5597
|
+
return JSON.parse(repairCommonJsonDefects2(text));
|
|
5598
|
+
} catch {
|
|
5599
|
+
}
|
|
5600
|
+
if (error instanceof SyntaxError) {
|
|
5601
|
+
const positionMatch = error.message.match(/position (\d+)/);
|
|
5602
|
+
const position = positionMatch ? parseInt(positionMatch[1], 10) : -1;
|
|
5603
|
+
if (position > 0) {
|
|
5604
|
+
const context = text.substring(Math.max(0, position - 50), position + 50);
|
|
5605
|
+
onError?.(`JSON parse error at position ${position}: "${context}"`);
|
|
5606
|
+
} else {
|
|
5607
|
+
onError?.(`JSON parse error: ${error.message}`);
|
|
5608
|
+
}
|
|
5609
|
+
}
|
|
5610
|
+
return fallback;
|
|
5611
|
+
}
|
|
5612
|
+
}
|
|
5613
|
+
function extractJSON(text) {
|
|
5614
|
+
const codeBlockMatch = text.match(/```(?:json)?\s*([\s\S]*?)```/);
|
|
5615
|
+
if (codeBlockMatch && codeBlockMatch[1]) {
|
|
5616
|
+
const candidate = codeBlockMatch[1].trim();
|
|
5617
|
+
if (candidate.startsWith("{") || candidate.startsWith("[")) {
|
|
5618
|
+
return candidate;
|
|
5619
|
+
}
|
|
5620
|
+
}
|
|
5621
|
+
const objectMatch = text.match(/\{[\s\S]*\}/);
|
|
5622
|
+
if (objectMatch) {
|
|
5623
|
+
return objectMatch[0];
|
|
5624
|
+
}
|
|
5625
|
+
const arrayMatch = text.match(/\[[\s\S]*\]/);
|
|
5626
|
+
if (arrayMatch) {
|
|
5627
|
+
return arrayMatch[0];
|
|
5628
|
+
}
|
|
5629
|
+
return null;
|
|
5630
|
+
}
|
|
5631
|
+
function parseAIResponse(response, fallback, onError) {
|
|
5632
|
+
const json = extractJSON(response);
|
|
5633
|
+
if (!json) {
|
|
5634
|
+
onError?.("No JSON payload found in response");
|
|
5635
|
+
return fallback;
|
|
5636
|
+
}
|
|
5637
|
+
return safeJSONParse(json, fallback, onError);
|
|
5638
|
+
}
|
|
5639
|
+
function isValidJSON(text) {
|
|
5640
|
+
const trimmed = text.trim();
|
|
5641
|
+
if (trimmed.length === 0) return false;
|
|
5642
|
+
if (!(trimmed.startsWith("{") && trimmed.endsWith("}") || trimmed.startsWith("[") && trimmed.endsWith("]"))) {
|
|
5643
|
+
return false;
|
|
5644
|
+
}
|
|
5645
|
+
try {
|
|
5646
|
+
JSON.parse(trimmed);
|
|
5647
|
+
return true;
|
|
5648
|
+
} catch {
|
|
5649
|
+
return false;
|
|
5650
|
+
}
|
|
5651
|
+
}
|
|
5652
|
+
|
|
5653
|
+
// src/content/application/services/GenerationExecutor.ts
|
|
5654
|
+
var GenerationExecutor = class {
|
|
5655
|
+
constructor(generator) {
|
|
5656
|
+
this.generator = generator;
|
|
5657
|
+
}
|
|
5658
|
+
generator;
|
|
5659
|
+
async runJson(prompt, fallback, generationOptions = {}) {
|
|
5660
|
+
const response = await this.generator.generateText(prompt, generationOptions);
|
|
5661
|
+
return parseAIResponse(response, fallback);
|
|
5662
|
+
}
|
|
5663
|
+
runText(prompt, options = {}) {
|
|
5664
|
+
return this.generator.generateText(prompt, options);
|
|
5665
|
+
}
|
|
5666
|
+
/** Usage-complete pass-through; requires a ProviderFactory engine. */
|
|
5667
|
+
runChat(request) {
|
|
5668
|
+
if (!(this.generator instanceof ProviderFactory)) {
|
|
5669
|
+
throw new AIError(
|
|
5670
|
+
"runChat requires a ProviderFactory engine \u2014 construct AIContentService with a provider config, not a custom ITextGenerator",
|
|
5671
|
+
"PROVIDER_UNAVAILABLE"
|
|
5672
|
+
);
|
|
5673
|
+
}
|
|
5674
|
+
return this.generator.chat(request);
|
|
5675
|
+
}
|
|
5676
|
+
};
|
|
5677
|
+
|
|
5678
|
+
// src/content/application/services/AIContentService.ts
|
|
5679
|
+
var isTextGenerator = (value) => typeof value === "object" && value !== null && typeof value.generateText === "function";
|
|
5680
|
+
function toAIProviderConfig(config) {
|
|
5681
|
+
const legacy = config;
|
|
5682
|
+
const modern = config;
|
|
5683
|
+
const anthropic = modern.anthropic ?? (legacy.anthropic?.enabled ? {
|
|
5684
|
+
apiKey: legacy.anthropic.apiKey,
|
|
5685
|
+
baseUrl: legacy.anthropic.baseUrl,
|
|
5686
|
+
timeoutMs: legacy.anthropic.timeout,
|
|
5687
|
+
models: legacy.anthropic.models,
|
|
5688
|
+
effort: legacy.anthropic.effort
|
|
5689
|
+
} : void 0);
|
|
5690
|
+
const groq = modern.groq ?? (legacy.groq?.enabled ? {
|
|
5691
|
+
apiKey: legacy.groq.apiKey,
|
|
5692
|
+
baseUrl: legacy.groq.baseUrl,
|
|
5693
|
+
timeoutMs: legacy.groq.timeout,
|
|
5694
|
+
// legacy {text, chat} model pins map onto the neutral tier slots
|
|
5695
|
+
...legacy.groq.models?.text ? { models: { balanced: legacy.groq.models.text } } : {}
|
|
5696
|
+
} : void 0);
|
|
5697
|
+
const gemini = modern.gemini ?? (legacy.gemini?.enabled ? { ...legacy.gemini } : void 0);
|
|
5698
|
+
const fal = modern.fal ?? (legacy.fal?.enabled ? { ...legacy.fal } : void 0);
|
|
5699
|
+
const pruna = modern.pruna ?? (legacy.pruna?.enabled ? { ...legacy.pruna } : void 0);
|
|
5700
|
+
return {
|
|
5701
|
+
priority: modern.priority,
|
|
5702
|
+
fallbackEnabled: modern.fallbackEnabled,
|
|
5703
|
+
defaultTier: modern.defaultTier,
|
|
5704
|
+
...anthropic ? { anthropic } : {},
|
|
5705
|
+
...groq ? { groq } : {},
|
|
5706
|
+
...gemini ? { gemini } : {},
|
|
5707
|
+
...fal ? { fal } : {},
|
|
5708
|
+
...pruna ? { pruna } : {}
|
|
5709
|
+
};
|
|
5710
|
+
}
|
|
5711
|
+
var buildServices = (configOrGenerator, model, customGenerator) => {
|
|
5712
|
+
if (customGenerator) {
|
|
5713
|
+
const executor2 = new GenerationExecutor(customGenerator);
|
|
5714
|
+
const emptyFactory = new ProviderFactory({
|
|
5715
|
+
priority: [],
|
|
5716
|
+
fallbackEnabled: false
|
|
5717
|
+
});
|
|
5718
|
+
return {
|
|
5719
|
+
providerFactory: emptyFactory,
|
|
5720
|
+
blogService: new BlogService(executor2),
|
|
5721
|
+
socialService: new SocialService(executor2),
|
|
5722
|
+
videoScriptService: new VideoScriptService(executor2),
|
|
5723
|
+
analysisService: new AnalysisService(executor2),
|
|
5724
|
+
seoService: new SeoService(executor2),
|
|
5725
|
+
abTestService: new ABTestService(executor2),
|
|
5726
|
+
imagePromptService: new ImagePromptService(executor2),
|
|
5727
|
+
contentCalendarService: new ContentCalendarService(executor2),
|
|
5728
|
+
mediaGenerationService: new MediaGenerationService(emptyFactory)
|
|
5729
|
+
};
|
|
5730
|
+
}
|
|
5731
|
+
if (typeof configOrGenerator === "string") {
|
|
5732
|
+
const aiConfig = {
|
|
5733
|
+
anthropic: {
|
|
5734
|
+
apiKey: configOrGenerator,
|
|
5735
|
+
...model ? { models: { balanced: model } } : {}
|
|
5736
|
+
}
|
|
5737
|
+
};
|
|
5738
|
+
const factory2 = createAI(aiConfig);
|
|
5739
|
+
const executor2 = new GenerationExecutor(factory2);
|
|
5740
|
+
return {
|
|
5741
|
+
providerFactory: factory2,
|
|
5742
|
+
blogService: new BlogService(executor2),
|
|
5743
|
+
socialService: new SocialService(executor2),
|
|
5744
|
+
videoScriptService: new VideoScriptService(executor2),
|
|
5745
|
+
analysisService: new AnalysisService(executor2),
|
|
5746
|
+
seoService: new SeoService(executor2),
|
|
5747
|
+
abTestService: new ABTestService(executor2),
|
|
5748
|
+
imagePromptService: new ImagePromptService(executor2),
|
|
5749
|
+
contentCalendarService: new ContentCalendarService(executor2),
|
|
5750
|
+
mediaGenerationService: new MediaGenerationService(factory2)
|
|
5751
|
+
};
|
|
5752
|
+
}
|
|
5753
|
+
if (isTextGenerator(configOrGenerator)) {
|
|
5754
|
+
const executor2 = new GenerationExecutor(configOrGenerator);
|
|
5755
|
+
const emptyFactory = new ProviderFactory({
|
|
5756
|
+
priority: [],
|
|
5757
|
+
fallbackEnabled: false
|
|
5758
|
+
});
|
|
5759
|
+
return {
|
|
5760
|
+
providerFactory: emptyFactory,
|
|
5761
|
+
blogService: new BlogService(executor2),
|
|
5762
|
+
socialService: new SocialService(executor2),
|
|
5763
|
+
videoScriptService: new VideoScriptService(executor2),
|
|
5764
|
+
analysisService: new AnalysisService(executor2),
|
|
5765
|
+
seoService: new SeoService(executor2),
|
|
5766
|
+
abTestService: new ABTestService(executor2),
|
|
5767
|
+
imagePromptService: new ImagePromptService(executor2),
|
|
5768
|
+
contentCalendarService: new ContentCalendarService(executor2),
|
|
5769
|
+
mediaGenerationService: new MediaGenerationService(emptyFactory)
|
|
5770
|
+
};
|
|
5771
|
+
}
|
|
5772
|
+
const factory = createAI(toAIProviderConfig(configOrGenerator));
|
|
5773
|
+
const executor = new GenerationExecutor(factory);
|
|
5774
|
+
return {
|
|
5775
|
+
providerFactory: factory,
|
|
5776
|
+
blogService: new BlogService(executor),
|
|
5777
|
+
socialService: new SocialService(executor),
|
|
5778
|
+
videoScriptService: new VideoScriptService(executor),
|
|
5779
|
+
analysisService: new AnalysisService(executor),
|
|
5780
|
+
seoService: new SeoService(executor),
|
|
5781
|
+
abTestService: new ABTestService(executor),
|
|
5782
|
+
imagePromptService: new ImagePromptService(executor),
|
|
5783
|
+
contentCalendarService: new ContentCalendarService(executor),
|
|
5784
|
+
mediaGenerationService: new MediaGenerationService(factory)
|
|
5785
|
+
};
|
|
5786
|
+
};
|
|
5787
|
+
var AIContentService = class {
|
|
5788
|
+
providerFactory;
|
|
5789
|
+
blogService;
|
|
5790
|
+
socialService;
|
|
5791
|
+
videoScriptService;
|
|
5792
|
+
analysisService;
|
|
5793
|
+
seoService;
|
|
5794
|
+
abTestService;
|
|
5795
|
+
imagePromptService;
|
|
5796
|
+
contentCalendarService;
|
|
5797
|
+
mediaGenerationService;
|
|
5798
|
+
constructor(configOrGenerator, model, textGenerator) {
|
|
5799
|
+
const bundle = buildServices(configOrGenerator, model, textGenerator);
|
|
5800
|
+
this.providerFactory = bundle.providerFactory;
|
|
5801
|
+
this.blogService = bundle.blogService;
|
|
5802
|
+
this.socialService = bundle.socialService;
|
|
5803
|
+
this.videoScriptService = bundle.videoScriptService;
|
|
5804
|
+
this.analysisService = bundle.analysisService;
|
|
5805
|
+
this.seoService = bundle.seoService;
|
|
5806
|
+
this.abTestService = bundle.abTestService;
|
|
5807
|
+
this.imagePromptService = bundle.imagePromptService;
|
|
5808
|
+
this.contentCalendarService = bundle.contentCalendarService;
|
|
5809
|
+
this.mediaGenerationService = bundle.mediaGenerationService;
|
|
5810
|
+
}
|
|
5811
|
+
/** The composed factory — chat()/chatStream() with usage, health, fallback. */
|
|
5812
|
+
get providers() {
|
|
5813
|
+
return this.providerFactory;
|
|
5814
|
+
}
|
|
5815
|
+
generateBlogPost(request) {
|
|
5816
|
+
return this.blogService.generateBlogPost(request);
|
|
5817
|
+
}
|
|
5818
|
+
generateSocialContent(request) {
|
|
5819
|
+
return this.socialService.generateSocialContent(request);
|
|
5820
|
+
}
|
|
5821
|
+
generateForAllPlatforms(topic, tone) {
|
|
5822
|
+
return this.socialService.generateForAllPlatforms(topic, tone);
|
|
5823
|
+
}
|
|
5824
|
+
generateHashtags(content, count) {
|
|
5825
|
+
return this.socialService.generateHashtags(content, count);
|
|
5826
|
+
}
|
|
5827
|
+
optimizeHashtags(hashtags, platform) {
|
|
5828
|
+
return Promise.resolve(this.socialService.optimizeHashtags(hashtags, platform));
|
|
5829
|
+
}
|
|
5830
|
+
generateVideoScript(request) {
|
|
5831
|
+
return this.videoScriptService.generateVideoScript(request);
|
|
5832
|
+
}
|
|
5833
|
+
generateVoiceScript(topic, emotion, duration) {
|
|
5834
|
+
return this.videoScriptService.generateVoiceScript(topic, emotion, duration);
|
|
5835
|
+
}
|
|
5836
|
+
generateContentCalendar(niche, days) {
|
|
5837
|
+
return this.contentCalendarService.generateContentCalendar(niche, days);
|
|
5838
|
+
}
|
|
5839
|
+
analyzeSentiment(content) {
|
|
5840
|
+
return this.analysisService.analyzeSentiment(content);
|
|
5841
|
+
}
|
|
5842
|
+
analyzeContent(request) {
|
|
5843
|
+
return this.analysisService.analyzeContent(request);
|
|
5844
|
+
}
|
|
5845
|
+
optimizeSEO(request) {
|
|
5846
|
+
return this.seoService.optimizeSEO(request);
|
|
5847
|
+
}
|
|
5848
|
+
calculateSEOScore(content, keywords) {
|
|
5849
|
+
return this.seoService.calculateSEOScore(content, keywords);
|
|
5850
|
+
}
|
|
5851
|
+
analyzeKeywords(content, keywords) {
|
|
5852
|
+
return Promise.resolve(this.seoService.analyzeKeywords(content, keywords));
|
|
5853
|
+
}
|
|
5854
|
+
predictABTest(request) {
|
|
5855
|
+
return this.abTestService.predictABTest(request);
|
|
5856
|
+
}
|
|
5857
|
+
compareVariants(variantA, variantB) {
|
|
5858
|
+
return this.abTestService.compareVariants(variantA, variantB);
|
|
5859
|
+
}
|
|
5860
|
+
generateImagePrompt(description, style) {
|
|
5861
|
+
return this.imagePromptService.generateImagePrompt(description, style);
|
|
5862
|
+
}
|
|
5863
|
+
generateImagePromptsForBlog(blogContent) {
|
|
5864
|
+
return this.imagePromptService.generateImagePromptsForBlog(blogContent);
|
|
5865
|
+
}
|
|
5866
|
+
generateImage(request) {
|
|
5867
|
+
return this.mediaGenerationService.generateImage(request);
|
|
5868
|
+
}
|
|
5869
|
+
generateVideo(request) {
|
|
5870
|
+
return this.mediaGenerationService.generateVideo(request);
|
|
5871
|
+
}
|
|
5872
|
+
convertImageToVideo(request) {
|
|
5873
|
+
return this.mediaGenerationService.convertImageToVideo(request);
|
|
5874
|
+
}
|
|
5875
|
+
transformVideo(request) {
|
|
5876
|
+
return this.mediaGenerationService.transformVideo(request);
|
|
5877
|
+
}
|
|
5878
|
+
};
|
|
5879
|
+
|
|
5880
|
+
// src/wizard/content.wizard.ts
|
|
5881
|
+
var CONTENT_WIZARD_STEPS = [
|
|
5882
|
+
{
|
|
5883
|
+
id: "select-type",
|
|
5884
|
+
label: "Select Type",
|
|
5885
|
+
icon: "Layers",
|
|
5886
|
+
description: "Choose the type of content you want to generate",
|
|
5887
|
+
validate: (data) => Boolean(data.contentType)
|
|
5888
|
+
},
|
|
5889
|
+
{
|
|
5890
|
+
id: "input-topic",
|
|
5891
|
+
label: "Topic",
|
|
5892
|
+
icon: "Lightbulb",
|
|
5893
|
+
description: "Enter your topic or idea",
|
|
5894
|
+
validate: (data) => {
|
|
5895
|
+
const topic = data.topic;
|
|
5896
|
+
return typeof topic === "string" && topic.length > 0;
|
|
5897
|
+
}
|
|
5898
|
+
},
|
|
5899
|
+
{
|
|
5900
|
+
id: "configure",
|
|
5901
|
+
label: "Configure",
|
|
5902
|
+
icon: "Settings",
|
|
5903
|
+
description: "Set tone, audience, and platform",
|
|
5904
|
+
validate: (data) => {
|
|
5905
|
+
const d = data;
|
|
5906
|
+
return Boolean(d.tone && d.targetAudience);
|
|
5907
|
+
}
|
|
5908
|
+
},
|
|
5909
|
+
{
|
|
5910
|
+
id: "advanced",
|
|
5911
|
+
label: "Advanced",
|
|
5912
|
+
icon: "Sliders",
|
|
5913
|
+
description: "Additional options and optimizations",
|
|
5914
|
+
optional: true
|
|
5915
|
+
},
|
|
5916
|
+
{
|
|
5917
|
+
id: "preview",
|
|
5918
|
+
label: "Preview",
|
|
5919
|
+
icon: "Eye",
|
|
5920
|
+
description: "Review your settings before generation"
|
|
5921
|
+
},
|
|
5922
|
+
{
|
|
5923
|
+
id: "generating",
|
|
5924
|
+
label: "Generating",
|
|
5925
|
+
icon: "Sparkles",
|
|
5926
|
+
description: "AI is generating your content"
|
|
5927
|
+
},
|
|
5928
|
+
{
|
|
5929
|
+
id: "results",
|
|
5930
|
+
label: "Results",
|
|
5931
|
+
icon: "CheckCircle",
|
|
5932
|
+
description: "Your generated content is ready"
|
|
5933
|
+
}
|
|
5934
|
+
];
|
|
5935
|
+
function buildContentRequest(data) {
|
|
5936
|
+
switch (data.contentType) {
|
|
5937
|
+
case "blog":
|
|
5938
|
+
return {
|
|
5939
|
+
topic: data.topic ?? "",
|
|
5940
|
+
blogType: "tutorial",
|
|
5941
|
+
targetKeywords: data.keywords ?? [],
|
|
5942
|
+
tone: data.tone ?? "professional",
|
|
5943
|
+
wordCount: data.wordCount ?? 1e3,
|
|
5944
|
+
targetAudience: data.targetAudience ?? "",
|
|
5945
|
+
seoOptimization: data.seoOptimization ?? false,
|
|
5946
|
+
includeImages: data.includeImages ?? false,
|
|
5947
|
+
includeSchema: false
|
|
5948
|
+
};
|
|
5949
|
+
case "social":
|
|
5950
|
+
return {
|
|
5951
|
+
topic: data.topic ?? "",
|
|
5952
|
+
platform: data.platform ?? "twitter",
|
|
5953
|
+
tone: data.tone ?? "casual",
|
|
5954
|
+
hashtags: true,
|
|
5955
|
+
targetAudience: data.targetAudience,
|
|
5956
|
+
includeCallToAction: data.includeCallToAction
|
|
5957
|
+
};
|
|
5958
|
+
case "script":
|
|
5959
|
+
return {
|
|
5960
|
+
topic: data.topic ?? "",
|
|
5961
|
+
tone: data.tone ?? "professional",
|
|
5962
|
+
duration: data.duration ?? 60,
|
|
5963
|
+
targetAudience: data.targetAudience ?? "",
|
|
5964
|
+
includeVisuals: true,
|
|
5965
|
+
includeCallToAction: data.includeCallToAction ?? false
|
|
5966
|
+
};
|
|
5967
|
+
default:
|
|
5968
|
+
throw new Error(`Unsupported content type: ${data.contentType}`);
|
|
5969
|
+
}
|
|
5970
|
+
}
|
|
5971
|
+
|
|
5972
|
+
// src/wizard/image.wizard.ts
|
|
5973
|
+
var IMAGE_WIZARD_STEPS = [
|
|
5974
|
+
{
|
|
5975
|
+
id: "input-prompt",
|
|
5976
|
+
label: "Describe Image",
|
|
5977
|
+
icon: "Image",
|
|
5978
|
+
description: "Describe the image you want to create",
|
|
5979
|
+
validate: (data) => {
|
|
5980
|
+
const prompt = data.prompt;
|
|
5981
|
+
return typeof prompt === "string" && prompt.length > 0;
|
|
5982
|
+
}
|
|
5983
|
+
},
|
|
5984
|
+
{
|
|
5985
|
+
id: "select-style",
|
|
5986
|
+
label: "Style",
|
|
5987
|
+
icon: "Palette",
|
|
5988
|
+
description: "Choose the artistic style",
|
|
5989
|
+
validate: (data) => Boolean(data.style)
|
|
5990
|
+
},
|
|
5991
|
+
{
|
|
5992
|
+
id: "configure",
|
|
5993
|
+
label: "Configure",
|
|
5994
|
+
icon: "Settings",
|
|
5995
|
+
description: "Set format, quality, and quantity",
|
|
5996
|
+
validate: (data) => {
|
|
5997
|
+
const d = data;
|
|
5998
|
+
return Boolean(d.format && d.quality);
|
|
5999
|
+
}
|
|
6000
|
+
},
|
|
6001
|
+
{
|
|
6002
|
+
id: "advanced",
|
|
6003
|
+
label: "Advanced",
|
|
6004
|
+
icon: "Sliders",
|
|
6005
|
+
description: "Color palette and platform optimization",
|
|
6006
|
+
optional: true
|
|
6007
|
+
},
|
|
6008
|
+
{ id: "preview", label: "Preview", icon: "Eye", description: "Review your settings" },
|
|
6009
|
+
{ id: "generating", label: "Generating", icon: "Sparkles", description: "AI is creating your image" },
|
|
6010
|
+
{ id: "results", label: "Results", icon: "Image", description: "Your generated image is ready" }
|
|
6011
|
+
];
|
|
6012
|
+
function buildImageRequest(data) {
|
|
6013
|
+
return {
|
|
6014
|
+
type: "image",
|
|
6015
|
+
prompt: data.prompt ?? "",
|
|
6016
|
+
style: data.style,
|
|
6017
|
+
format: data.format,
|
|
6018
|
+
quality: data.quality,
|
|
6019
|
+
quantity: data.quantity ?? 1
|
|
6020
|
+
};
|
|
6021
|
+
}
|
|
6022
|
+
|
|
6023
|
+
// src/wizard/video.wizard.ts
|
|
6024
|
+
var validateSource = (data) => {
|
|
6025
|
+
const d = data;
|
|
6026
|
+
if (d.generationType === "text-to-video") {
|
|
6027
|
+
return typeof d.prompt === "string" && d.prompt.length > 0;
|
|
6028
|
+
}
|
|
6029
|
+
if (d.generationType === "image-to-video") {
|
|
6030
|
+
return typeof d.imageUrl === "string" && d.imageUrl.length > 0;
|
|
6031
|
+
}
|
|
6032
|
+
if (d.generationType === "video-to-video") {
|
|
6033
|
+
return typeof d.sourceVideoUrl === "string" && d.sourceVideoUrl.length > 0 && typeof d.prompt === "string" && d.prompt.length > 0;
|
|
6034
|
+
}
|
|
6035
|
+
return false;
|
|
6036
|
+
};
|
|
6037
|
+
var VIDEO_WIZARD_STEPS = [
|
|
6038
|
+
{
|
|
6039
|
+
id: "select-type",
|
|
6040
|
+
label: "Select Type",
|
|
6041
|
+
icon: "Video",
|
|
6042
|
+
description: "Choose video generation type",
|
|
6043
|
+
validate: (data) => Boolean(data.generationType)
|
|
6044
|
+
},
|
|
6045
|
+
{
|
|
6046
|
+
id: "input-source",
|
|
6047
|
+
label: "Source",
|
|
6048
|
+
icon: "FileInput",
|
|
6049
|
+
description: "Provide your source (prompt, image, or video)",
|
|
6050
|
+
validate: validateSource
|
|
6051
|
+
},
|
|
6052
|
+
{
|
|
6053
|
+
id: "configure",
|
|
6054
|
+
label: "Configure",
|
|
6055
|
+
icon: "Settings",
|
|
6056
|
+
description: "Set duration, aspect ratio, and style",
|
|
6057
|
+
validate: (data) => {
|
|
6058
|
+
const d = data;
|
|
6059
|
+
return Boolean(d.duration && d.aspectRatio);
|
|
6060
|
+
}
|
|
6061
|
+
},
|
|
6062
|
+
{ id: "advanced", label: "Advanced", icon: "Sliders", description: "Additional video options", optional: true },
|
|
6063
|
+
{ id: "preview", label: "Preview", icon: "Eye", description: "Review your settings" },
|
|
6064
|
+
{ id: "generating", label: "Generating", icon: "Sparkles", description: "AI is creating your video" },
|
|
6065
|
+
{ id: "results", label: "Results", icon: "Video", description: "Your generated video is ready" }
|
|
6066
|
+
];
|
|
6067
|
+
function buildVideoRequest(data) {
|
|
6068
|
+
switch (data.generationType) {
|
|
6069
|
+
case "text-to-video":
|
|
6070
|
+
return {
|
|
6071
|
+
type: "video",
|
|
6072
|
+
prompt: data.prompt ?? "",
|
|
6073
|
+
duration: data.duration ?? 5,
|
|
6074
|
+
aspectRatio: data.aspectRatio ?? "16:9",
|
|
6075
|
+
style: data.style,
|
|
6076
|
+
quality: data.quality
|
|
6077
|
+
};
|
|
6078
|
+
case "image-to-video":
|
|
6079
|
+
return {
|
|
6080
|
+
type: "video",
|
|
6081
|
+
imageUrl: data.imageUrl ?? "",
|
|
6082
|
+
prompt: data.prompt,
|
|
6083
|
+
duration: data.duration ?? 5,
|
|
6084
|
+
motion: data.motion ?? "medium",
|
|
6085
|
+
camera: data.camera ?? "static"
|
|
6086
|
+
};
|
|
6087
|
+
case "video-to-video":
|
|
6088
|
+
return {
|
|
6089
|
+
type: "video",
|
|
6090
|
+
sourceVideoUrl: data.sourceVideoUrl ?? "",
|
|
6091
|
+
prompt: data.prompt ?? "",
|
|
6092
|
+
styleTransfer: data.styleTransfer,
|
|
6093
|
+
enhanceQuality: data.enhanceQuality
|
|
6094
|
+
};
|
|
6095
|
+
default:
|
|
6096
|
+
throw new Error(`Unsupported generation type: ${data.generationType}`);
|
|
6097
|
+
}
|
|
6098
|
+
}
|
|
6099
|
+
|
|
6100
|
+
export { ABTestService, AIContentService, AIError, AIErrorType, ANTHROPIC_API_VERSION, ANTHROPIC_DEFAULT_MAX_TOKENS, ANTHROPIC_MODELS, ANTHROPIC_TIERS, API_ENDPOINTS, ASPECT_RATIO_OPTIONS, ASPECT_RATIO_VALUES, AnalysisService, AnthropicHttpTransport, AnthropicProvider, AnthropicRequestBuilder, AuthenticationError, BaseProvider as BaseAIProvider, BaseProvider, BlogService, CONTENT_WIZARD_STEPS, CacheManager, CancellationError, ChatIdGenerator, ChatService, CompositeExecutor, ContentCalendarService, DEFAULT_API_KEY_RULE, DEFAULT_BASE_URL, DEFAULT_ERROR_CLASSIFICATION_RULE, DEFAULT_GENERATION_CONFIG, DEFAULT_HTTP_STATUS_RULE, DEFAULT_MODELS, DEFAULT_PROMPT_STRATEGY, DEFAULT_RETRY_BACKOFF_MULTIPLIER, DEFAULT_RETRY_INITIAL_DELAY_MS, DEFAULT_RETRY_JITTER_FACTOR, DEFAULT_RETRY_MAX_ATTEMPTS, DEFAULT_RETRY_MAX_DELAY_MS, DebounceManager, DedupeExecutor, FalProvider, GEMINI_TIERS, CREDIT_COSTS as GENERATION_COSTS, GROQ_MODELS, GROQ_TIERS, GeminiProvider, GenerationExecutor, GenerationFailedError, GroqChatRequestBuilder, GroqConfigStore, GroqError, AIErrorType as GroqErrorType, GroqHttpClient, GroqHttpTransport, GroqProvider, IMAGE_QUALITY_OPTIONS, IMAGE_QUALITY_VALUES, IMAGE_WIZARD_STEPS, ImagePromptService, JSON_CODE_BLOCK_PATTERN, JSON_OBJECT_PATTERN, JsonResponseParser, MOTION_OPTIONS, MediaGenerationService, PromptBuilder, ProviderError, ProviderFactory, ProviderQuotaExhaustedError, ProviderUnavailableError, PrunaProvider, QueueExecutor, RequestDeduplicator, RequestPriority, RequestQueue, RetryExecutor, RetryManager, SSE_BRIDGE_EVENTS, SSE_DONE_MARKER, SSE_PREFIX, STYLE_PRESETS, SeoService, SocialService, StreamingResponseParser, StructuredPromptBuilder, TEXT_TIERS, TIMEOUTS, TextGenerationService, ThrottleManager, TimeoutError, USER_FRIENDLY_ERROR_MESSAGES, VIDEO_DURATION_OPTIONS, VIDEO_DURATION_OPTIONS_SECONDS, VIDEO_QUALITY_OPTIONS, VIDEO_QUALITY_VALUES, VIDEO_WIZARD_STEPS, ValidationError2 as ValidationError, VideoScriptService, asObjectArray, asRecord, asStringArray, asTrimmedOptionalString, batchRequest, buildCacheKey, buildContentRequest, buildHttpStatusFallback, buildImageRequest, buildVideoRequest, cacheManager, calculateContentCreditCost as calculateCreditCost, chatIdGenerator, clampScore, classifyHttpStatus, configureProvider, consumeAnthropicStream, consumeGroqStream, createAI, createAssistantMessage, createFalProvider, createGeminiProvider, createGroqProvider, createMessage, createProviderFactory, createPrunaProvider, createSseResponse, createSystemMessage, createUserMessage, debounce, debounceManager, defaultEffortForModel, describeAIErrorType, extractContentFromSsePayload, extractErrorMessageFromJsonBody, extractErrorMessageFromResponse, extractJSON, extractJsonArray, extractJsonCandidate, extractJsonFromCodeFence, extractJsonObject, extractSseDataPayload, extractTextFromMessages, extractTokenUsage, formatErrorForLogging, formatMessagesForDisplay, generateImageThenVideo, generate as generatePruna, generateWithPruna, getDimensionsForAspectRatio, getProvider, getRecommendedQuality, isAuthErrorType, isMediaProvider, isRetryableErrorType, isSseDataLine, isSseDoneMarker, isTextProvider, isTextTier, isValidApiKey, isValidJSON, mapAnthropicStopReason, mergeTierOverrides, messageFormatter, normalizeSseChunk, oneOfCatalog, parseAIResponse, pollForResult, promptToMessages, repairCommonJsonDefects, requestDeduplicator, requestQueue, requestStructuredJson, resetProvider, resolveModel, resolveUserFriendlyErrorMessage, resolveUserFriendlyMessage, retryManager, safeJSONParse, splitSseLines, submitPrediction, throttle, throttleManager, toGroqMessages, uploadImage, validateApiKey, withRetry };
|
|
4359
6101
|
//# sourceMappingURL=index.js.map
|
|
4360
6102
|
//# sourceMappingURL=index.js.map
|