# Agent Plugin — CLAUDE.md

Real-time AI pharmacy support chatbot. Anonymous site visitors chat through a Vue widget; a
`PharmacyAgent` (built on the **NeuronAI** framework) answers using **OpenAI**, live product/category
database lookups, and **Pinecone** RAG over uploaded documents. Responses stream back to the browser
over **Laravel Reverb** websockets. An admin SPA configures the widget, edits the agent's instructions,
uploads RAG context, and reviews chat history + token usage.

Detailed human docs live in `docs/` — see [Where to read more](#where-to-read-more). This file is the
quick orientation; read the relevant `docs/*.md` before deep changes.

## How it boots

- The whole plugin is gated by `config('neuron.enabled')` (env `AGENT_ENABLED`). When false, routes,
  migrations, and the admin menu are skipped.
- `loader.php` — legacy auto-discovery entry point. Only injects the "AI Agent" admin menu via
  `AdminController::injectAdminMenuItems()`.
- `Providers/AgentServiceProvider.php` — merges `config/neuron.php`, loads `routes/web.php` and
  `database/migrations`, aliases the `agent.anonymous` middleware, defines the `agent-chat` rate
  limiter (**10 req/min per IP**), and seeds default `agent_settings` once (cached) if the table is empty.
- `Providers/SocketServiceProvider.php` — registers broadcast auth routes (`web` + `agent.anonymous`
  middleware) and pulls in the **app-level** `routes/channels.php`.
- Channel authorization for `agent-channel.{guestId}` is defined in the project root
  `routes/channels.php` (NOT in this plugin): it checks `(string) $user->id === (string) $guestId`.

## Directory map

- `Agents/` — the AI core.
  - `PharmacyAgent.php` — extends `NeuronAI\RAG`; wires provider, tools, vector store, history, and
    builds the system prompt in `instructions()`.
  - `Tools/GetProducts.php`, `Tools/GetCategory.php` — tool-calls that query `\Mtc\Shop\Item` /
    `\Mtc\Shop\Category`. **They escape `%`/`_` wildcards — preserve that.**
  - `Outputs/ProductOutput.php` — structured-output schema every response conforms to.
  - `History/DatabaseChatHistory.php` — loads/persists conversation to `ai_chat_history` (~50K token window).
  - `VectorStore/PineconeVectorStore.php` — Pinecone HTTP adapter (namespace `pharmacy-products`).
  - `Observers/TokenUsageObserver.php` — `SplObserver` on NeuronAI's `inference-stop`; logs token usage.
- `Models/` — `AgentSettings` (singleton config), `AIChatHistory`, `TokenUsage`,
  `AgentSettingsInstruction` (the system-prompt lines; one table keyed by `type` =
  background/step/output), and `ChatGuestUser` (in-memory `Authenticatable`, no DB table).
- `Http/Controllers/` — `ChatController` (chat + session + admin history), `AgentSettingsController`
  (settings/instruction CRUD, token-access check, RAG context upload), `TokenUsageController`,
  `AdminController` (menu).
- `Http/Middlewares/AgentAnonymous.php` — issues the guest session (see gotchas).
- `Events/` — `Thinking.php` (broadcastAs `new.progress`) and `ChatGenerated.php` (broadcastAs
  `new.notification`), both on `PrivateChannel('agent-channel.'.$guestId)`.
- `routes/web.php` — public `agent/*` routes (`agent.anonymous` middleware) + `admin/agent/*` routes
  (`auth` middleware). There is no `api.php`.
- `config/neuron.php` — env-backed defaults for `enabled`, `openai.*`, `pinecone.*`.
- `database/migrations/` + `database/seeders/` — tables and default settings/instructions.
- `components/` — Vue 2 SFCs: chat widget (`agentChatPopup.vue`, `agentChat.vue`, `chat/**`) and the
  admin SPA (`admin/**`).
- `styles/` — LESS for the widget and admin SPA (variables in `styles/utils/`).
- `templates/admin/scripts.twig` + `admin/*.php` — thin PHP/Twig wrappers that mount the Vue admin UI
  and render a single chat-history record (`admin/view.php`).
- `docs/` — full reference documentation (9 files).

## Request / response flow

1. Widget POSTs to `/agent/chat` (rate-limited `throttle:agent-chat`).
2. `AgentAnonymous` resolves/creates the guest from the `agent_guest_id` cookie.
3. `ChatController::sendMessage()` validates the message and checks the daily token budget.
4. A `Thinking` event broadcasts → widget shows the thinking indicator.
5. `PharmacyAgent->structured()` runs: system prompt + history + (optional) `GetProducts`/`GetCategory`
   tools + Pinecone RAG → returns a `ProductOutput`.
6. `TokenUsageObserver` records input/output tokens to `ai_chat_token_usage`.
7. A `ChatGenerated` event broadcasts the response (+ matched product) → widget renders it.

## Key conventions & gotchas

- **The system prompt is database-driven, not hardcoded.** It is assembled at runtime from the
  `agent_settings_instructions` table (one row per line, `type` = background/step/output, ordered by
  `order`; editable in the admin UI). Edit agent behaviour there; only touch
  `PharmacyAgent::instructions()` to change the hardcoded fallbacks.
- **Admin DB settings override env.** `agent_settings` (API keys, model, position, token limits) takes
  precedence over `config/neuron.php` / `.env` at runtime.
- **Guests have no users-table row.** They are in-memory `ChatGuestUser` instances keyed by an
  encrypted, HttpOnly `agent_guest_id` cookie (30-day TTL). The guest's `id` is the UUID used in the
  broadcast channel name.
- **Sensitive fields are encrypted at rest** via the `OptionalEncrypted` cast (OpenAI/Pinecone keys on
  `AgentSettings`, messages on `AIChatHistory`). Never log or expose decrypted values.
- **All responses go through `ProductOutput`** (`name`, `productId`, `response`, `isMedicalAdvice`).
  Changing the response shape means updating that class AND the Vue consumer in `components/chat/`.
- **Real-time requires Reverb running.** Event names must stay matched on both sides: PHP
  `broadcastAs()` (`new.progress` / `new.notification`) and the Vue Echo listeners.
- **Token budget is enforced before each chat.** If the daily input/output limit is exceeded, the user
  gets an apology instead of an AI call.

Also follow the root `/CLAUDE.md`: no `var` in JS (use `let`/`const`), Vue 2, PSR brace style in PHP,
snake_case LESS, `<div>` (not `<p>`) around `|raw` Twig.

## Where to read more

- `docs/getting-started.md` — install, env vars, migrations, seeding (don't duplicate setup here).
- `docs/architecture.md` — full directory + data-flow + design decisions.
- `docs/ai-agent.md` — PharmacyAgent, tools, structured output, RAG pipeline, chat history.
- `docs/chat-widget.md` — Vue widget structure and behaviour.
- `docs/real-time-setup.md` — Reverb + Echo configuration and troubleshooting.
- `docs/configuration.md` — env vars and admin-panel settings.
- `docs/admin-panel.md` — the four admin tabs (Metrics, Chats, Context, Settings).
- `docs/api-reference.md` — endpoint request/response schemas.
- `docs/security.md` — encryption, rate limiting, SQL-injection prevention, guest auth, CSRF.
