@umituz/web-ai 1.0.4 → 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.
@@ -4190,7 +4190,14 @@ var BlogService = class {
4190
4190
  };
4191
4191
 
4192
4192
  // src/content/infrastructure/utils/requestQueue.ts
4193
- ({
4193
+ var RequestPriority = /* @__PURE__ */ ((RequestPriority2) => {
4194
+ RequestPriority2[RequestPriority2["LOW"] = 0] = "LOW";
4195
+ RequestPriority2[RequestPriority2["NORMAL"] = 1] = "NORMAL";
4196
+ RequestPriority2[RequestPriority2["HIGH"] = 2] = "HIGH";
4197
+ RequestPriority2[RequestPriority2["URGENT"] = 3] = "URGENT";
4198
+ return RequestPriority2;
4199
+ })(RequestPriority || {});
4200
+ var DEFAULT_CONFIG = {
4194
4201
  maxConcurrent: RequestQueueConfig.MAX_CONCURRENT,
4195
4202
  maxQueueSize: RequestQueueConfig.MAX_QUEUE_SIZE,
4196
4203
  defaultTimeout: RequestQueueConfig.DEFAULT_TIMEOUT_MS,
@@ -4198,7 +4205,133 @@ var BlogService = class {
4198
4205
  enableRateLimit: RequestQueueConfig.RATE_LIMIT.ENABLED,
4199
4206
  rateLimitWindow: RequestQueueConfig.RATE_LIMIT.WINDOW_MS,
4200
4207
  rateLimitMaxRequests: RequestQueueConfig.RATE_LIMIT.MAX_REQUESTS_PER_WINDOW
4201
- });
4208
+ };
4209
+ var RequestQueue2 = class {
4210
+ queue = [];
4211
+ running = /* @__PURE__ */ new Set();
4212
+ config;
4213
+ requestHistory = [];
4214
+ isProcessing = false;
4215
+ constructor(config = {}) {
4216
+ this.config = { ...DEFAULT_CONFIG, ...config };
4217
+ }
4218
+ async add(fn, priority = 1 /* NORMAL */, maxRetries = 3) {
4219
+ if (this.queue.length >= this.config.maxQueueSize) {
4220
+ throw new Error("Queue is full");
4221
+ }
4222
+ return new Promise((resolve, reject) => {
4223
+ const request = {
4224
+ id: generateId("req"),
4225
+ priority,
4226
+ timestamp: Date.now(),
4227
+ fn,
4228
+ resolve,
4229
+ reject,
4230
+ retries: 0,
4231
+ maxRetries
4232
+ };
4233
+ this.queue.push(request);
4234
+ this.sortQueue();
4235
+ if (!this.isProcessing) {
4236
+ this.process();
4237
+ }
4238
+ });
4239
+ }
4240
+ sortQueue() {
4241
+ this.queue.sort((a, b) => {
4242
+ if (a.priority !== b.priority) {
4243
+ return b.priority - a.priority;
4244
+ }
4245
+ return a.timestamp - b.timestamp;
4246
+ });
4247
+ }
4248
+ async process() {
4249
+ if (this.isProcessing) return;
4250
+ this.isProcessing = true;
4251
+ while (this.queue.length > 0 || this.running.size > 0) {
4252
+ while (this.queue.length > 0 && this.running.size < this.config.maxConcurrent) {
4253
+ if (this.config.enableRateLimit && !this.canMakeRequest()) {
4254
+ break;
4255
+ }
4256
+ const request = this.queue.shift();
4257
+ if (!request) break;
4258
+ this.running.add(request.id);
4259
+ this.executeRequest(request);
4260
+ }
4261
+ await new Promise((resolve) => setTimeout(resolve, RequestQueueConfig.POLL_INTERVAL_MS));
4262
+ }
4263
+ this.isProcessing = false;
4264
+ }
4265
+ canMakeRequest() {
4266
+ const now = Date.now();
4267
+ const windowStart = now - this.config.rateLimitWindow;
4268
+ this.requestHistory = this.requestHistory.filter(
4269
+ (timestamp) => timestamp > windowStart
4270
+ );
4271
+ return this.requestHistory.length < this.config.rateLimitMaxRequests;
4272
+ }
4273
+ async executeRequest(request) {
4274
+ try {
4275
+ if (this.config.enableRateLimit) {
4276
+ this.requestHistory.push(Date.now());
4277
+ }
4278
+ const result = await this.withTimeout(
4279
+ request.fn,
4280
+ this.config.defaultTimeout
4281
+ );
4282
+ request.resolve(result);
4283
+ } catch (error) {
4284
+ if (request.retries < request.maxRetries) {
4285
+ request.retries++;
4286
+ const delay = this.config.retryDelay * request.retries;
4287
+ setTimeout(() => {
4288
+ this.queue.unshift(request);
4289
+ this.sortQueue();
4290
+ }, delay);
4291
+ } else {
4292
+ request.reject(error);
4293
+ }
4294
+ } finally {
4295
+ this.running.delete(request.id);
4296
+ }
4297
+ }
4298
+ async withTimeout(fn, timeout) {
4299
+ const controller = new AbortController();
4300
+ let timeoutId;
4301
+ const timeoutPromise = new Promise((_, reject) => {
4302
+ timeoutId = setTimeout(() => {
4303
+ controller.abort();
4304
+ reject(new Error("Request timeout"));
4305
+ }, timeout);
4306
+ });
4307
+ try {
4308
+ const result = await Promise.race([fn(controller.signal), timeoutPromise]);
4309
+ return result;
4310
+ } finally {
4311
+ if (timeoutId) clearTimeout(timeoutId);
4312
+ }
4313
+ }
4314
+ getStats() {
4315
+ return {
4316
+ queued: this.queue.length,
4317
+ running: this.running.size,
4318
+ rateLimitRemaining: this.config.enableRateLimit ? this.config.rateLimitMaxRequests - this.requestHistory.filter(
4319
+ (timestamp) => Date.now() - timestamp < this.config.rateLimitWindow
4320
+ ).length : Infinity
4321
+ };
4322
+ }
4323
+ clear() {
4324
+ for (const request of this.queue) {
4325
+ request.reject(new Error("Queue cleared"));
4326
+ }
4327
+ this.queue = [];
4328
+ }
4329
+ async drain() {
4330
+ while (this.running.size > 0) {
4331
+ await new Promise((resolve) => setTimeout(resolve, RequestQueueConfig.POLL_INTERVAL_MS));
4332
+ }
4333
+ }
4334
+ };
4202
4335
  async function batchRequest(requests, options = {}) {
4203
4336
  const {
4204
4337
  concurrency = 3,
@@ -4682,7 +4815,10 @@ function safeJSONParse(text, fallback, onError) {
4682
4815
  const positionMatch = error.message.match(/position (\d+)/);
4683
4816
  const position = positionMatch ? parseInt(positionMatch[1], 10) : -1;
4684
4817
  if (position > 0) {
4685
- text.substring(Math.max(0, position - 50), position + 50);
4818
+ const context = text.substring(Math.max(0, position - 50), position + 50);
4819
+ onError?.(`JSON parse error at position ${position}: "${context}"`);
4820
+ } else {
4821
+ onError?.(`JSON parse error: ${error.message}`);
4686
4822
  }
4687
4823
  }
4688
4824
  return fallback;
@@ -4709,9 +4845,23 @@ function extractJSON(text) {
4709
4845
  function parseAIResponse(response, fallback, onError) {
4710
4846
  const json = extractJSON(response);
4711
4847
  if (!json) {
4848
+ onError?.("No JSON payload found in response");
4712
4849
  return fallback;
4713
4850
  }
4714
- return safeJSONParse(json, fallback);
4851
+ return safeJSONParse(json, fallback, onError);
4852
+ }
4853
+ function isValidJSON(text) {
4854
+ const trimmed = text.trim();
4855
+ if (trimmed.length === 0) return false;
4856
+ if (!(trimmed.startsWith("{") && trimmed.endsWith("}") || trimmed.startsWith("[") && trimmed.endsWith("]"))) {
4857
+ return false;
4858
+ }
4859
+ try {
4860
+ JSON.parse(trimmed);
4861
+ return true;
4862
+ } catch {
4863
+ return false;
4864
+ }
4715
4865
  }
4716
4866
 
4717
4867
  // src/content/application/services/GenerationExecutor.ts
@@ -4772,7 +4922,48 @@ function toAIProviderConfig(config) {
4772
4922
  ...pruna ? { pruna } : {}
4773
4923
  };
4774
4924
  }
4775
- var buildServices = (configOrGenerator) => {
4925
+ var buildServices = (configOrGenerator, model, customGenerator) => {
4926
+ if (customGenerator) {
4927
+ const executor2 = new GenerationExecutor(customGenerator);
4928
+ const emptyFactory = new ProviderFactory({
4929
+ priority: [],
4930
+ fallbackEnabled: false
4931
+ });
4932
+ return {
4933
+ providerFactory: emptyFactory,
4934
+ blogService: new BlogService(executor2),
4935
+ socialService: new SocialService(executor2),
4936
+ videoScriptService: new VideoScriptService(executor2),
4937
+ analysisService: new AnalysisService(executor2),
4938
+ seoService: new SeoService(executor2),
4939
+ abTestService: new ABTestService(executor2),
4940
+ imagePromptService: new ImagePromptService(executor2),
4941
+ contentCalendarService: new ContentCalendarService(executor2),
4942
+ mediaGenerationService: new MediaGenerationService(emptyFactory)
4943
+ };
4944
+ }
4945
+ if (typeof configOrGenerator === "string") {
4946
+ const aiConfig = {
4947
+ anthropic: {
4948
+ apiKey: configOrGenerator,
4949
+ ...model ? { models: { balanced: model } } : {}
4950
+ }
4951
+ };
4952
+ const factory2 = createAI(aiConfig);
4953
+ const executor2 = new GenerationExecutor(factory2);
4954
+ return {
4955
+ providerFactory: factory2,
4956
+ blogService: new BlogService(executor2),
4957
+ socialService: new SocialService(executor2),
4958
+ videoScriptService: new VideoScriptService(executor2),
4959
+ analysisService: new AnalysisService(executor2),
4960
+ seoService: new SeoService(executor2),
4961
+ abTestService: new ABTestService(executor2),
4962
+ imagePromptService: new ImagePromptService(executor2),
4963
+ contentCalendarService: new ContentCalendarService(executor2),
4964
+ mediaGenerationService: new MediaGenerationService(factory2)
4965
+ };
4966
+ }
4776
4967
  if (isTextGenerator(configOrGenerator)) {
4777
4968
  const executor2 = new GenerationExecutor(configOrGenerator);
4778
4969
  const emptyFactory = new ProviderFactory({
@@ -4818,8 +5009,8 @@ var AIContentService = class {
4818
5009
  imagePromptService;
4819
5010
  contentCalendarService;
4820
5011
  mediaGenerationService;
4821
- constructor(configOrGenerator) {
4822
- const bundle = buildServices(configOrGenerator);
5012
+ constructor(configOrGenerator, model, textGenerator) {
5013
+ const bundle = buildServices(configOrGenerator, model, textGenerator);
4823
5014
  this.providerFactory = bundle.providerFactory;
4824
5015
  this.blogService = bundle.blogService;
4825
5016
  this.socialService = bundle.socialService;
@@ -5131,6 +5322,7 @@ exports.BlogService = BlogService;
5131
5322
  exports.CONTENT_WIZARD_STEPS = CONTENT_WIZARD_STEPS;
5132
5323
  exports.CREDIT_COSTS = CREDIT_COSTS;
5133
5324
  exports.ContentCalendarService = ContentCalendarService;
5325
+ exports.ContentRequestQueue = RequestQueue2;
5134
5326
  exports.DEFAULT_CREDIT_COST = DEFAULT_CREDIT_COST;
5135
5327
  exports.DEFAULT_HASHTAG_BUDGET = DEFAULT_HASHTAG_BUDGET;
5136
5328
  exports.GENERATION_COSTS = CREDIT_COSTS;
@@ -5148,6 +5340,7 @@ exports.PromptBuilder = PromptBuilder;
5148
5340
  exports.ProviderQuotaExhaustedError = ProviderQuotaExhaustedError;
5149
5341
  exports.ProviderTimingConfig = ProviderTimingConfig;
5150
5342
  exports.ProviderUnavailableError = ProviderUnavailableError;
5343
+ exports.RequestPriority = RequestPriority;
5151
5344
  exports.RequestQueueConfig = RequestQueueConfig;
5152
5345
  exports.STYLE_PRESETS = STYLE_PRESETS;
5153
5346
  exports.SeoService = SeoService;
@@ -5162,6 +5355,7 @@ exports.VIDEO_WIZARD_STEPS = VIDEO_WIZARD_STEPS;
5162
5355
  exports.ValidationError = ValidationError;
5163
5356
  exports.ValidationLimits = ValidationLimits;
5164
5357
  exports.VideoScriptService = VideoScriptService;
5358
+ exports.batchRequest = batchRequest;
5165
5359
  exports.buildContentRequest = buildContentRequest;
5166
5360
  exports.buildImageRequest = buildImageRequest;
5167
5361
  exports.buildVideoRequest = buildVideoRequest;
@@ -5183,10 +5377,13 @@ exports.estimateTokenBudgetForCalendarDays = estimateTokenBudgetForCalendarDays;
5183
5377
  exports.estimateTokenBudgetForDuration = estimateTokenBudgetForDuration;
5184
5378
  exports.estimateUnknownProviderCost = estimateUnknownProviderCost;
5185
5379
  exports.estimateWordCountForDuration = estimateWordCountForDuration;
5380
+ exports.extractJSON = extractJSON;
5186
5381
  exports.generateId = generateId;
5187
5382
  exports.getDimensionsForAspectRatio = getDimensionsForAspectRatio;
5188
5383
  exports.getRecommendedQuality = getRecommendedQuality;
5189
5384
  exports.isUnderutilizedKeyword = isUnderutilizedKeyword;
5385
+ exports.isValidJSON = isValidJSON;
5386
+ exports.parseAIResponse = parseAIResponse;
5190
5387
  exports.rankAndTrimHashtags = rankAndTrimHashtags;
5191
5388
  exports.recommendQualityForAspectRatio = recommendQualityForAspectRatio;
5192
5389
  exports.resolveCalendarEntryDate = resolveCalendarEntryDate;
@@ -5197,6 +5394,7 @@ exports.resolveFalInferenceSteps = resolveFalInferenceSteps;
5197
5394
  exports.resolveHashtagBudget = resolveHashtagBudget;
5198
5395
  exports.resolveMaxContentLength = resolveMaxContentLength;
5199
5396
  exports.resolvePlatformSpec = resolvePlatformSpec;
5397
+ exports.safeJSONParse = safeJSONParse;
5200
5398
  exports.selectHigherScoreVariantId = selectHigherScoreVariantId;
5201
5399
  exports.toQualityTier = toQualityTier;
5202
5400
  exports.truncateForAbVariantPreview = truncateForAbVariantPreview;