@factorypure/client-helpers 1.1.22 → 1.1.24

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/index.d.ts CHANGED
@@ -389,6 +389,8 @@ export declare const scrapeResultsSchema: z.ZodObject<{
389
389
  is_immersive: z.ZodOptional<z.ZodNull>;
390
390
  brand: z.ZodOptional<z.ZodNull>;
391
391
  company_id: z.ZodOptional<z.ZodNull>;
392
+ candidate_result: z.ZodOptional<z.ZodAny>;
393
+ confidence_override_active: z.ZodOptional<z.ZodBoolean>;
392
394
  }, z.core.$strip>;
393
395
  export declare const immersiveScrapeResultsSchema: z.ZodObject<{
394
396
  id: z.ZodNumber;
@@ -516,6 +518,8 @@ export declare const immersiveScrapeResultsSchema: z.ZodObject<{
516
518
  listing_hash: z.ZodOptional<z.ZodNullable<z.ZodString>>;
517
519
  inline_link: z.ZodOptional<z.ZodNull>;
518
520
  delivery: z.ZodOptional<z.ZodNull>;
521
+ candidate_result: z.ZodOptional<z.ZodAny>;
522
+ confidence_override_active: z.ZodOptional<z.ZodBoolean>;
519
523
  }, z.core.$strip>;
520
524
  export type ScrapeResultsType = z.infer<typeof scrapeResultsSchema>;
521
525
  export type ImmersiveScrapeResultsType = z.infer<typeof immersiveScrapeResultsSchema>;
@@ -685,6 +689,30 @@ export declare const HIDE_OVERRIDE_REASONS: {
685
689
  };
686
690
  export declare const TOO_CHEAP_MULTIPLIER = 0.75;
687
691
  export declare const TOO_EXPENSIVE_MULTIPLIER = 1.15;
692
+ /**
693
+ * Rule IDs that are absolute blocks — high matching-engine confidence cannot override them.
694
+ * These represent explicit user intent or unambiguously bad data.
695
+ */
696
+ export declare const ABSOLUTE_BLOCK_RULE_IDS: readonly string[];
697
+ /**
698
+ * Rule IDs that can be overridden when the matching-engine confidence is high enough.
699
+ * These represent heuristics that may be wrong when identifier/title matching is strong.
700
+ */
701
+ export declare const CONFIDENCE_OVERRIDABLE_RULE_IDS: readonly string[];
702
+ /**
703
+ * Evaluates whether a result should be surfaced given its filter state and matching confidence.
704
+ *
705
+ * Returns:
706
+ * - `'hide'` — result must not be shown
707
+ * - `'show'` — result passes all filters normally
708
+ * - `'show_with_override'`— result failed soft filters but confidence is high enough to surface it anyway
709
+ *
710
+ * @param filterResults The filter_results array from the filter engine
711
+ * @param visibilityState The visibility_state computed by the filter engine
712
+ * @param confidence Matching-engine confidence score (0–100)
713
+ * @param overrideThreshold Minimum confidence to override a soft BLOCK rule (default 80)
714
+ */
715
+ export declare function evaluateConfidenceOverride(filterResults: FilterResult[], visibilityState: VisibilityState, confidence: number, overrideThreshold?: number): 'show' | 'show_with_override' | 'hide';
688
716
  /**
689
717
  * Registry for filter rules with configuration management
690
718
  */
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@ import { startOfDay, subDays } from 'date-fns';
3
3
  import { Index } from 'flexsearch';
4
4
  import EnglishPreset from 'flexsearch/lang/en';
5
5
  import { z } from 'zod';
6
+ // npm install /Users/kokkoalex/Documents/GitHub/npm-packages/client-helpers
6
7
  /**
7
8
  * @packageDocumentation
8
9
  * @module @factorypure/client-helpers
@@ -280,6 +281,9 @@ export const scrapeResultsSchema = z.object({
280
281
  is_immersive: z.null().optional(),
281
282
  brand: z.null().optional(),
282
283
  company_id: z.null().optional(),
284
+ // Populated by matching engine helpers
285
+ candidate_result: z.any().optional(),
286
+ confidence_override_active: z.boolean().optional(),
283
287
  });
284
288
  export const immersiveScrapeResultsSchema = z.object({
285
289
  id: z.number(),
@@ -342,6 +346,9 @@ export const immersiveScrapeResultsSchema = z.object({
342
346
  listing_hash: z.string().nullable().optional(),
343
347
  inline_link: z.null().optional(),
344
348
  delivery: z.null().optional(),
349
+ // Populated by matching engine helpers
350
+ candidate_result: z.any().optional(),
351
+ confidence_override_active: z.boolean().optional(),
345
352
  });
346
353
  export const ResultIgnoreSchema = z.object({
347
354
  id: z.number(),
@@ -444,6 +451,60 @@ const HIDE_ALWAYS_MAP = {
444
451
  };
445
452
  export const TOO_CHEAP_MULTIPLIER = 0.75;
446
453
  export const TOO_EXPENSIVE_MULTIPLIER = 1.15;
454
+ /**
455
+ * Rule IDs that are absolute blocks — high matching-engine confidence cannot override them.
456
+ * These represent explicit user intent or unambiguously bad data.
457
+ */
458
+ export const ABSOLUTE_BLOCK_RULE_IDS = [
459
+ 'manually_ignored',
460
+ 'scam_source_exclusion',
461
+ 'duplicate',
462
+ 'high_price_outlier',
463
+ 'low_price_outlier',
464
+ 'skip_sku',
465
+ ];
466
+ /**
467
+ * Rule IDs that can be overridden when the matching-engine confidence is high enough.
468
+ * These represent heuristics that may be wrong when identifier/title matching is strong.
469
+ */
470
+ export const CONFIDENCE_OVERRIDABLE_RULE_IDS = [
471
+ 'ai_comparison_mismatch',
472
+ 'ai_sku_mismatch',
473
+ 'calculated_sku_mismatch',
474
+ 'search_exclusion',
475
+ 'brand_mismatch',
476
+ 'vendor_exclusion',
477
+ 'competitor_exclusion',
478
+ 'date_outlier',
479
+ 'critical_spec_mismatch',
480
+ ];
481
+ /**
482
+ * Evaluates whether a result should be surfaced given its filter state and matching confidence.
483
+ *
484
+ * Returns:
485
+ * - `'hide'` — result must not be shown
486
+ * - `'show'` — result passes all filters normally
487
+ * - `'show_with_override'`— result failed soft filters but confidence is high enough to surface it anyway
488
+ *
489
+ * @param filterResults The filter_results array from the filter engine
490
+ * @param visibilityState The visibility_state computed by the filter engine
491
+ * @param confidence Matching-engine confidence score (0–100)
492
+ * @param overrideThreshold Minimum confidence to override a soft BLOCK rule (default 80)
493
+ */
494
+ export function evaluateConfidenceOverride(filterResults, visibilityState, confidence, overrideThreshold = 80) {
495
+ // Absolute blocks can never be overridden regardless of confidence
496
+ const hasAbsoluteBlock = filterResults.some((fr) => ABSOLUTE_BLOCK_RULE_IDS.includes(fr.ruleId));
497
+ if (hasAbsoluteBlock)
498
+ return 'hide';
499
+ if (visibilityState !== VisibilityState.HIDDEN)
500
+ return 'show';
501
+ // Result is hidden — check if all BLOCK-severity rules are confidence-overridable
502
+ const blockRules = filterResults.filter((fr) => fr.severity === FilterSeverity.BLOCK);
503
+ const allBlocksOverridable = blockRules.length > 0 && blockRules.every((fr) => CONFIDENCE_OVERRIDABLE_RULE_IDS.includes(fr.ruleId));
504
+ if (allBlocksOverridable && confidence >= overrideThreshold)
505
+ return 'show_with_override';
506
+ return 'hide';
507
+ }
447
508
  // const wattages = Array.from({ length: 41 }, (_, i) => (5000 + i * 500).toString())
448
509
  // ===============================
449
510
  // Filter Rule Registry
@@ -1522,8 +1583,8 @@ export const filterScrapeResultsV2 = ({ scrapeResults, variant, variantScrapeOpt
1522
1583
  function handleDuplicatesV2(results) {
1523
1584
  const filteredUniqueResultsMap = {};
1524
1585
  results.forEach((item) => {
1525
- // TODO ALEX this should probably compare on listing_hash
1526
- const key = `${item.source}-${item.title}-${item.extracted_total ?? item.extracted_price}`;
1586
+ // @ts-ignore
1587
+ const key = item.listing_hash;
1527
1588
  if (!filteredUniqueResultsMap[key]) {
1528
1589
  filteredUniqueResultsMap[key] = item;
1529
1590
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@factorypure/client-helpers",
3
- "version": "1.1.22",
3
+ "version": "1.1.24",
4
4
  "description": "",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",