/** * Crawler LLM — Schema definitions for structured product extraction. * * Every schema includes a `confidence` and `source_evidence` field so the LLM * is forced to cite its work. This enables validation and debugging. */ export interface StockExtractionResult { is_product_page: boolean; // false = category/listing page → discard confidence: number; // 0.0 – 1.0 — LLM self-assessment source_evidence: string; // which text passage the LLM used // Pricing price: number | null; currency: "USD" | "EUR" | "GBP" | "CNY" | null; price_breaks: PriceBreak[]; // volume discount tiers // Stock stock_level: "in_stock" | "out_of_stock" | "limited" | "unknown"; stock_quantity: number | null; // exact qty if shown incoming_quantity: number | null; // "18 im Zulauf" incoming_eta: string | null; // ISO date string "2026-04-15" lead_time_days: number | null; moq: number | null; // minimum order quantity // Product identity (for cross-validation) part_number: string | null; standard_name: string | null; // manufacturer's exact product name form_factor: string | null; speed_gbps: number | null; } export interface PriceBreak { qty: number; price: number; } export interface MarketIntelExtractionResult { is_relevant: boolean; // false = skip confidence: number; source_evidence: string; intel_type: "capex_cycle" | "trade_show" | "standard_ratified" | "standard_draft" | "distributor_lead_time" | "supply_chain" | "tender"; title: string; summary: string; technologies: string[]; // ['400G', 'QSFP-DD', ...] buy_signal_implication: "buy_now" | "wait" | "hold" | "monitor" | "none"; impact_horizon_months: number; published_at: string | null; // ISO date } /** Vendor-specific hints to improve LLM extraction accuracy */ export interface VendorProfile { slug: string; name: string; currency: "USD" | "EUR" | "GBP" | "CNY"; product_page_signals: string[]; // text patterns that indicate a product page category_page_signals: string[]; // text patterns that indicate a category page price_hint: string | null; // natural language hint for the LLM stock_hint: string | null; known_moq: number | null; } export const VENDOR_PROFILES: Record = { "flexoptix": { slug: "flexoptix", name: "Flexoptix", currency: "EUR", product_page_signals: ["In den Warenkorb", "Add to Cart", "part number", "SKU:", "P/N:"], category_page_signals: ["Alle Produkte", "Filter", "Ergebnisse", "products found"], price_hint: "Price is shown in EUR, usually near 'In den Warenkorb' button. May show 'auf Anfrage' if not listed.", stock_hint: "Look for 'auf Lager', 'Lieferzeit', 'sofort lieferbar', or stock badge near price.", known_moq: 1, }, "fs-com": { slug: "fs-com", name: "FS.com", currency: "USD", product_page_signals: ["Add to Cart", "Part No.", "SKU", "In Stock", "Reviews"], category_page_signals: ["Products", "Filter by", "Sort by", "items found", "Category"], price_hint: "Price is in USD, shown prominently near 'Add to Cart'. May show qty pricing table.", stock_hint: "Look for 'In Stock', exact number like '847 In Stock', or 'Out of Stock'.", known_moq: 1, }, "10gtek": { slug: "10gtek", name: "10Gtek", currency: "USD", product_page_signals: ["Add to Cart", "Product Code:", "In Stock", "Ships from"], category_page_signals: ["Shop All", "Filter", "Category", "Sort By"], price_hint: "Price in USD near Add to Cart button. Volume pricing sometimes shown as table.", stock_hint: "Stock level shown as text: 'In Stock', 'Low Stock', 'Out of Stock'.", known_moq: 1, }, "atgbics": { slug: "atgbics", name: "ATGBICS", currency: "GBP", product_page_signals: ["Add to Basket", "Part Number:", "Stock:", "Delivery"], category_page_signals: ["Products", "Browse by", "Refine by"], price_hint: "Price in GBP. ATGBICS uses Shopify, price is in a span with class 'price'.", stock_hint: "Stock shown as 'In Stock', 'Limited Stock', or 'Out of Stock' near price.", known_moq: 1, }, "prolabs": { slug: "prolabs", name: "ProLabs", currency: "USD", product_page_signals: ["Add to Cart", "Part Number", "In Stock", "Specs"], category_page_signals: ["Results", "Filter", "Category", "Sort"], price_hint: "Price in USD. ProLabs may require login for prices — if so, mark price as null.", stock_hint: "Stock availability shown near product title.", known_moq: 1, }, "farnell": { slug: "farnell", name: "Farnell", currency: "EUR", product_page_signals: ["Add to Basket", "Order Code:", "Stock:", "Lead Time:"], category_page_signals: ["Products", "Refine Search", "Category", "results for"], price_hint: "Price in EUR or GBP. Farnell shows break prices in a table with columns Qty/Price.", stock_hint: "Stock shown as number, e.g. '47 In Stock'. Lead time shown in business days.", known_moq: 1, }, "mouser": { slug: "mouser", name: "Mouser Electronics", currency: "EUR", product_page_signals: ["Add to Cart", "Mouser Part No.", "Mfr. Part No.", "In Stock:"], category_page_signals: ["Search Results", "Filter Results", "Products (", "Sort By"], price_hint: "Mouser shows price per unit and break quantities. USD or EUR depending on locale.", stock_hint: "Stock shown as exact number: 'In Stock: 124'. Lead time shown for out-of-stock items.", known_moq: null, }, };