BlunxAI BlunxAI

Documentation

Installation, configuration, contrat API et référence technique de BlunxAI.
Laravel & Node.js Web SDK API REST

Aperçu

BlunxAI transforme votre base de données en un collaborateur agentique : vos utilisateurs posent des questions en langage naturel et reçoivent des réponses, des graphiques, des tableaux et des insights automatiques — directement dans votre application.

Le principe

BlunxAI n'est pas une plateforme externe vers laquelle vous exporteriez vos données : c'est un SDK que vous embarquez dans votre infrastructure. Le SQL est exécuté localement, en lecture seule, et le système multi-agents est piloté par le serveur Blunx (le point d'entrée cloud /api/v1/*).

Architecture

Votre application (front)
Le Web SDK s'intègre dans votre front : HTML, Laravel Blade, React, Vue, Angular, Svelte…
SDK backend
Le SDK de votre langage (Laravel et Node.js aujourd'hui, Django, Go, Spring Boot… à venir) sert l'API locale /api/blunx/* et exécute le SQL sur votre base.
Serveur Blunx
Le serveur Blunx (/api/v1/*) orchestre les agents IA et dialogue avec le fournisseur LLM de votre choix.
LLM
OpenAI, Claude, Gemini, Ollama, Groq, DeepSeek… via l'adaptateur compatible OpenAI ou le format natif.
L'exécution SQL est locale. Seuls les plans de requêtes, schémas et métadonnées transitent vers le serveur Blunx — jamais vos lignes de données.

Ce que vous devez retenir

  • Lecture seule stricte : seuls des SELECT / WITH sont exécutés, à plusieurs niveaux de garde-fous (voir Sécurité).
  • Backend-agnostique : le Web SDK n'attend qu'un contrat REST /api/blunx/*. Les packages Laravel et Node.js l'implémentent aujourd'hui ; les SDK Django, Go, Spring Boot suivront sans rien changer côté front.
  • Un serveur, plusieurs clés : le SDK backend s'authentifie auprès du serveur Blunx avec une clé d'application (X-Blunx-Key) et une clé LLM (X-Blunx-LLM-Key).
  • Votre BDD, vos règles : MySQL, MariaDB, PostgreSQL, SQLite et SQL Server sont pris en charge ; vous contrôlez les accès par rôle (RBAC).
Par où commencer ?

Allez à la section Démarrage rapide : installation de bout en bout, avec des onglets par langage backend.

Démarrage rapide

Installez Blunx dans votre application en ~10 minutes. Choisissez votre backend (Laravel ou Node.js) : le schéma est identique, seul le SDK change. Chaque étape est minimale — les détails sont dans les guides.

Ce que vous allez faire : 1 · récupérer vos clés → 2 · installer le SDK → 3 · configurer le .env → 4 · connecter Blunx et exclure les tables sensibles → 5 · générer le schéma de votre base → 6 · intégrer l'interface (Web SDK) dans vos pages. Une fois en place, Blunx transforme les questions de vos utilisateurs en SQL en lecture seule sur votre base : il ne modifie jamais vos données.

Prérequis

PrérequisDétail
ApplicationLaravel 9-12 (PHP 8.1+) ou Node.js 18+ (Express, Fastify, Koa, NestJS, HTTP natif)
Base de donnéesMySQL, MariaDB, PostgreSQL, SQLite ou SQL Server (celle de votre app)
Compte BlunxUne application créée sur le dashboard → votre clé d'application
Fournisseur LLMUn compte avec clé API (OpenAI, Claude, Gemini, Ollama, Groq, DeepSeek…)

1 · Récupérer vos clés

Regroupez ces 4 informations — vous en aurez besoin à l'étape 3 :

À récupérerVariableExemple
Clé d'applicationBLUNX_API_KEYblunx_app_live_xxxx
Clé LLMBLUNX_LLM_API_KEYsk-xxxxxxxxxxxx
Endpoint LLMBLUNX_LLM_ENDPOINThttps://api.openai.com/v1
ModèleBLUNX_LLM_MODELgpt-4o
Pas encore de LLM ?

Ollama fonctionne en local, sans compte : endpoint http://localhost:11434/v1, modèle llama3.1. Voir Fournisseurs LLM.

2

Installer le package

Terminal Bash
composer require blunx/ai
php artisan vendor:publish --tag=blunx-config

Provider en auto-discovery, aucune migration à publier.

3

Renseigner votre .env

Ajoutez vos 4 clés de l'étape 1 :

.env Env
BLUNX_API_KEY=blunx_app_live_xxxxxxxxxxxx
BLUNX_LLM_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxx
BLUNX_LLM_ENDPOINT=https://api.openai.com/v1
BLUNX_LLM_MODEL=gpt-4o

Puis : php artisan config:clear. La connexion BDD par défaut de votre app est utilisée automatiquement.

4

Exclure les tables à ignorer

À l'init, Blunx scanne toutes les tables de votre base. Les tables techniques de Laravel (migrations, jobs, sessions, cache…) et les tables internes blunx_* sont déjà exclues par défaut. Ajoutez vos tables sensibles ou sans intérêt à la clé excluded_tables du fichier publié config/blunx.php (étape 2) :

config/blunx.php PHP
// Déjà exclus par défaut : migrations, failed_jobs, cache, jobs, sessions,
// password_reset_tokens, personal_access_tokens… + toutes les tables blunx_*
'excluded_tables' => [
    'admin_logs', 'notifications', 'settings', 'audit_trail',   // ▶ vos tables
],

Puis videz le cache de configuration pour que blunx:init relise le fichier : php artisan config:clear.

À ne pas confondre avec les règles RBAC

Une table exclue n'est jamais scannée ni proposée à l'assistant. Une table interdite (forbidden_tables, fichier blunx_access.php) reste dans le schéma mais est bloquée selon le rôle. Détail dans Configuration.

5

Générer et verrouiller le schéma

Terminal Bash
php artisan blunx:init    # scanne la base → storage/app/blunx_schema.json
php artisan blunx:setup   # verrouille le schéma + crée les 8 tables

blunx:init appelle le serveur Blunx pour enrichir les descriptions : la clé LLM doit être valide.

6

Ajouter getUserRoleName() au modèle User

Pour appliquer vos règles d'accès (RBAC), Blunx appelle automatiquement Auth::user()?->getUserRoleName() à chaque requête. Vous devez donc ajouter une méthode nommée exactement getUserRoleName() à votre modèle User — ce n'est pas une alternative : c'est cette méthode que Blunx va réellement exécuter.

app/Models/User.php PHP
public function getUserRoleName(): ?string
{
    return $this->role->name ?? null;
}
Ce que doit faire cette méthode

Elle doit retourner le libellé du rôle de l'utilisateur connecté (une chaîne, ex. 'admin', 'vendeur'), ou null s'il n'a pas de rôle. L'exemple ci-dessus suppose une relation role et une colonne name sur votre table roles. Si votre schéma diffère (colonne role directe, table roles avec libelle…), adaptez uniquement l'intérieur de la méthode — gardez le même nom et le même type de retour.

7

Intégrer le Web SDK

Collez ce snippet à l'endroit où vous voulez que l'assistant Blunx apparaisse. Deux cas possibles :

  • Sur une page entière — créez une vue dédiée (ex. resources/views/blunx.blade.php) avec un conteneur plein écran (height:100vh) : c'est exactement l'exemple ci-dessous.
  • Dans une page existante — ajoutez simplement le <div id="blunx"> (avec la hauteur de votre choix, ex. height:600px) à l'emplacement voulu, et la même balise <script> à la fin du <body>. Rien d'autre à changer.
resources/views/blunx.blade.php Blade
<div id="blunx" style="height:100vh;"></div>
<script src="https://cdn.jsdelivr.net/npm/@blunx/web-sdk/dist/blunx-loader.min.js"
        data-container="#blunx"
        data-view="auto"></script>

data-container="#blunx" indique au SDK le div dans lequel se monter ; data-view="auto" laisse le SDK choisir la vue. L'API /api/blunx/* est servie par votre Laravel (même origine) : data-api-base-url reste vide. La session est envoyée automatiquement.

2

Installer le package

Terminal Bash
npm install blunx-ai

Le .env est chargé automatiquement (dotenv). Aucune migration à publier.

3

Renseigner votre .env

Ajoutez vos 4 clés de l'étape 1 plus votre base de données (ligne BLUNX_DB_URL). Cette ligne est lue par la CLI (étape 6) et par votre application (étape 4) :

.env Env
BLUNX_API_KEY=blunx_app_live_xxxxxxxxxxxx
BLUNX_LLM_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxx
BLUNX_LLM_ENDPOINT=https://api.openai.com/v1
BLUNX_LLM_MODEL=gpt-4o
# Votre base (ADAPTEZ) — mysql://user:motdepasse@hote:port/base
BLUNX_DB_URL=mysql://root:secret@127.0.0.1:3306/ma_base

Autres bases supportées : postgres://…, sqlite:///chemin/vers/base.sqlite, sqlsrv://….

4

Initialiser Blunx dans votre serveur

Deux situations possibles — choisissez celle qui vous correspond :

Cas A — Vous avez déjà un serveur Express (le plus courant)

Pas besoin de créer de fichier ni de toucher à votre point d'entrée. Ajoutez simplement ces 3 blocs dans votre code serveur existant :

Votre fichier serveur existant JavaScript
const { Blunx, blunxExpress } = require('blunx-ai');   // 1. import

// 2. Runtime Blunx — clés (BLUNX_API_KEY, BLUNX_LLM_*) et base (BLUNX_DB_URL)
//    lues dans le .env. Les 2 hooks ci-dessous sont OBLIGATOIRES :
const blunx = Blunx.init({
  getUserRole: (userId) => null,   // TODO : retournez le libellé du rôle (ex. 'admin')
  getUser: (userId) => null,       // TODO : retournez { name, email } ou null
});

// 3. Montez le routeur Blunx APRÈS votre middleware d'authentification
//    (celui-ci doit avoir rempli req.user avant)
app.use('/api/blunx', blunxExpress(blunx));
Un exemple concret des 2 hooks

Implémentation typique à adapter (ici une table users) :

Hooks — exemple à adapter JavaScript
getUserRole: (userId) => users[userId]?.role ?? null,
getUser: (userId) => {
  const u = users[userId];
  return u ? { name: u.name, email: u.email } : null;
},
Cas B — Vous partez de zéro (aucun serveur existant)

Créez un fichier app.js complet (Express). Adaptez les 2 endroits marqués ADAPTEZ puis lancez node app.js : le fichier gère l'auth, monte Blunx et démarre le serveur.

app.js — Express (fichier complet) JavaScript
const express = require('express');                   // framework HTTP
const { Blunx, blunxExpress } = require('blunx-ai');   // SDK Blunx

const app = express();
app.use(express.json());   // lit le body JSON

// ── Utilisateurs de démo (ADAPTEZ : venez de votre table users) ──
const USERS = {
  1: { name: 'Amir',  email: 'amir@x.com',  role: 'admin'   },
  2: { name: 'Sarah', email: 'sarah@x.com', role: 'vendeur' },
};

// ── Authentification (ADAPTEZ : Passport, JWT, session…) ──
// Blunx renvoie 401 si req.user est absent : votre middleware d'auth
// doit s'exécuter AVANT le routeur Blunx et remplir req.user.
app.use((req, res, next) => {
  req.user = USERS[1];   // démo : l'utilisateur 1 est connecté
  next();
});

// ── Runtime Blunx (clés + BDD lues dans le .env) ──
const blunx = Blunx.init({
  getUserRole: (userId) => USERS[userId]?.role ?? null,
  getUser: (userId) => {
    const u = USERS[userId];
    return u ? { name: u.name, email: u.email } : null;
  },
});

// ── Routeur Blunx monté APRÈS l'auth ──
app.use('/api/blunx', blunxExpress(blunx));

// ── Démarrage ──
app.listen(3000, () => console.log('Blunx prêt sur http://localhost:3000'));

Autres frameworks (Fastify, Koa, NestJS, HTTP natif) : fichiers complets dans Backend Node.js.

Option (avancé) — Gérer la configuration dans des fichiers TypeScript

Vous n'en avez pas besoin pour démarrer : le .env suffit. Cette option ne remplace pas l'intégration ci-dessus — elle change uniquement la source de la configuration : au lieu de tout passer à Blunx.init(), vous chargez 2 fichiers TypeScript versionnables (équivalent de vendor:publish). Les hooks et le montage du routeur restent identiques :

Terminal Bash
cp node_modules/blunx-ai/config/blunx.config.ts ./config/blunx.config.ts
cp node_modules/blunx-ai/config/blunx-access.config.ts ./config/blunx-access.config.ts
app.ts — TypeScript TypeScript
import blunxConfig from './config/blunx.config';            // ta copie éditée
import blunxAccessConfig from './config/blunx-access.config'; // tes règles RBAC

const blunx = Blunx.init({
  ...blunxConfig,             // serverUrl, apiKey, llm, currency, locale…
  access: blunxAccessConfig,  // règles RBAC
  // hooks identiques à ceux du Cas A / B ci-dessus (USERS) :
  getUserRole: (userId) => USERS[userId]?.role ?? null,
  getUser: (userId) => {
    const u = USERS[userId];
    return u ? { name: u.name, email: u.email } : null;
  },
});

Deux fichiers pour deux rôles : blunx.config.ts = configuration générale du runtime (clés, serveur, LLM, devise, langue) ; blunx-access.config.ts = vos règles d'accès RBAC. Détail dans Configuration.

5

Exclure les tables à ignorer

À l'init, Blunx scanne toutes les tables de votre base. Par défaut, seules les tables internes blunx_* sont ignorées. Ajoutez vos tables techniques (migrations, sessions…) et sensibles (logs, notifications, réglages…) à l'option excludedTables, en éditant le fichier config/blunx.config.ts chargé dans Blunx.init() :

config/blunx.config.ts TypeScript
export default {
  // Tables internes blunx_* déjà ignorées par défaut.
  // ▶ Ajoutez vos tables techniques / sensibles à ne pas scanner :
  excludedTables: ['migrations', 'sessions', 'log_errors', 'admin_logs', 'notifications'],
};
À ne pas confondre avec les règles RBAC

Une table exclue n'est jamais scannée ni proposée à l'assistant. Une table interdite (forbidden_tables, fichier blunx-access.config.ts) reste dans le schéma mais est bloquée selon le rôle. Détail dans Configuration.

6

Générer et verrouiller le schéma

Terminal Bash
npx blunx-ai init    # scanne la base → storage/app/blunx_schema.json
npx blunx-ai setup   # verrouille le schéma + crée les 8 tables

Lancez depuis la racine de votre projet : la CLI lit le .env pour construire sa connexion.

7

Intégrer le Web SDK

index.html HTML
<div id="blunx" style="height:100vh;"></div>
<script src="https://cdn.jsdelivr.net/npm/@blunx/web-sdk/dist/blunx-loader.min.js"
        data-container="#blunx"
        data-view="auto"></script>

L'API /api/blunx/* est servie par votre app Node (même origine) : data-api-base-url reste vide.

Vérifier que tout fonctionne

Connectez-vous avec un utilisateur de votre application et ouvrez la page. Posez une question (ex. « Quel est le nombre total de clients ? ») : le cockpit affiche le pipeline puis le résultat.

Erreur 401 ou 422 ?

C'est presque toujours les clés BLUNX_API_KEY / BLUNX_LLM_API_KEY ou une configuration LLM incomplète. Voir Erreurs & dépannage.

Guide complet

Pour aller plus loin (BDD, jobs, auth, RBAC…) : Backend Laravel ou Backend Node.js.

Compatibilité

Les versions et environnements pris en charge, par brique de l'intégration. Les SDK backend : Laravel et Node.js sont disponibles, les autres suivent.

Bases de données

Blunx fonctionne avec la connexion de votre application et exécute le SQL en lecture seule. Les bases suivantes sont prises en charge par le SDK Laravel et par le serveur Blunx :

Base de donnéesValeur db_connectionNotes
MySQLmysqlDéfaut
MariaDBmariadbTraité comme MySQL côté SDK
PostgreSQLpgsqlScan limité au schéma BLUNX_PGSQL_SCHEMA (défaut public)
SQLitesqliteFichier local
SQL ServersqlsrvDriver sqlsrv / sqlserver

Backend (SDK serveur)

TechnologieStatutNotes
Laravel (package blunx/ai)● DisponibleLaravel 9 à 12 (testé sous 12), PHP 8.1+
Node.js (package blunx-ai)● DisponibleNode.js 18+, npm, même contrat /api/blunx/*
Django (Python)● BientôtMême contrat /api/blunx/*
Go● BientôtMême contrat /api/blunx/*
Spring Boot (Java)● BientôtMême contrat /api/blunx/*

Front-end (Web SDK @blunx/web-sdk)

TechnologieMéthodeContrainte
HTML pur / PHP / Laravel Blade<script> + loader (auto-update)Aucune
React (Vite, CRA, Next.js)npm install + init()/destroy()Next.js : côté client uniquement ('use client' / dynamic(…, {ssr:false}))
Vue 3 (Vite, Nuxt)npm install + init()/destroy()Appeler init() dans onMounted
Angularnpm install + init()/destroy()Appeler init() dans ngAfterViewInit
Svelte / SvelteKitnpm install + init()/destroy()Chargement côté client uniquement
Widget isolé (iframe)Page hôte qui embarque le SDKIsolation maximale recommandée

Fournisseurs LLM

Le driver openai est un adaptateur compatible OpenAI : il fonctionne avec la quasi-totalité des fournisseurs propriétaires ET open-source. Voir Fournisseurs LLM pour le détail.

DriverFournisseurs
openaiOpenAI, Azure OpenAI, Ollama (local), Groq, DeepSeek, Mistral, Together, Fireworks, OpenRouter, vLLM, LM Studio, llama.cpp…
anthropicAnthropic Claude (format natif /v1/messages)
geminiGoogle Gemini (format natif generateContent)

Navigateurs & environnements

ÉlémentPrise en charge
NavigateursChrome, Edge, Firefox, Safari (ES2019+, pas d'IE)
BundlersVite, webpack, esbuild, Rollup (module ESM)
SSRNon supporté nativement — à exécuter côté client uniquement
CDNjsDelivr (loader + bundle), unpkg

Backend Laravel

Le package blunx/ai sert le contrat /api/blunx/* attendu par le Web SDK, exécute le SQL en lecture seule sur votre base et proxie vers le serveur Blunx. Prérequis : Laravel 9 à 12 (testé sous 12), PHP 8.1+.

Installation

Terminal Bash
composer require blunx/ai
php artisan vendor:publish --tag=blunx-config
  • Provider en auto-discovery — aucune déclaration manuelle.
  • Aucune migration à publier : les 8 tables Blunx sont créées par blunx:setup.

Configuration

Deux fichiers publiés dans config/ : blunx.php (lu depuis vos variables BLUNX_*) et blunx_access.php (règles RBAC). La référence complète des variables est dans Configuration.

Méthode getUserRoleName() obligatoire

Le package appelle Auth::user()?->getUserRoleName() à chaque requête pour résoudre les règles d'accès. Cette méthode doit donc exister avec ce nom exact sur votre modèle User et retourner le libellé du rôle de l'utilisateur (une chaîne, ou null s'il n'a pas de rôle). L'exemple ci-dessous suppose une relation role avec une colonne name — si votre schéma diffère, adaptez l'intérieur de la méthode mais gardez le nom et le type de retour :

app/Models/User.php PHP
public function getUserRoleName(): ?string
{
    return $this->role->name ?? null;
}

Commandes artisan

CommandeRôle
blunx:initScanne la base et génère storage/app/blunx_schema.json (enrichi via le serveur Blunx).
blunx:editÉdition manuelle des descriptions ou ré-indexation après évolution de la base.
blunx:setupVerrouille le schéma et crée les 8 tables Blunx (idempotent).
blunx:feedbackRévise les retours utilisateurs non résolus.
blunx:run-insightsExécute immédiatement les insights « dus » (next_run_at dépassé), avec retry — équivalent du scheduler horaire déclenché manuellement. En cas d'échec après les retries, le job re-tente dans 30 min.

Workflow : blunx:init → (optionnel) blunx:editblunx:setup. Relancez blunx:edit après chaque évolution de votre base.

Tables créées

Toutes ont un id auto-incrémenté + un uuid unique (routes liées par uuid) :

TableRôle
blunx_conversationsConversations de chat
blunx_messagesMessages (user|assistant)
blunx_feedbacksRetours utilisateurs
blunx_dashboardsDashboards
blunx_dashboard_widgetsWidgets (chart|table) + reference_queries
blunx_insightsInsights + report_pdf
blunx_widget_insight_settingsRéglages d'insights par widget
blunx_cacheCache (dont schema_id 48 h)

Authentification & routes

Toutes les routes /api/blunx/* sont dans le groupe de middleware blunx = session + auth (utilisateur connecté exigé, sans CSRF) + throttle:60,1. Rien à configurer : une requête non authentifiée est bloquée par le framework (401/redirection).

Route blunx.dashboard

La vue email référence route('blunx.dashboard', …). Cette route n'est pas définie par le package : définissez-la dans votre application.

File d'attente & insights

  • GenerateWidgetInsightJob : ShouldQueue, tries=5, timeout=200 — exécute le widget, génère le rapport PDF et l'email.
  • BlunxInsightMail : email coloré selon la sévérité, PDF en pièce jointe.
  • Planification : toutes les heures pour les réglages « dus » ; un nouveau réglage est exécuté immédiatement.
  • Échec après retries (ex. appel serveur en erreur) : le job n'avance pas vers le prochain créneau — il re-tente dans 30 min (next_run_at = maintenant + 30 min, last_run_at inchangé tant que le job n'a pas abouti).
  • En local : php artisan queue:work --once (ou QUEUE_CONNECTION=sync en dev).
Étapes suivantes

Le guide d'intégration pas à pas est dans Démarrage rapide. La référence des endpoints dans Contrat API, les erreurs dans Erreurs & dépannage.

Backend Node.js

Le package blunx-ai sert le contrat /api/blunx/* attendu par le Web SDK, exécute le SQL en lecture seule sur votre base et proxie vers le serveur Blunx. Prérequis : Node.js 18+, framework agnostique (Express, Fastify, Koa, NestJS ou HTTP natif).

Installation

Terminal Bash
npm install blunx-ai
  • Le .env est chargé automatiquement (dotenv) — aucune publication de config obligatoire.
  • Aucune migration à publier : les 8 tables Blunx sont créées par blunx-ai setup.

Initialisation

Créez le runtime Blunx une seule fois avec vos hooks d'authentification. La priorité de configuration : option de Blunx.init() > variable BLUNX_* > défaut (voir Configuration).

La connexion à votre base se fournit de 3 façons (du plus simple au plus intégré) :

MéthodeCommentQuand l'utiliser
BLUNX_DB_URL dans le .env (recommandé)Une URL de connexion, lue par la CLI et le runtimeLa majorité des cas — une seule config pour tout.
database: { client, connection }Config de connexion passée à Blunx.init()Quand la CLI n'est pas utilisée (runtime seul).
knex: instanceKnexVotre instance knex existanteVotre app utilise déjà knex — on la réutilise.
app.js — initialisation (clés + BDD depuis le .env) JavaScript
const { Blunx } = require('blunx-ai');

// Clés (BLUNX_API_KEY, BLUNX_LLM_*) et base (BLUNX_DB_URL) lues dans le .env.
// Exemple de résolution des utilisateurs (ADAPTEZ : venez de votre base) :
const USERS = {
  1: { name: 'Amir',  email: 'amir@x.com',  role: 'admin'   },
  2: { name: 'Sarah', email: 'sarah@x.com', role: 'vendeur' },
};

const blunx = Blunx.init({
  // Résout le rôle de l'utilisateur (RBAC) — équivaut getUserRoleName() de Laravel
  getUserRole: (userId) => USERS[userId]?.role ?? null,
  // Résout {name, email} pour /api/blunx/user — équivaut Auth::user() de Laravel
  getUser: (userId) => {
    const u = USERS[userId];
    return u ? { name: u.name, email: u.email } : null;
  },
});

Option (avancé) — publier et charger les fichiers de config

Vous n'en avez pas besoin pour démarrer : le .env suffit. Cette option ne remplace pas l'initialisation ci-dessus — elle change seulement la source de la configuration. Utilisez-la si vous voulez versionner vos réglages et vos règles RBAC dans des fichiers TypeScript plutôt que dans le .env. Copiez les 2 templates (aucune dépendance), éditez-les, puis chargez-les dans Blunx.init() :

Terminal Bash
cp node_modules/blunx-ai/config/blunx.config.ts ./config/blunx.config.ts
cp node_modules/blunx-ai/config/blunx-access.config.ts ./config/blunx-access.config.ts
app.ts — charger les fichiers TypeScript
import blunxConfig from './config/blunx.config';            // ta copie éditée
import blunxAccessConfig from './config/blunx-access.config'; // tes règles RBAC

const blunx = Blunx.init({
  ...blunxConfig,             // serverUrl, apiKey, llm, currency, locale…
  access: blunxAccessConfig,  // règles RBAC
  // hooks identiques à ci-dessus (USERS) :
  getUserRole: (userId) => USERS[userId]?.role ?? null,
  getUser: (userId) => {
    const u = USERS[userId];
    return u ? { name: u.name, email: u.email } : null;
  },
});

La base se passe par BLUNX_DB_URL (.env) ou l'option database. Détail des règles RBAC dans Configuration.

Commandes (CLI blunx-ai)

CommandeRôle
npx blunx-ai initScanne la base et génère storage/app/blunx_schema.json (enrichi via le serveur Blunx).
npx blunx-ai editÉdition manuelle des descriptions ou ré-indexation après évolution de la base.
npx blunx-ai setupVerrouille le schéma et crée les 8 tables Blunx (idempotent).
npx blunx-ai feedbackRévise les retours utilisateurs non résolus.
npx blunx-ai run-insightsExécute maintenant les insights « dus » (équivalent du scheduler horaire). En cas d'échec après les retries, le job re-tente dans 30 min.

Workflow : blunx-ai init → (optionnel) blunx-ai editblunx-ai setup. La CLI construit sa propre connexion depuis le .env (BLUNX_DB_URL ou BLUNX_DB_*) — lancez-la depuis la racine de votre projet.

Tables créées

Identiques au package Laravel : blunx_conversations, blunx_messages, blunx_feedbacks, blunx_dashboards, blunx_dashboard_widgets, blunx_insights, blunx_widget_insight_settings, blunx_cache (toutes avec id + uuid unique).

Authentification & routes

Le package protège lui-même les routes : sans utilisateur authentifié (req.user / ctx.state.user absent), il renvoie 401 {"message":"Unauthenticated."} — équivalent du middleware auth du groupe blunx de Laravel. Aucun garde requireAuth à ajouter.

app.js — Express JavaScript
const express = require('express');
const { Blunx, blunxExpress } = require('blunx-ai');

const app = express();
app.use(express.json());

// Utilisateurs de démo (ADAPTEZ : venez de votre base)
const USERS = {
  1: { name: 'Amir',  email: 'amir@x.com',  role: 'admin'   },
  2: { name: 'Sarah', email: 'sarah@x.com', role: 'vendeur' },
};

// 1. Authentification : votre middleware d'auth (Passport, JWT, session…)
//    remplit req.user. Exemple de démo :
app.use((req, res, next) => {
  req.user = USERS[1];
  next();
});

const blunx = Blunx.init({
  getUserRole: (userId) => USERS[userId]?.role ?? null,
  getUser: (userId) => {
    const u = USERS[userId];
    return u ? { name: u.name, email: u.email } : null;
  },
});

// 2. Blunx monté APRÈS : il vérifie req.user et renvoie 401 s'il est absent
app.use('/api/blunx', blunxExpress(blunx));

app.listen(3000);

Blunx lit req.user.id (filtrage user_id), req.user.name/email (endpoint /user) et optionnellement req.user.getUserRoleName() (sinon votre hook getUserRole est appelé). Autres adaptateurs : blunxFastify, blunxKoa, createBlunxNestController, blunxNodeHttp.

Rate limit

Laravel applique throttle:60,1. En Node, ajoutez votre rate limiter sur le routeur Blunx (ex. express-rate-limit). Ne compressez pas le flux /stream (SSE).

Planification des insights

  • Scheduler (node-cron) : toutes les heures, trouve les réglages « dus » et exécute GenerateWidgetInsightJob. Activé par défaut (enableScheduler: true), désactivable via Blunx.init({ enableScheduler: false }).
  • npx blunx-ai run-insights : exécution manuelle immédiate.
  • Échec après retries (ex. appel serveur en erreur) : le job n'avance pas vers le prochain créneau — il re-tente dans 30 min (next_run_at = maintenant + 30 min, last_run_at inchangé tant que le job n'a pas abouti).
  • sendInsightMail (nodemailer) : email coloré selon la sévérité, PDF en pièce jointe (généré par InsightPdfGenerator — rendu 100 % JS, aucun navigateur).
Liens des emails (dashboardUrl) & PDF

En Laravel c'est la route blunx.dashboard ; en Node, fournissez le hook dashboardUrl: (uuid) => '…' à Blunx.init(). Pour le PDF, aucun navigateur ni chemin à configurer : rendu HTML→PDF via Puppeteer (Chromium embarqué, pas de Chrome installé sur la machine), comme dompdf côté PHP.

Exemples complets par framework

Chaque exemple est un fichier complet et copiable : utilisateurs de démo, authentification, runtime et démarrage. Remplacez les blocs marqués ADAPTEZ (base, auth, rôles) par vos vraies données. Clés + BDD dans le .env.

app.js — Express JavaScript
const express = require('express');                   // framework HTTP
const { Blunx, blunxExpress } = require('blunx-ai');   // SDK Blunx

const app = express();
app.use(express.json());   // lit le body JSON

// ── Utilisateurs de démo (ADAPTEZ : venez de votre table users) ──
const USERS = {
  1: { name: 'Amir',  email: 'amir@x.com',  role: 'admin'   },
  2: { name: 'Sarah', email: 'sarah@x.com', role: 'vendeur' },
};

// ── Authentification (ADAPTEZ : Passport, JWT, session…) ──
app.use((req, res, next) => {
  req.user = USERS[1];   // démo : l'utilisateur 1 est connecté
  next();
});

// ── Runtime Blunx (clés + BDD depuis le .env) ──
const blunx = Blunx.init({
  getUserRole: (userId) => USERS[userId]?.role ?? null,
  getUser: (userId) => {
    const u = USERS[userId];
    return u ? { name: u.name, email: u.email } : null;
  },
});

// ── Routeur Blunx monté APRÈS l'auth ──
app.use('/api/blunx', blunxExpress(blunx));

app.listen(3000, () => console.log('Blunx prêt sur http://localhost:3000'));
app.js — Fastify JavaScript
const fastify = require('fastify');
const { Blunx, blunxFastify } = require('blunx-ai');

const app = fastify();

// Utilisateurs de démo (ADAPTEZ)
const USERS = {
  1: { name: 'Amir',  email: 'amir@x.com',  role: 'admin'   },
  2: { name: 'Sarah', email: 'sarah@x.com', role: 'vendeur' },
};

// Authentification (ADAPTEZ) : remplit req.user avant le routeur Blunx
app.addHook('onRequest', (req, reply, done) => {
  req.user = USERS[1];
  done();
});

// Runtime Blunx (clés + BDD depuis le .env)
const blunx = Blunx.init({
  getUserRole: (userId) => USERS[userId]?.role ?? null,
  getUser: (userId) => {
    const u = USERS[userId];
    return u ? { name: u.name, email: u.email } : null;
  },
});

// Montage du routeur Blunx
blunxFastify(app, blunx);

app.listen({ port: 3000 }).then(() => console.log('Blunx prêt sur http://localhost:3000'));
app.js — Koa JavaScript
const Koa = require('koa');
const bodyParser = require('koa-bodyparser');   // requis : lit le body JSON
const { Blunx, blunxKoa } = require('blunx-ai');

const app = new Koa();
app.use(bodyParser());

// Utilisateurs de démo (ADAPTEZ)
const USERS = {
  1: { name: 'Amir',  email: 'amir@x.com',  role: 'admin'   },
  2: { name: 'Sarah', email: 'sarah@x.com', role: 'vendeur' },
};

// Authentification (ADAPTEZ) : remplit ctx.state.user avant le routeur Blunx
app.use(async (ctx, next) => {
  ctx.state.user = USERS[1];
  await next();
});

// Runtime Blunx (clés + BDD depuis le .env)
const blunx = Blunx.init({
  getUserRole: (userId) => USERS[userId]?.role ?? null,
  getUser: (userId) => {
    const u = USERS[userId];
    return u ? { name: u.name, email: u.email } : null;
  },
});

// Montage du routeur Blunx
app.use(blunxKoa(blunx));

app.listen(3000, () => console.log('Blunx prêt sur http://localhost:3000'));
blunx.module.ts — NestJS TypeScript
import { Module } from '@nestjs/common';
import { Blunx, createBlunxNestController } from 'blunx-ai';

// Utilisateurs de démo (ADAPTEZ)
const USERS: Record<number, any> = {
  1: { name: 'Amir',  email: 'amir@x.com',  role: 'admin'   },
  2: { name: 'Sarah', email: 'sarah@x.com', role: 'vendeur' },
};

// Runtime Blunx (clés + BDD depuis le .env)
const blunx = Blunx.init({
  getUserRole: (userId: any) => USERS[userId]?.role ?? null,
  getUser: (userId: any) => {
    const u = USERS[userId];
    return u ? { name: u.name, email: u.email } : null;
  },
});

// Contrôleur Blunx (votre guard d'auth Nest doit remplir req.user — ADAPTEZ)
const BlunxController = createBlunxNestController(blunx);

@Module({ controllers: [BlunxController] })
export class BlunxModule {}
server.js — HTTP natif JavaScript
const http = require('http');
const { Blunx, blunxNodeHttp } = require('blunx-ai');

// Utilisateurs de démo (ADAPTEZ)
const USERS = {
  1: { name: 'Amir',  email: 'amir@x.com',  role: 'admin'   },
  2: { name: 'Sarah', email: 'sarah@x.com', role: 'vendeur' },
};

// Runtime Blunx (clés + BDD depuis le .env)
const blunx = Blunx.init({
  getUserRole: (userId) => USERS[userId]?.role ?? null,
  getUser: (userId) => {
    const u = USERS[userId];
    return u ? { name: u.name, email: u.email } : null;
  },
});

http.createServer((req, res) => {
  // Authentification (ADAPTEZ) : remplit req.user avant le routeur Blunx
  req.user = USERS[1];

  if (blunxNodeHttp(blunx, req, res)) return;   // requête gérée par Blunx
  res.writeHead(404).end();
}).listen(3000, () => console.log('Blunx prêt sur http://localhost:3000'));
Étapes suivantes

Le guide d'intégration pas à pas est dans Démarrage rapide. La référence des endpoints dans Contrat API, les erreurs dans Erreurs & dépannage.

Web SDK

Le Web SDK (@blunx/web-sdk) est une application front autonome et embarquable : cockpit de chat + canvas, dashboards et insights. Il se monte dans un simple conteneur DOM. L'intégration est identique quel que soit votre backend (Laravel, Node.js…).

Formats de distribution

FichierFormatUsage
dist/blunx-loader.min.jsIIFE<script> simple, auto-update (toujours la dernière version)
dist/blunx.min.jsIIFE<script> direct → window.Blunx
dist/blunx.esm.jsESMnpm install @blunx/web-sdkimport { init }
Locale automatique — rien à configurer

La langue est récupérée depuis /api/blunx/user (champ locale). Ne passez pas locale à l'initialisation : la valeur serveur fait foi.

Intégration par framework

Le SDK se monte dans un simple <div>. Deux intégrations possibles : sur une page entière (conteneur plein écran, ex. height:100vh) ou dans une page existante (placez le div à l'emplacement voulu, avec la hauteur de votre choix, et la balise <script> à la fin du <body>). Dans les deux cas, le snippet est le même — seul change le conteneur.

Loader (recommandé, mise à jour automatique) :

index.html / Vue Blade HTML
<div id="blunx" style="height:100vh;"></div>
<script src="https://cdn.jsdelivr.net/npm/@blunx/web-sdk/dist/blunx-loader.min.js"
        data-container="#blunx"
        data-view="auto"></script>

Bundle direct (version épinglée) :

index.html HTML
<div id="blunx" style="height:100vh;"></div>
<script src="https://cdn.jsdelivr.net/npm/@blunx/web-sdk/dist/blunx.min.js"></script>
<script>
  Blunx.init({ container: '#blunx', view: 'auto' })
    .then(function (info) { console.log('[Blunx] prêt', info); })
    .catch(function (err) { console.error('[Blunx] échec', err); });
</script>

L'API étant servie par votre backend (même origine), apiBaseUrl reste vide. Le cookie de session est envoyé automatiquement.

Terminal Bash
npm install @blunx/web-sdk
src/App.jsx JSX
import { useEffect } from 'react';
import { init, destroy, navigate } from '@blunx/web-sdk';

export default function App() {
    useEffect(() => {
        let mounted = true;

        init({
            container: '#blunx',
            apiBaseUrl: '', // cross-origin — vide en même origine
            view: 'auto',
            onReady: (info) => console.log('[React] Blunx prêt', info),
            onError: (err) => console.error('[React] Blunx erreur', err),
        })
            .then((info) => { if (mounted) console.log('[React] monté', info); })
            .catch((err) => console.error('[React] init échouée', err));

        return () => { mounted = false; destroy(); }; // démontage (StrictMode-safe)
    }, []);

    return (
        <div className="host">
            <header className="host-top">
                <strong>React hôte</strong>
                <span>SDK monté dans <code>#blunx</code></span>
            </header>
            <div id="blunx" className="blunx-zone" />
        </div>
    );
}

Le SDK touche window/document à l'évaluation : côté client uniquement. En App Router, on l'importe donc dynamiquement dans un useEffect (composant 'use client').

src/app/page.js JS — App Router
'use client';

import { useEffect, useRef } from 'react';

export default function Home() {
    const apiRef = useRef(null);

    useEffect(() => {
        let mounted = true;

        import('@blunx/web-sdk')
            .then(({ init, destroy, navigate }) => {
                apiRef.current = { destroy, navigate };
                return init({
                    container: '#blunx',
                    apiBaseUrl: '', // cross-origin — vide en même origine
                    view: 'auto',
                    onReady: (info) => console.log('[Next] Blunx prêt', info),
                    onError: (err) => console.error('[Next] Blunx erreur', err),
                });
            })
            .then((info) => { if (mounted) console.log('[Next] monté', info); })
            .catch((err) => console.error('[Next] init échouée', err));

        return () => { mounted = false; apiRef.current?.destroy?.(); };
    }, []);

    return (
        <main className="host">
            <header className="host-top">
                <strong>Next.js hôte</strong>
                <span>SDK importé dynamiquement (SSR-safe)</span>
            </header>
            <div id="blunx" className="blunx-zone" />
        </main>
    );
}
Terminal Bash
npm install @blunx/web-sdk
src/App.vue Vue
<script setup>
import { onMounted, onUnmounted } from 'vue';
import { init, destroy, navigate } from '@blunx/web-sdk';

onMounted(async () => {
    try {
        const info = await init({
            container: '#blunx',
            apiBaseUrl: '', // cross-origin — vide en même origine
            view: 'auto',
            onReady: (i) => console.log('[Vue] Blunx prêt', i),
            onError: (e) => console.error('[Vue] Blunx erreur', e),
        });
        console.log('[Vue] monté', info);
    } catch (e) {
        console.error('[Vue] init échouée', e);
    }
});

onUnmounted(() => {
    destroy(); // démonte le SDK quand le composant est retiré
});
</script>

<template>
    <div class="host">
        <header class="host-top">
            <strong>Vue 3 hôte</strong>
            <span>SDK monté dans <code>#blunx</code></span>
        </header>
        <div id="blunx" class="blunx-zone" />
    </div>
</template>
src/app/app.component.ts TypeScript
import { Component, OnInit, OnDestroy } from '@angular/core';
import { init, destroy, navigate } from '@blunx/web-sdk';

@Component({
    selector: 'app-root',
    standalone: true,
    template: `
        <div class="host">
            <header class="host-top">
                <strong>Angular hôte</strong>
                <span>SDK monté dans <code>#blunx</code></span>
            </header>
            <div id="blunx" class="blunx-zone"></div>
        </div>
    `,
})
export class AppComponent implements OnInit, OnDestroy {
    async ngOnInit(): Promise<void> {
        try {
            const info = await init({
                container: '#blunx',
                apiBaseUrl: '', // cross-origin — vide en même origine
                view: 'auto',
                onReady: (i) => console.log('[Angular] Blunx prêt', i),
                onError: (e) => console.error('[Angular] Blunx erreur', e),
            });
            console.log('[Angular] monté', info);
        } catch (e) {
            console.error('[Angular] init échouée', e);
        }
    }

    ngOnDestroy(): void {
        destroy(); // démonte le SDK quand le composant est détruit
    }

}
src/App.svelte Svelte
<script>
    import { onMount, onDestroy } from 'svelte';
    import { init, destroy, navigate } from '@blunx/web-sdk';

    onMount(async () => {
        try {
            const info = await init({
                container: '#blunx',
                apiBaseUrl: '', // cross-origin — vide en même origine
                view: 'auto',
                onReady: (i) => console.log('[Svelte] Blunx prêt', i),
                onError: (e) => console.error('[Svelte] Blunx erreur', e),
            });
            console.log('[Svelte] monté', info);
        } catch (e) {
            console.error('[Svelte] init échouée', e);
        }
    });

    onDestroy(() => {
        destroy(); // démonte le SDK quand le composant est détruit
    });
</script>

<div class="host">
    <header class="host-top">
        <strong>Svelte hôte</strong>
        <span>SDK monté dans <code>#blunx</code></span>
    </header>
    <div id="blunx" class="blunx-zone"></div>
</div>

API publique & options

API publique JS
import { init, destroy, navigate, version } from '@blunx/web-sdk';

init(options)  // → Promise<{ view: 'cockpit'|'dashboard', version }>
destroy()      // démonte et nettoie le listener hashchange + le contenu du conteneur
navigate(path) // navigation interne, ex. navigate('/dashboard/abc-123') → '#/dashboard/abc-123'
version        // string, ex. "0.1.0"
OptionTypeDéfautDescription
containerstring | HTMLElement'#blunx'Sélecteur / élément dans lequel monter l'application
apiBaseUrlstring''Base de l'API (vide = même origine, recommandé)
view'auto' | 'cockpit' | 'dashboard''auto'Vue initiale ('auto' suit le hash de l'URL)
dashboardUuidstring | nullnullUUID du dashboard si view: 'dashboard'
onReadyfunctionnullAppelé après le premier montage : (info) => {}
onErrorfunctionnullAppelé si init() échoue (conteneur, routage). La promesse rejette aussi.

Via script-tag, les options se passent en attributs data-* : data-container, data-api-base-url, data-view, data-dashboard-uuid.

Pièges & bonnes pratiques

Conteneur & hauteur

Le sélecteur doit exister au moment de init(), et le conteneur doit avoir une hauteur (height:100vh ou 70vh), sinon le rendu peut être écrasé.

SSR / Next.js

Le module accède à window/document à l'évaluation : importez-le uniquement côté client ('use client' ou ssr: false).

Conflit de hash

Le SDK réagit à tout hashchange. Si votre app utilise déjà le hash pour son routage, il peut y avoir conflit.

Cross-origin : session sur le stream

En cross-origin (apiBaseUrl sur un autre domaine), le fetch de /api/blunx/stream n'envoie pas credentials. Préférez une configuration même origine.

Versions des dépendances de la page hôte

Si la page hôte a déjà jQuery/Bootstrap/DataTables/ECharts, le SDK les réutilise. Une version incompatible (ex. Bootstrap 4) dégrade silencieusement certains composants.

Configuration

Cette page est la référence complète : toutes les variables d'environnement, toutes les options de Blunx.init() et les règles d'accès RBAC. Dans la majorité des cas, le .env suffit.

Les 3 façons de configurer

MéthodeLaravelNode.jsQuand l'utiliser
.env (recommandé) Chargé par Laravel Chargé automatiquement (dotenv) La quasi-totalité des cas : clés, LLM, BDD.
config/blunx.phpBlunx.init() config/blunx.php options de Blunx.init({...}) Pour forcer une valeur (monnaie, exclusions…) ou passer les règles RBAC.
Règles RBAC config/blunx_access.php init({ access }) Uniquement par fichier/option — aucune variable d'env.
Recharger la configuration

Laravel : php artisan config:clear. Node : rien à faire (le .env est relu à chaque démarrage).

Variables d'environnement

Colonne Alternative : clé blunx.* (Laravel) / option init() (Node).

VariableDéfautRôleAlternative (Laravel → Node)
BLUNX_SERVER_URLhttps://blunxai.comURL du serveur Blunx (/api/v1/*)server_url → serverUrl
BLUNX_REQUEST_TIMEOUT600Timeout (s) de chaque requête vers le Hub (SSE chat + JSON) — 0 = aucun (une question lourde qui fait réfléchir le LLM n'est jamais coupée)request_timeout → requestTimeout
BLUNX_API_KEYClé d'application → X-Blunx-Keyapi_key → apiKey
BLUNX_LLM_API_KEYClé LLM → X-Blunx-LLM-Keyllm_api_key → llmApiKey
BLUNX_LLM_DRIVERopenaiopenai (compatible : Ollama, Groq, DeepSeek…) | gemini | anthropicllm.driver → llm.driver
BLUNX_LLM_ENDPOINTEndpoint de votre fournisseurllm.endpoint → llm.endpoint
BLUNX_LLM_MODELModèle utilisé par l'IAllm.model → llm.model
BLUNX_LLM_SUPPORTS_JSON_FORMATtrueLe modèle gère response_format: json_object ? (false sur modèles locaux anciens)llm.supports_json_format → llm.supportsJsonFormat
BLUNX_DB_CONNECTIONmysqlDialecte SQL envoyé au serveur Blunx (la connexion locale réelle vient de votre app)db_connection → dbConnection
BLUNX_DB_URLURL de connexion (DSN) : remplace la connexion par défaut, SSL possibledb_url → databaseUrl
BLUNX_READONLY_DB_USERNAME / PASSWORDRôle BDD lecture seule (optionnel — voir modes de connexion)readonly_db → readonlyDb
BLUNX_PGSQL_SCHEMApublicSchéma PostgreSQL scannépgsql_schema → pgsqlSchema
BLUNX_CURRENCY_CODE / SYMBOL / LOCALEEUR / € / fr_FRFormat d'affichage des montantscurrency.* → currency.*
BLUNX_LOCALEfrLangue des prompts, messages et vueslocale → locale
BLUNX_SCHEMA_PATHstorage/app/blunx_schema.jsonChemin du fichier de schéma— → schemaPath

Les tables exclues du scan (excluded_tables en Laravel, excludedTables en Node) et les règles RBAC (access) n'ont pas de variable d'env : elles se passent par option/fichier (voir les sections ci-dessous).

Les 4 clés indispensables

BLUNX_API_KEY, BLUNX_LLM_API_KEY, BLUNX_LLM_ENDPOINT et BLUNX_LLM_MODEL. Tout le reste a une valeur par défaut utilisable.

Blunx.init() — toutes les options (Node.js)

Référence complète de ce que vous pouvez passer à Blunx.init(). Priorité : option > variable d'env > défaut. Le template TypeScript config/blunx.config.ts (exporté, sans dépendance) utilise ces clés en camelCase ; les clés snake_case (server_url, api_key, db_url…) sont aussi acceptées (miroir de config/blunx.php).

OptionTypeDéfautEnvDescription
enabledbooleantrueActive / désactive le SDK
serverUrlstringhttps://blunxai.comBLUNX_SERVER_URLURL du Hub Blunx (/api/v1/*)
requestTimeoutnumber600BLUNX_REQUEST_TIMEOUTTimeout (s) de chaque requête vers le Hub (SSE + JSON) — 0 = aucun timeout
apiKeystring | nullnullBLUNX_API_KEYClé d'application → en-tête X-Blunx-Key
llmApiKeystring | nullnullBLUNX_LLM_API_KEYClé LLM → en-tête X-Blunx-LLM-Key
dbConnectionstring | nullnullBLUNX_DB_CONNECTIONDialecte SQL envoyé au Hub (mysql, pgsql…) — ≠ connexion locale
databaseUrlstring | nullnullBLUNX_DB_URLURL de connexion BDD (DSN) — prioritaire (mysql://, postgres://, sqlite://…)
readonlyDb{ username, password }{ null, null }BLUNX_READONLY_DB_*Rôle BDD lecture seule (optionnel)
pgsqlSchemastringpublicBLUNX_PGSQL_SCHEMASchéma PostgreSQL scanné par init/edit
llm{ driver, endpoint, model, supportsJsonFormat }openai / null / null / trueBLUNX_LLM_*Config LLM relayée au Hub (les clés restent en en-tête)
users{ userTable, primaryKey }users / idTable et clé des utilisateurs de l'hôte
currency{ code, symbol, locale }EUR / € / fr_FRBLUNX_CURRENCY_*Format d'affichage des montants
excludedTablesstring[]blunx_* (8)Tables ignorées au scan de schéma (voir la section dédiée plus bas)
localestringfrBLUNX_LOCALELangue des messages et vues
tables{ conversations, messages, feedbacks, dashboards, widgets, insights, insightSettings, cache }blunx_*Noms de tables Blunx personnalisés
schemaPathstringstorage/app/blunx_schema.jsonBLUNX_SCHEMA_PATHChemin du fichier de schéma
accessAccessConfigdéfautRègles RBAC (voir ci-dessous)
knexinstanceInstance knex de l'hôte (connexion principale)
readonlyKnexinstanceInstance knex lecture seule
database{ client, connection, useNullAsDefault, pool }Config de connexion knex (si pas d'instance)
getUserRole(userId) => string | nullRésout le rôle de l'utilisateur — équivaut getUserRoleName()
getUser(userId) => { name, email } | nullRésout name/email pour /api/blunx/user — équivaut Auth::user()
dashboardUrl(uuid) => stringURL du dashboard (lien « Voir le dashboard » des emails)
mailMailOptionsSMTP des emails : host, port, secure, user, pass, from, transport (nodemailer)
enableSchedulerbooleantrueActive le scheduler horaire des insights
Règles importantes
  • apiKey / llmApiKey ne sont jamais envoyées dans le body (en-têtes uniquement).
  • dbConnection ≠ connexion locale : c'est le dialecte envoyé au Hub. La vraie connexion vient de databaseUrl, database ou knex.
  • readonlyDb : si username est vide, Blunx retombe sur la connexion par défaut (défense en profondeur).

Charger les fichiers de config (Node.js)

Exemple complet : on publie config/blunx.config.ts + config/blunx-access.config.ts (templates TypeScript, aucune dépendance), on les charge, et on ajoute la base + les hooks :

app.ts TypeScript
import blunxConfig from './config/blunx.config';            // ta copie éditée
import blunxAccessConfig from './config/blunx-access.config'; // tes règles RBAC

const blunx = Blunx.init({
  ...blunxConfig,          // serverUrl, apiKey, llm, currency, locale…
  access: blunxAccessConfig,  // règles RBAC
  // BDD : via BLUNX_DB_URL dans le .env (recommandé), ou :
  // database: { client: 'mysql2', connection: { host, user, password, database } },
  getUserRole: (userId) => USERS[userId]?.role ?? null,
  getUser: (userId) => {
    const u = USERS[userId];
    return u ? { name: u.name, email: u.email } : null;
  },
});

Règles d'accès RBAC (access)

Approche NÉGATIVE : on définit ce que l'utilisateur N'A PAS le droit de voir. En Laravel : config/blunx_access.php. En Node : option access de Blunx.init() (fichier config/blunx-access.config.ts). Aucune variable d'env.

Trois niveaux de restriction par rôle :

NiveauTypeRôle
forbidden_tablesstring[]Tables entièrement interdites au rôle
forbidden_columns{ table: string[] }Colonnes interdites par table ("*" = toutes les tables)
row_level{ table: { column, value } }Filtrage automatique des lignes (ex. WHERE user_id = X)

Exemple complet (fichier config/blunx-access.config.ts) :

config/blunx-access.config.ts TypeScript
export default {
  "vendeur": {
    "forbidden_tables": ["salaires", "comptabilite"],
    "forbidden_columns": {
      "users": ["salaire", "numero_secu", "adresse_complete"],
      "*": ["mot_de_passe", "token_api"]
    },
    "row_level": {
      "orders":   { "column": "user_id", "value": "USER_ID" },
      "products": { "column": "vendor_id", "value": "USER_ID" }
    }
  },
  "admin":   { "forbidden_tables": [], "forbidden_columns": [], "row_level": {} },
  "default": { "forbidden_tables": ["users"], "forbidden_columns": {}, "row_level": {} },
  "enabled": true
}
  • USER_ID : placeholder remplacé par l'ID de l'utilisateur connecté.
  • Le SDK fusionne default + les règles du rôle (fusion récursive, comme array_replace_recursive).
  • Si aucun rôle n'est résolu → null → erreur SSE Access rules not resolved.
  • enabled : active/désactive tout le système de permissions.

Tables exclues du scan (excluded_tables / excludedTables)

À la génération du schéma (blunx:init / npx blunx-ai init), Blunx scanne toutes les tables de votre base et les rend interrogeables par l'assistant. Listez ici les tables techniques, sensibles ou sans intérêt qui ne doivent jamais apparaître dans le schéma. Aucune variable d'env : la liste se déclare par fichier/option.

LaravelNode.js
config/blunx.php → 'excluded_tables'config/blunx.config.ts → excludedTables
DéfautTables techniques Laravel (migrations, jobs, sessions…) + blunx_*Tables internes blunx_* uniquement
Quand c'est luAu blunx:init / blunx:editAu init / edit (runtime chargé)
config/blunx.php — Laravel PHP
'excluded_tables' => [
    // Déjà exclus par défaut : migrations, failed_jobs, cache, jobs, sessions,
    // password_reset_tokens, personal_access_tokens… + les tables internes blunx_*
    'admin_logs', 'notifications', 'settings', 'audit_trail',   // ▶ vos tables
],
config/blunx.config.ts — Node.js TypeScript
export default {
  // ...
  // Tables internes blunx_* déjà ignorées par défaut.
  // ▶ Ajoutez vos tables techniques / sensibles à ne pas scanner :
  excludedTables: ['migrations', 'sessions', 'log_errors', 'admin_logs', 'notifications'],
};
Exclusion ≠ règle RBAC

Une table exclue n'est jamais scannée : elle n'existe pas pour Blunx (ni dans le schéma, ni proposée à l'assistant). Une table interdite (forbidden_tables, RBAC) reste dans le schéma mais son accès est bloqué selon le rôle de l'utilisateur. Modifiez la liste avant init ; après coup, relancez blunx:edit / npx blunx-ai edit pour retirer une table déjà scannée.

Un .env complet prêt à copier

.env Env
# --- Serveur Blunx ---
BLUNX_SERVER_URL=https://blunxai.com
# Timeout (s) de chaque requête vers le Hub — 600 (10 min) par défaut ; 0 = aucun
BLUNX_REQUEST_TIMEOUT=600
BLUNX_API_KEY=blunx_app_live_xxxxxxxxxxxx

# --- Fournisseur LLM (OpenAI dans cet exemple) ---
BLUNX_LLM_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxx
BLUNX_LLM_DRIVER=openai
BLUNX_LLM_ENDPOINT=https://api.openai.com/v1
BLUNX_LLM_MODEL=gpt-4o
BLUNX_LLM_SUPPORTS_JSON_FORMAT=true

# --- Base de données ---
BLUNX_DB_CONNECTION=mysql
# BLUNX_DB_URL=postgres://user:pass@host:5432/db?sslmode=require   # alternative : URL de connexion (DSN)
# BLUNX_READONLY_DB_USERNAME=blunx_readonly   # optionnel (voir modes de connexion)
# BLUNX_READONLY_DB_PASSWORD=secret
# BLUNX_PGSQL_SCHEMA=public                    # PostgreSQL uniquement

# --- Affichage & langue ---
BLUNX_CURRENCY_CODE=EUR
BLUNX_CURRENCY_SYMBOL=€
BLUNX_CURRENCY_LOCALE=fr_FR
BLUNX_LOCALE=fr

Les 3 modes de connexion à la base de données

Blunx exécute le SQL sur votre base. Trois notions complémentaires — à ne pas confondre :

ModeVariableCe que c'estQuand l'utiliser
1 · Connexion par défaut de l'app BLUNX_DB_CONNECTION La connexion que votre application utilise déjà (connexion Laravel par défaut, ou instance/config knex passée à Blunx.init()). Cas le plus courant : Blunx réutilise la base de votre app telle quelle.
2 · URL de connexion (DSN) BLUNX_DB_URL Une URL complète (hôte, port, base, user, mot de passe, SSL) qui remplace la connexion par défaut. Bases cloud (Neon, Railway, Heroku…) ou cibler une autre base sans toucher à la config de l'app.
3 · Rôle lecture seule BLUNX_READONLY_DB_* Un override de credentials appliqué par-dessus le mode 1 ou 2 pour forcer l'exécution en lecture seule. Verrou de sécurité : la connexion porte le rôle principal mais Blunx ne doit jamais écrire.
Règle de priorité

BLUNX_DB_URL prime sur la connexion par défaut (mode 2 > mode 1). Le rôle lecture seule (mode 3) est ensuite appliqué par-dessus, SSL conservé. Si l'URL contient déjà un rôle read-only, le mode 3 est inutile : laissez-le vide.

Contrat API

Deux familles d'endpoints : le Web SDK ne connaît que les endpoints locaux /api/blunx/* servis par votre SDK backend ; celui-ci proxie vers le serveur Blunx /api/v1/*.

Endpoints locaux (/api/blunx/*)

Session + auth, sans CSRF, throttle 60:1. Réponses enveloppées dans { "data": … }, sauf /user (objet direct).

MéthodeCheminRôle
GET/api/blunx/userUtilisateur connecté (champ locale)
GET · POST/api/blunx/conversationsLister / créer une conversation
DELETE/api/blunx/conversations/{uuid}Supprimer une conversation
GET/api/blunx/conversations/{uuid}/messagesMessages d'une conversation
POST/api/blunx/messagesSauvegarder un message (crée la conversation si conversation_uuid nul)
DELETE/api/blunx/messages/{uuid}Supprimer un message
POST/api/blunx/feedbackRetour utilisateur
GET · POST/api/blunx/dashboardsLister / créer un dashboard
GET · DELETE/api/blunx/dashboards/{uuid}Afficher / supprimer un dashboard
POST/api/blunx/widgetsCréer un widget
PATCH · DELETE/api/blunx/widgets/{uuid}Modifier / supprimer un widget
POST/api/blunx/widgets/{uuid}/executeExécuter un widget
GET/api/blunx/insights/{dashUuid}Insights d'un dashboard
GET/api/blunx/insights/{dashUuid}/settingsRéglages d'insights
POST/api/blunx/insights/{uuid}/mark-readMarquer un insight lu
DELETE/api/blunx/insights/{uuid}Supprimer un insight
GET/api/blunx/insights/{uuid}/downloadTélécharger le rapport PDF
POST/api/blunx/insight-settingsCréer / mettre à jour un réglage d'insight
DELETE/api/blunx/insights/jobs/{widgetUuid}Annuler un job d'insight planifié
POST/api/blunx/execute-sqlExécuter une requête stockée sur un message
POST/api/blunx/streamChat SSE : pipeline multi-agents en streaming

Endpoints du serveur Blunx (/api/v1/*)

Middlewares : ValidateBlunxKey (X-Blunx-Key) puis RequireLLMConfig (X-Blunx-LLM-Key + bloc llm dans le body).

EndpointMéthodeFormat réponse
/api/v1/chat/queriesPOSTSSE
/api/v1/chat/validatePOSTSSE
/api/v1/chat/synthesizePOSTSSE
/api/v1/insights/analyzePOSTJSON
/api/v1/insights/reportPOSTJSON
/api/v1/schema/enrichPOSTJSON
/api/v1/reference/generatePOSTJSON

En-têtes communs

En-têtes HTTP
X-Blunx-Key: blunx_app_live_xxxxxxx      # clé d'application (requis)
X-Blunx-LLM-Key: sk-xxxxxxxxxxxxxxxx     # clé du fournisseur LLM (requis)
Content-Type: application/json
Accept: text/event-stream | application/json

Payload de base

Chaque appel au serveur Blunx transporte la connexion BDD et la configuration LLM. Les clés passent par les en-têtes, jamais dans le body (pas de fuite dans les logs).

JSON JSON
{
  "db_connection": "mysql",
  "locale": "fr",
  "currency": { "code": "XOF", "symbol": "FCFA", "locale": "fr_FR" },
  "llm": {
    "driver": "openai",
    "endpoint": "https://api.openai.com/v1",
    "model": "gpt-4o",
    "supports_json_format": true
  }
}

Chat — POST /api/v1/chat/queries

Requête :

JSON JSON
{
  "question": "Quel est le chiffre d'affaires par région ?",
  "conversation_history": [ { "role": "user", "content": "…" } ],
  "access_rules": { "forbidden_tables": [], "forbidden_columns": [], "row_level": [] },
  "schema": "… schéma complet en JSON string (ou schema_id) …",
  "schema_id": "uuid-optionnel",
  "db_connection": "mysql",
  "locale": "fr",
  "currency": { "code": "XOF", "symbol": "FCFA", "locale": "fr_FR" },
  "llm": { "driver": "openai", "endpoint": "…", "model": "…", "supports_json_format": true }
}

Réponse SSE — événement result :

JSON JSON
{
  "needs_data": true,
  "needs_clarification": false,
  "normalized_question": "…",
  "intent": "…",
  "queries": [ { "sql": "SELECT …", "ui_hint": "chart", "chart_type": "bar" } ],
  "warnings": [],
  "filtered_schema_id": "uuid"
}

Cas terminaux : needs_clarification (+ clarification_question), needs_data=false, access_denied (+ message, forbidden_info).

Chat — validate & synthesize

Validate : {normalized_question, intent, execution_results, filtered_schema_id, access_rules, locale, db_connection, llm}{queries[], warnings[]} (SQL corrigés).

Synthesize : {normalized_question, execution_results, conversation_history, needs_data, locale, currency, llm} → réponse structurée :

JSON JSON
{
  "title": "Chiffre d'affaires par région",
  "layout": [
    { "type": "paragraph", "content": "… HTML Bootstrap 5 …" },
    { "type": "chart", "chart_type": "bar", "title": "…", "label_column": "…",
      "data_columns": ["…"], "comment": "…", "sql_query": "…" },
    { "type": "table", "title": "…", "comment": "…", "sql_query": "…" }
  ],
  "Resume": "… résumé markdown …"
}

Si needs_data=false : { "Resume": "…", "is_conversational": true }.

Insights, schéma & références

  • Analyze : {widget_title, sql_query, current_meta, previous_meta?, metric_weights?, locale, currency, llm}{type, severity, message, meta}.
  • Report : {insight_result, current_meta, previous_meta?, last_insight?, widget_title, dashboard_name, report_frequency, locale, currency, llm}{html}.
  • Schema enrich : {columns, locale, llm}{columns} avec descriptions.
  • Reference generate : {widget_sql, widget_title?, numeric_columns[], access_rules?, db_connection, locale, llm}{queries}.

Flux SSE — événements

Flux SSE SSE
event: step
data: {"step":1,"status":"running","duration":1}

event: result
data: { …resultat… }

event: done
data: {"result":{ "title":"…", "Resume":"…", "layout":[…] }, "message_uuid":"…"}

event: error
data: {"message":"…"}
ÉvénementSignification
stepProgression (étapes 1 à 6 : Analyse, Planification, Collecte, Exécution, Validation, Synthèse)
resultRésultat intermédiaire (ex. requêtes générées)
doneFin : réponse finale + message_uuid
errorErreur ({message, code, fields, plan, limit, used})
En-têtes SSE à respecter

Content-Type: text/event-stream; charset=UTF-8, Cache-Control: no-cache, no-store, X-Accel-Buffering: no. Ne bufferisez pas la réponse.

Sécurité & accès

Blunx applique une défense en profondeur sur plusieurs niveaux pour garantir que vos données ne sont jamais modifiées ni exposées au-delà de ce que vous autorisez.

1. Lecture seule stricte (SqlGuard)

Chaque requête SQL est validée localement avant exécution. Les règles sont multiples :

  • La requête doit commencer par SELECT ou WITH (CTE).
  • Mots-clés dangereux interdits : INSERT, UPDATE, DELETE, DROP, ALTER, CREATE, TRUNCATE, GRANT, REVOKE, EXEC, VACUUM, LOCK, COPY, etc.
  • Fonctions dangereuses interdites : pg_sleep, pg_read_file, lo_import, dblink, pg_execute_server_program, set_config, etc.
  • SELECT … INTO interdit.
  • Un sanitize() retire les littéraux chaîne et les commentaires avant analyse (évite les faux positifs sur les valeurs).
Exemple de refus Texte
invalid statement type: INSERT (only SELECT allowed)
forbidden keyword found: DROP
forbidden function call found: pg_sleep
SELECT ... INTO is forbidden ...

Même si une requête était altérée entre la génération et l'exécution, l'agent d'exécution (DataExecutorAgent) re-valide et saute toute requête non-SELECT.

2. Connexion BDD en lecture seule dédiée

C'est le verrou de sécurité principal. Si BLUNX_READONLY_DB_USERNAME est renseigné, le package crée une connexion blunx_readonly (même driver/hôte/base, identifiants dédiés) utilisée pour toutes les exécutions. En base, accordez à ce rôle uniquement GRANT SELECT, USAGE :

SQL (une fois, côté DBA) SQL
-- MySQL
CREATE USER 'blunx_readonly'@'%' IDENTIFIED BY 'mot_de_passe_fort';
GRANT SELECT ON votre_base.* TO 'blunx_readonly'@'%';

-- PostgreSQL
CREATE ROLE blunx_readonly LOGIN PASSWORD 'mot_de_passe_fort';
GRANT CONNECT ON DATABASE votre_base TO blunx_readonly;
GRANT USAGE ON SCHEMA public TO blunx_readonly;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO blunx_readonly;
Recommandé en production

Créez toujours un rôle BDD en lecture seule. Sans cela, le package utilise la connexion principale de Laravel — les garde-fous SqlGuard restent actifs, mais un rôle dédié ajoute une protection au niveau de la base elle-même.

3. Règles d'accès par rôle (RBAC)

Le fichier config/blunx_access.php définit, par rôle, les tables et colonnes interdites et le filtrage par ligne. Voir la section Configuration pour la syntaxe complète. Le rôle provient de getUserRoleName() sur votre modèle User.

  • Tables interdites : jamais scannées ni exposées au LLM.
  • Colonnes interdites : masquées (motif '*' = toutes les tables).
  • Filtrage par ligne : le placeholder USER_ID est remplacé par l'ID de l'utilisateur connecté (ex. un vendeur ne voit que orders.user_id = lui-même).

4. Authentification

ContexteMécanisme
Web SDK → package LaravelCookie de session Laravel (middleware auth du groupe blunx)
Web SDK → package Node.jsUtilisateur authentifié de l'app hôte (req.user / ctx.state.user) — le routeur renvoie 401 s'il est absent
SDK backend → Serveur BlunxEn-têtes X-Blunx-Key (clé app) + X-Blunx-LLM-Key (clé LLM)

En cross-origin, le backend doit accepter credentials: include (Access-Control-Allow-Credentials + origine explicite, pas *) et les en-têtes Accept, Content-Type, X-Requested-With (préflight CORS).

5. Autres protections

  • Rate limiting : 60 requêtes/min/IP sur le groupe local /api/blunx/* (throttle Laravel ; en Node, ajoutez votre rate limiter, ex. express-rate-limit), sauf webhook Stripe (non concerné ici).
  • Validation SQL : double vérification (client + serveur), une requête non-SELECT n'est jamais exécutée.
  • Schéma PostgreSQL : le scan ne touche que le schéma configuré (BLUNX_PGSQL_SCHEMA), jamais les autres.
  • CSRF : le groupe blunx reproduit web sans CSRF (l'auth par session suffit pour cette API AJAX).

Fournisseurs LLM

Choisissez votre fournisseur via le driver et l'endpoint. L'adaptateur openai est « compatible OpenAI » : il fonctionne avec la quasi-totalité des fournisseurs, propriétaires comme open-source.

Le driver openai n'est pas réservé à OpenAI

L'adaptateur openai ne fait aucune hypothèse sur l'hôte : il POSTe exactement à l'URL fournie dans llm.endpoint, au format standard chat/completions. C'est un adaptateur « compatible OpenAI », pas « OpenAI uniquement ». Or la quasi-totalité des fournisseurs actuels — propriétaires ET open-source — exposent cette API compatible.

Tableau des fournisseurs

FournisseurDriverEndpoint (à mettre dans BLUNX_LLM_ENDPOINT)
OpenAIopenaihttps://api.openai.com/v1
Azure OpenAIopenaihttps://{ressource}.openai.azure.com/openai/v1
Ollama (local)openaihttp://localhost:11434/v1
Groqopenaihttps://api.groq.com/openai/v1
DeepSeekopenaihttps://api.deepseek.com/v1
Mistralopenaihttps://api.mistral.ai/v1
Together, Fireworks, OpenRouter…openaiURL compatible OpenAI du fournisseur
vLLM, LM Studio, llama.cppopenaiURL locale / self-hosted (ex. http://localhost:8000/v1)
Anthropic Claudeanthropichttps://api.anthropic.com/v1/messages (format natif)
Google Geminigeminihttps://generativelanguage.googleapis.com (format natif generateContent)

Configurer un fournisseur

Exemple : DeepSeek (API compatible OpenAI)

.env Env
BLUNX_LLM_DRIVER=openai
BLUNX_LLM_ENDPOINT=https://api.deepseek.com/v1
BLUNX_LLM_MODEL=deepseek-chat
BLUNX_LLM_API_KEY=sk-xxxxxxxxxxxx
BLUNX_LLM_SUPPORTS_JSON_FORMAT=true

Exemple : Ollama en local (zéro dépendance cloud)

.env Env
BLUNX_LLM_DRIVER=openai
BLUNX_LLM_ENDPOINT=http://localhost:11434/v1
BLUNX_LLM_MODEL=llama3.1
BLUNX_LLM_API_KEY=ollama          # valeur non utilisée, peut rester vide
BLUNX_LLM_SUPPORTS_JSON_FORMAT=true

Exemple : Groq

.env Env
BLUNX_LLM_DRIVER=openai
BLUNX_LLM_ENDPOINT=https://api.groq.com/openai/v1
BLUNX_LLM_MODEL=llama-3.3-70b-versatile
BLUNX_LLM_API_KEY=gsk_xxxxxxxxxxxx
BLUNX_LLM_SUPPORTS_JSON_FORMAT=true

Détail des drivers

DriverFormatRemarques
openai POST {endpoint}/chat/completions Compatible OpenAI + tous les fournisseurs cités ci-dessus. endpoint peut inclure ou non le suffixe /chat/completions.
anthropic POST /v1/messages (format natif) Anthropic Claude. Endpoint natif, headers Anthropic.
gemini generateContent (format natif) Google Gemini. Endpoint natif Google.

supports_json_format

Indique si le modèle gère le mode response_format: json_object. Les modèles modernes (GPT-4o, DeepSeek, Groq…) le supportent (true) ; certains modèles locaux plus anciens non. Si le modèle ne le supporte pas, mettez false pour que le pipeline demande le JSON en langage naturel plutôt qu'en mode structuré.

Recommandations de robustesse

Pour un usage en production, préférez un modèle fiable en sortie JSON (supports_json_format=true) et un endpoint à faible latence. Le pipeline gère un retry automatique en cas de réponse LLM vide ou d'échec transitoire.

Erreurs & dépannage

Organisé par niveau : serveur Blunx (HTTP), backend (Laravel / Node), SSE et Web SDK. Cherchez d'abord le code HTTP, puis le niveau concerné.

1 · Codes HTTP du serveur Blunx

Communs aux deux backends — renvoyés par le hub /api/v1/* :

CodeSignificationDéclencheur / action
400Bad RequestJSON invalide. Vérifiez le corps de la requête.
401UnauthorizedClé manquante/invalide (missing_key / invalid_key). Vérifiez BLUNX_API_KEY.
402Payment RequiredAbonnement inactif/expiré (billing_inactive). Consultez votre facturation.
403ForbiddenApplication suspendue/inactive (frozen). Contactez le support.
404Not FoundSCHEMA_NOT_FOUND → le package vide le cache et réessaie sans schema_id.
413Payload Too LargeBody trop volumineux. Réduisez le schéma envoyé.
422Unprocessable EntityValidation / config LLM manquante (missing_llm_config, invalid_llm_driver).
429Too Many RequestsQuota dépassé (plan, limit, used). Attendez ou augmentez votre plan.
500Internal Server ErrorErreur LLM côté serveur Blunx. Réessayez, vérifiez votre clé LLM.

2 · Backend

Les deux SDK lèvent une exception avec un message humain (le message du serveur prime s'il existe) :

Mapping du BlunxApiClient (PHP) :

Mapping client PHP
401 => "Invalid or expired API key"
402 => "Billing inactive. Please check your subscription."
403 => "Application suspended. Contact support."
429 => "Quota exceeded. Please wait before retrying."
422 => "LLM configuration missing. Check your settings."
default => "AI service error. Please try again later."

Le BlunxError (JS) porte un message et un statusCode — même mapping que Laravel :

BlunxError JavaScript
try {
  await blunx.api.someCall();
} catch (e) {
  if (e instanceof BlunxError) {
    console.error(e.statusCode, e.message); // ex. 401 "Invalid or expired API key"
  }
}

3 · Erreurs SSE

  • Événement error : {message, code, fields, plan, limit, used}.
  • HTTP ≥ 400 : extraction de message / error / detail.
  • Erreur réseau : cURL error: … (PHP) / fetch failed (Node).
  • SCHEMA_NOT_FOUND : retry automatique sans schema_id.

4 · Erreurs du Web SDK

CasComportement
Conteneur introuvableinit() rejette : [Blunx] Conteneur introuvable : "#blunx"
view:'dashboard' sans UUID[Blunx] Vue dashboard sans UUID.
Réponse HTTP non-OK (API)Erreur HTTP {status}: {statusText} (ou message du body)
Échec streamServer error (HTTP {status}) / Unknown error / Connection failed
Dépendance CDN en échecconsole.warn non bloquant

5 · Erreurs fréquentes à l'intégration

SymptômeCause probableSolution
401 au premier appelClé BLUNX_API_KEY manquante/invalideVérifiez le .env et config:clear (Laravel).
422 / missing_llm_configLLM incomplet (endpoint, modèle, clé)Complétez les 4 variables LLM (voir Configuration).
401 sur /api/blunx/* (Node)req.user non rempliVotre middleware d'auth doit s'exécuter avant blunxExpress.
Listes vides en réponseRequête non authentifiée (Node) ou user_id absentAuthentifiez l'utilisateur avant le routeur Blunx.
SCHEMA_NOT_FOUNDSchéma non envoyé au hubRelancez blunx:init / blunx-ai init.

Versions & mises à jour

Politique de versioning du Web SDK et mise à jour du SDK backend.

Politique de versioning

Le Web SDK suit le versioning sémantique (MAJEUR.MINEUR.CORRECTIF) :

  • Correctif : bugfix sans rupture (aucune action requise).
  • Mineur : nouvelle fonctionnalité rétro-compatible.
  • Majeur : rupture (API publique, contrat REST, navigation).

Mises à jour du Web SDK

Mode d'intégrationComportement de mise à jour
Loader auto-update (blunx-loader.min.js) Résout ./blunx.min.js relatif à lui-même : servi depuis jsDelivr « latest », il est toujours à la même version que le loader. Aucune action requise de votre part.
Bundle direct (blunx.min.js) Vous épinglez la version. Pour mettre à jour, changez l'URL ou ajoutez ?v=.
npm (@blunx/web-sdk) Épinglez la version (^0.1.0) et exécutez npm update.
Cache-busting du loader

Sur CDN, le loader ajoute ?v={version} (le CDN purge au release). En local/auto-hébergé, il ajoute un horodatage : vous servez toujours le dernier build sans vider le cache navigateur.

Changelog du Web SDK

VersionDatePoints clés
0.1.0 7 août 2026 Refonte en projet autonome ; API publique init/destroy/navigate/version ; routage par hash ; build esbuild 3 cibles ; loader auto-update ; dépendances auto-injectées ; CSS + logo embarqués ; config par options ; traductions embarquées ; isolation CSS .blunx-root ; démo PHP mock complète.

Package Laravel

  • Mettez à jour avec composer update blunx/ai.
  • Vérifiez la version : composer show blunx/ai.
  • Après mise à jour majeure, revérifiez config/blunx.php publié (le fichier publié n'est pas écrasé automatiquement).
Config publiée vs config du package

Après une mise à jour majeure, comparez config/blunx.php avec la version publiée du package (vendor/blunx/ai/config/blunx.php) et reportez les nouvelles clés si nécessaire.

Support

Un problème non résolu par cette documentation ? L'équipe Blunx vous répond sous 24 h.

CanalDétail
Formulaire de contact/contact — sujet « Intégration technique » recommandé pour les questions d'implémentation
Retours produitLe module feedback de l'application (thumbs + commentaire) remonte directement à l'équipe
Signalement de bugDécrivez : version SDK (info.version), version Laravel/PHP, étapes de reproduction, code d'erreur HTTP/SSE
Préparer une demande d'aide efficace

Joignez systématiquement : le message d'erreur exact (code HTTP + body), votre bloc llm (sans la clé), le résultat de composer show blunx/ai et, si pertinent, les logs de votre file d'attente.

Licence : MIT — © 2026 BlunxAI. Package Laravel : blunx/ai · Web SDK : @blunx/web-sdk.