@umituz/web-ai 1.0.3 → 1.0.4

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 (47) hide show
  1. package/dist/{AIErrors-B2ogd1PB.d.ts → AIErrors-CLjXRty-.d.ts} +99 -92
  2. package/dist/{AIErrors-C5EasV_c.d.cts → AIErrors-DjZXUiLT.d.cts} +99 -92
  3. package/dist/PromptBuilder-B5Lm1znm.d.ts +215 -0
  4. package/dist/PromptBuilder-DIUZlfV6.d.cts +215 -0
  5. package/dist/{cancellation-error-DwHrDKBz.d.cts → cancellation-error-Cj7fJyCg.d.cts} +3 -3
  6. package/dist/{cancellation-error-CKcZRhFg.d.ts → cancellation-error-CkMn5Kft.d.ts} +3 -3
  7. package/dist/chat/index.cjs.map +1 -1
  8. package/dist/chat/index.d.cts +3 -3
  9. package/dist/chat/index.d.ts +3 -3
  10. package/dist/chat/index.js.map +1 -1
  11. package/dist/{chat.service-CL1qtYxe.d.cts → chat.service-9M-KpLo-.d.cts} +1 -1
  12. package/dist/{chat.service-q05GnhEm.d.ts → chat.service-B4FLFxR1.d.ts} +1 -1
  13. package/dist/content/index.cjs +759 -400
  14. package/dist/content/index.cjs.map +1 -1
  15. package/dist/content/index.d.cts +165 -219
  16. package/dist/content/index.d.ts +165 -219
  17. package/dist/content/index.js +702 -401
  18. package/dist/content/index.js.map +1 -1
  19. package/dist/{create-ai-9PW752z8.d.ts → create-ai-0eZFFqTw.d.ts} +1 -1
  20. package/dist/{create-ai-CXYKPK6G.d.cts → create-ai-BrKR_5fQ.d.cts} +1 -1
  21. package/dist/hooks/index.cjs +2 -0
  22. package/dist/hooks/index.cjs.map +1 -1
  23. package/dist/hooks/index.d.cts +9 -9
  24. package/dist/hooks/index.d.ts +9 -9
  25. package/dist/hooks/index.js +1 -1
  26. package/dist/hooks/index.js.map +1 -1
  27. package/dist/index-BUVULo3h.d.ts +177 -0
  28. package/dist/index-BulSkB2L.d.cts +177 -0
  29. package/dist/index.cjs +1727 -15
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.d.cts +8 -5
  32. package/dist/index.d.ts +8 -5
  33. package/dist/index.js +1690 -15
  34. package/dist/index.js.map +1 -1
  35. package/dist/{provider.factory-DfDfk0dK.d.ts → provider.factory-BwPnqSEU.d.ts} +3 -1
  36. package/dist/{provider.factory-BxsfK4WW.d.cts → provider.factory-DyfJtR8M.d.cts} +3 -1
  37. package/dist/providers/index.cjs +9 -0
  38. package/dist/providers/index.cjs.map +1 -1
  39. package/dist/providers/index.d.cts +10 -8
  40. package/dist/providers/index.d.ts +10 -8
  41. package/dist/providers/index.js +7 -1
  42. package/dist/providers/index.js.map +1 -1
  43. package/dist/wizard/index.d.cts +2 -86
  44. package/dist/wizard/index.d.ts +2 -86
  45. package/package.json +16 -1
  46. package/dist/ContentGeneration-B6iK2B33.d.cts +0 -93
  47. 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 ValidationError = class extends Error {
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 ValidationError({
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 ValidationError({
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 ValidationError({
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 ValidationError({
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 ValidationError({
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 ValidationError({
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 ValidationError({
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 ValidationError({
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 ValidationError({
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 ValidationError({
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 ValidationError({
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 ValidationError({
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 ValidationError({
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,1533 @@ function resetProvider() {
4355
4503
  container = null;
4356
4504
  }
4357
4505
 
4358
- export { AIError, AIErrorType, ANTHROPIC_API_VERSION, ANTHROPIC_DEFAULT_MAX_TOKENS, ANTHROPIC_MODELS, ANTHROPIC_TIERS, API_ENDPOINTS, AnthropicHttpTransport, AnthropicProvider, AnthropicRequestBuilder, AuthenticationError, BaseProvider, CacheManager, CancellationError, ChatIdGenerator, ChatService, CompositeExecutor, 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, GROQ_MODELS, GROQ_TIERS, GeminiProvider, GenerationFailedError, GroqChatRequestBuilder, GroqConfigStore, GroqError, AIErrorType as GroqErrorType, GroqHttpClient, GroqHttpTransport, GroqProvider, JSON_CODE_BLOCK_PATTERN, JSON_OBJECT_PATTERN, JsonResponseParser, ProviderError, ProviderFactory, PrunaProvider, QueueExecutor, RequestDeduplicator, RequestQueue, RetryExecutor, RetryManager, SSE_BRIDGE_EVENTS, SSE_DONE_MARKER, SSE_PREFIX, StreamingResponseParser, StructuredPromptBuilder, TEXT_TIERS, TIMEOUTS, TextGenerationService, ThrottleManager, TimeoutError, USER_FRIENDLY_ERROR_MESSAGES, ValidationError, asObjectArray, asRecord, asStringArray, asTrimmedOptionalString, buildCacheKey, buildHttpStatusFallback, cacheManager, chatIdGenerator, clampScore, classifyHttpStatus, configureProvider, consumeAnthropicStream, consumeGroqStream, createAI, createAssistantMessage, createFalProvider, createGeminiProvider, createMessage, createPrunaProvider, createSseResponse, createSystemMessage, createUserMessage, debounce, debounceManager, defaultEffortForModel, describeAIErrorType, extractContentFromSsePayload, extractErrorMessageFromJsonBody, extractErrorMessageFromResponse, extractJsonArray, extractJsonCandidate, extractJsonFromCodeFence, extractJsonObject, extractSseDataPayload, extractTextFromMessages, extractTokenUsage, formatErrorForLogging, formatMessagesForDisplay, generateImageThenVideo, generate as generatePruna, generateWithPruna, getProvider, isAuthErrorType, isMediaProvider, isRetryableErrorType, isSseDataLine, isSseDoneMarker, isTextProvider, isTextTier, isValidApiKey, mapAnthropicStopReason, mergeTierOverrides, messageFormatter, normalizeSseChunk, oneOfCatalog, pollForResult, promptToMessages, repairCommonJsonDefects, requestDeduplicator, requestQueue, requestStructuredJson, resetProvider, resolveModel, resolveUserFriendlyErrorMessage, resolveUserFriendlyMessage, retryManager, splitSseLines, submitPrediction, throttle, throttleManager, toGroqMessages, uploadImage, validateApiKey, withRetry };
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
+ async function batchRequest(requests, options = {}) {
5113
+ const {
5114
+ concurrency = 3,
5115
+ stopOnError = false
5116
+ } = options;
5117
+ const results = [];
5118
+ const errors = [];
5119
+ for (let i = 0; i < requests.length; i += concurrency) {
5120
+ const batch = requests.slice(i, i + concurrency);
5121
+ const batchResults = await Promise.allSettled(
5122
+ batch.map((fn) => fn())
5123
+ );
5124
+ for (const result of batchResults) {
5125
+ if (result.status === "fulfilled") {
5126
+ results.push(result.value);
5127
+ } else {
5128
+ errors.push(result.reason);
5129
+ if (stopOnError) {
5130
+ throw new Error(
5131
+ `Batch request failed: ${errors[0].message}`
5132
+ );
5133
+ }
5134
+ }
5135
+ }
5136
+ }
5137
+ if (errors.length > 0 && !stopOnError) {
5138
+ console.warn(`${errors.length} requests failed in batch`);
5139
+ }
5140
+ return results;
5141
+ }
5142
+
5143
+ // src/content/application/services/SocialService.ts
5144
+ var MULTI_PLATFORMS = [
5145
+ "twitter",
5146
+ "linkedin",
5147
+ "instagram",
5148
+ "threads",
5149
+ "tiktok"
5150
+ ];
5151
+ var DEFAULT_SOCIAL_RESULT = {
5152
+ content: "",
5153
+ platform: "twitter",
5154
+ hashtags: [],
5155
+ emojis: [],
5156
+ characterCount: 0,
5157
+ estimatedEngagement: 0
5158
+ };
5159
+ var SocialService = class {
5160
+ constructor(executor) {
5161
+ this.executor = executor;
5162
+ }
5163
+ executor;
5164
+ async generateSocialContent(request) {
5165
+ const topic = validateTopicText(request.topic);
5166
+ const spec = resolvePlatformSpec(request.platform);
5167
+ const maxLength = resolveMaxContentLength(request.platform, request.maxLength);
5168
+ const prompt = PromptBuilder.socialPost({
5169
+ topic,
5170
+ platform: request.platform,
5171
+ tone: request.tone,
5172
+ style: spec.style,
5173
+ maxLength,
5174
+ includeHashtags: request.hashtags !== false,
5175
+ includeCallToAction: Boolean(request.includeCallToAction)
5176
+ });
5177
+ const parsed = await this.executor.runJson(
5178
+ prompt,
5179
+ { ...DEFAULT_SOCIAL_RESULT, platform: request.platform },
5180
+ { maxTokens: 500, temperature: 0.8 }
5181
+ );
5182
+ return {
5183
+ ...parsed,
5184
+ platform: request.platform,
5185
+ characterCount: parsed.content?.length ?? 0
5186
+ };
5187
+ }
5188
+ async generateForAllPlatforms(topic, tone) {
5189
+ const requests = MULTI_PLATFORMS.map(
5190
+ (platform) => () => this.generateSocialContent({ topic, platform, tone })
5191
+ );
5192
+ try {
5193
+ return await batchRequest(requests, { concurrency: 2, stopOnError: false });
5194
+ } catch (error) {
5195
+ console.warn("Batch execution failed, falling back to sequential:", error);
5196
+ const results = [];
5197
+ for (const platform of MULTI_PLATFORMS) {
5198
+ try {
5199
+ results.push(await this.generateSocialContent({ topic, platform, tone }));
5200
+ } catch (err) {
5201
+ console.error(`Failed to generate for ${platform}:`, err);
5202
+ }
5203
+ }
5204
+ return results;
5205
+ }
5206
+ }
5207
+ async generateHashtags(content, count) {
5208
+ const validated = validateHashtagCount(count);
5209
+ const prompt = PromptBuilder.hashtags(content, validated);
5210
+ const response = await this.executor.runText(prompt, { maxTokens: 200, temperature: 0.7 });
5211
+ const hashtags = response.match(/#[\w-]+/g) || [];
5212
+ return hashtags.slice(0, validated);
5213
+ }
5214
+ optimizeHashtags(hashtags, platform) {
5215
+ const budget = resolveHashtagBudget(platform);
5216
+ return rankAndTrimHashtags(hashtags, budget);
5217
+ }
5218
+ };
5219
+
5220
+ // src/content/application/services/VideoScriptService.ts
5221
+ var buildScriptResult = (parsed, duration) => {
5222
+ const script = parsed.script ?? "";
5223
+ if (!script) {
5224
+ throw new Error("AI response missing script field");
5225
+ }
5226
+ const wordCount = script.trim().length === 0 ? 0 : script.trim().split(/\s+/).length;
5227
+ return {
5228
+ ...parsed,
5229
+ script,
5230
+ duration,
5231
+ wordCount
5232
+ };
5233
+ };
5234
+ var VideoScriptService = class {
5235
+ constructor(executor) {
5236
+ this.executor = executor;
5237
+ }
5238
+ executor;
5239
+ async generateVideoScript(request) {
5240
+ const topic = validateTopicText(request.topic);
5241
+ const duration = validateDurationSeconds(request.duration);
5242
+ const prompt = PromptBuilder.videoScript({
5243
+ topic,
5244
+ tone: request.tone,
5245
+ duration,
5246
+ targetAudience: request.targetAudience,
5247
+ includeVisuals: request.includeVisuals,
5248
+ includeCallToAction: request.includeCallToAction
5249
+ });
5250
+ const parsed = await this.executor.runJson(
5251
+ prompt,
5252
+ { script: "", visualCues: [], duration, wordCount: 0, estimatedEngagement: 0 },
5253
+ { maxTokens: estimateTokenBudgetForDuration(duration), temperature: 0.8 }
5254
+ );
5255
+ return buildScriptResult(parsed, duration);
5256
+ }
5257
+ async generateVoiceScript(topic, emotion, duration) {
5258
+ const validatedTopic = validateTopicText(topic);
5259
+ const validatedDuration = validateDurationSeconds(duration);
5260
+ const prompt = PromptBuilder.voiceScript({
5261
+ topic: validatedTopic,
5262
+ emotion,
5263
+ duration: validatedDuration
5264
+ });
5265
+ const parsed = await this.executor.runJson(
5266
+ prompt,
5267
+ { script: "", visualCues: [], duration: validatedDuration, wordCount: 0, estimatedEngagement: 0 },
5268
+ { maxTokens: estimateTokenBudgetForDuration(validatedDuration), temperature: 0.8 }
5269
+ );
5270
+ return buildScriptResult(parsed, validatedDuration);
5271
+ }
5272
+ };
5273
+
5274
+ // src/content/application/services/AnalysisService.ts
5275
+ var DEFAULT_SENTIMENT = {
5276
+ sentiment: "neutral",
5277
+ confidence: 0.5,
5278
+ emotions: []
5279
+ };
5280
+ var DEFAULT_ANALYSIS = {
5281
+ sentiment: DEFAULT_SENTIMENT,
5282
+ keywords: [],
5283
+ entities: [],
5284
+ suggestedImprovements: [],
5285
+ readabilityScore: 50,
5286
+ estimatedEngagement: 50
5287
+ };
5288
+ var AnalysisService = class {
5289
+ constructor(executor) {
5290
+ this.executor = executor;
5291
+ }
5292
+ executor;
5293
+ async analyzeSentiment(content) {
5294
+ const validated = validateContentBody(content);
5295
+ const prompt = PromptBuilder.sentiment(validated);
5296
+ const result = await this.executor.runJson(
5297
+ prompt,
5298
+ DEFAULT_SENTIMENT,
5299
+ { maxTokens: 200, temperature: 0.3 }
5300
+ );
5301
+ return {
5302
+ ...result,
5303
+ confidence: clampConfidenceToValidRange(result.confidence)
5304
+ };
5305
+ }
5306
+ async analyzeContent(request) {
5307
+ const validated = validateContentBody(request.content);
5308
+ const sentimentResult = await this.analyzeSentiment(validated);
5309
+ const prompt = PromptBuilder.contentAnalysis(validated);
5310
+ const parsed = await this.executor.runJson(
5311
+ prompt,
5312
+ { ...DEFAULT_ANALYSIS, sentiment: sentimentResult },
5313
+ { maxTokens: 300, temperature: 0.5 }
5314
+ );
5315
+ return {
5316
+ sentiment: sentimentResult,
5317
+ keywords: parsed.keywords ?? [],
5318
+ entities: parsed.entities ?? [],
5319
+ suggestedImprovements: parsed.suggestedImprovements ?? [],
5320
+ readabilityScore: clampScoreToValidRange(parsed.readabilityScore),
5321
+ estimatedEngagement: clampScoreToValidRange(parsed.estimatedEngagement)
5322
+ };
5323
+ }
5324
+ };
5325
+
5326
+ // src/content/application/services/SeoService.ts
5327
+ var DEFAULT_SEO_SCORE = {
5328
+ keywordDensity: 50,
5329
+ readabilityScore: 50,
5330
+ titleOptimization: 50,
5331
+ metaDescription: 50,
5332
+ headingStructure: 50,
5333
+ internalLinking: 50,
5334
+ overall: 50
5335
+ };
5336
+ var UNDERUTILIZED_SUGGESTION = "Consider using this keyword more frequently";
5337
+ var SeoService = class {
5338
+ constructor(executor) {
5339
+ this.executor = executor;
5340
+ }
5341
+ executor;
5342
+ async optimizeSEO(request) {
5343
+ const content = validateContentBody(request.content);
5344
+ const keywords = validateKeywordList(request.keywords);
5345
+ const prompt = PromptBuilder.seoOptimization(content, keywords);
5346
+ const result = await this.executor.runJson(
5347
+ prompt,
5348
+ {
5349
+ optimized: content,
5350
+ score: 50,
5351
+ suggestions: [],
5352
+ addedKeywords: [],
5353
+ removedFillerWords: 0,
5354
+ readabilityImprovements: []
5355
+ },
5356
+ { maxTokens: 1e3, temperature: 0.7 }
5357
+ );
5358
+ return {
5359
+ ...result,
5360
+ score: clampScoreToValidRange(result.score)
5361
+ };
5362
+ }
5363
+ async calculateSEOScore(content, keywords) {
5364
+ const validatedContent = validateContentBody(content);
5365
+ const validatedKeywords = validateKeywordList(keywords);
5366
+ const prompt = PromptBuilder.seoOptimization(
5367
+ truncateForSeoPreview(validatedContent),
5368
+ validatedKeywords
5369
+ );
5370
+ const result = await this.executor.runJson(
5371
+ prompt,
5372
+ DEFAULT_SEO_SCORE,
5373
+ { maxTokens: 200, temperature: 0.3 }
5374
+ );
5375
+ return {
5376
+ keywordDensity: clampScoreToValidRange(result.keywordDensity),
5377
+ readabilityScore: clampScoreToValidRange(result.readabilityScore),
5378
+ titleOptimization: clampScoreToValidRange(result.titleOptimization),
5379
+ metaDescription: clampScoreToValidRange(result.metaDescription),
5380
+ headingStructure: clampScoreToValidRange(result.headingStructure),
5381
+ internalLinking: clampScoreToValidRange(result.internalLinking),
5382
+ overall: clampScoreToValidRange(result.overall)
5383
+ };
5384
+ }
5385
+ analyzeKeywords(content, keywords) {
5386
+ const validatedContent = validateContentBody(content);
5387
+ const validatedKeywords = validateKeywordList(keywords);
5388
+ return validatedKeywords.map((keyword) => {
5389
+ const count = countKeywordOccurrences(validatedContent, keyword);
5390
+ const density = calculateKeywordDensity(validatedContent, keyword);
5391
+ return {
5392
+ keyword,
5393
+ count,
5394
+ density,
5395
+ prominence: classifyKeywordProminence(density),
5396
+ suggestions: isUnderutilizedKeyword(density) ? [UNDERUTILIZED_SUGGESTION] : []
5397
+ };
5398
+ });
5399
+ }
5400
+ };
5401
+
5402
+ // src/content/application/services/ABTestService.ts
5403
+ var DEFAULT_PREDICTION = {
5404
+ variantId: "",
5405
+ predictedEngagement: 0,
5406
+ predictedCTR: 0,
5407
+ predictedConversions: 0,
5408
+ confidence: 0,
5409
+ reasoning: "",
5410
+ strengths: [],
5411
+ weaknesses: [],
5412
+ suggestions: []
5413
+ };
5414
+ var VARIANT_A_ID = "A";
5415
+ var VARIANT_B_ID = "B";
5416
+ var FALLBACK_ENGAGEMENT = 50;
5417
+ var DEFAULT_RECOMMENDATIONS = [
5418
+ "Test with larger audience",
5419
+ "Monitor click-through rates"
5420
+ ];
5421
+ var ABTestService = class {
5422
+ constructor(executor) {
5423
+ this.executor = executor;
5424
+ }
5425
+ executor;
5426
+ async predictABTest(request) {
5427
+ const predictions = [];
5428
+ for (const variant of request.variants) {
5429
+ const prompt = PromptBuilder.abTestVariant({
5430
+ content: truncateForAbVariantPreview(variant.content),
5431
+ contentType: variant.contentType,
5432
+ tone: variant.tone,
5433
+ targetAudience: request.targetAudience,
5434
+ platform: request.platform,
5435
+ goals: request.goals
5436
+ });
5437
+ const parsed = await this.executor.runJson(
5438
+ prompt,
5439
+ { ...DEFAULT_PREDICTION, variantId: variant.id },
5440
+ { maxTokens: 300, temperature: 0.5 }
5441
+ );
5442
+ predictions.push({
5443
+ variantId: variant.id,
5444
+ predictedEngagement: clampScoreToValidRange(parsed.predictedEngagement),
5445
+ predictedCTR: clampScoreToValidRange(parsed.predictedCTR),
5446
+ predictedConversions: clampScoreToValidRange(parsed.predictedConversions),
5447
+ confidence: clampConfidenceToValidRange(parsed.confidence),
5448
+ reasoning: parsed.reasoning ?? "",
5449
+ strengths: parsed.strengths ?? [],
5450
+ weaknesses: parsed.weaknesses ?? [],
5451
+ suggestions: parsed.suggestions ?? []
5452
+ });
5453
+ }
5454
+ return predictions;
5455
+ }
5456
+ async compareVariants(variantA, variantB) {
5457
+ const predictions = await this.predictABTest({
5458
+ variants: [
5459
+ { id: VARIANT_A_ID, content: variantA, contentType: "social", tone: "casual" },
5460
+ { id: VARIANT_B_ID, content: variantB, contentType: "social", tone: "casual" }
5461
+ ],
5462
+ targetAudience: "general",
5463
+ platform: "twitter",
5464
+ goals: ["engagement", "clicks"]
5465
+ });
5466
+ const scoreA = predictions[0]?.predictedEngagement ?? FALLBACK_ENGAGEMENT;
5467
+ const scoreB = predictions[1]?.predictedEngagement ?? FALLBACK_ENGAGEMENT;
5468
+ const isTie = scoreA === scoreB;
5469
+ const winner = selectHigherScoreVariantId(scoreA, scoreB, VARIANT_A_ID, VARIANT_B_ID);
5470
+ const improvement = calculateImprovementPercentage(scoreA, scoreB);
5471
+ return {
5472
+ winner,
5473
+ confidence: AB_TEST_DEFAULT_CONFIDENCE,
5474
+ improvement: isTie ? "0%" : `+${improvement}% engagement`,
5475
+ reasoning: isTie ? "Both variants have equal predicted engagement" : winner === VARIANT_A_ID ? "Variant A has more engaging content" : "Variant B has more engaging content",
5476
+ recommendations: [...DEFAULT_RECOMMENDATIONS]
5477
+ };
5478
+ }
5479
+ };
5480
+
5481
+ // src/content/application/services/ImagePromptService.ts
5482
+ var ImagePromptService = class {
5483
+ constructor(executor) {
5484
+ this.executor = executor;
5485
+ }
5486
+ executor;
5487
+ async generateImagePrompt(description, style) {
5488
+ const validated = validateTopicText(description);
5489
+ const prompt = PromptBuilder.imagePrompt(validated, style);
5490
+ return this.executor.runText(prompt, { maxTokens: 300, temperature: 0.8 });
5491
+ }
5492
+ async generateImagePromptsForBlog(blogContent) {
5493
+ const truncated = truncateForBlogPromptPreview(validateContentBody(blogContent));
5494
+ const prompt = PromptBuilder.blogImagePrompts(truncated);
5495
+ const prompts = await this.executor.runJson(prompt, [], {
5496
+ maxTokens: 500,
5497
+ temperature: 0.8
5498
+ });
5499
+ return Array.isArray(prompts) ? prompts : [];
5500
+ }
5501
+ };
5502
+
5503
+ // src/content/application/services/ContentCalendarService.ts
5504
+ var toCalendarEntry = (item) => ({
5505
+ date: resolveCalendarEntryDate(item.day),
5506
+ topic: item.topic,
5507
+ contentType: item.contentType,
5508
+ platform: item.platform,
5509
+ description: item.description,
5510
+ estimatedEngagement: item.estimatedEngagement,
5511
+ priority: item.priority
5512
+ });
5513
+ var ContentCalendarService = class {
5514
+ constructor(executor) {
5515
+ this.executor = executor;
5516
+ }
5517
+ executor;
5518
+ async generateContentCalendar(niche, days) {
5519
+ const validatedNiche = validateTopicText(niche);
5520
+ const validatedDays = validateCalendarDays(days);
5521
+ const prompt = PromptBuilder.contentCalendar(validatedNiche, validatedDays);
5522
+ const data = await this.executor.runJson(
5523
+ prompt,
5524
+ [],
5525
+ {
5526
+ maxTokens: estimateTokenBudgetForCalendarDays(validatedDays),
5527
+ temperature: 0.8
5528
+ }
5529
+ );
5530
+ const items = Array.isArray(data) ? data : Array.isArray(data?.calendar) ? data.calendar : Array.isArray(data?.entries) ? data.entries : [];
5531
+ return items.map(toCalendarEntry);
5532
+ }
5533
+ };
5534
+
5535
+ // src/content/application/services/ProviderServices.ts
5536
+ var wrapProviderError = (operation, error) => {
5537
+ const message = error instanceof Error ? error.message : "Unknown error";
5538
+ return new AIError(`${operation} failed: ${message}`, "PROVIDER_ERROR", error);
5539
+ };
5540
+ var ensureFactory = (factory, operation) => {
5541
+ if (factory.getAllProviders().length === 0) {
5542
+ throw new AIError(
5543
+ `${operation} failed: No providers are registered. Provide a ProviderConfig with at least one enabled provider when constructing AIContentService.`,
5544
+ "PROVIDER_UNAVAILABLE"
5545
+ );
5546
+ }
5547
+ };
5548
+ var MediaGenerationService = class {
5549
+ constructor(providerFactory) {
5550
+ this.providerFactory = providerFactory;
5551
+ }
5552
+ providerFactory;
5553
+ generateImage(request) {
5554
+ ensureFactory(this.providerFactory, "Image generation");
5555
+ return this.providerFactory.generateImage(request).catch((err) => {
5556
+ throw wrapProviderError("Image generation", err);
5557
+ });
5558
+ }
5559
+ generateVideo(request) {
5560
+ ensureFactory(this.providerFactory, "Video generation");
5561
+ return this.providerFactory.generateVideo(request).catch((err) => {
5562
+ throw wrapProviderError("Video generation", err);
5563
+ });
5564
+ }
5565
+ convertImageToVideo(request) {
5566
+ ensureFactory(this.providerFactory, "Image-to-video conversion");
5567
+ return this.providerFactory.imageToVideo(request).catch((err) => {
5568
+ throw wrapProviderError("Image-to-video conversion", err);
5569
+ });
5570
+ }
5571
+ transformVideo(request) {
5572
+ ensureFactory(this.providerFactory, "Video-to-video transformation");
5573
+ return this.providerFactory.videoToVideo(request).catch((err) => {
5574
+ throw wrapProviderError("Video-to-video transformation", err);
5575
+ });
5576
+ }
5577
+ };
5578
+
5579
+ // src/content/infrastructure/utils/jsonParser.ts
5580
+ function repairCommonJsonDefects2(text) {
5581
+ return text.replace(/(:\s*-?\d+(?:\.\d+)?)\s*"/g, "$1").replace(/(:\s*"[^"]*")"/g, "$1");
5582
+ }
5583
+ function safeJSONParse(text, fallback, onError) {
5584
+ try {
5585
+ return JSON.parse(text);
5586
+ } catch (error) {
5587
+ try {
5588
+ return JSON.parse(repairCommonJsonDefects2(text));
5589
+ } catch {
5590
+ }
5591
+ if (error instanceof SyntaxError) {
5592
+ const positionMatch = error.message.match(/position (\d+)/);
5593
+ const position = positionMatch ? parseInt(positionMatch[1], 10) : -1;
5594
+ if (position > 0) {
5595
+ text.substring(Math.max(0, position - 50), position + 50);
5596
+ }
5597
+ }
5598
+ return fallback;
5599
+ }
5600
+ }
5601
+ function extractJSON(text) {
5602
+ const codeBlockMatch = text.match(/```(?:json)?\s*([\s\S]*?)```/);
5603
+ if (codeBlockMatch && codeBlockMatch[1]) {
5604
+ const candidate = codeBlockMatch[1].trim();
5605
+ if (candidate.startsWith("{") || candidate.startsWith("[")) {
5606
+ return candidate;
5607
+ }
5608
+ }
5609
+ const objectMatch = text.match(/\{[\s\S]*\}/);
5610
+ if (objectMatch) {
5611
+ return objectMatch[0];
5612
+ }
5613
+ const arrayMatch = text.match(/\[[\s\S]*\]/);
5614
+ if (arrayMatch) {
5615
+ return arrayMatch[0];
5616
+ }
5617
+ return null;
5618
+ }
5619
+ function parseAIResponse(response, fallback, onError) {
5620
+ const json = extractJSON(response);
5621
+ if (!json) {
5622
+ return fallback;
5623
+ }
5624
+ return safeJSONParse(json, fallback);
5625
+ }
5626
+
5627
+ // src/content/application/services/GenerationExecutor.ts
5628
+ var GenerationExecutor = class {
5629
+ constructor(generator) {
5630
+ this.generator = generator;
5631
+ }
5632
+ generator;
5633
+ async runJson(prompt, fallback, generationOptions = {}) {
5634
+ const response = await this.generator.generateText(prompt, generationOptions);
5635
+ return parseAIResponse(response, fallback);
5636
+ }
5637
+ runText(prompt, options = {}) {
5638
+ return this.generator.generateText(prompt, options);
5639
+ }
5640
+ /** Usage-complete pass-through; requires a ProviderFactory engine. */
5641
+ runChat(request) {
5642
+ if (!(this.generator instanceof ProviderFactory)) {
5643
+ throw new AIError(
5644
+ "runChat requires a ProviderFactory engine \u2014 construct AIContentService with a provider config, not a custom ITextGenerator",
5645
+ "PROVIDER_UNAVAILABLE"
5646
+ );
5647
+ }
5648
+ return this.generator.chat(request);
5649
+ }
5650
+ };
5651
+
5652
+ // src/content/application/services/AIContentService.ts
5653
+ var isTextGenerator = (value) => typeof value === "object" && value !== null && typeof value.generateText === "function";
5654
+ function toAIProviderConfig(config) {
5655
+ const legacy = config;
5656
+ const modern = config;
5657
+ const anthropic = modern.anthropic ?? (legacy.anthropic?.enabled ? {
5658
+ apiKey: legacy.anthropic.apiKey,
5659
+ baseUrl: legacy.anthropic.baseUrl,
5660
+ timeoutMs: legacy.anthropic.timeout,
5661
+ models: legacy.anthropic.models,
5662
+ effort: legacy.anthropic.effort
5663
+ } : void 0);
5664
+ const groq = modern.groq ?? (legacy.groq?.enabled ? {
5665
+ apiKey: legacy.groq.apiKey,
5666
+ baseUrl: legacy.groq.baseUrl,
5667
+ timeoutMs: legacy.groq.timeout,
5668
+ // legacy {text, chat} model pins map onto the neutral tier slots
5669
+ ...legacy.groq.models?.text ? { models: { balanced: legacy.groq.models.text } } : {}
5670
+ } : void 0);
5671
+ const gemini = modern.gemini ?? (legacy.gemini?.enabled ? { ...legacy.gemini } : void 0);
5672
+ const fal = modern.fal ?? (legacy.fal?.enabled ? { ...legacy.fal } : void 0);
5673
+ const pruna = modern.pruna ?? (legacy.pruna?.enabled ? { ...legacy.pruna } : void 0);
5674
+ return {
5675
+ priority: modern.priority,
5676
+ fallbackEnabled: modern.fallbackEnabled,
5677
+ defaultTier: modern.defaultTier,
5678
+ ...anthropic ? { anthropic } : {},
5679
+ ...groq ? { groq } : {},
5680
+ ...gemini ? { gemini } : {},
5681
+ ...fal ? { fal } : {},
5682
+ ...pruna ? { pruna } : {}
5683
+ };
5684
+ }
5685
+ var buildServices = (configOrGenerator) => {
5686
+ if (isTextGenerator(configOrGenerator)) {
5687
+ const executor2 = new GenerationExecutor(configOrGenerator);
5688
+ const emptyFactory = new ProviderFactory({
5689
+ priority: [],
5690
+ fallbackEnabled: false
5691
+ });
5692
+ return {
5693
+ providerFactory: emptyFactory,
5694
+ blogService: new BlogService(executor2),
5695
+ socialService: new SocialService(executor2),
5696
+ videoScriptService: new VideoScriptService(executor2),
5697
+ analysisService: new AnalysisService(executor2),
5698
+ seoService: new SeoService(executor2),
5699
+ abTestService: new ABTestService(executor2),
5700
+ imagePromptService: new ImagePromptService(executor2),
5701
+ contentCalendarService: new ContentCalendarService(executor2),
5702
+ mediaGenerationService: new MediaGenerationService(emptyFactory)
5703
+ };
5704
+ }
5705
+ const factory = createAI(toAIProviderConfig(configOrGenerator));
5706
+ const executor = new GenerationExecutor(factory);
5707
+ return {
5708
+ providerFactory: factory,
5709
+ blogService: new BlogService(executor),
5710
+ socialService: new SocialService(executor),
5711
+ videoScriptService: new VideoScriptService(executor),
5712
+ analysisService: new AnalysisService(executor),
5713
+ seoService: new SeoService(executor),
5714
+ abTestService: new ABTestService(executor),
5715
+ imagePromptService: new ImagePromptService(executor),
5716
+ contentCalendarService: new ContentCalendarService(executor),
5717
+ mediaGenerationService: new MediaGenerationService(factory)
5718
+ };
5719
+ };
5720
+ var AIContentService = class {
5721
+ providerFactory;
5722
+ blogService;
5723
+ socialService;
5724
+ videoScriptService;
5725
+ analysisService;
5726
+ seoService;
5727
+ abTestService;
5728
+ imagePromptService;
5729
+ contentCalendarService;
5730
+ mediaGenerationService;
5731
+ constructor(configOrGenerator) {
5732
+ const bundle = buildServices(configOrGenerator);
5733
+ this.providerFactory = bundle.providerFactory;
5734
+ this.blogService = bundle.blogService;
5735
+ this.socialService = bundle.socialService;
5736
+ this.videoScriptService = bundle.videoScriptService;
5737
+ this.analysisService = bundle.analysisService;
5738
+ this.seoService = bundle.seoService;
5739
+ this.abTestService = bundle.abTestService;
5740
+ this.imagePromptService = bundle.imagePromptService;
5741
+ this.contentCalendarService = bundle.contentCalendarService;
5742
+ this.mediaGenerationService = bundle.mediaGenerationService;
5743
+ }
5744
+ /** The composed factory — chat()/chatStream() with usage, health, fallback. */
5745
+ get providers() {
5746
+ return this.providerFactory;
5747
+ }
5748
+ generateBlogPost(request) {
5749
+ return this.blogService.generateBlogPost(request);
5750
+ }
5751
+ generateSocialContent(request) {
5752
+ return this.socialService.generateSocialContent(request);
5753
+ }
5754
+ generateForAllPlatforms(topic, tone) {
5755
+ return this.socialService.generateForAllPlatforms(topic, tone);
5756
+ }
5757
+ generateHashtags(content, count) {
5758
+ return this.socialService.generateHashtags(content, count);
5759
+ }
5760
+ optimizeHashtags(hashtags, platform) {
5761
+ return Promise.resolve(this.socialService.optimizeHashtags(hashtags, platform));
5762
+ }
5763
+ generateVideoScript(request) {
5764
+ return this.videoScriptService.generateVideoScript(request);
5765
+ }
5766
+ generateVoiceScript(topic, emotion, duration) {
5767
+ return this.videoScriptService.generateVoiceScript(topic, emotion, duration);
5768
+ }
5769
+ generateContentCalendar(niche, days) {
5770
+ return this.contentCalendarService.generateContentCalendar(niche, days);
5771
+ }
5772
+ analyzeSentiment(content) {
5773
+ return this.analysisService.analyzeSentiment(content);
5774
+ }
5775
+ analyzeContent(request) {
5776
+ return this.analysisService.analyzeContent(request);
5777
+ }
5778
+ optimizeSEO(request) {
5779
+ return this.seoService.optimizeSEO(request);
5780
+ }
5781
+ calculateSEOScore(content, keywords) {
5782
+ return this.seoService.calculateSEOScore(content, keywords);
5783
+ }
5784
+ analyzeKeywords(content, keywords) {
5785
+ return Promise.resolve(this.seoService.analyzeKeywords(content, keywords));
5786
+ }
5787
+ predictABTest(request) {
5788
+ return this.abTestService.predictABTest(request);
5789
+ }
5790
+ compareVariants(variantA, variantB) {
5791
+ return this.abTestService.compareVariants(variantA, variantB);
5792
+ }
5793
+ generateImagePrompt(description, style) {
5794
+ return this.imagePromptService.generateImagePrompt(description, style);
5795
+ }
5796
+ generateImagePromptsForBlog(blogContent) {
5797
+ return this.imagePromptService.generateImagePromptsForBlog(blogContent);
5798
+ }
5799
+ generateImage(request) {
5800
+ return this.mediaGenerationService.generateImage(request);
5801
+ }
5802
+ generateVideo(request) {
5803
+ return this.mediaGenerationService.generateVideo(request);
5804
+ }
5805
+ convertImageToVideo(request) {
5806
+ return this.mediaGenerationService.convertImageToVideo(request);
5807
+ }
5808
+ transformVideo(request) {
5809
+ return this.mediaGenerationService.transformVideo(request);
5810
+ }
5811
+ };
5812
+
5813
+ // src/wizard/content.wizard.ts
5814
+ var CONTENT_WIZARD_STEPS = [
5815
+ {
5816
+ id: "select-type",
5817
+ label: "Select Type",
5818
+ icon: "Layers",
5819
+ description: "Choose the type of content you want to generate",
5820
+ validate: (data) => Boolean(data.contentType)
5821
+ },
5822
+ {
5823
+ id: "input-topic",
5824
+ label: "Topic",
5825
+ icon: "Lightbulb",
5826
+ description: "Enter your topic or idea",
5827
+ validate: (data) => {
5828
+ const topic = data.topic;
5829
+ return typeof topic === "string" && topic.length > 0;
5830
+ }
5831
+ },
5832
+ {
5833
+ id: "configure",
5834
+ label: "Configure",
5835
+ icon: "Settings",
5836
+ description: "Set tone, audience, and platform",
5837
+ validate: (data) => {
5838
+ const d = data;
5839
+ return Boolean(d.tone && d.targetAudience);
5840
+ }
5841
+ },
5842
+ {
5843
+ id: "advanced",
5844
+ label: "Advanced",
5845
+ icon: "Sliders",
5846
+ description: "Additional options and optimizations",
5847
+ optional: true
5848
+ },
5849
+ {
5850
+ id: "preview",
5851
+ label: "Preview",
5852
+ icon: "Eye",
5853
+ description: "Review your settings before generation"
5854
+ },
5855
+ {
5856
+ id: "generating",
5857
+ label: "Generating",
5858
+ icon: "Sparkles",
5859
+ description: "AI is generating your content"
5860
+ },
5861
+ {
5862
+ id: "results",
5863
+ label: "Results",
5864
+ icon: "CheckCircle",
5865
+ description: "Your generated content is ready"
5866
+ }
5867
+ ];
5868
+ function buildContentRequest(data) {
5869
+ switch (data.contentType) {
5870
+ case "blog":
5871
+ return {
5872
+ topic: data.topic ?? "",
5873
+ blogType: "tutorial",
5874
+ targetKeywords: data.keywords ?? [],
5875
+ tone: data.tone ?? "professional",
5876
+ wordCount: data.wordCount ?? 1e3,
5877
+ targetAudience: data.targetAudience ?? "",
5878
+ seoOptimization: data.seoOptimization ?? false,
5879
+ includeImages: data.includeImages ?? false,
5880
+ includeSchema: false
5881
+ };
5882
+ case "social":
5883
+ return {
5884
+ topic: data.topic ?? "",
5885
+ platform: data.platform ?? "twitter",
5886
+ tone: data.tone ?? "casual",
5887
+ hashtags: true,
5888
+ targetAudience: data.targetAudience,
5889
+ includeCallToAction: data.includeCallToAction
5890
+ };
5891
+ case "script":
5892
+ return {
5893
+ topic: data.topic ?? "",
5894
+ tone: data.tone ?? "professional",
5895
+ duration: data.duration ?? 60,
5896
+ targetAudience: data.targetAudience ?? "",
5897
+ includeVisuals: true,
5898
+ includeCallToAction: data.includeCallToAction ?? false
5899
+ };
5900
+ default:
5901
+ throw new Error(`Unsupported content type: ${data.contentType}`);
5902
+ }
5903
+ }
5904
+
5905
+ // src/wizard/image.wizard.ts
5906
+ var IMAGE_WIZARD_STEPS = [
5907
+ {
5908
+ id: "input-prompt",
5909
+ label: "Describe Image",
5910
+ icon: "Image",
5911
+ description: "Describe the image you want to create",
5912
+ validate: (data) => {
5913
+ const prompt = data.prompt;
5914
+ return typeof prompt === "string" && prompt.length > 0;
5915
+ }
5916
+ },
5917
+ {
5918
+ id: "select-style",
5919
+ label: "Style",
5920
+ icon: "Palette",
5921
+ description: "Choose the artistic style",
5922
+ validate: (data) => Boolean(data.style)
5923
+ },
5924
+ {
5925
+ id: "configure",
5926
+ label: "Configure",
5927
+ icon: "Settings",
5928
+ description: "Set format, quality, and quantity",
5929
+ validate: (data) => {
5930
+ const d = data;
5931
+ return Boolean(d.format && d.quality);
5932
+ }
5933
+ },
5934
+ {
5935
+ id: "advanced",
5936
+ label: "Advanced",
5937
+ icon: "Sliders",
5938
+ description: "Color palette and platform optimization",
5939
+ optional: true
5940
+ },
5941
+ { id: "preview", label: "Preview", icon: "Eye", description: "Review your settings" },
5942
+ { id: "generating", label: "Generating", icon: "Sparkles", description: "AI is creating your image" },
5943
+ { id: "results", label: "Results", icon: "Image", description: "Your generated image is ready" }
5944
+ ];
5945
+ function buildImageRequest(data) {
5946
+ return {
5947
+ type: "image",
5948
+ prompt: data.prompt ?? "",
5949
+ style: data.style,
5950
+ format: data.format,
5951
+ quality: data.quality,
5952
+ quantity: data.quantity ?? 1
5953
+ };
5954
+ }
5955
+
5956
+ // src/wizard/video.wizard.ts
5957
+ var validateSource = (data) => {
5958
+ const d = data;
5959
+ if (d.generationType === "text-to-video") {
5960
+ return typeof d.prompt === "string" && d.prompt.length > 0;
5961
+ }
5962
+ if (d.generationType === "image-to-video") {
5963
+ return typeof d.imageUrl === "string" && d.imageUrl.length > 0;
5964
+ }
5965
+ if (d.generationType === "video-to-video") {
5966
+ return typeof d.sourceVideoUrl === "string" && d.sourceVideoUrl.length > 0 && typeof d.prompt === "string" && d.prompt.length > 0;
5967
+ }
5968
+ return false;
5969
+ };
5970
+ var VIDEO_WIZARD_STEPS = [
5971
+ {
5972
+ id: "select-type",
5973
+ label: "Select Type",
5974
+ icon: "Video",
5975
+ description: "Choose video generation type",
5976
+ validate: (data) => Boolean(data.generationType)
5977
+ },
5978
+ {
5979
+ id: "input-source",
5980
+ label: "Source",
5981
+ icon: "FileInput",
5982
+ description: "Provide your source (prompt, image, or video)",
5983
+ validate: validateSource
5984
+ },
5985
+ {
5986
+ id: "configure",
5987
+ label: "Configure",
5988
+ icon: "Settings",
5989
+ description: "Set duration, aspect ratio, and style",
5990
+ validate: (data) => {
5991
+ const d = data;
5992
+ return Boolean(d.duration && d.aspectRatio);
5993
+ }
5994
+ },
5995
+ { id: "advanced", label: "Advanced", icon: "Sliders", description: "Additional video options", optional: true },
5996
+ { id: "preview", label: "Preview", icon: "Eye", description: "Review your settings" },
5997
+ { id: "generating", label: "Generating", icon: "Sparkles", description: "AI is creating your video" },
5998
+ { id: "results", label: "Results", icon: "Video", description: "Your generated video is ready" }
5999
+ ];
6000
+ function buildVideoRequest(data) {
6001
+ switch (data.generationType) {
6002
+ case "text-to-video":
6003
+ return {
6004
+ type: "video",
6005
+ prompt: data.prompt ?? "",
6006
+ duration: data.duration ?? 5,
6007
+ aspectRatio: data.aspectRatio ?? "16:9",
6008
+ style: data.style,
6009
+ quality: data.quality
6010
+ };
6011
+ case "image-to-video":
6012
+ return {
6013
+ type: "video",
6014
+ imageUrl: data.imageUrl ?? "",
6015
+ prompt: data.prompt,
6016
+ duration: data.duration ?? 5,
6017
+ motion: data.motion ?? "medium",
6018
+ camera: data.camera ?? "static"
6019
+ };
6020
+ case "video-to-video":
6021
+ return {
6022
+ type: "video",
6023
+ sourceVideoUrl: data.sourceVideoUrl ?? "",
6024
+ prompt: data.prompt ?? "",
6025
+ styleTransfer: data.styleTransfer,
6026
+ enhanceQuality: data.enhanceQuality
6027
+ };
6028
+ default:
6029
+ throw new Error(`Unsupported generation type: ${data.generationType}`);
6030
+ }
6031
+ }
6032
+
6033
+ 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, 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, 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, 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, mapAnthropicStopReason, mergeTierOverrides, messageFormatter, normalizeSseChunk, oneOfCatalog, pollForResult, promptToMessages, repairCommonJsonDefects, requestDeduplicator, requestQueue, requestStructuredJson, resetProvider, resolveModel, resolveUserFriendlyErrorMessage, resolveUserFriendlyMessage, retryManager, splitSseLines, submitPrediction, throttle, throttleManager, toGroqMessages, uploadImage, validateApiKey, withRetry };
4359
6034
  //# sourceMappingURL=index.js.map
4360
6035
  //# sourceMappingURL=index.js.map