=== Beplus Site Assistant ===
Contributors: bearsthemes, ducdung2026
Tags: ai, chat, assistant, chatbot, knowledge base
Requires at least: 6.1
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 2.12.5
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

AI chat assistant that knows your site content, plugins, themes, forms and features.

== Description ==

Beplus Site Assistant adds an AI chat box to your WordPress site. Visitors can ask questions in natural language and get accurate answers based on your actual site content and structure: not generic guesses.

**What it knows:**

* Pages, posts and products (indexed content)
* Active plugins and themes (names only)
* Navigation menus and their links
* Post types, forms, search, comments, login/registration
* WooCommerce presence (cart, checkout)

**Key features:**

* Floating chat widget for visitors
* **WordPress AI Client integration**: reads your API key from *Settings → Connectors*
* **Custom endpoint mode**: works with any OpenAI-compatible endpoint (OpenAI, OpenRouter, Anthropic via gateway, DeepSeek, Ollama, or your own server)
* Automatic daily re-scan of your content (cron)
* Manual re-scan button in settings
* Security guardrails: describes features, never reveals code, keys or internal implementation
* Sources included with answers so visitors can verify

**Privacy:** the plugin never exposes your API key. Content is stored in your own database. You choose which provider receives your content.

**Documentation:** setup guides, screenshots and troubleshooting for every screen are published at [beplus-assistant-doc.beplus-agency.cloud](https://beplus-assistant-doc.beplus-agency.cloud/).

== External services ==

This plugin answers questions with the help of an AI service. It sends data out,
and it only works because it does: so here is exactly what leaves your site and
where it goes. Nothing is sent until you connect a provider and enable the
assistant.

**Who receives it**

The service *you* choose. There is no fixed destination and no account of ours
in the middle:

* the AI provider plugin you connect under *Settings → Connectors* (for example OpenAI, Anthropic or Google); or
* the OpenAI-compatible endpoint you type into **Custom endpoint** mode: your own gateway, or a locally hosted model such as Ollama on your own server.

In Custom endpoint mode the plugin sends your content only to the address you
entered.

**What is sent**

* The visitor's question, as typed.
* The excerpts from your own site content the plugin judged relevant to that question, so the answer can be grounded in your pages rather than invented.
* The site's structure summary: post types, menu names and active plugin or theme names: so the assistant can describe what the site offers.

**What is never sent**

* Your API key, which stays in your database and is used only by your server to authenticate the request.
* The visitor's IP address, name or email address. The lead form stores those in your own database; they are not part of the AI request.
* Other visitors' conversations, or any transcript from an earlier session.

**What is stored, and where**

Everything the plugin records: the content index, the conversations, the leads
and the analysis results: is stored in your own WordPress database. The plugin
has no server of its own and collects nothing.

**Your provider's own terms**

Every AI provider has its own retention and training policy for the requests it
receives. Which policy applies to you depends on the provider you pick, so please
read theirs before enabling the assistant:

* OpenAI: https://openai.com/policies/privacy-policy
* Anthropic: https://www.anthropic.com/legal/privacy
* Google: https://policies.google.com/privacy
* OpenRouter: https://openrouter.ai/privacy

If you would rather nothing left your site at all, host a model yourself and
point Custom endpoint mode at it.

= About BePlus =

This plugin is developed and maintained by BePlus, a WordPress and Shopify development studio with 10+ years of experience building themes and plugins for nonprofits and eCommerce brands.

Learn more at [beplusthemes.com](https://beplusthemes.com/).

== Screenshots ==

1. Desktop chat widget: a visitor asks a question and receives guided next steps with source links.
2. Mobile chat widget: full-width replies, quick actions, and a message box designed for a phone screen.
3. Welcome form: optional name and email capture before a visitor starts a conversation.
4. AI & Model settings: AI connection, model selection, and content-indexing controls.
5. Knowledge Base: content sources, custom instructions, and the one-click site scan.
6. Appearance & FAQs: mascot style, chat colours, placement, and visitor-facing copy.
7. Leads & Email: lead-capture behaviour, notification recipients, and daily delivery settings.
8. Security & Limits: rate limits, blocked topics, and information the assistant must refuse.
9. Embed Script: approved websites and a ready-to-paste snippet for external installation.
10. Conversations: visitor conversations, contact details, delivery status, and transcripts.
11. SEO Insights: recurring visitor topics and questions your current site content does not answer.
12. Storage: retained conversation count, space usage, and cleanup controls.
13. Export: download conversation records as CSV or JSONL by date range or newest-record count.

== Installation ==

1. Upload the `beplus-site-assistant` folder to `/wp-content/plugins/`, or install the ZIP via *Plugins → Add New → Upload Plugin*.
2. Activate the plugin.
3. Go to **Site Assistant** in the admin menu.
4. **Recommended:** install an AI provider plugin (e.g. OpenAI, Anthropic, Google) and add your API key under **Settings → Connectors**. Beplus Site Assistant uses it automatically.
5. *Alternatively*, switch to **Custom endpoint** mode and enter your own OpenAI-compatible endpoint URL, API key and model.
6. Click **Re-scan site** to index your content, then open the chat widget to answer questions.

== Frequently Asked Questions ==

= Which AI providers are supported? =

Two modes: **(1)** any provider plugin you install under *Settings → Connectors* (OpenAI, Anthropic, Google and more); **(2)** Custom endpoint mode: any provider that implements the OpenAI chat completions format (OpenAI, OpenRouter, Groq, DeepSeek, Ollama, or your own gateway), just paste the endpoint URL and API key.

= Can I choose the AI model? =

Yes. The **AI model** field in Site Assistant settings lets you pick any model the provider exposes: for example `gemini-3.7-flash` to avoid high-demand 503 errors, or leave it empty to use the provider's default. It works in both Connectors and Custom endpoint modes.

= Does it reveal my code or API keys? =

No. Security guardrails instruct the assistant to describe features at a high level and refuse requests for source code, credentials or internal implementation. Your API key is stored in site options and never sent to the browser.

= How often is content updated? =

The site is re-scanned daily via WordPress cron. You can also click *Re-scan site now* in settings any time.

= What data leaves my site? =

Only what the AI request needs: the visitor's question, the excerpts from your content that answer it, and a short summary of your site's structure. It goes to the one provider you configured: no one else. Your API key, your visitors' IP addresses and their contact details are never part of that request. See *External services* above for the full list.

= Does one visitor see another visitor's conversation? =

No. Each conversation is separate, and the AI request contains only the current visitor's question and your own site content.

== Upgrade Notice ==

= 2.12.1 =
Security and PHP 7.4 compatibility update. Existing conversations remain intact;
new visitor sessions use an ownership verifier before they can be ended or timed out.

= 2.12.0 =
A compatibility update requested by the WordPress.org review team. Your content,
settings and conversations are untouched, and there is nothing to reconfigure.

= 2.11.0 =
Groundwork for the WordPress.org release: no settings change, and nothing to
reconfigure. The assistant behaves exactly as it did in 2.10.0.

== Changelog ==

= 2.12.5 =
* Refined readme copy for a more natural writing style.

= 2.12.4 =
* Moved About BePlus section below "Your provider's own terms" right above Screenshots.

= 2.12.3 =
* Reordered sections so About BePlus displays correctly above the screenshot gallery on the WordPress.org Details tab.

= 2.12.2 =
* Refreshed WordPress.org screenshots with selective-blur documentation captures.
* Added the About BePlus section immediately before the screenshot gallery.

= 2.12.1 =
* **Protected anonymous chat sessions.** A browser receives a high-entropy session secret only when it starts a new conversation. WordPress stores only its hash, and a missing, wrong, or cross-session secret cannot end or time out another visitor's conversation.
* **PHP 7.4 compatibility restored.** Removed a PHP 8-only union return type while retaining the same documented return value.
* **No unimplemented shortcode claim.** The listing now accurately describes the floating widget that the plugin ships.
* **Preset FAQ answers stay in the browser.** The server only stores answers it generated itself, so a visitor cannot submit an arbitrary answer into conversation history or AI memory.
* **Internal worker HTTPS is verified.** The timeout worker no longer disables certificate verification.

= 2.12.0 =
* **No promotional wording in anything a visitor sees.** The starter questions
  that used to appear on the chat welcome screen described this company's own
  services, before the site owner had chosen to add them. That list now ships
  empty, and the examples in the settings screen are neutral prompts about
  *your* site. Nothing is displayed to a visitor unless you write it yourself.
* **One consistent prefix across the code.** Every function, setting, AJAX
  action and browser variable now uses the `beplsa_` / `beplsa` prefix instead
  of the three-letter `bsa`. This is what the directory requires so that two
  plugins can never collide. Nothing you configured changes.
* **The copy-paste embed snippet is generated by WordPress itself** rather than
  assembled from a text template, so it always follows the platform's own
  escaping rules.
* **Default assistant name is now "Site Assistant"**: a neutral starting point
  you can rename to anything.

= 2.11.0 =
* **Groundwork for the WordPress.org plugin directory.** No functional change:
  your settings, your indexed content and your conversations are untouched.
* **Admin pages load only what they need.** The stylesheet and script now load
  on the Site Assistant screens alone, instead of across the whole dashboard.
* **Admin assets are loaded the WordPress way**, so they no longer risk loading
  twice or clashing with another plugin on the same screen.
* **More of the privacy story, in plainer words.** The readme now spells out
  which provider receives what, and what is never sent. See *External services*.


= 2.10.0 =
* **New report: questions the assistant could not answer.** Under the topic
  table, SEO Insights now lists the subjects visitors asked about that your site
  has no page for: "Do you ship to Japan?", "What are your support hours?".
  Each row is a page worth writing. It comes from the same one-click analysis as
  the topics, so it costs no extra AI calls.
* **Honest gap detection.** Only genuine content gaps are listed. Questions the
  assistant answered, greetings and small talk, and questions it was configured
  to refuse are all left out: a refusal is a setting, not a missing page.
  Works for questions asked in any language.
* **"Questions, word for word" has been removed.** It counted the same question
  twice whenever the wording differed slightly, which the topic report already
  handles properly by meaning.
* **Live Conversations is easier to work with.** The heading sits on one line
  with the Refresh and Export buttons at the right edge, and each conversation
  has a checkbox.
* **Act on many conversations at once.** Select any number and delete them in
  one go, or end them and send the summary email: a confirmed report says
  exactly what succeeded and what did not.
* **Pagination.** Choose 10, 20, 30 or 40 conversations per page, with "Showing
  21–40 of 152" underneath so the total is never a guess.
* **Export by count, not just by date.** The Export dialog now offers "Last N
  conversations" alongside the date range, for when you want the most recent
  hundred rather than everything since Tuesday.
* **The export size estimate is now accurate.** It was understating the real
  file size by more than five times, which made a large export look harmless
  before it started.
* **The release package now ships the embed loader.** Every earlier ZIP was
  built without `assets/embed.js`, so a site installed from a ZIP: rather than
  from the plugin folder: served a 404 for the script that puts the assistant
  on a non-WordPress website. The packaging step now includes it.

= 2.9.1 =
* **Questions are now grouped by meaning, not wording.** A new report at the
  top of SEO Insights lists the subjects visitors actually ask about. "How do I
  install it?" and "steps to set it up" count as one topic instead of two
  separate one-off rows, so the report stays readable however much traffic the
  site gets.
* **Analysis runs on demand, from a button.** Nothing is analysed behind the
  scenes: one press reads the conversations and groups them, with a progress
  bar showing how far along it is. Analysis costs AI calls, so it happens when
  an administrator asks for it rather than continuously in the background.
* **A conversation is only ever analysed once.** Finished conversations are
  marked, and the next press looks at new conversations only, so pressing the
  button repeatedly costs nothing extra. Closing the page part-way through is
  safe too: the next press continues from where it stopped instead of starting
  over.
* **The report is bounded.** Topics are stored as a small permanent tally, and
  the table keeps the most-asked 300 so a long-running site cannot accumulate
  thousands of one-off subjects.
* **Word-for-word questions and top pages are still listed**, counted directly
  from the log without the AI, so both keep working even when the AI is
  unavailable.
* **Rebuild from scratch** re-reads every conversation and throws the tally
  away, for when an earlier run's results are not trustworthy.

= 2.8.0 =
* **One conversation, one record.** The separate per-turn chat log is gone.
  Everything it held: the whole exchange and the page the visitor was on :
  now lives on the conversation itself, so there is a single place to look and
  a single place to delete from.
* **Deleting a conversation now deletes all of it.** Previously the delete
  button removed the conversation but left its turns behind, and the SEO report
  kept showing chats that had already been deleted. Deleting now clears the
  conversation, its transcript and what the assistant remembered about that
  visitor, together.
* **The SEO report sees every conversation.** It used to read the per-turn log,
  which only recent chats reached: on a site with 14 conversations it reported
  on 2. Top pages and top questions are now counted from the conversations
  themselves.
* **Export is one row per conversation** instead of one row per message. The
  full back-and-forth sits in a single `transcript` column, so one row reads as
  one conversation.
* The admin screen drops the separate Chat Log tab: **Live Sessions**, **SEO
  Insights** and **Storage** cover everything. The menu entry is renamed
  **Conversations** and the table gains a **Page** column showing where each
  visitor was when they started chatting.

= 2.7.0 =
* **Every conversation is now kept permanently.** A new chat log records each
  visitor question and each answer with the page URL it came from, so you can
  finally answer "which pages make people ask us things, and what do they ask?"
  That page-level record is what turns traffic into content decisions: the
  questions that repeat are the pages and FAQs you are missing.
* The new **Chat Log** screen replaces Live Chats and has four tabs: Live
  Sessions, Chat Log (searchable, paginated, with full transcripts), SEO
  Insights (top pages and top questions over any date range) and Storage (table
  size, growth and free disk).
* **Storage is small and predictable**: each turn costs roughly 326 bytes, so a
  million turns is about 650 MB. Nothing is ever deleted automatically: the log
  is yours to keep.
* **Assistant memory is now 7 days** (previously 30) and is purely short-term
  context for follow-up questions. The permanent record lives in the chat log,
  so shortening it no longer loses anything.
* Live-chat sessions are no longer deleted after 24 hours, and the session list
  is paginated: it previously selected every row with no limit.
* **The stored API key is no longer sent to the browser.** The settings screen
  now only reports whether a key is saved; it can be replaced but never read
  back. The admin JavaScript no longer keeps a copy either.
* **Security fix:** the typing-time check was skipped whenever the widget's
  elapsed field was 0 or absent, so a scripted client could bypass it by simply
  omitting the value. A missing value is now treated as instant, which is what a
  bot looks like.
* **Upgrade fix:** the chat log table was gated behind a plugin-version check
  that returns early on any install already past 2.2.0, so a site updating from
  2.5.x would never create it and the feature would silently record nothing. The
  schema now has its own version gate and is also applied on admin load.
* Export now reads the chat log when present and includes the page URL column,
  so an exported file is directly usable for SEO analysis.
* Table indexes declare a 191-character prefix on the URL column. This is not
  defensive: on MariaDB 10.5 a plain index on a 255-character utf8mb4 column is
  rejected outright (error 1709, "maximum column size is 767 bytes"), and a
  schema that fails to create leaves the log table missing on that host. The
  prefix keeps the key at 764 bytes, inside the limit.
* **Every entry point now records.** Three separate paths answer a visitor :
  on-site chat, a widget embedded on another website, and the Quick FAQ button :
  and two of them were not writing to the permanent log at all. Conversations on
  embedded sites and quick-FAQ replies were therefore invisible in SEO Insights.
  All three now write the same record.
* **Visitor details are now kept for embedded sites.** The lead form lives in
  the widget, so a visitor on another website types their name and email there.
  Those two fields were never read on the way in, so every embedded conversation
  was stored without them and appeared as "Guest" in Live Conversations with no
  way to follow up. They are now validated and stored alongside the transcript
  and in the permanent log.
* Fixed: the version shown in the header was hardcoded and had been wrong since
  2.1.2; it now reports the running version.
* Fixed: "Load older turns" stacked a second table below the first instead of
  extending one log, leaving two scroll positions and two headers.

= 2.6.0 =
* Add an Export button to the Live Chats screen. One click produces a single
  flat file: CSV for spreadsheets or JSONL for AI analysis: containing every
  conversation turn on the site, including questions the assistant refused to
  answer. A date range is offered, and the dialog states how many rows and how
  much data the download will contain before it starts.
* The export is read-only and streams out one row at a time, so peak memory
  stays flat no matter how much history a site has: measured at 64 MB for a
  250,000-row export, the same as for 500 rows. Nothing in the chat tables is
  written, altered or deleted.
* Exports over a hard ceiling are refused up front with a message asking for a
  narrower date range, so a mistaken click cannot fill the disk.
* Conversations the assistant declined to answer are included with their
  refusal reason, so the most interesting rows for improving a site are not
  the ones missing from the file.

= 2.5.2 =
* Say on the Embed Script screen that example.com and www.example.com are two
  different sites. A mismatch is refused silently, so a correct-looking setup
  can produce no chat at all with nothing to point at.

= 2.5.1 =
* Warn in Embed Script when the WordPress address is plain HTTP. The script is
  then refused by every HTTPS site ("mixed content") and the visitor sees no
  chat at all, with nothing logged anywhere. The notice names the address and
  says what to do.
* Document the HTTPS requirement and the reverse-proxy setup.

= 2.5.0 =
* Improvement: one place for everything external: **Site Assistant -> Embed Script**. Each connected website shows its own Connect/Pause switch, its own script and its own status. Keys are minted and retired automatically.
* Improvement: pausing a website (or every embed) is refused on every transport, including signed server requests. Reconnecting needs no new script.
* Improvement: the duplicate External Embed controls in Settings are gone; the website list there could silently override this screen.
* Security: the bridge secret is never printed in full and no longer returned by the settings API. Use Copy on the Embed Script screen.
* Security: removed the "Require signed server requests" switch, which did not gate any request and could make an admin believe unsigned traffic was blocked.
* Compatibility: websites previously approved in the old Settings allowlist are moved into the website list automatically, so nothing stops working.

= 2.4.0 =
* Feature: new **Embed Script** screen. Enter the address of the site you want the assistant on, get a ready-to-copy script, paste it into that site's footer. No proxy, no secret, no code editing.
* Feature: each approved site gets its own public site key, bound to that exact address. Removing a site disables its script immediately.
* Feature: the widget now loads from the same host the browser used, so embeds work on HTTPS, behind a tunnel or any reverse proxy.
* Security: external chat requests are rate limited against the real visitor IP; a direct embed can never spoof it.

= 2.3.0 =
* Security: External embeds can require signed server-to-server requests using HMAC, a 60-second validity window, one-time nonces, and replay rejection.
* Security: External chat requests use a verified client IP for rate limiting; unsigned browser-supplied IP headers are never trusted.
* Security: Added exact-origin controls and safe bridge configuration guidance. No bridge or AI secret is sent to the widget/browser.

= 2.1.0 =
* Feature: Pre-chat Lead Capture gate (Visitor Name + Email) with seamless continuous chat persistence.
* Feature: Live Conversations Admin Dashboard (`Site Assistant -> Live Chats`) with real-time countdown timer, live chat viewer modal, and instant force-send.
* Feature: Zero database bloat architecture: transient sessions automatically emailed upon inactivity timeout or chat clear, then permanently purged.
* Improvement: Removed old Activity Log in favor of the new Live Chats dashboard.
* Improvement: Added configurable inactivity timeout and recipient email options.

= 2.0.8 =
* Fix: chat history was saved from only the first text node of a reply, so after clicking a link (popup reopen) the bot's message lost most of its content. History now keeps the full reply including markdown links/formatting.
* Fix: bot bubble text color is now fixed and no longer inherits the host theme/current homepage template color.

= 2.0.7 =
* The cached-answer indicator ("⚡ cached answer") is no longer shown to visitors: the answer cache still works (faster replies), it is just silent now.

= 2.0.6 =
* Removed all remaining embedding / semantic-search mentions from the admin UI. The assistant runs in clean keyword-search mode; no embedding data is stored. Backend support stays intact and is ready for a later release if an embedding provider is added.

= 2.0.5 =
* Embedding / semantic search section removed from the admin UI for now (backend support remains; the assistant keeps using fast keyword search and stores no embedding data). It can be re-enabled later when an embedding provider is available.
* New "Scan mode" option: Auto (batched, best for large sites: processes content in batches so memory stays bounded even with 10,000+ items) or Full (one pass, slightly faster on small sites).

= 2.0.4 =
* New: "Clear index" button in the admin: wipes the entire AI knowledge base (all indexed chunks + site fingerprint) in one click, so you can re-scan from a clean slate. Chat history and cached answers are kept. Protected by a confirmation dialog.

= 2.0.3 =
* Fix: upgrading from v1 to v2 (and re-scanning) left stale v1 chunks behind, so the same post could end up with both an old single chunk and fresh smart chunks: polluting retrieval with outdated/duplicated content. Re-scan now removes legacy v1 (position=0) chunks before indexing, so the knowledge base stays clean after upgrade.

= 2.0.2 =
* Mobile chat: full-screen panel on phones (correctly handles the address-bar viewport height), safe-area insets for notched devices, 16px input font so iOS doesn't zoom on focus, and 48px+ touch targets for the send button / input / FAB.
* Send button is now a clean paper-plane icon (easier to reach with a thumb) instead of a cramped text button.

= 2.0.1 =
* Fix: duplicate RELATED LINKS when several chunks of the same page are used: links are now deduplicated by URL.
* Fix: inline markdown rendering reordered text (bold/italic text appearing glued to surrounding text): the parser now walks tokens left-to-right in source order.
* Fix: sporadic "Unexpected AI response format": the SSE fallback now also handles gateways that put content under message.content instead of delta.content, and skips empty data: lines.
* Embedding settings are now grouped behind an "Enable semantic search" toggle: the embedding model, top-k and minimum-similarity fields only appear when enabled. When disabled, the plugin runs keyword search exactly as before.

= 2.0.0 =
* Smart, semantic chunking: content is split on paragraph/sentence boundaries (not fixed length) with overlap, and tagged with position metadata: so chunked instructions (e.g. step-by-step guides) stay intact and can be merged back into the full source.
* Retrieval mode auto-detection: if your AI endpoint offers an embedding model, the assistant uses **semantic (vector) search**: it matches by meaning, not just exact words, and pulls in the whole parent document for full context. If no embedding model is configured, it automatically falls back to **keyword search** so the plugin always works.
* New "Embedding model (optional)" setting + a Retrieval mode indicator in the admin panel (shows whether semantic or keyword search is active).
* Multi-chunk storage: a post's content now spans multiple indexed rows (one per chunk), so long posts/guides are fully searchable instead of truncated to a single entry.

= 1.3.0 =
* Conversation memory: the widget sends a stable per-browser `client_id`; the server stores every turn (visitor + assistant) and injects the last 8 messages plus keyword-matched older context into the prompt: follow-ups like "what name did you pick?" or A/B "which is better?" now work.
* Language lock: each message's language (vi/en) is detected on the widget and pinned in the prompt, so conversations no longer drift from English to Vietnamese (or vice versa) mid-chat.
* Markdown rendering in chat bubbles (bold, italic, code, lists, links, code blocks) built safely with DOM APIs: AI output can never inject HTML/scripts.

= 1.2.4 =
* Fix chat history lost when navigating between pages: history is always restored from localStorage (no welcome re-show), with a restore guard preventing overwrite.

= 1.2.3 =
* Fix welcome bubble re-shown on every widget reopen; crisp SVG clear-chat icon.

= 1.2.2 =
* Redesigned chat widget (teal theme, trash + close on the right edge of the header).
* Current-page context: the AI knows which page the visitor is on and can answer "what's on this page?".

= 1.2.0 =
* Added a full Security & Limits panel: honeypot, min-typing-time, per-IP rate limits (minute + hour), daily question budget with 80% email warning.
* Response caching: repeated identical questions are answered from cache (no AI call, saves tokens).
* Prompt-injection protection: hardened system prompt + keyword filter that refuses malicious prompts before the AI runs.
* Chat activity log + manual/automatic IP ban/unban (banned IPs shown in the admin panel).
* Friendly blocked notices in the chat widget: each refusal explains the reason and what to do next.

= 1.1.4 =
* E-commerce permission applies only to the native WooCommerce `product` post type; other custom post types stay under Site content.

= 1.1.3 =
* Indexes every public post type (auto-detected custom post types), not just posts/pages/products.

= 1.1.0 =
* Permissions simplified to Site content + E-commerce (removed plugins/themes/menus/forms).
* Site content covers posts/pages/CPTs only; product data requires the E-commerce permission.
* Shows exactly what is indexed (per-group counts + item titles).
* Extra info now supports three sources: free text, an external web link, and an uploaded .md file.
* Grouped settings: "Answer & Site Status" card with its own save + re-scan buttons.
* MySQL FULLTEXT search for fast retrieval on large sites.
* Removed the separate "Enable frontend chat widget" toggle (Enable assistant drives it).
* Endpoint now accepts a base URL (…/v1) and auto-appends /chat/completions.

= 1.0.0 =
* Initial release.
