@lastbrain/module-ai 0.1.10 → 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 +1 -2
- 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.map +1 -1
- package/dist/components/Doc.js +2 -5
- 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 +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- 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 +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,
|
|
@@ -1,10 +1,26 @@
|
|
|
1
1
|
import { NextRequest, NextResponse } from "next/server";
|
|
2
|
-
export declare function GET(
|
|
2
|
+
export declare function GET(request: NextRequest): Promise<NextResponse<{
|
|
3
3
|
users: {
|
|
4
|
+
userId: string;
|
|
5
|
+
email: string;
|
|
6
|
+
fullName: string | undefined;
|
|
7
|
+
avatarUrl: any;
|
|
8
|
+
balance: number;
|
|
9
|
+
totalAdded: number;
|
|
10
|
+
totalUsed: number;
|
|
11
|
+
lastActivity: string | undefined;
|
|
12
|
+
}[];
|
|
13
|
+
transactions: {
|
|
4
14
|
id: any;
|
|
15
|
+
userId: any;
|
|
5
16
|
email: string;
|
|
6
|
-
|
|
7
|
-
|
|
17
|
+
fullName: string | undefined;
|
|
18
|
+
avatarUrl: any;
|
|
19
|
+
amount: any;
|
|
20
|
+
type: any;
|
|
21
|
+
description: any;
|
|
22
|
+
model: any;
|
|
23
|
+
created_at: any;
|
|
8
24
|
}[];
|
|
9
25
|
total: number;
|
|
10
26
|
}> | NextResponse<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-token.d.ts","sourceRoot":"","sources":["../../../src/api/admin/user-token.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAKxD,wBAAsB,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"user-token.d.ts","sourceRoot":"","sources":["../../../src/api/admin/user-token.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAKxD,wBAAsB,GAAG,CAAC,OAAO,EAAE,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;IA2H7C;AAGD,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW;;;;;;IAiD9C"}
|
|
@@ -1,36 +1,96 @@
|
|
|
1
1
|
import { NextResponse } from "next/server";
|
|
2
|
-
import {
|
|
2
|
+
import { getSupabaseServiceClient } from "@lastbrain/core/server";
|
|
3
3
|
import { addTokens } from "../../server";
|
|
4
|
-
// GET /api/ai/admin/user-token - Liste tous les utilisateurs avec leur balance
|
|
5
|
-
export async function GET(
|
|
4
|
+
// GET /api/ai/admin/user-token - Liste tous les utilisateurs avec leur balance et transactions
|
|
5
|
+
export async function GET(request) {
|
|
6
6
|
try {
|
|
7
|
-
const supabase =
|
|
7
|
+
const supabase = getSupabaseServiceClient();
|
|
8
8
|
// L'authentification et les droits superadmin sont déjà vérifiés par le middleware
|
|
9
|
-
// Récupérer tous les utilisateurs
|
|
10
|
-
const { data:
|
|
11
|
-
.from("user_token_balance_v")
|
|
12
|
-
.select("owner_id, balance")
|
|
13
|
-
.order("balance", { ascending: false });
|
|
14
|
-
if (balanceError)
|
|
15
|
-
throw balanceError;
|
|
16
|
-
// Récupérer les informations des utilisateurs
|
|
17
|
-
const _userIds = balances?.map((b) => b.owner_id) || [];
|
|
18
|
-
const { data: users, error: usersError } = await supabase.auth.admin.listUsers();
|
|
9
|
+
// Récupérer tous les utilisateurs
|
|
10
|
+
const { data: authUsers, error: usersError } = await supabase.auth.admin.listUsers();
|
|
19
11
|
if (usersError)
|
|
20
12
|
throw usersError;
|
|
21
|
-
//
|
|
22
|
-
const
|
|
23
|
-
|
|
13
|
+
// Récupérer toutes les transactions pour calculer les balances et stats
|
|
14
|
+
const { data: transactions, error: txError } = await supabase
|
|
15
|
+
.from("user_token_ledger")
|
|
16
|
+
.select("*")
|
|
17
|
+
.order("ts", { ascending: false })
|
|
18
|
+
.limit(1000);
|
|
19
|
+
if (txError)
|
|
20
|
+
throw txError;
|
|
21
|
+
// Calculer les stats par utilisateur
|
|
22
|
+
const userStatsMap = new Map();
|
|
23
|
+
transactions?.forEach((tx) => {
|
|
24
|
+
const stats = userStatsMap.get(tx.owner_id) || {
|
|
25
|
+
balance: 0,
|
|
26
|
+
totalAdded: 0,
|
|
27
|
+
totalUsed: 0,
|
|
28
|
+
};
|
|
29
|
+
stats.balance += tx.amount;
|
|
30
|
+
if (tx.amount > 0) {
|
|
31
|
+
stats.totalAdded += tx.amount;
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
stats.totalUsed += Math.abs(tx.amount);
|
|
35
|
+
}
|
|
36
|
+
if (!stats.lastActivity || tx.ts > stats.lastActivity) {
|
|
37
|
+
stats.lastActivity = tx.ts;
|
|
38
|
+
}
|
|
39
|
+
userStatsMap.set(tx.owner_id, stats);
|
|
40
|
+
});
|
|
41
|
+
// Récupérer les profils utilisateurs pour avatar et nom
|
|
42
|
+
const userIds = authUsers.users.map((u) => u.id);
|
|
43
|
+
const { data: profiles } = await supabase
|
|
44
|
+
.from("user_profil")
|
|
45
|
+
.select("id, first_name, last_name, avatar_url")
|
|
46
|
+
.in("id", userIds);
|
|
47
|
+
const profilesMap = new Map(profiles?.map((p) => [
|
|
48
|
+
p.id,
|
|
49
|
+
{
|
|
50
|
+
fullName: [p.first_name, p.last_name].filter(Boolean).join(" "),
|
|
51
|
+
avatarUrl: p.avatar_url,
|
|
52
|
+
},
|
|
53
|
+
]));
|
|
54
|
+
// Combiner toutes les données
|
|
55
|
+
const usersData = authUsers.users.map((user) => {
|
|
56
|
+
const stats = userStatsMap.get(user.id) || {
|
|
57
|
+
balance: 0,
|
|
58
|
+
totalAdded: 0,
|
|
59
|
+
totalUsed: 0,
|
|
60
|
+
};
|
|
61
|
+
const profile = profilesMap.get(user.id);
|
|
62
|
+
return {
|
|
63
|
+
userId: user.id,
|
|
64
|
+
email: user.email || "Unknown",
|
|
65
|
+
fullName: profile?.fullName,
|
|
66
|
+
avatarUrl: profile?.avatarUrl,
|
|
67
|
+
balance: stats.balance,
|
|
68
|
+
totalAdded: stats.totalAdded,
|
|
69
|
+
totalUsed: stats.totalUsed,
|
|
70
|
+
lastActivity: stats.lastActivity,
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
// Préparer les transactions avec infos utilisateurs
|
|
74
|
+
const transactionsWithUsers = transactions?.map((tx) => {
|
|
75
|
+
const user = authUsers.users.find((u) => u.id === tx.owner_id);
|
|
76
|
+
const profile = profilesMap.get(tx.owner_id);
|
|
24
77
|
return {
|
|
25
|
-
id:
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
78
|
+
id: tx.id,
|
|
79
|
+
userId: tx.owner_id,
|
|
80
|
+
email: user?.email || "Unknown",
|
|
81
|
+
fullName: profile?.fullName,
|
|
82
|
+
avatarUrl: profile?.avatarUrl,
|
|
83
|
+
amount: tx.amount,
|
|
84
|
+
type: tx.type,
|
|
85
|
+
description: tx.meta?.reason,
|
|
86
|
+
model: tx.model,
|
|
87
|
+
created_at: tx.ts,
|
|
29
88
|
};
|
|
30
89
|
});
|
|
31
90
|
return NextResponse.json({
|
|
32
|
-
users:
|
|
33
|
-
|
|
91
|
+
users: usersData,
|
|
92
|
+
transactions: transactionsWithUsers,
|
|
93
|
+
total: usersData.length,
|
|
34
94
|
});
|
|
35
95
|
}
|
|
36
96
|
catch (error) {
|
|
@@ -41,9 +101,8 @@ export async function GET(_request) {
|
|
|
41
101
|
// POST /api/ai/admin/user-token - Ajouter/retirer des tokens à un utilisateur
|
|
42
102
|
export async function POST(request) {
|
|
43
103
|
try {
|
|
44
|
-
const supabase =
|
|
104
|
+
const supabase = getSupabaseServiceClient();
|
|
45
105
|
// L'authentification et les droits superadmin sont déjà vérifiés par le middleware
|
|
46
|
-
const { data: { user }, } = await supabase.auth.getUser();
|
|
47
106
|
const body = await request.json();
|
|
48
107
|
const { userId, amount, type, reason } = body;
|
|
49
108
|
if (!userId || !amount) {
|
|
@@ -54,7 +113,7 @@ export async function POST(request) {
|
|
|
54
113
|
}
|
|
55
114
|
// Déterminer le type d'opération
|
|
56
115
|
const operationType = type || (amount > 0 ? "adjust" : "adjust");
|
|
57
|
-
const result = await addTokens(userId, amount, operationType, { reason: reason || "Ajustement manuel par admin"
|
|
116
|
+
const result = await addTokens(userId, amount, operationType, { reason: reason || "Ajustement manuel par admin" }, undefined);
|
|
58
117
|
if (!result.success) {
|
|
59
118
|
return NextResponse.json({ error: result.error }, { status: 500 });
|
|
60
119
|
}
|
|
@@ -12,7 +12,7 @@ export async function POST(request) {
|
|
|
12
12
|
const { data: { user }, } = await supabase.auth.getUser();
|
|
13
13
|
// L'utilisateur est déjà authentifié grâce au middleware
|
|
14
14
|
const body = await request.json();
|
|
15
|
-
const { prompt, model = "gpt-4o-mini", context, maxTokens =
|
|
15
|
+
const { prompt, model = "gpt-4o-mini", context, maxTokens = 100, temperature = 0.7, } = body;
|
|
16
16
|
if (!prompt) {
|
|
17
17
|
return NextResponse.json({ error: "Le prompt est requis" }, { status: 400 });
|
|
18
18
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from "next/server";
|
|
2
|
+
export declare function GET(request: NextRequest): Promise<NextResponse<{
|
|
3
|
+
userId: string;
|
|
4
|
+
balance: number;
|
|
5
|
+
stats: {
|
|
6
|
+
balance: number;
|
|
7
|
+
totalPurchased: number;
|
|
8
|
+
totalGifted: number;
|
|
9
|
+
totalUsed: number;
|
|
10
|
+
totalAdjusted: number;
|
|
11
|
+
};
|
|
12
|
+
history: import("../../server").TokenLedgerEntry[];
|
|
13
|
+
count: number;
|
|
14
|
+
}> | NextResponse<{
|
|
15
|
+
error: any;
|
|
16
|
+
}>>;
|
|
17
|
+
//# sourceMappingURL=user-tokens.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-tokens.d.ts","sourceRoot":"","sources":["../../../src/api/auth/user-tokens.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAKxD,wBAAsB,GAAG,CAAC,OAAO,EAAE,WAAW;;;;;;;;;;;;;;IA0C7C"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { NextResponse } from "next/server";
|
|
2
|
+
import { getSupabaseServerClient } from "@lastbrain/core/server";
|
|
3
|
+
import { getTokenBalance, getTokenHistory, getTokenStats } from "../../server";
|
|
4
|
+
// GET /api/ai/user/tokens - Récupérer le solde et l'historique de l'utilisateur courant
|
|
5
|
+
export async function GET(request) {
|
|
6
|
+
try {
|
|
7
|
+
const supabase = await getSupabaseServerClient();
|
|
8
|
+
// Récupérer l'utilisateur courant
|
|
9
|
+
const { data: { user }, error: authError, } = await supabase.auth.getUser();
|
|
10
|
+
if (authError || !user) {
|
|
11
|
+
return NextResponse.json({ error: "Non authentifié" }, { status: 401 });
|
|
12
|
+
}
|
|
13
|
+
const userId = user.id;
|
|
14
|
+
// Récupérer le solde
|
|
15
|
+
const balance = await getTokenBalance(userId);
|
|
16
|
+
// Récupérer les statistiques
|
|
17
|
+
const stats = await getTokenStats(userId);
|
|
18
|
+
// Récupérer l'historique complet (12 derniers mois)
|
|
19
|
+
const searchParams = request.nextUrl.searchParams;
|
|
20
|
+
const limit = parseInt(searchParams.get("limit") || "500");
|
|
21
|
+
const history = await getTokenHistory(userId, limit, 0);
|
|
22
|
+
return NextResponse.json({
|
|
23
|
+
userId,
|
|
24
|
+
balance,
|
|
25
|
+
stats,
|
|
26
|
+
history,
|
|
27
|
+
count: history.length,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
console.error("[GET /api/ai/user/tokens] Error:", error);
|
|
32
|
+
return NextResponse.json({ error: error.message || "Erreur serveur" }, { status: 500 });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Doc.d.ts","sourceRoot":"","sources":["../../src/components/Doc.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Doc.d.ts","sourceRoot":"","sources":["../../src/components/Doc.tsx"],"names":[],"mappings":"AAiBA;;;;;;GAMG;AACH,wBAAgB,GAAG,4CAsOlB"}
|
package/dist/components/Doc.js
CHANGED
|
@@ -6,6 +6,7 @@ import { Snippet } from "@lastbrain/ui";
|
|
|
6
6
|
import { Alert } from "@lastbrain/ui";
|
|
7
7
|
import { TableStructure } from "@lastbrain/ui";
|
|
8
8
|
import { FileText, Zap, Database, Package, BookOpen, AlertTriangle, } from "lucide-react";
|
|
9
|
+
import { DocUsageCustom } from "./DocUsageCustom";
|
|
9
10
|
/**
|
|
10
11
|
* Documentation component for @lastbrain/module-ai
|
|
11
12
|
* Auto-generated from module-ai.build.config.ts
|
|
@@ -14,9 +15,5 @@ import { FileText, Zap, Database, Package, BookOpen, AlertTriangle, } from "luci
|
|
|
14
15
|
* pnpm update:module-docs
|
|
15
16
|
*/
|
|
16
17
|
export function Doc() {
|
|
17
|
-
return (_jsxs("div", { className: "container mx-auto p-6 space-y-6", children: [_jsxs(Card, { children: [_jsx(CardHeader, { children: _jsxs("div", { children: [_jsx("h1", { className: "text-3xl font-bold mb-2", children: "\uD83D\uDCE6 Module ai" }), _jsx("p", { className: "text-slate-600 dark:text-slate-400", children: "@lastbrain/module-ai" })] }) }), _jsx(CardBody, { children: _jsxs("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-4", children: [_jsxs("div", { children: [_jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Package" }), _jsx("code", { className: "text-sm font-semibold", children: "@lastbrain/module-ai" })] }), _jsxs("div", { children: [_jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Slug" }), _jsx("code", { className: "text-sm font-semibold", children: "module-ai" })] }), _jsxs("div", { children: [_jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Type" }), _jsx("code", { className: "text-sm font-semibold", children: "Module LastBrain" })] })] }) })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsxs("h2", { className: "text-2xl font-semibold flex items-center gap-2", children: [_jsx(FileText, { size: 24 }), "Pages Disponibles"] }) }), _jsxs(CardBody, { className: "space-y-4", children: [_jsxs("div", { children: [_jsx("h3", { className: "text-lg font-semibold mb-2", children: "Pages Prot\u00E9g\u00E9es (Auth)" }), _jsx("div", { className: "space-y-2", children: _jsxs("div", { className: "flex items-start gap-2", children: [_jsx(Chip, { size: "sm", color: "primary", variant: "flat", children: "GET" }), _jsx("code", { className: "text-sm", children: "/token" }), _jsx("span", { className: "text-sm text-slate-600 dark:text-slate-400", children: "- TokenPage" })] }) })] }), _jsxs("div", { children: [_jsx("h3", { className: "text-lg font-semibold mb-2", children: "Pages Admin" }), _jsx("div", { className: "space-y-2", children: _jsxs("div", { className: "flex items-start gap-2", children: [_jsx(Chip, { size: "sm", color: "secondary", variant: "flat", children: "GET" }), _jsx("code", { className: "text-sm", children: "/user-token" }), _jsx("span", { className: "text-sm text-slate-600 dark:text-slate-400", children: "- UserTokenPage" })] }) })] })] })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsxs("h2", { className: "text-2xl font-semibold flex items-center gap-2", children: [_jsx(Zap, { size: 24 }), "API Routes"] }) }), _jsxs(CardBody, { className: "space-y-4", children: [_jsxs("div", { children: [_jsx("h3", { className: "text-lg font-semibold mb-2", children: _jsx("code", { children: "/api/auth/user_token_ledger" }) }), _jsxs("div", { className: "flex gap-2", children: [_jsx(Chip, { size: "sm", color: "success", variant: "flat", children: "GET" }), _jsx(Chip, { size: "sm", color: "primary", variant: "flat", children: "POST" }), _jsx(Chip, { size: "sm", color: "warning", variant: "flat", children: "PUT" }), _jsx(Chip, { size: "sm", color: "danger", variant: "flat", children: "DELETE" })] })] }), _jsxs("div", { children: [_jsx("h3", { className: "text-lg font-semibold mb-2", children: _jsx("code", { children: "/api/auth/user_prompts" }) }), _jsxs("div", { className: "flex gap-2", children: [_jsx(Chip, { size: "sm", color: "success", variant: "flat", children: "GET" }), _jsx(Chip, { size: "sm", color: "primary", variant: "flat", children: "POST" }), _jsx(Chip, { size: "sm", color: "warning", variant: "flat", children: "PUT" }), _jsx(Chip, { size: "sm", color: "danger", variant: "flat", children: "DELETE" })] })] })] })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsxs("h2", { className: "text-2xl font-semibold flex items-center gap-2", children: [_jsx(Database, { size: 24 }), "Base de Donn\u00E9es"] }) }), _jsxs(CardBody, { className: "space-y-6", children: [_jsx(TableStructure, { tableName: "user_token_ledger", title: "user_token_ledger", description: "Table user_token_ledger du module ai" }), _jsx(TableStructure, { tableName: "user_prompts", title: "user_prompts", description: "Table user_prompts du module ai" })] })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsxs("h2", { className: "text-2xl font-semibold flex items-center gap-2", children: [_jsx(Package, { size: 24 }), "Installation"] }) }), _jsxs(CardBody, { className: "space-y-4", children: [_jsxs("div", { children: [_jsx("h3", { className: "text-lg font-semibold mb-2", children: "Ajouter le module" }), _jsx(Snippet, { symbol: "", hideSymbol: true, className: "text-sm mb-2", children: "pnpm lastbrain add-module ai" }), _jsx(Snippet, { symbol: "", hideSymbol: true, className: "text-sm mb-2", children: "pnpm build:modules" })] }), _jsxs("div", { children: [_jsx("h3", { className: "text-lg font-semibold mb-2", children: "Appliquer les migrations" }), _jsx(Snippet, { symbol: "", hideSymbol: true, className: "text-sm mb-2", children: "cd apps/votre-app" }), _jsx(Snippet, { symbol: "", hideSymbol: true, className: "text-sm mb-2", children: "supabase migration up" })] })] })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsxs("h2", { className: "text-2xl font-semibold flex items-center gap-2", children: [_jsx(BookOpen, { size: 24 }), "Utilisation"] }) }),
|
|
18
|
-
import { TokenPage } from "@lastbrain/module-ai";
|
|
19
|
-
|
|
20
|
-
// Utilisez-les dans votre application
|
|
21
|
-
<TokenPage />` }) })] })] })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsxs("h2", { className: "text-2xl font-semibold flex items-center gap-2 text-danger", children: [_jsx(AlertTriangle, { size: 24 }), "Danger Zone"] }) }), _jsxs(CardBody, { className: "space-y-4", children: [_jsxs(Alert, { color: "danger", className: "mb-4", children: [_jsx("p", { className: "text-sm font-semibold", children: "\u26A0\uFE0F Cette action est irr\u00E9versible" }), _jsx("p", { className: "text-sm mt-2", children: "La suppression du module supprimera toutes les pages, routes API et migrations associ\u00E9es." })] }), _jsxs("div", { children: [_jsx("h3", { className: "text-lg font-semibold mb-2", children: "Supprimer le module" }), _jsx(Snippet, { symbol: "", hideSymbol: true, color: "danger", className: "text-sm mb-2", children: "pnpm lastbrain remove-module ai" }), _jsx(Snippet, { symbol: "", hideSymbol: true, color: "danger", className: "text-sm mb-2", children: "pnpm build:modules" })] })] })] })] }));
|
|
18
|
+
return (_jsxs("div", { className: "container mx-auto p-6 space-y-6", children: [_jsxs(Card, { children: [_jsx(CardHeader, { children: _jsxs("div", { children: [_jsx("h1", { className: "text-3xl font-bold mb-2", children: "\uD83D\uDCE6 Module ai" }), _jsx("p", { className: "text-slate-600 dark:text-slate-400", children: "@lastbrain/module-ai" })] }) }), _jsx(CardBody, { children: _jsxs("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-4", children: [_jsxs("div", { children: [_jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Package" }), _jsx("code", { className: "text-sm font-semibold", children: "@lastbrain/module-ai" })] }), _jsxs("div", { children: [_jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Slug" }), _jsx("code", { className: "text-sm font-semibold", children: "module-ai" })] }), _jsxs("div", { children: [_jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Type" }), _jsx("code", { className: "text-sm font-semibold", children: "Module LastBrain" })] })] }) })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsxs("h2", { className: "text-2xl font-semibold flex items-center gap-2", children: [_jsx(FileText, { size: 24 }), "Pages Disponibles"] }) }), _jsxs(CardBody, { className: "space-y-4", children: [_jsxs("div", { children: [_jsx("h3", { className: "text-lg font-semibold mb-2", children: "Pages Prot\u00E9g\u00E9es (Auth)" }), _jsx("div", { className: "space-y-2", children: _jsxs("div", { className: "flex items-start gap-2", children: [_jsx(Chip, { size: "sm", color: "primary", variant: "flat", children: "GET" }), _jsx("code", { className: "text-sm", children: "/token" }), _jsx("span", { className: "text-sm text-slate-600 dark:text-slate-400", children: "- TokenPage" })] }) })] }), _jsxs("div", { children: [_jsx("h3", { className: "text-lg font-semibold mb-2", children: "Pages Admin" }), _jsx("div", { className: "space-y-2", children: _jsxs("div", { className: "flex items-start gap-2", children: [_jsx(Chip, { size: "sm", color: "secondary", variant: "flat", children: "GET" }), _jsx("code", { className: "text-sm", children: "/user-token" }), _jsx("span", { className: "text-sm text-slate-600 dark:text-slate-400", children: "- UserTokenPage" })] }) })] })] })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsxs("h2", { className: "text-2xl font-semibold flex items-center gap-2", children: [_jsx(Zap, { size: 24 }), "API Routes"] }) }), _jsxs(CardBody, { className: "space-y-4", children: [_jsxs("div", { children: [_jsx("h3", { className: "text-lg font-semibold mb-2", children: _jsx("code", { children: "/api/auth/user_token_ledger" }) }), _jsxs("div", { className: "flex gap-2", children: [_jsx(Chip, { size: "sm", color: "success", variant: "flat", children: "GET" }), _jsx(Chip, { size: "sm", color: "primary", variant: "flat", children: "POST" }), _jsx(Chip, { size: "sm", color: "warning", variant: "flat", children: "PUT" }), _jsx(Chip, { size: "sm", color: "danger", variant: "flat", children: "DELETE" })] })] }), _jsxs("div", { children: [_jsx("h3", { className: "text-lg font-semibold mb-2", children: _jsx("code", { children: "/api/auth/user_prompts" }) }), _jsxs("div", { className: "flex gap-2", children: [_jsx(Chip, { size: "sm", color: "success", variant: "flat", children: "GET" }), _jsx(Chip, { size: "sm", color: "primary", variant: "flat", children: "POST" }), _jsx(Chip, { size: "sm", color: "warning", variant: "flat", children: "PUT" }), _jsx(Chip, { size: "sm", color: "danger", variant: "flat", children: "DELETE" })] })] })] })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsxs("h2", { className: "text-2xl font-semibold flex items-center gap-2", children: [_jsx(Database, { size: 24 }), "Base de Donn\u00E9es"] }) }), _jsxs(CardBody, { className: "space-y-6", children: [_jsx(TableStructure, { tableName: "user_token_ledger", title: "user_token_ledger", description: "Table user_token_ledger du module ai" }), _jsx(TableStructure, { tableName: "user_prompts", title: "user_prompts", description: "Table user_prompts du module ai" })] })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsxs("h2", { className: "text-2xl font-semibold flex items-center gap-2", children: [_jsx(Package, { size: 24 }), "Installation"] }) }), _jsxs(CardBody, { className: "space-y-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx("h3", { className: "text-lg font-semibold mb-2", children: "Ajouter le module" }), _jsx(Snippet, { symbol: "", hideSymbol: true, className: "text-sm mb-2", children: "pnpm lastbrain add-module ai" }), _jsx(Snippet, { symbol: "", hideSymbol: true, className: "text-sm mb-2", children: "pnpm build:modules" })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx("h3", { className: "text-lg font-semibold mb-2", children: "Appliquer les migrations" }), _jsx(Snippet, { symbol: "", hideSymbol: true, className: "text-sm mb-2", children: "cd apps/votre-app" }), _jsx(Snippet, { symbol: "", hideSymbol: true, className: "text-sm mb-2", children: "supabase migration up" })] })] })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsxs("h2", { className: "text-2xl font-semibold flex items-center gap-2", children: [_jsx(BookOpen, { size: 24 }), "Utilisation"] }) }), _jsx(CardBody, { className: "space-y-4", children: _jsx(DocUsageCustom, {}) })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsxs("h2", { className: "text-2xl font-semibold flex items-center gap-2 text-danger", children: [_jsx(AlertTriangle, { size: 24 }), "Danger Zone"] }) }), _jsxs(CardBody, { className: "space-y-4", children: [_jsxs(Alert, { color: "danger", className: "mb-4", children: [_jsx("p", { className: "text-sm font-semibold", children: "Cette action est irr\u00E9versible" }), _jsx("p", { className: "text-sm mt-2", children: "La suppression du module supprimera toutes les pages, routes API et migrations associ\u00E9es." })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx("h3", { className: "text-lg font-semibold mb-2", children: "Supprimer le module" }), _jsx(Snippet, { symbol: "", hideSymbol: true, color: "danger", className: "text-sm mb-2", children: "pnpm lastbrain remove-module ai" }), _jsx(Snippet, { symbol: "", hideSymbol: true, color: "danger", className: "text-sm mb-2", children: "pnpm build:modules" })] })] })] })] }));
|
|
22
19
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Section personnalisée de documentation pour le module-ai
|
|
3
|
+
* Ce fichier NE SERA JAMAIS écrasé par update:module-docs
|
|
4
|
+
*
|
|
5
|
+
* Utilisez ce composant pour documenter l'utilisation spécifique
|
|
6
|
+
* de vos composants avec des exemples interactifs.
|
|
7
|
+
*/
|
|
8
|
+
export declare function DocUsageCustom(): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
//# sourceMappingURL=DocUsageCustom.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DocUsageCustom.d.ts","sourceRoot":"","sources":["../../src/components/DocUsageCustom.tsx"],"names":[],"mappings":"AAOA;;;;;;GAMG;AACH,wBAAgB,cAAc,4CA2V7B"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Card, CardBody, CardHeader, Alert, Tabs, Tab } from "@lastbrain/ui";
|
|
4
|
+
import { TextareaGenerative } from "../web/components/TextareaGenerative";
|
|
5
|
+
import { ImageGenerative } from "../web/components/ImageGenerative";
|
|
6
|
+
import { Lightbulb } from "lucide-react";
|
|
7
|
+
/**
|
|
8
|
+
* Section personnalisée de documentation pour le module-ai
|
|
9
|
+
* Ce fichier NE SERA JAMAIS écrasé par update:module-docs
|
|
10
|
+
*
|
|
11
|
+
* Utilisez ce composant pour documenter l'utilisation spécifique
|
|
12
|
+
* de vos composants avec des exemples interactifs.
|
|
13
|
+
*/
|
|
14
|
+
export function DocUsageCustom() {
|
|
15
|
+
return (_jsxs("div", { className: "space-y-6", children: [_jsx(Alert, { hideIcon: true, variant: "flat", color: "primary", className: "mb-6", children: _jsxs("div", { className: "flex items-start gap-2", children: [_jsx(Lightbulb, { size: 20, className: "mt-0.5 flex-shrink-0" }), _jsxs("div", { children: [_jsx("p", { className: "font-semibold", children: "Composants IA G\u00E9n\u00E9ratives" }), _jsx("p", { className: "text-sm mt-1", children: "Le module AI fournit des composants pr\u00EAts \u00E0 l'emploi pour int\u00E9grer la g\u00E9n\u00E9ration de texte et d'images par IA dans vos applications." })] })] }) }), _jsxs(Tabs, { "aria-label": "Exemples d'utilisation", color: "primary", variant: "bordered", fullWidth: true, children: [_jsx(Tab, { title: "G\u00E9n\u00E9ration de Texte", children: _jsxs(Card, { className: "mt-4", children: [_jsx(CardHeader, { children: _jsx("h3", { className: "text-xl font-semibold", children: "TextareaGenerative" }) }), _jsxs(CardBody, { className: "space-y-6", children: [_jsxs("div", { children: [_jsx("h4", { className: "text-lg font-semibold mb-2", children: "Description" }), _jsx("p", { className: "text-slate-600 dark:text-slate-400", children: "Composant de g\u00E9n\u00E9ration de texte avec gestion automatique des tokens, support de streaming, et affichage du co\u00FBt en temps r\u00E9el." })] }), _jsxs("div", { children: [_jsx("h4", { className: "text-lg font-semibold mb-3", children: "Exemple interactif" }), _jsx(TextareaGenerative, { defaultPrompt: "\u00C9cris une courte description pour un produit innovant", placeholder: "Le texte g\u00E9n\u00E9r\u00E9 appara\u00EEtra ici...", model: "gpt-4o-mini", showTokenBalance: true })] }), _jsxs("div", { children: [_jsx("h4", { className: "text-lg font-semibold mb-2", children: "Code d'utilisation" }), _jsx(Alert, { hideIcon: true, variant: "flat", color: "primary", className: "p-4", children: _jsx("pre", { className: "whitespace-pre-wrap text-sm", children: `import { TextareaGenerative } from "@lastbrain/module-ai";
|
|
16
|
+
|
|
17
|
+
export function MyComponent() {
|
|
18
|
+
return (
|
|
19
|
+
<TextareaGenerative
|
|
20
|
+
defaultPrompt="Votre prompt par défaut ici"
|
|
21
|
+
placeholder="Le texte généré apparaîtra ici..."
|
|
22
|
+
model="gpt-4o-mini"
|
|
23
|
+
showTokenBalance={true}
|
|
24
|
+
onChange={(text, response) => {
|
|
25
|
+
console.log("Texte généré:", text);
|
|
26
|
+
console.log("Tokens utilisés:", response?.tokensUsed);
|
|
27
|
+
}}
|
|
28
|
+
onError={(error) => {
|
|
29
|
+
console.error("Erreur:", error);
|
|
30
|
+
}}
|
|
31
|
+
/>
|
|
32
|
+
);
|
|
33
|
+
}` }) })] }), _jsxs("div", { children: [_jsx("h4", { className: "text-lg font-semibold mb-2", children: "Props disponibles" }), _jsx("div", { className: "overflow-x-auto", children: _jsxs("table", { className: "w-full text-sm", children: [_jsx("thead", { className: "border-b", children: _jsxs("tr", { children: [_jsx("th", { className: "text-left py-2 px-2", children: "Prop" }), _jsx("th", { className: "text-left py-2 px-2", children: "Type" }), _jsx("th", { className: "text-left py-2 px-2", children: "Description" })] }) }), _jsxs("tbody", { className: "divide-y", children: [_jsxs("tr", { children: [_jsx("td", { className: "py-2 px-2 font-mono", children: "prompt" }), _jsx("td", { className: "py-2 px-2", children: "string" }), _jsx("td", { className: "py-2 px-2", children: "Le prompt \u00E0 envoyer \u00E0 l'IA" })] }), _jsxs("tr", { children: [_jsx("td", { className: "py-2 px-2 font-mono", children: "model" }), _jsx("td", { className: "py-2 px-2", children: "string" }), _jsx("td", { className: "py-2 px-2", children: "Mod\u00E8le \u00E0 utiliser (d\u00E9faut: gpt-4o-mini)" })] }), _jsxs("tr", { children: [_jsx("td", { className: "py-2 px-2 font-mono", children: "placeholder" }), _jsx("td", { className: "py-2 px-2", children: "string" }), _jsx("td", { className: "py-2 px-2", children: "Texte placeholder du textarea" })] }), _jsxs("tr", { children: [_jsx("td", { className: "py-2 px-2 font-mono", children: "onChange" }), _jsx("td", { className: "py-2 px-2", children: "function" }), _jsx("td", { className: "py-2 px-2", children: "Callback apr\u00E8s g\u00E9n\u00E9ration r\u00E9ussie" })] }), _jsxs("tr", { children: [_jsx("td", { className: "py-2 px-2 font-mono", children: "onError" }), _jsx("td", { className: "py-2 px-2", children: "function" }), _jsx("td", { className: "py-2 px-2", children: "Callback en cas d'erreur" })] }), _jsxs("tr", { children: [_jsx("td", { className: "py-2 px-2 font-mono", children: "showTokenBalance" }), _jsx("td", { className: "py-2 px-2", children: "boolean" }), _jsx("td", { className: "py-2 px-2", children: "Afficher le solde de tokens" })] })] })] }) })] })] })] }) }, "textarea"), _jsx(Tab, { title: "G\u00E9n\u00E9ration d'Images", children: _jsxs(Card, { className: "mt-4", children: [_jsx(CardHeader, { children: _jsx("h3", { className: "text-xl font-semibold", children: "ImageGenerative" }) }), _jsxs(CardBody, { className: "space-y-6", children: [_jsxs("div", { children: [_jsx("h4", { className: "text-lg font-semibold mb-2", children: "Description" }), _jsx("p", { className: "text-slate-600 dark:text-slate-400", children: "Composant de g\u00E9n\u00E9ration d'images avec DALL-E, support de diff\u00E9rentes tailles et qualit\u00E9s, et t\u00E9l\u00E9chargement direct de l'image." })] }), _jsxs("div", { children: [_jsx("h4", { className: "text-lg font-semibold mb-3", children: "Exemple interactif" }), _jsx(ImageGenerative, { defaultPrompt: "Un chat astronaute dans l'espace, style cartoon color\u00E9", model: "dall-e-3", size: "1024x1024", quality: "standard", showTokenBalance: true, defaultStyle: "digital-art" })] }), _jsxs("div", { children: [_jsx("h4", { className: "text-lg font-semibold mb-2", children: "Code d'utilisation" }), _jsx(Alert, { hideIcon: true, variant: "flat", color: "primary", className: "p-4", children: _jsx("pre", { className: "whitespace-pre-wrap text-sm", children: `import { ImageGenerative } from "@lastbrain/module-ai";
|
|
34
|
+
|
|
35
|
+
export function MyComponent() {
|
|
36
|
+
return (
|
|
37
|
+
<ImageGenerative
|
|
38
|
+
defaultPrompt="Un paysage futuriste avec des buildings"
|
|
39
|
+
defaultStyle="realistic"
|
|
40
|
+
model="dall-e-3"
|
|
41
|
+
size="1024x1024"
|
|
42
|
+
quality="hd"
|
|
43
|
+
showTokenBalance={true}
|
|
44
|
+
onChange={(imageUrl, response) => {
|
|
45
|
+
console.log("Image générée:", imageUrl);
|
|
46
|
+
console.log("Tokens utilisés:", response?.tokensUsed);
|
|
47
|
+
}}
|
|
48
|
+
onError={(error) => {
|
|
49
|
+
console.error("Erreur:", error);
|
|
50
|
+
}}
|
|
51
|
+
/>
|
|
52
|
+
);
|
|
53
|
+
}` }) })] }), _jsxs("div", { children: [_jsx("h4", { className: "text-lg font-semibold mb-2", children: "Props disponibles" }), _jsx("div", { className: "overflow-x-auto", children: _jsxs("table", { className: "w-full text-sm", children: [_jsx("thead", { className: "border-b", children: _jsxs("tr", { children: [_jsx("th", { className: "text-left py-2 px-2", children: "Prop" }), _jsx("th", { className: "text-left py-2 px-2", children: "Type" }), _jsx("th", { className: "text-left py-2 px-2", children: "Description" })] }) }), _jsxs("tbody", { className: "divide-y", children: [_jsxs("tr", { children: [_jsx("td", { className: "py-2 px-2 font-mono", children: "prompt" }), _jsx("td", { className: "py-2 px-2", children: "string" }), _jsx("td", { className: "py-2 px-2", children: "Description de l'image \u00E0 g\u00E9n\u00E9rer" })] }), _jsxs("tr", { children: [_jsx("td", { className: "py-2 px-2 font-mono", children: "model" }), _jsx("td", { className: "py-2 px-2", children: "string" }), _jsx("td", { className: "py-2 px-2", children: "Mod\u00E8le (dall-e-2 ou dall-e-3)" })] }), _jsxs("tr", { children: [_jsx("td", { className: "py-2 px-2 font-mono", children: "size" }), _jsx("td", { className: "py-2 px-2", children: "string" }), _jsx("td", { className: "py-2 px-2", children: "Taille: 256x256, 512x512, 1024x1024, etc." })] }), _jsxs("tr", { children: [_jsx("td", { className: "py-2 px-2 font-mono", children: "quality" }), _jsx("td", { className: "py-2 px-2", children: "string" }), _jsx("td", { className: "py-2 px-2", children: "Qualit\u00E9: standard ou hd" })] }), _jsxs("tr", { children: [_jsx("td", { className: "py-2 px-2 font-mono", children: "onChange" }), _jsx("td", { className: "py-2 px-2", children: "function" }), _jsx("td", { className: "py-2 px-2", children: "Callback apr\u00E8s g\u00E9n\u00E9ration r\u00E9ussie" })] }), _jsxs("tr", { children: [_jsx("td", { className: "py-2 px-2 font-mono", children: "onError" }), _jsx("td", { className: "py-2 px-2", children: "function" }), _jsx("td", { className: "py-2 px-2", children: "Callback en cas d'erreur" })] })] })] }) })] })] })] }) }, "image"), _jsx(Tab, { title: "Utilisation Avanc\u00E9e", children: _jsxs(Card, { className: "mt-4", children: [_jsx(CardHeader, { children: _jsx("h3", { className: "text-xl font-semibold", children: "Configuration Avanc\u00E9e" }) }), _jsxs(CardBody, { className: "space-y-6", children: [_jsxs("div", { children: [_jsx("h4", { className: "text-lg font-semibold mb-2", children: "API Endpoints Personnalis\u00E9s" }), _jsx(Alert, { hideIcon: true, variant: "flat", color: "primary", className: "p-4", children: _jsx("pre", { className: "whitespace-pre-wrap text-sm", children: `// Utilisez vos propres endpoints API
|
|
54
|
+
<TextareaGenerative
|
|
55
|
+
prompt="Votre prompt"
|
|
56
|
+
apiEndpoint="/api/custom/generate-text"
|
|
57
|
+
/>
|
|
58
|
+
|
|
59
|
+
<ImageGenerative
|
|
60
|
+
prompt="Votre prompt"
|
|
61
|
+
apiEndpoint="/api/custom/generate-image"
|
|
62
|
+
/>` }) })] }), _jsxs("div", { children: [_jsx("h4", { className: "text-lg font-semibold mb-2", children: "Gestion des Tokens" }), _jsx("p", { className: "text-slate-600 dark:text-slate-400 mb-3", children: "Les composants utilisent automatiquement le syst\u00E8me de tokens du module. Chaque g\u00E9n\u00E9ration d\u00E9duit le nombre de tokens utilis\u00E9s du solde de l'utilisateur." }), _jsx(Alert, { hideIcon: true, variant: "flat", color: "warning", className: "p-4", children: _jsx("pre", { className: "whitespace-pre-wrap text-sm", children: `// Les tokens sont automatiquement gérés
|
|
63
|
+
// via la table user_token_ledger
|
|
64
|
+
|
|
65
|
+
// Pour recharger les tokens :
|
|
66
|
+
// 1. Accédez à /admin/user-token
|
|
67
|
+
// 2. Créditez les utilisateurs
|
|
68
|
+
// 3. Les composants détectent automatiquement
|
|
69
|
+
// le nouveau solde` }) })] }), _jsxs("div", { children: [_jsx("h4", { className: "text-lg font-semibold mb-2", children: "Best Practices" }), _jsxs("ul", { className: "list-disc list-inside space-y-2 text-slate-600 dark:text-slate-400", children: [_jsxs("li", { children: ["Utilisez", " ", _jsx("code", { className: "text-xs bg-slate-100 dark:bg-slate-800 px-1 py-0.5 rounded", children: "gpt-4o-mini" }), " ", "pour les t\u00E2ches simples (moins cher)"] }), _jsx("li", { children: "Limitez la longueur des prompts pour \u00E9conomiser les tokens" }), _jsxs("li", { children: ["G\u00E9rez les erreurs avec", " ", _jsx("code", { className: "text-xs bg-slate-100 dark:bg-slate-800 px-1 py-0.5 rounded", children: "onError" })] }), _jsxs("li", { children: ["Affichez toujours le solde de tokens avec", " ", _jsx("code", { className: "text-xs bg-slate-100 dark:bg-slate-800 px-1 py-0.5 rounded", children: "showTokenBalance" })] }), _jsxs("li", { children: ["Pour les images, utilisez", " ", _jsx("code", { className: "text-xs bg-slate-100 dark:bg-slate-800 px-1 py-0.5 rounded", children: "standard" }), " ", "par d\u00E9faut,", " ", _jsx("code", { className: "text-xs bg-slate-100 dark:bg-slate-800 px-1 py-0.5 rounded", children: "hd" }), " ", "uniquement si n\u00E9cessaire"] })] })] })] })] }) }, "advanced")] })] }));
|
|
70
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UserTokenTab.d.ts","sourceRoot":"","sources":["../../../src/components/admin/UserTokenTab.tsx"],"names":[],"mappings":"AAeA,UAAU,iBAAiB;IACzB,MAAM,EAAE,MAAM,CAAC;CAChB;AAiBD,wBAAgB,YAAY,CAAC,EAAE,MAAM,EAAE,EAAE,iBAAiB,2CA2OzD"}
|