@lastbrain/module-ai 0.1.8 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -442
- package/dist/ai.build.config.d.ts.map +1 -1
- package/dist/ai.build.config.js +24 -6
- package/dist/api/admin/user-token/[id].d.ts +6 -1
- package/dist/api/admin/user-token/[id].d.ts.map +1 -1
- package/dist/api/admin/user-token/[id].js +16 -14
- package/dist/api/admin/user-token.d.ts +19 -3
- package/dist/api/admin/user-token.d.ts.map +1 -1
- package/dist/api/admin/user-token.js +85 -26
- package/dist/api/auth/generate-text.js +1 -1
- package/dist/api/auth/user-tokens.d.ts +17 -0
- package/dist/api/auth/user-tokens.d.ts.map +1 -0
- package/dist/api/auth/user-tokens.js +34 -0
- package/dist/components/Doc.d.ts +8 -1
- package/dist/components/Doc.d.ts.map +1 -1
- package/dist/components/Doc.js +17 -3
- package/dist/components/DocUsageCustom.d.ts +9 -0
- package/dist/components/DocUsageCustom.d.ts.map +1 -0
- package/dist/components/DocUsageCustom.js +70 -0
- package/dist/components/admin/UserTokenTab.d.ts +6 -0
- package/dist/components/admin/UserTokenTab.d.ts.map +1 -0
- package/dist/components/admin/UserTokenTab.js +112 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/web/admin/UserTokenPage.d.ts.map +1 -1
- package/dist/web/admin/UserTokenPage.js +103 -2
- package/dist/web/auth/TokenPage.d.ts.map +1 -1
- package/dist/web/auth/TokenPage.js +110 -2
- package/dist/web/components/ImageGenerative.d.ts +6 -3
- package/dist/web/components/ImageGenerative.d.ts.map +1 -1
- package/dist/web/components/ImageGenerative.js +51 -12
- package/dist/web/components/TextareaGenerative.d.ts +5 -3
- package/dist/web/components/TextareaGenerative.d.ts.map +1 -1
- package/dist/web/components/TextareaGenerative.js +33 -12
- package/package.json +4 -4
- package/supabase/migrations-down/20251125000000_ai_tokens.sql +45 -0
- package/supabase/migrations/20251121093113_module-ai_init.sql +0 -122
- package/supabase/migrations-down/20251121000000_ai_tokens.sql +0 -23
- package/supabase/migrations-down/20251121093113_module-ai_init.sql +0 -11
- /package/supabase/migrations/{20251121000000_ai_tokens.sql → 20251125000000_ai_tokens.sql} +0 -0
package/README.md
CHANGED
|
@@ -1,481 +1,88 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 📦 Module ai
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> @lastbrain/module-ai
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## 📋 Informations
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- **Nom du package**: `@lastbrain/module-ai`
|
|
8
|
+
- **Slug**: `module-ai`
|
|
9
|
+
- **Type**: Module LastBrain
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
- 🎨 **Génération d'images** - Intégration DALL-E pour créer des images
|
|
11
|
-
- 💳 **Gestion de tokens** - Système de crédits et suivi de consommation
|
|
12
|
-
- 📊 **Dashboard admin** - Gestion des tokens utilisateurs par les admins
|
|
13
|
-
- 🛡️ **Sécurité** - Protection RLS et contrôle d'accès
|
|
11
|
+
## 📄 Pages Disponibles
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
### Pages Protégées (Auth)
|
|
16
14
|
|
|
17
|
-
|
|
15
|
+
- **GET** `/token` - TokenPage
|
|
18
16
|
|
|
19
|
-
|
|
20
|
-
# Créer une nouvelle application avec le module AI inclus
|
|
21
|
-
pnpx @lastbrain/app@latest init mon-app
|
|
22
|
-
# Sélectionner "🤖 AI Generation" lors de la création
|
|
23
|
-
|
|
24
|
-
cd mon-app
|
|
25
|
-
pnpm db:init # Applique automatiquement les migrations
|
|
26
|
-
pnpm dev
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
## 📦 Installation manuelle
|
|
30
|
-
|
|
31
|
-
Si vous intégrez LastBrain dans un projet existant :
|
|
32
|
-
|
|
33
|
-
```bash
|
|
34
|
-
pnpm add @lastbrain/module-ai @lastbrain/core @lastbrain/ui
|
|
35
|
-
```
|
|
17
|
+
### Pages Admin
|
|
36
18
|
|
|
37
|
-
|
|
19
|
+
- **GET** `/user-token` - UserTokenPage
|
|
38
20
|
|
|
39
|
-
|
|
40
|
-
pnpm lastbrain add-module ai
|
|
41
|
-
pnpm build:modules
|
|
42
|
-
```
|
|
21
|
+
## 🗄️ Base de Données
|
|
43
22
|
|
|
44
|
-
|
|
23
|
+
### Tables
|
|
45
24
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
```bash
|
|
49
|
-
# .env.local
|
|
50
|
-
OPENAI_API_KEY=sk-your-openai-api-key-here
|
|
51
|
-
|
|
52
|
-
# Supabase (requis)
|
|
53
|
-
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
|
|
54
|
-
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
|
|
55
|
-
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
### Configuration OpenAI
|
|
59
|
-
|
|
60
|
-
Le module utilise les modèles OpenAI suivants par défaut :
|
|
61
|
-
|
|
62
|
-
- **Texte** : `gpt-4o` (ou `gpt-4o-mini` pour les tâches simples)
|
|
63
|
-
- **Images** : `dall-e-3` (ou `dall-e-2` pour des coûts réduits)
|
|
64
|
-
|
|
65
|
-
## 🖼️ Pages Web fournies
|
|
66
|
-
|
|
67
|
-
### Pages Utilisateur Authentifié
|
|
68
|
-
|
|
69
|
-
#### 1. Gestion des Tokens (`/auth/ai/token`)
|
|
70
|
-
|
|
71
|
-
**Component**: `TokenPage`
|
|
72
|
-
|
|
73
|
-
Page de gestion des tokens utilisateur :
|
|
74
|
-
|
|
75
|
-
- Solde actuel de tokens
|
|
76
|
-
- Historique des transactions
|
|
77
|
-
- Bouton pour acheter des tokens (placeholder)
|
|
78
|
-
- Statistiques d'utilisation
|
|
25
|
+
#### `user_token_ledger`
|
|
79
26
|
|
|
80
27
|
```tsx
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
28
|
+
<TableStructure
|
|
29
|
+
tableName="user_token_ledger"
|
|
30
|
+
title="user_token_ledger"
|
|
31
|
+
description="Table user_token_ledger du module ai"
|
|
32
|
+
/>
|
|
86
33
|
```
|
|
87
34
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
#### 2. Administration des Tokens (`/admin/ai/user-token`)
|
|
91
|
-
|
|
92
|
-
**Component**: `AdminUserTokenPage`
|
|
93
|
-
|
|
94
|
-
Page d'administration pour gérer les tokens de tous les utilisateurs :
|
|
95
|
-
|
|
96
|
-
- Liste de tous les utilisateurs avec leurs soldes
|
|
97
|
-
- Recherche par email ou nom
|
|
98
|
-
- Ajout/retrait de tokens pour un utilisateur
|
|
99
|
-
- Pagination et tri
|
|
35
|
+
#### `user_prompts`
|
|
100
36
|
|
|
101
37
|
```tsx
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
#### 3. Détail Utilisateur (`/admin/ai/user-token/[id]`)
|
|
110
|
-
|
|
111
|
-
**Component**: `AdminUserTokenDetailPage`
|
|
112
|
-
|
|
113
|
-
Page détaillée pour un utilisateur spécifique :
|
|
114
|
-
|
|
115
|
-
- Historique complet des transactions
|
|
116
|
-
- Ajout/retrait de tokens avec commentaire
|
|
117
|
-
- Statistiques d'utilisation détaillées
|
|
118
|
-
|
|
119
|
-
```tsx
|
|
120
|
-
import { AdminUserTokenDetailPage } from "@lastbrain/module-ai";
|
|
121
|
-
|
|
122
|
-
export default function AdminUserDetail() {
|
|
123
|
-
return <AdminUserTokenDetailPage />;
|
|
124
|
-
}
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
## 🔌 Routes API
|
|
128
|
-
|
|
129
|
-
### API Génération IA (`/api/ai/*`)
|
|
130
|
-
|
|
131
|
-
#### POST `/api/ai/generate-text`
|
|
132
|
-
|
|
133
|
-
Génère du texte avec GPT.
|
|
134
|
-
|
|
135
|
-
**Body** :
|
|
136
|
-
|
|
137
|
-
```json
|
|
138
|
-
{
|
|
139
|
-
"prompt": "Écris un article sur l'IA",
|
|
140
|
-
"model": "gpt-4o", // optionnel, défaut: gpt-4o
|
|
141
|
-
"max_tokens": 1000, // optionnel, défaut: 500
|
|
142
|
-
"temperature": 0.7, // optionnel, défaut: 0.7
|
|
143
|
-
"cost_tokens": 100 // coût en tokens pour cette génération
|
|
144
|
-
}
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
**Réponse** :
|
|
148
|
-
|
|
149
|
-
```json
|
|
150
|
-
{
|
|
151
|
-
"data": {
|
|
152
|
-
"text": "L'intelligence artificielle...",
|
|
153
|
-
"tokens_used": 95,
|
|
154
|
-
"model": "gpt-4o",
|
|
155
|
-
"cost_tokens": 100,
|
|
156
|
-
"remaining_tokens": 900
|
|
157
|
-
}
|
|
158
|
-
}
|
|
38
|
+
<TableStructure
|
|
39
|
+
tableName="user_prompts"
|
|
40
|
+
title="user_prompts"
|
|
41
|
+
description="Table user_prompts du module ai"
|
|
42
|
+
/>
|
|
159
43
|
```
|
|
160
44
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
Génère une image avec DALL-E.
|
|
164
|
-
|
|
165
|
-
**Body** :
|
|
166
|
-
|
|
167
|
-
```json
|
|
168
|
-
{
|
|
169
|
-
"prompt": "Un chat en costume d'astronaute",
|
|
170
|
-
"model": "dall-e-3", // optionnel, défaut: dall-e-3
|
|
171
|
-
"size": "1024x1024", // optionnel, défaut: 1024x1024
|
|
172
|
-
"quality": "hd", // optionnel, défaut: standard
|
|
173
|
-
"cost_tokens": 200 // coût en tokens pour cette génération
|
|
174
|
-
}
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
**Réponse** :
|
|
178
|
-
|
|
179
|
-
```json
|
|
180
|
-
{
|
|
181
|
-
"data": {
|
|
182
|
-
"image_url": "https://...",
|
|
183
|
-
"revised_prompt": "A cat wearing an astronaut suit...",
|
|
184
|
-
"model": "dall-e-3",
|
|
185
|
-
"cost_tokens": 200,
|
|
186
|
-
"remaining_tokens": 800
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
### API Administration (`/api/ai/admin/*`)
|
|
192
|
-
|
|
193
|
-
⚠️ **Toutes les routes admin nécessitent un accès super admin.**
|
|
194
|
-
|
|
195
|
-
#### GET `/api/ai/admin/user-token`
|
|
196
|
-
|
|
197
|
-
Liste tous les utilisateurs avec leurs soldes de tokens.
|
|
45
|
+
### Migrations
|
|
198
46
|
|
|
199
|
-
|
|
47
|
+
- `20251125000000_ai_tokens.sql`
|
|
200
48
|
|
|
201
|
-
|
|
202
|
-
- `per_page` (optionnel, défaut: 20)
|
|
203
|
-
- `search` (optionnel) : Recherche par email ou nom
|
|
49
|
+
## 📦 Installation
|
|
204
50
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
{
|
|
209
|
-
"data": [
|
|
210
|
-
{
|
|
211
|
-
"user_id": "uuid",
|
|
212
|
-
"email": "user@example.com",
|
|
213
|
-
"full_name": "John Doe",
|
|
214
|
-
"balance": 1500,
|
|
215
|
-
"total_spent": 500,
|
|
216
|
-
"last_transaction": "2024-01-01T00:00:00Z"
|
|
217
|
-
}
|
|
218
|
-
],
|
|
219
|
-
"pagination": {
|
|
220
|
-
"page": 1,
|
|
221
|
-
"per_page": 20,
|
|
222
|
-
"total": 100,
|
|
223
|
-
"total_pages": 5
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
#### POST `/api/ai/admin/user-token`
|
|
229
|
-
|
|
230
|
-
Ajoute ou retire des tokens pour un utilisateur.
|
|
231
|
-
|
|
232
|
-
**Body** :
|
|
233
|
-
|
|
234
|
-
```json
|
|
235
|
-
{
|
|
236
|
-
"user_id": "uuid",
|
|
237
|
-
"amount": 1000, // positif pour ajouter, négatif pour retirer
|
|
238
|
-
"description": "Achat de tokens premium",
|
|
239
|
-
"transaction_type": "purchase" // purchase, admin_grant, admin_debit, etc.
|
|
240
|
-
}
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
#### GET `/api/ai/admin/user-token/[id]`
|
|
244
|
-
|
|
245
|
-
Détails et historique pour un utilisateur spécifique.
|
|
246
|
-
|
|
247
|
-
**Réponse** :
|
|
248
|
-
|
|
249
|
-
```json
|
|
250
|
-
{
|
|
251
|
-
"data": {
|
|
252
|
-
"user": {
|
|
253
|
-
"id": "uuid",
|
|
254
|
-
"email": "user@example.com",
|
|
255
|
-
"full_name": "John Doe",
|
|
256
|
-
"balance": 1500
|
|
257
|
-
},
|
|
258
|
-
"transactions": [
|
|
259
|
-
{
|
|
260
|
-
"id": "uuid",
|
|
261
|
-
"amount": 1000,
|
|
262
|
-
"description": "Achat de tokens",
|
|
263
|
-
"transaction_type": "purchase",
|
|
264
|
-
"created_at": "2024-01-01T00:00:00Z"
|
|
265
|
-
}
|
|
266
|
-
],
|
|
267
|
-
"stats": {
|
|
268
|
-
"total_spent": 500,
|
|
269
|
-
"total_generated_texts": 25,
|
|
270
|
-
"total_generated_images": 10
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
## 🗄️ Schéma de Base de Données
|
|
277
|
-
|
|
278
|
-
### Table `user_token_ledger`
|
|
279
|
-
|
|
280
|
-
Stocke les transactions de tokens des utilisateurs.
|
|
281
|
-
|
|
282
|
-
```sql
|
|
283
|
-
CREATE TABLE public.user_token_ledger (
|
|
284
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
285
|
-
owner_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
|
|
286
|
-
amount INTEGER NOT NULL,
|
|
287
|
-
balance_after INTEGER NOT NULL,
|
|
288
|
-
description TEXT,
|
|
289
|
-
transaction_type TEXT NOT NULL DEFAULT 'usage',
|
|
290
|
-
metadata JSONB DEFAULT '{}'::jsonb,
|
|
291
|
-
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
292
|
-
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
293
|
-
);
|
|
51
|
+
```bash
|
|
52
|
+
pnpm lastbrain add-module ai
|
|
53
|
+
pnpm build:modules
|
|
294
54
|
```
|
|
295
55
|
|
|
296
|
-
|
|
56
|
+
### Appliquer les migrations
|
|
297
57
|
|
|
298
|
-
|
|
299
|
-
-
|
|
300
|
-
|
|
301
|
-
- `admin_debit` : Retrait par un admin
|
|
302
|
-
- `refund` : Remboursement
|
|
303
|
-
|
|
304
|
-
### Table `user_prompts`
|
|
305
|
-
|
|
306
|
-
Stocke l'historique des prompts et générations.
|
|
307
|
-
|
|
308
|
-
```sql
|
|
309
|
-
CREATE TABLE public.user_prompts (
|
|
310
|
-
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
311
|
-
owner_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
|
|
312
|
-
prompt TEXT NOT NULL,
|
|
313
|
-
response TEXT,
|
|
314
|
-
model TEXT NOT NULL,
|
|
315
|
-
tokens_used INTEGER,
|
|
316
|
-
cost_tokens INTEGER,
|
|
317
|
-
generation_type TEXT NOT NULL, -- 'text' ou 'image'
|
|
318
|
-
metadata JSONB DEFAULT '{}'::jsonb,
|
|
319
|
-
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
320
|
-
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
321
|
-
);
|
|
58
|
+
```bash
|
|
59
|
+
cd apps/votre-app
|
|
60
|
+
supabase migration up
|
|
322
61
|
```
|
|
323
62
|
|
|
324
|
-
|
|
63
|
+
## 💡 Utilisation
|
|
325
64
|
|
|
326
|
-
|
|
65
|
+
<!-- 📝 Section à compléter par l'auteur du module -->
|
|
327
66
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
```sql
|
|
331
|
-
CREATE VIEW user_token_balance_v AS
|
|
332
|
-
SELECT
|
|
333
|
-
owner_id,
|
|
334
|
-
COALESCE(SUM(amount), 0) as balance,
|
|
335
|
-
COUNT(*) as total_transactions,
|
|
336
|
-
MAX(created_at) as last_transaction
|
|
337
|
-
FROM user_token_ledger
|
|
338
|
-
GROUP BY owner_id;
|
|
339
|
-
```
|
|
340
|
-
|
|
341
|
-
## 🔧 Utilisation dans le Code
|
|
342
|
-
|
|
343
|
-
### Hooks React
|
|
67
|
+
### Exemple d'utilisation
|
|
344
68
|
|
|
345
69
|
```tsx
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
function MyAIComponent() {
|
|
349
|
-
const { balance, loading, refetch } = useTokenBalance();
|
|
350
|
-
const { generateText, generating } = useAIGeneration();
|
|
351
|
-
|
|
352
|
-
const handleGenerate = async () => {
|
|
353
|
-
const result = await generateText({
|
|
354
|
-
prompt: "Écris un poème sur l'automne",
|
|
355
|
-
max_tokens: 200,
|
|
356
|
-
cost_tokens: 50,
|
|
357
|
-
});
|
|
358
|
-
|
|
359
|
-
if (result.success) {
|
|
360
|
-
console.log("Texte généré:", result.data.text);
|
|
361
|
-
refetch(); // Rafraîchir le solde
|
|
362
|
-
}
|
|
363
|
-
};
|
|
364
|
-
|
|
365
|
-
return (
|
|
366
|
-
<div>
|
|
367
|
-
<p>Solde: {balance} tokens</p>
|
|
368
|
-
<Button onPress={handleGenerate} isLoading={generating}>
|
|
369
|
-
Générer du texte
|
|
370
|
-
</Button>
|
|
371
|
-
</div>
|
|
372
|
-
);
|
|
373
|
-
}
|
|
374
|
-
```
|
|
375
|
-
|
|
376
|
-
### Utilisation directe des APIs
|
|
377
|
-
|
|
378
|
-
```typescript
|
|
379
|
-
// Génération de texte
|
|
380
|
-
const response = await fetch("/api/ai/generate-text", {
|
|
381
|
-
method: "POST",
|
|
382
|
-
headers: { "Content-Type": "application/json" },
|
|
383
|
-
body: JSON.stringify({
|
|
384
|
-
prompt: "Explique l'intelligence artificielle",
|
|
385
|
-
max_tokens: 500,
|
|
386
|
-
cost_tokens: 100,
|
|
387
|
-
}),
|
|
388
|
-
});
|
|
389
|
-
|
|
390
|
-
const result = await response.json();
|
|
391
|
-
console.log(result.data.text);
|
|
392
|
-
|
|
393
|
-
// Génération d'image
|
|
394
|
-
const imageResponse = await fetch("/api/ai/generate-image", {
|
|
395
|
-
method: "POST",
|
|
396
|
-
headers: { "Content-Type": "application/json" },
|
|
397
|
-
body: JSON.stringify({
|
|
398
|
-
prompt: "Un paysage futuriste",
|
|
399
|
-
size: "1024x1024",
|
|
400
|
-
cost_tokens: 200,
|
|
401
|
-
}),
|
|
402
|
-
});
|
|
403
|
-
|
|
404
|
-
const imageResult = await imageResponse.json();
|
|
405
|
-
console.log(imageResult.data.image_url);
|
|
406
|
-
```
|
|
407
|
-
|
|
408
|
-
## 💳 Système de Tokens
|
|
409
|
-
|
|
410
|
-
### Coûts par défaut
|
|
411
|
-
|
|
412
|
-
Les coûts en tokens sont configurables mais voici les valeurs par défaut :
|
|
413
|
-
|
|
414
|
-
**Génération de texte** :
|
|
415
|
-
|
|
416
|
-
- GPT-4o : 1 token = ~10 tokens OpenAI
|
|
417
|
-
- GPT-4o-mini : 1 token = ~5 tokens OpenAI
|
|
418
|
-
|
|
419
|
-
**Génération d'images** :
|
|
420
|
-
|
|
421
|
-
- DALL-E 3 (1024x1024) : 200 tokens
|
|
422
|
-
- DALL-E 2 (1024x1024) : 100 tokens
|
|
423
|
-
|
|
424
|
-
### Gestion du solde
|
|
425
|
-
|
|
426
|
-
```typescript
|
|
427
|
-
// Vérifier le solde avant génération
|
|
428
|
-
const checkBalance = async (requiredTokens: number) => {
|
|
429
|
-
const response = await fetch("/api/ai/user/balance");
|
|
430
|
-
const { balance } = await response.json();
|
|
431
|
-
|
|
432
|
-
if (balance < requiredTokens) {
|
|
433
|
-
throw new Error("Solde insuffisant");
|
|
434
|
-
}
|
|
435
|
-
};
|
|
70
|
+
// Importez les composants depuis le module
|
|
71
|
+
import { TokenPage } from "@lastbrain/module-ai";
|
|
436
72
|
|
|
437
|
-
//
|
|
438
|
-
|
|
439
|
-
prompt: "...",
|
|
440
|
-
cost_tokens: 100, // Sera automatiquement débité
|
|
441
|
-
});
|
|
73
|
+
// Utilisez-les dans votre application
|
|
74
|
+
<TokenPage />;
|
|
442
75
|
```
|
|
443
76
|
|
|
444
|
-
|
|
77
|
+
### Configuration
|
|
445
78
|
|
|
446
|
-
|
|
79
|
+
<!-- Ajoutez ici les détails de configuration spécifiques -->
|
|
447
80
|
|
|
448
|
-
|
|
449
|
-
- **Validation des prompts** : Filtrage du contenu inapproprié
|
|
450
|
-
- **Vérification du solde** : Impossible de générer sans tokens suffisants
|
|
81
|
+
## ⚠️ Danger Zone
|
|
451
82
|
|
|
452
|
-
|
|
83
|
+
La suppression du module supprimera toutes les pages, routes API et migrations associées. **Cette action est irréversible.**
|
|
453
84
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
### Exemple de politique RLS
|
|
458
|
-
|
|
459
|
-
```sql
|
|
460
|
-
-- Les utilisateurs ne voient que leurs propres transactions
|
|
461
|
-
CREATE POLICY "user_token_ledger_owner_select" ON public.user_token_ledger
|
|
462
|
-
FOR SELECT USING (auth.uid() = owner_id);
|
|
463
|
-
|
|
464
|
-
-- Seuls les admins peuvent modifier via les APIs admin
|
|
465
|
-
CREATE POLICY "user_token_ledger_admin_all" ON public.user_token_ledger
|
|
466
|
-
FOR ALL USING (public.is_superadmin(auth.uid()));
|
|
85
|
+
```bash
|
|
86
|
+
pnpm lastbrain remove-module ai
|
|
87
|
+
pnpm build:modules
|
|
467
88
|
```
|
|
468
|
-
|
|
469
|
-
## 🤝 Contribuer
|
|
470
|
-
|
|
471
|
-
Ce package fait partie du monorepo LastBrain. Voir le [CONTRIBUTING.md](../../CONTRIBUTING.md) principal.
|
|
472
|
-
|
|
473
|
-
## 📄 Licence
|
|
474
|
-
|
|
475
|
-
MIT - Voir [LICENSE](../../LICENSE)
|
|
476
|
-
|
|
477
|
-
## 🔗 Liens utiles
|
|
478
|
-
|
|
479
|
-
- [OpenAI API Documentation](https://platform.openai.com/docs/api-reference)
|
|
480
|
-
- [DALL-E Guide](https://platform.openai.com/docs/guides/images)
|
|
481
|
-
- [GPT-4 Documentation](https://platform.openai.com/docs/models/gpt-4)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai.build.config.d.ts","sourceRoot":"","sources":["../src/ai.build.config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,QAAA,MAAM,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"ai.build.config.d.ts","sourceRoot":"","sources":["../src/ai.build.config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,QAAA,MAAM,WAAW,EAAE,iBAsGlB,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
package/dist/ai.build.config.js
CHANGED
|
@@ -11,11 +11,6 @@ const buildConfig = {
|
|
|
11
11
|
path: "/user-token",
|
|
12
12
|
componentExport: "UserTokenPage",
|
|
13
13
|
},
|
|
14
|
-
{
|
|
15
|
-
section: "admin",
|
|
16
|
-
path: "/user-token/[id]",
|
|
17
|
-
componentExport: "UserTokenIdPage",
|
|
18
|
-
},
|
|
19
14
|
],
|
|
20
15
|
apis: [
|
|
21
16
|
// Routes de génération IA
|
|
@@ -33,6 +28,14 @@ const buildConfig = {
|
|
|
33
28
|
entryPoint: "api/auth/generate-image",
|
|
34
29
|
authRequired: true,
|
|
35
30
|
},
|
|
31
|
+
// Route utilisateur pour les tokens
|
|
32
|
+
{
|
|
33
|
+
method: "GET",
|
|
34
|
+
path: "/api/ai/user/tokens",
|
|
35
|
+
handlerExport: "GET",
|
|
36
|
+
entryPoint: "api/auth/user-tokens",
|
|
37
|
+
authRequired: true,
|
|
38
|
+
},
|
|
36
39
|
// Routes admin pour la gestion des tokens
|
|
37
40
|
{
|
|
38
41
|
method: "GET",
|
|
@@ -60,7 +63,8 @@ const buildConfig = {
|
|
|
60
63
|
enabled: true,
|
|
61
64
|
priority: 30,
|
|
62
65
|
path: "supabase/migrations",
|
|
63
|
-
files: ["
|
|
66
|
+
files: ["20251125000000_ai_tokens.sql"],
|
|
67
|
+
migrationsDownPath: "supabase/migrations-down",
|
|
64
68
|
},
|
|
65
69
|
menu: {
|
|
66
70
|
auth: [
|
|
@@ -70,6 +74,8 @@ const buildConfig = {
|
|
|
70
74
|
icon: "Coins",
|
|
71
75
|
path: "/auth/ai/token",
|
|
72
76
|
order: 100,
|
|
77
|
+
shortcut: "cmd+shift+o",
|
|
78
|
+
shortcutDisplay: "⌘⇧O",
|
|
73
79
|
},
|
|
74
80
|
],
|
|
75
81
|
admin: [
|
|
@@ -79,8 +85,20 @@ const buildConfig = {
|
|
|
79
85
|
icon: "DatabaseZap",
|
|
80
86
|
path: "/admin/ai/user-token",
|
|
81
87
|
order: 100,
|
|
88
|
+
shortcut: "cmd+shift+g",
|
|
89
|
+
shortcutDisplay: "⌘⇧G",
|
|
82
90
|
},
|
|
83
91
|
],
|
|
84
92
|
},
|
|
93
|
+
userTabs: [
|
|
94
|
+
{
|
|
95
|
+
key: "tokens",
|
|
96
|
+
title: "Tokens IA",
|
|
97
|
+
icon: "Coins",
|
|
98
|
+
componentExport: "UserTokenTab",
|
|
99
|
+
entryPoint: "components/admin/UserTokenTab",
|
|
100
|
+
order: 100,
|
|
101
|
+
},
|
|
102
|
+
],
|
|
85
103
|
};
|
|
86
104
|
export default buildConfig;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NextRequest, NextResponse } from "next/server";
|
|
2
|
-
export declare function GET(request: NextRequest,
|
|
2
|
+
export declare function GET(request: NextRequest, context: {
|
|
3
3
|
params: Promise<{
|
|
4
4
|
id: string;
|
|
5
5
|
}>;
|
|
@@ -8,6 +8,10 @@ export declare function GET(request: NextRequest, props: {
|
|
|
8
8
|
id: string;
|
|
9
9
|
email: string | undefined;
|
|
10
10
|
createdAt: string;
|
|
11
|
+
} | {
|
|
12
|
+
id: string;
|
|
13
|
+
email?: undefined;
|
|
14
|
+
createdAt?: undefined;
|
|
11
15
|
};
|
|
12
16
|
balance: number;
|
|
13
17
|
stats: {
|
|
@@ -18,6 +22,7 @@ export declare function GET(request: NextRequest, props: {
|
|
|
18
22
|
totalAdjusted: number;
|
|
19
23
|
};
|
|
20
24
|
history: import("../../../server").TokenLedgerEntry[];
|
|
25
|
+
data: import("../../../server").TokenLedgerEntry[];
|
|
21
26
|
pagination: {
|
|
22
27
|
limit: number;
|
|
23
28
|
offset: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"[id].d.ts","sourceRoot":"","sources":["../../../../src/api/admin/user-token/[id].ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AASxD,wBAAsB,GAAG,CACvB,OAAO,EAAE,WAAW,EACpB,
|
|
1
|
+
{"version":3,"file":"[id].d.ts","sourceRoot":"","sources":["../../../../src/api/admin/user-token/[id].ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AASxD,wBAAsB,GAAG,CACvB,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;IA4D7C"}
|
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
import { NextResponse } from "next/server";
|
|
2
|
-
import {
|
|
2
|
+
import { getSupabaseServiceClient } from "@lastbrain/core/server";
|
|
3
3
|
import { getTokenBalance, getTokenHistory, getTokenStats, } from "../../../server";
|
|
4
4
|
// GET /api/ai/admin/user-token/[id] - Détails d'un utilisateur spécifique
|
|
5
|
-
export async function GET(request,
|
|
6
|
-
const
|
|
7
|
-
const { id } = params;
|
|
5
|
+
export async function GET(request, context) {
|
|
6
|
+
const { id: userId } = await context.params;
|
|
8
7
|
try {
|
|
9
|
-
const supabase =
|
|
8
|
+
const supabase = getSupabaseServiceClient();
|
|
10
9
|
// Vérifier l'authentification et les permissions admin
|
|
11
|
-
|
|
10
|
+
// Pas besoin de session utilisateur, on utilise la clé service
|
|
12
11
|
// L'authentification et les droits superadmin sont déjà vérifiés par le middleware
|
|
13
|
-
const targetUserId =
|
|
12
|
+
const targetUserId = userId;
|
|
14
13
|
// Récupérer les informations de l'utilisateur
|
|
15
14
|
const { data: targetUser, error: userError } = await supabase.auth.admin.getUserById(targetUserId);
|
|
16
|
-
if (userError
|
|
17
|
-
return NextResponse.json({ error: "
|
|
15
|
+
if (userError) {
|
|
16
|
+
return NextResponse.json({ error: "Accès admin insuffisant" }, { status: 403 });
|
|
18
17
|
}
|
|
19
18
|
// Récupérer le solde
|
|
20
19
|
const balance = await getTokenBalance(targetUserId);
|
|
@@ -26,14 +25,17 @@ export async function GET(request, props) {
|
|
|
26
25
|
const offset = parseInt(searchParams.get("offset") || "0");
|
|
27
26
|
const history = await getTokenHistory(targetUserId, limit, offset);
|
|
28
27
|
return NextResponse.json({
|
|
29
|
-
user:
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
user: targetUser
|
|
29
|
+
? {
|
|
30
|
+
id: targetUser.user.id,
|
|
31
|
+
email: targetUser.user.email,
|
|
32
|
+
createdAt: targetUser.user.created_at,
|
|
33
|
+
}
|
|
34
|
+
: { id: targetUserId },
|
|
34
35
|
balance,
|
|
35
36
|
stats,
|
|
36
37
|
history,
|
|
38
|
+
data: history, // Compat front-end (moduleUserTabs component attend data)
|
|
37
39
|
pagination: {
|
|
38
40
|
limit,
|
|
39
41
|
offset,
|