Add --disable-crash-reporter flag to Puppeteer launch args to fix
"chrome_crashpad_handler: --database is required" error that occurs
when running in Docker containers with system Chromium.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add server URL field (defaults to ntfy.sh if blank)
- Add optional username/password for protected servers
- Auth fields only shown when custom server URL is entered
- Database migration for ntfy_server_url, ntfy_username, ntfy_password
- Update CHANGELOG with self-hosted ntfy feature
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Gemini as new AI provider option alongside Anthropic, OpenAI, Ollama
- Support models: Gemini 2.5 Flash Lite (default), Flash, Pro, 3 Flash Preview
- Add test API key endpoint to verify connection before saving
- Full support for extraction, verification, stock status, and arbitration
- Update all version files to 1.0.6
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Users can now pause and resume price checking for individual products
or in bulk via the Actions menu.
Backend:
- Added checking_paused column to products table
- Scheduler skips products with checking_paused=true
- Added POST /products/bulk/pause endpoint for bulk pause/resume
Frontend:
- Added Pause Checking and Resume Checking to bulk Actions menu
- Added filter dropdown (All/Active/Paused) next to sort controls
- Paused products show greyed out with pause icon and "Paused" label
- Progress bar hidden when paused
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New Features:
- AI model selector for Anthropic and OpenAI
- Per-product AI extraction/verification disable toggles
- Gotify self-hosted notification support with connection testing
- AI stock status verification for variant products
Fixes:
- Ollama thinking mode (/nothink message, num_ctx: 16384)
- AI now returns out_of_stock for pre-order/coming soon items
Documentation:
- Added recommended models: Claude Haiku 4.5 and Qwen3
- Added Gotify setup instructions
- Updated API reference with new endpoints
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Updated prompts to explicitly require 'out_of_stock' when the AI's
reasoning mentions the product is not available, coming soon, pre-order,
or has a future availability date.
The AI was returning 'unknown' even when its reason clearly stated
"not available for purchase right now" - now it must use 'out_of_stock'.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Send /nothink as a separate message before the actual prompt,
with a mock assistant response. This properly disables thinking
mode for Qwen3/DeepSeek models.
Removed the ineffective think:false API parameter.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Default 4K context was truncating the HTML before the model could see it.
Added num_ctx: 16384 to all 4 Ollama API calls to ensure the full
~25K character HTML content fits in context.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The /nothink prefix in prompt text doesn't work for Qwen3/DeepSeek.
The correct way is to pass "think": false in the API request body.
- Added think: false to all 4 Ollama API calls (extract, verify,
stock status, arbitrate)
- Removed ineffective /nothink prefixes from prompts
- Kept stripThinkingTags() as additional fallback protection
Ref: https://docs.ollama.com/capabilities/thinking
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
These models output <think>...</think> blocks before their actual JSON
response when in "thinking mode". This fix:
1. Adds /nothink prefix to all AI prompts (EXTRACTION_PROMPT,
VERIFICATION_PROMPT, STOCK_STATUS_PROMPT, ARBITRATION_PROMPT)
to request models disable thinking mode
2. Adds stripThinkingTags() helper function that removes <think>
blocks from responses as a fallback if models ignore /nothink
3. Applies stripping in all parse functions before JSON extraction
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When anchor price matches (user previously selected a specific variant),
we now call AI specifically to verify stock status for that price point.
- Add STOCK_STATUS_PROMPT focused on variant availability
- Add AIStockStatusResult interface
- Add verifyStockStatusWith{Anthropic,OpenAI,Ollama} functions
- Add tryAIStockStatusVerification export function
- Call stock verification when anchor price matches in scraper
The prompt instructs AI to only check stock for the specific variant at
the user's selected price, ignoring other variants that may be out of
stock. This fixes false "out of stock" reports on variant product pages.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add gotify_url, gotify_app_token, gotify_enabled columns to users table
- Add sendGotifyNotification function with priority levels
- Add testGotifyConnection function to verify server connectivity
- Add test-gotify endpoint for connection testing before save
- Add Gotify section in Settings with:
- Server URL input with Test Connection button
- App Token input (masked)
- Enable/disable toggle
- Send Test button (after configured)
- Include Gotify in notification dispatching
Gotify is a self-hosted push notification server popular in the
self-hosted community, complementing the existing ntfy support.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update refresh endpoint to use scrapeProductWithVoting instead of scrapeProduct
- Pass skipAiVerification and skipAiExtraction flags from product settings
- Also use preferred extraction method and anchor price for consistency
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add ai_extraction_disabled column to products table
- Add toggle in Advanced Settings alongside AI verification disable
- Pass skipAiExtraction flag through scheduler to scraper
- Skip AI extraction fallback when flag is set for product
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add anthropic_model and openai_model columns to database
- Allow users to select their preferred AI model in settings
- Update defaults to current models (Claude Haiku 4.5, GPT-4.1 Nano)
- Include model options: Claude 4.5 series, GPT-4.1/5.1 series
- Pass user-selected model to all AI extraction/verification functions
- Log which model is being used for debugging
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Sonnet 4 is ~4-12x more expensive than Haiku 3.5.
Haiku 3.5 should still be capable enough for price extraction.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Users can now disable AI verification for individual products that
AI is having trouble with (e.g., Amazon products where AI keeps
picking the main buy box price instead of "other sellers").
Changes:
- Add ai_verification_disabled column to products table
- Add toggle in product detail page under "Advanced Settings"
- Pass skip flag to scrapeProductWithVoting
- Skip AI verification when flag is set
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Haiku was being too literal in price extraction, often "correcting"
valid alternative prices (like Amazon other sellers) to the main
buy box price.
Sonnet is more capable and should handle nuanced cases better.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When the scraper finds multiple valid prices (e.g., Amazon main price +
other sellers), skip AI verification entirely. AI was "correcting"
valid alternative prices to the main buy box price.
Now with multiple candidates, users see all options in the modal and
choose themselves - no AI interference.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Amazon products can have multiple prices:
- Main buy box price
- "Other Sellers" prices
- Subscribe & Save prices
- New & Used prices
The scraper now extracts ALL prices, not just the main one. This allows
anchor price matching to find the specific price the user selected.
Also fixed AI verification overriding user's anchor price selection.
When user deliberately chose a price (e.g., "other sellers" at $52.91),
don't let AI "correct" it to the main buy box price ($79.99).
Changes:
- Amazon scraper now collects all price variants
- extractSiteSpecificCandidates handles allPrices array
- Anchor matching now always returns (no fall-through to AI override)
- Increased anchor tolerance from 10% to 15% for small sales
- Added debug logging showing all candidate prices
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The previous logic checked preferred method first, which could select
a wrong price even when anchor price was available. Now:
1. PRIORITY 1: Anchor price - if user confirmed a price, find closest
match (within 10% tolerance) across ALL candidates
2. PRIORITY 2: Preferred method - only used if no anchor match found
3. PRIORITY 3: Consensus voting
Also added debug logging to trace anchor price saving and retrieval.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When a user confirms a price from the modal, we now store it as an
"anchor price". On subsequent refreshes, if multiple price candidates
are found (common with variant products like different sizes/colors),
we select the candidate closest to the anchor price.
This fixes the issue where variant products would randomly switch to
a different variant's price on refresh.
Changes:
- Add anchor_price column to products table
- Save anchor price when user confirms a price selection
- Use anchor price to select correct variant on refresh
- 20% tolerance - if no candidate is within 20% of anchor, fall back to consensus
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix TypeScript narrowing issue in Best Buy scraper
- Add browser rendering for JS-heavy sites (Best Buy, Target, Walmart, Costco)
- Improve Best Buy site-specific scraper with better selectors and logging
- Skip payment plan prices (/mo, per month, etc.)
- Enhance AI HTML preparation:
- Extract JSON-LD data before removing scripts
- Add price element extraction for better context
- Increase character limit from 15000 to 25000
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Always show price selection modal when adding a product so users can verify
- Use browser rendering for known JS-heavy sites (Best Buy, Target, Walmart, Costco)
- Update modal text to say "Confirm Price" for single candidates
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add multi-strategy voting: runs JSON-LD, site-specific, generic CSS,
and AI extraction methods in parallel
- Implement consensus voting to select the correct price when methods agree
- Add AI arbitration when extraction methods disagree
- Add PriceSelectionModal for users to select correct price when ambiguous
- Store preferred extraction method per product for faster re-checks
- Add database columns for preferred_extraction_method and needs_price_review
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add global filter in priceParser to reject monthly/payment plan prices
- Filters: "/mo", "per month", "payments starting", "4 payments", etc.
- Update Best Buy scraper to check each price element for payment terms
- Prevents scraping "$25/mo" instead of actual "$229.99" price
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add notifications_cleared_at column to users table
- Clear button marks notifications as seen without deleting history
- Badge and dropdown only show notifications after last clear
- History page still shows all notifications
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add notification_history database table for logging all triggered notifications
- Create API endpoints for fetching recent and historical notifications
- Add NotificationBell component in navbar with badge showing recent count
- Dropdown shows 5 most recent notifications with links to products
- Create full NotificationHistory page with filtering by notification type
- Log notifications when sent: price drops, target prices, back-in-stock
- Track which channels (telegram, discord, pushover, ntfy) received each notification
- Update sendNotifications to return which channels succeeded
- Bump version to 1.0.3
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove overly generic pre-order phrases that caused false positives
("available in", "coming in", "arriving in" matched normal text)
- Add in-stock phrase priority check - "in stock", "add to cart",
"add to basket" now take precedence over pre-order detection
- Add Magento 2 stock status detection using stock classes and
add-to-cart buttons
- Bump version to 1.0.2
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- If no price found in static HTML, automatically try headless browser
- Re-runs all extraction methods on browser-rendered HTML
- Fixes price extraction for Magento, React, Vue, and other JS-heavy sites
- AI extraction now also benefits from rendered HTML
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- AI verification now checks if product is purchasable RIGHT NOW
- AI returns stockStatus field for pre-order/coming soon detection
- Enhanced generic stock status detection with pre-order phrases:
- Coming soon, available soon, releases on, pre-order, etc.
- Notify me when available, join waitlist, etc.
- Pre-order buttons no longer count as Add to Cart
- Fixes issue where unreleased products showed as in stock
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Backend now creates all required tables if they do not exist
- Migrations run BEFORE server accepts connections (prevents race condition)
- Server exits if migrations fail instead of running with broken DB
- Fixes registration failure on fresh Docker installs without init.sql
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add ai_status column to price_history table (verified/corrected/null)
- Track AI verification status through scraper and scheduler
- Display badges next to prices:
- ✓ AI (green): AI verified the price is correct
- ⚡ AI (orange): AI corrected an incorrect price
- Show badges on Dashboard product cards and ProductDetail page
- Add legend explaining badges in Settings when AI Verification is enabled
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The GET and PUT /api/settings/ai endpoints were missing
ai_verification_enabled in the request/response handling.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When enabled, AI verifies every scraped price to ensure accuracy.
This catches issues like scraped "savings" amounts instead of actual prices.
- Add ai_verification_enabled column to users table
- Create verification prompt and functions for Anthropic, OpenAI, Ollama
- Integrate verification step into scraper after traditional scraping
- Add verification toggle to Settings page (separate from AI extraction)
- AI verification is independent of AI extraction fallback
Flow: Traditional scraping -> AI verification (if enabled) -> AI extraction fallback (if no price found)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add helper to detect savings/combo/bundle containers
- Prioritize JSON-LD data as primary price source (most reliable)
- Skip price elements inside savings containers
- Add minimum price threshold to filter out discount amounts
Fixes issue where $189.99 bundle savings was extracted instead of
actual $675.59 product price for items like AMD Ryzen 9 9950X3D.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add ntfy_topic and ntfy_enabled columns to database
- Add sendNtfyNotification function with emoji tags
- Add /settings/notifications/test/ntfy endpoint
- Add ntfy section in Settings UI with topic input
- Show ntfy badge in ProductDetail notification status
ntfy.sh is a free, simple notification service - no account needed.
Users just pick a topic name and subscribe in the ntfy app.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Backend:
- Update /settings/notifications to return actual tokens/keys
- Update /settings/ai to return actual API keys
Frontend:
- Update NotificationSettings and AISettings types
- Populate form fields with actual saved values on load
- Eye toggle now reveals actual stored values
- Always show toggle button for consistent UX
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add database migration for ollama_base_url and ollama_model columns
- Update backend models and queries for Ollama settings
- Add extractWithOllama function using Ollama's /api/chat endpoint
- Add /api/settings/ai/test-ollama endpoint to test connection and list models
- Update frontend Settings page with Ollama configuration UI
- Support model selection from dropdown after testing connection
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create stock_status_history table to track status changes over time
- Add stockStatusHistoryQueries with getByProductId, recordChange, getStats
- Update scheduler to record status changes
- Update product creation and manual refresh to record initial/changed status
- Add GET /products/:id/stock-history API endpoint
- Create StockTimeline component with:
- Visual timeline bar showing in-stock (green) vs out-of-stock (red)
- Availability percentage
- Outage count and duration stats
- Integrate timeline into ProductDetail page
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add CHF to currency detection patterns in priceParser
- Add getCurrencySymbol helper in notifications service
- Update all frontend price formatting to support CHF
- Swiss francs display as "CHF 29.99" format
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add telegram_enabled, discord_enabled, pushover_enabled columns to database
- Update notification service to check enabled status before sending
- Add toggle switches in Settings UI for each configured channel
- Update ProductDetail to only show badges for enabled channels
- Channels default to enabled so existing users keep notifications
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add pushover_user_key and pushover_app_token columns to users table
- Add sendPushoverNotification function to notifications service
- Add Pushover test endpoint
- Add Pushover settings UI in Settings page
- User provides both User Key and App Token (self-hosted friendly)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add name field to auth login/register responses
- Update User interface in AuthContext to include name
- Show name (or email as fallback) in navbar dropdown
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Extract JSON-LD scripts BEFORE removing script tags
- Add logging for prepared HTML, AI responses, and parsed data
- Include more detailed error messages in test endpoint
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add AI extraction service supporting Anthropic (Claude) and OpenAI
- Add AI settings UI in Settings page with provider selection
- Add database migration for AI settings columns
- Integrate AI fallback into scraper when standard methods fail
- Add API endpoints for AI settings and test extraction
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Now extracts availability/stock status from JSON-LD structured data
(e.g., "https://schema.org/OutOfStock"). This fixes stock detection
for sites like Ubiquiti Store that provide availability in JSON-LD.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Some sites (like Ubiquiti Store) use the priceSpecification nested
format in their JSON-LD structured data instead of direct price
property. Now checks offer.priceSpecification.price as fallback.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>