# @mostajs/chatbot — fiche LLM
> Assistant / copilote / agent conversationnel GÉNÉRIQUE et réutilisable pour apps @mostajs/*. Activable/désactivable et **entièrement piloté par `.env`**. Backends pluggables (scripted | ai) ; providers LLM pluggables (anthropic/claude-opus-4-8, deepseek) avec **fallback** ; ancrage tool-use ; recherche web optionnelle. Registres façon dialectes ORM.

- Version: 0.0.1 (scaffold) · Licence: AGPL-3.0-or-later · Auteur: Dr Hamid MADANI <drmdh@msn.com>
- Chemin: mostajs/mosta-chatbot · Livrables #1-#3: `docs/01..03` + `docs/scripts-recherche-chatbot-08062026.sh`

## RÔLE
L'app hôte fournit son **profil métier** (`DomainProfile`) + ses **outils** (`ChatTool`, lecture seule par
défaut, RBAC) ; le module route vers le **backend** configuré et, en mode `ai`, vers un **provider LLM**
(avec fallback). Aucune logique d'une app particulière dans le module (réutilisable partout : CRM, santé, …).

## EXPORTS
- `.` (serveur-safe) : `createChatbot({domain,tools,intents?,agent?,assignable?})` → `{enabled(), stream, ask,
  agent(), isAgent(id), ensureAssignable(), assignableLabel(id)}` ;
  `registerBackend/getBackend/listBackends`, `registerLlmProvider/getLlmProvider/listLlmProviders`,
  `registerTool/getTool/listTools` ; **agent** : `DEFAULT_AGENT`/`resolveAgent` + types `AgentIdentity`/`AgentConfig`/`AssignableAgentPort` ;
  toute la config (`chatbot*`) ; types.
- `./server` : built-ins concrets (`scriptedBackend`, `aiBackend`, `anthropicProvider`, `deepseekProvider`).
- `./client` (React) : `<Chatbot send=… title? greeting? />` (widget bulle+panneau ; SSE en 0.3).

## CONFIG (.env — @mostajs/config, cascade MOSTA_ENV) — TOUT par .env
- `CHATBOT_ENABLED=0|1` (défaut 0, opt-in) · `CHATBOT_ROLES=admin,employe` (vide=tous) · `CHATBOT_MODE=assistant|agent`
- `CHATBOT_BACKEND=scripted|ai` (défaut scripted)
- `CHATBOT_PROVIDERS=deepseek,anthropic` (liste priorité+fallback ; `CHATBOT_PROVIDER` = single, compat)
- `CHATBOT_MODEL=` (vide ⇒ défaut provider : anthropic→claude-opus-4-8, deepseek→deepseek-chat)
- Anthropic : `ANTHROPIC_API_KEY` · `CHATBOT_WEB_SEARCH=0|1` · `CHATBOT_EFFORT=low|medium|high|xhigh|max`
- DeepSeek : `DEEPSEEK_API_KEY` · `DEEPSEEK_BASE_URL=https://api.deepseek.com` (compatible OpenAI)
- `CHATBOT_MAX_TOKENS` · `CHATBOT_QUOTA_PER_ROLE` (à venir)

## PROVIDERS LLM (registre — ajouter = un fichier + register)
- `anthropic` : `@anthropic-ai/sdk`, modèle `claude-opus-4-8`, `thinking:{type:"adaptive"}`, streaming, outils
  serveur `web_search`/`web_fetch` si `CHATBOT_WEB_SEARCH=1`.
- `deepseek` : endpoint `/chat/completions` (OpenAI-compatible), SSE en `fetch`, modèles `deepseek-chat` /
  `deepseek-v4-flash` / `deepseek-v4-pro`. Sans dépendance.
- Extension : `registerLlmProvider({ key:"openai", stream(messages,tools,opts){…} })`.

## TYPES CLÉS
DomainProfile { appName, description, locale? } · ChatTool { name, description, schema, permission?, run(input,actor) }
ChatActor { id, role, permissions? } · ChatChunk { type:'text'|'tool'|'done'|'error', text?, tool? }
IChatBackend { key, reply(ctx): AsyncIterable<ChatChunk> } · ILlmProvider { key, stream(msgs,tools,opts) }

## PATTERN (app Next.js)
```ts
// serveur
import { createChatbot, registerTool } from "@mostajs/chatbot";
registerTool({ name:"orders_by_state", description:"Compter les commandes par état", schema:{...},
  permission:"order.read", run: async ({state}) => crm.repositories.orders.find(o=>o.state===state).length });
const bot = createChatbot({ domain:{ appName:"CRM TRADING", description:"Négoce: commandes/fournisseurs/proformats", locale:"fr" } });
if (bot.enabled()) for await (const c of bot.stream(messages, actor)) { /* stream */ }
```

## DÉPEND DE (peers)
- `@mostajs/config` (env). `@anthropic-ai/sdk` (optionnel — provider anthropic). `react` (optionnel — `./client`).
- DeepSeek : aucune dépendance (fetch). Composition prévue : `@mostajs/repository` (outils/historique),
  `@mostajs/auth`/`rbac` (accès+outils), `@mostajs/audit` (traçabilité), `@mostajs/i18n`, `@mostajs/net` (SSE).

## PIÈGES
- `CHATBOT_ENABLED=0` par défaut : rien ne s'affiche/ne coûte tant qu'on n'a pas opt-in.
- `./client` est 'use client' : importer `createChatbot` (serveur) à part, passer un `send()` au widget.
- Multi-provider : laisser `CHATBOT_MODEL` vide pour que chaque provider applique son défaut.
- Backend `ai` envoie le contexte à un tiers (Anthropic/DeepSeek) : opt-in, pas de secret au prompt, audit, RGPD.
