@lastbrain/module-ai 0.1.1 → 0.1.3
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/dist/ai.build.config.js +11 -11
- package/dist/api/admin/user-token/[id].d.ts.map +1 -1
- package/dist/api/admin/user-token/[id].js +5 -14
- package/dist/api/admin/user-token.d.ts +1 -1
- package/dist/api/admin/user-token.d.ts.map +1 -1
- package/dist/api/admin/user-token.js +9 -30
- package/dist/api/admin/user_prompts.d.ts +1 -1
- package/dist/api/admin/user_prompts.d.ts.map +1 -1
- package/dist/api/admin/user_prompts.js +9 -14
- package/dist/api/admin/user_token_ledger.d.ts +1 -1
- package/dist/api/admin/user_token_ledger.d.ts.map +1 -1
- package/dist/api/admin/user_token_ledger.js +8 -10
- package/dist/api/auth/generate-image.d.ts.map +1 -1
- package/dist/api/auth/generate-image.js +10 -12
- package/dist/api/auth/generate-text.d.ts.map +1 -1
- package/dist/api/auth/generate-text.js +10 -9
- package/dist/api/auth/user_prompts.d.ts +1 -1
- package/dist/api/auth/user_prompts.d.ts.map +1 -1
- package/dist/api/auth/user_prompts.js +9 -14
- package/dist/api/auth/user_token_ledger.d.ts +1 -1
- package/dist/api/auth/user_token_ledger.d.ts.map +1 -1
- package/dist/api/auth/user_token_ledger.js +8 -10
- package/dist/components/Doc.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/server.d.ts +3 -3
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +60 -40
- package/dist/web/components/ImageGenerative.d.ts.map +1 -1
- package/dist/web/components/ImageGenerative.js +1 -1
- package/dist/web/components/TextareaGenerative.d.ts.map +1 -1
- package/dist/web/components/TextareaGenerative.js +1 -1
- package/package.json +6 -4
package/dist/ai.build.config.js
CHANGED
|
@@ -15,20 +15,20 @@ const buildConfig = {
|
|
|
15
15
|
section: "admin",
|
|
16
16
|
path: "/user-token/[id]",
|
|
17
17
|
componentExport: "UserTokenIdPage",
|
|
18
|
-
}
|
|
18
|
+
},
|
|
19
19
|
],
|
|
20
20
|
apis: [
|
|
21
21
|
// Routes de génération IA
|
|
22
22
|
{
|
|
23
23
|
method: "POST",
|
|
24
|
-
path: "/api/
|
|
24
|
+
path: "/api/ai/generate-text",
|
|
25
25
|
handlerExport: "POST",
|
|
26
26
|
entryPoint: "api/auth/generate-text",
|
|
27
27
|
authRequired: true,
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
30
|
method: "POST",
|
|
31
|
-
path: "/api/
|
|
31
|
+
path: "/api/ai/generate-image",
|
|
32
32
|
handlerExport: "POST",
|
|
33
33
|
entryPoint: "api/auth/generate-image",
|
|
34
34
|
authRequired: true,
|
|
@@ -36,21 +36,21 @@ const buildConfig = {
|
|
|
36
36
|
// Routes admin pour la gestion des tokens
|
|
37
37
|
{
|
|
38
38
|
method: "GET",
|
|
39
|
-
path: "/api/admin/user-token",
|
|
39
|
+
path: "/api/ai/admin/user-token",
|
|
40
40
|
handlerExport: "GET",
|
|
41
41
|
entryPoint: "api/admin/user-token",
|
|
42
42
|
authRequired: true,
|
|
43
43
|
},
|
|
44
44
|
{
|
|
45
45
|
method: "POST",
|
|
46
|
-
path: "/api/admin/user-token",
|
|
46
|
+
path: "/api/ai/admin/user-token",
|
|
47
47
|
handlerExport: "POST",
|
|
48
48
|
entryPoint: "api/admin/user-token",
|
|
49
49
|
authRequired: true,
|
|
50
50
|
},
|
|
51
51
|
{
|
|
52
52
|
method: "GET",
|
|
53
|
-
path: "/api/admin/user-token/[id]",
|
|
53
|
+
path: "/api/ai/admin/user-token/[id]",
|
|
54
54
|
handlerExport: "GET",
|
|
55
55
|
entryPoint: "api/admin/user-token/[id]",
|
|
56
56
|
authRequired: true,
|
|
@@ -68,19 +68,19 @@ const buildConfig = {
|
|
|
68
68
|
title: "Mes Tokens",
|
|
69
69
|
description: "Historique et balance des tokens IA",
|
|
70
70
|
icon: "Coins",
|
|
71
|
-
path: "/auth/token",
|
|
71
|
+
path: "/auth/ai/token",
|
|
72
72
|
order: 100,
|
|
73
|
-
}
|
|
73
|
+
},
|
|
74
74
|
],
|
|
75
75
|
admin: [
|
|
76
76
|
{
|
|
77
77
|
title: "Gestion Tokens",
|
|
78
78
|
description: "Gestion des tokens utilisateurs",
|
|
79
79
|
icon: "DatabaseZap",
|
|
80
|
-
path: "/admin/user-token",
|
|
80
|
+
path: "/admin/ai/user-token",
|
|
81
81
|
order: 100,
|
|
82
|
-
}
|
|
83
|
-
]
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
84
|
},
|
|
85
85
|
};
|
|
86
86
|
export default buildConfig;
|
|
@@ -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;
|
|
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,KAAK,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE;;;;;;;;;;;;;;;;;;;;;;IA6D3C"}
|
|
@@ -1,24 +1,15 @@
|
|
|
1
1
|
import { NextResponse } from "next/server";
|
|
2
2
|
import { getSupabaseServerClient } from "@lastbrain/core/server";
|
|
3
|
-
import { getTokenBalance, getTokenHistory, getTokenStats } from "../../../server";
|
|
4
|
-
// GET /api/admin/user-token/[id] - Détails d'un utilisateur spécifique
|
|
3
|
+
import { getTokenBalance, getTokenHistory, getTokenStats, } from "../../../server";
|
|
4
|
+
// GET /api/ai/admin/user-token/[id] - Détails d'un utilisateur spécifique
|
|
5
5
|
export async function GET(request, props) {
|
|
6
6
|
const params = await props.params;
|
|
7
7
|
const { id } = params;
|
|
8
8
|
try {
|
|
9
9
|
const supabase = await getSupabaseServerClient();
|
|
10
10
|
// Vérifier l'authentification et les permissions admin
|
|
11
|
-
const { data: { user },
|
|
12
|
-
|
|
13
|
-
return NextResponse.json({ error: "Non autorisé" }, { status: 401 });
|
|
14
|
-
}
|
|
15
|
-
// Vérifier si l'utilisateur est superadmin
|
|
16
|
-
const { data: isSuperAdmin } = await supabase.rpc("is_superadmin", {
|
|
17
|
-
user_id: user.id,
|
|
18
|
-
});
|
|
19
|
-
if (!isSuperAdmin) {
|
|
20
|
-
return NextResponse.json({ error: "Accès refusé. Droits administrateur requis." }, { status: 403 });
|
|
21
|
-
}
|
|
11
|
+
const { data: { user: _user }, } = await supabase.auth.getUser();
|
|
12
|
+
// L'authentification et les droits superadmin sont déjà vérifiés par le middleware
|
|
22
13
|
const targetUserId = id;
|
|
23
14
|
// Récupérer les informations de l'utilisateur
|
|
24
15
|
const { data: targetUser, error: userError } = await supabase.auth.admin.getUserById(targetUserId);
|
|
@@ -51,7 +42,7 @@ export async function GET(request, props) {
|
|
|
51
42
|
});
|
|
52
43
|
}
|
|
53
44
|
catch (error) {
|
|
54
|
-
console.error("[GET /api/admin/user-token/[id]] Error:", error);
|
|
45
|
+
console.error("[GET /api/ai/admin/user-token/[id]] Error:", error);
|
|
55
46
|
return NextResponse.json({ error: error.message || "Erreur serveur" }, { status: 500 });
|
|
56
47
|
}
|
|
57
48
|
}
|
|
@@ -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,QAAQ,EAAE,WAAW;;;;;;;;;;IA0C9C;AAGD,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW;;;;;;IAqD9C"}
|
|
@@ -1,22 +1,11 @@
|
|
|
1
1
|
import { NextResponse } from "next/server";
|
|
2
2
|
import { getSupabaseServerClient } from "@lastbrain/core/server";
|
|
3
3
|
import { addTokens } from "../../server";
|
|
4
|
-
// GET /api/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
|
|
5
|
+
export async function GET(_request) {
|
|
6
6
|
try {
|
|
7
7
|
const supabase = await getSupabaseServerClient();
|
|
8
|
-
//
|
|
9
|
-
const { data: { user }, error: authError, } = await supabase.auth.getUser();
|
|
10
|
-
if (authError || !user) {
|
|
11
|
-
return NextResponse.json({ error: "Non autorisé" }, { status: 401 });
|
|
12
|
-
}
|
|
13
|
-
// Vérifier si l'utilisateur est superadmin
|
|
14
|
-
const { data: isSuperAdmin } = await supabase.rpc("is_superadmin", {
|
|
15
|
-
user_id: user.id,
|
|
16
|
-
});
|
|
17
|
-
if (!isSuperAdmin) {
|
|
18
|
-
return NextResponse.json({ error: "Accès refusé. Droits administrateur requis." }, { status: 403 });
|
|
19
|
-
}
|
|
8
|
+
// L'authentification et les droits superadmin sont déjà vérifiés par le middleware
|
|
20
9
|
// Récupérer tous les utilisateurs avec leur balance
|
|
21
10
|
const { data: balances, error: balanceError } = await supabase
|
|
22
11
|
.from("user_token_balance_v")
|
|
@@ -25,7 +14,7 @@ export async function GET(request) {
|
|
|
25
14
|
if (balanceError)
|
|
26
15
|
throw balanceError;
|
|
27
16
|
// Récupérer les informations des utilisateurs
|
|
28
|
-
const
|
|
17
|
+
const _userIds = balances?.map((b) => b.owner_id) || [];
|
|
29
18
|
const { data: users, error: usersError } = await supabase.auth.admin.listUsers();
|
|
30
19
|
if (usersError)
|
|
31
20
|
throw usersError;
|
|
@@ -45,26 +34,16 @@ export async function GET(request) {
|
|
|
45
34
|
});
|
|
46
35
|
}
|
|
47
36
|
catch (error) {
|
|
48
|
-
console.error("[GET /api/admin/user-token] Error:", error);
|
|
37
|
+
console.error("[GET /api/ai/admin/user-token] Error:", error);
|
|
49
38
|
return NextResponse.json({ error: error.message || "Erreur serveur" }, { status: 500 });
|
|
50
39
|
}
|
|
51
40
|
}
|
|
52
|
-
// POST /api/admin/user-token - Ajouter/retirer des tokens à un utilisateur
|
|
41
|
+
// POST /api/ai/admin/user-token - Ajouter/retirer des tokens à un utilisateur
|
|
53
42
|
export async function POST(request) {
|
|
54
43
|
try {
|
|
55
44
|
const supabase = await getSupabaseServerClient();
|
|
56
|
-
//
|
|
57
|
-
const { data: { user },
|
|
58
|
-
if (authError || !user) {
|
|
59
|
-
return NextResponse.json({ error: "Non autorisé" }, { status: 401 });
|
|
60
|
-
}
|
|
61
|
-
// Vérifier si l'utilisateur est superadmin
|
|
62
|
-
const { data: isSuperAdmin } = await supabase.rpc("is_superadmin", {
|
|
63
|
-
user_id: user.id,
|
|
64
|
-
});
|
|
65
|
-
if (!isSuperAdmin) {
|
|
66
|
-
return NextResponse.json({ error: "Accès refusé. Droits administrateur requis." }, { status: 403 });
|
|
67
|
-
}
|
|
45
|
+
// L'authentification et les droits superadmin sont déjà vérifiés par le middleware
|
|
46
|
+
const { data: { user }, } = await supabase.auth.getUser();
|
|
68
47
|
const body = await request.json();
|
|
69
48
|
const { userId, amount, type, reason } = body;
|
|
70
49
|
if (!userId || !amount) {
|
|
@@ -86,7 +65,7 @@ export async function POST(request) {
|
|
|
86
65
|
});
|
|
87
66
|
}
|
|
88
67
|
catch (error) {
|
|
89
|
-
console.error("[POST /api/admin/user-token] Error:", error);
|
|
68
|
+
console.error("[POST /api/ai/admin/user-token] Error:", error);
|
|
90
69
|
return NextResponse.json({ error: error.message || "Erreur serveur" }, { status: 500 });
|
|
91
70
|
}
|
|
92
71
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* GET - Liste tous les enregistrements de user_prompts
|
|
3
3
|
*/
|
|
4
|
-
export declare function GET(
|
|
4
|
+
export declare function GET(_request: Request): Promise<Response>;
|
|
5
5
|
/**
|
|
6
6
|
* POST - Crée un nouvel enregistrement dans user_prompts
|
|
7
7
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user_prompts.d.ts","sourceRoot":"","sources":["../../../src/api/admin/user_prompts.ts"],"names":[],"mappings":"AAWA;;GAEG;AACH,wBAAsB,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"user_prompts.d.ts","sourceRoot":"","sources":["../../../src/api/admin/user_prompts.ts"],"names":[],"mappings":"AAWA;;GAEG;AACH,wBAAsB,GAAG,CAAC,QAAQ,EAAE,OAAO,qBAkB1C;AAED;;GAEG;AACH,wBAAsB,IAAI,CAAC,OAAO,EAAE,OAAO,qBAwB1C;AAED;;GAEG;AACH,wBAAsB,GAAG,CAAC,OAAO,EAAE,OAAO,qBA8BzC;AAED;;GAEG;AACH,wBAAsB,MAAM,CAAC,OAAO,EAAE,OAAO,qBAyB5C"}
|
|
@@ -2,23 +2,21 @@ import { getSupabaseServerClient } from "@lastbrain/core/server";
|
|
|
2
2
|
const jsonResponse = (payload, status = 200) => {
|
|
3
3
|
return new Response(JSON.stringify(payload), {
|
|
4
4
|
headers: {
|
|
5
|
-
"content-type": "application/json"
|
|
5
|
+
"content-type": "application/json",
|
|
6
6
|
},
|
|
7
|
-
status
|
|
7
|
+
status,
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
/**
|
|
11
11
|
* GET - Liste tous les enregistrements de user_prompts
|
|
12
12
|
*/
|
|
13
|
-
export async function GET(
|
|
13
|
+
export async function GET(_request) {
|
|
14
14
|
const supabase = await getSupabaseServerClient();
|
|
15
|
-
const { data: { user }, error: authError } = await supabase.auth.getUser();
|
|
15
|
+
const { data: { user }, error: authError, } = await supabase.auth.getUser();
|
|
16
16
|
if (authError || !user) {
|
|
17
17
|
return jsonResponse({ error: "Non authentifié" }, 401);
|
|
18
18
|
}
|
|
19
|
-
const { data, error } = await supabase
|
|
20
|
-
.from("user_prompts")
|
|
21
|
-
.select("*");
|
|
19
|
+
const { data, error } = await supabase.from("user_prompts").select("*");
|
|
22
20
|
if (error) {
|
|
23
21
|
return jsonResponse({ error: error.message }, 400);
|
|
24
22
|
}
|
|
@@ -29,7 +27,7 @@ export async function GET(request) {
|
|
|
29
27
|
*/
|
|
30
28
|
export async function POST(request) {
|
|
31
29
|
const supabase = await getSupabaseServerClient();
|
|
32
|
-
const { data: { user }, error: authError } = await supabase.auth.getUser();
|
|
30
|
+
const { data: { user }, error: authError, } = await supabase.auth.getUser();
|
|
33
31
|
if (authError || !user) {
|
|
34
32
|
return jsonResponse({ error: "Non authentifié" }, 401);
|
|
35
33
|
}
|
|
@@ -49,7 +47,7 @@ export async function POST(request) {
|
|
|
49
47
|
*/
|
|
50
48
|
export async function PUT(request) {
|
|
51
49
|
const supabase = await getSupabaseServerClient();
|
|
52
|
-
const { data: { user }, error: authError } = await supabase.auth.getUser();
|
|
50
|
+
const { data: { user }, error: authError, } = await supabase.auth.getUser();
|
|
53
51
|
if (authError || !user) {
|
|
54
52
|
return jsonResponse({ error: "Non authentifié" }, 401);
|
|
55
53
|
}
|
|
@@ -74,7 +72,7 @@ export async function PUT(request) {
|
|
|
74
72
|
*/
|
|
75
73
|
export async function DELETE(request) {
|
|
76
74
|
const supabase = await getSupabaseServerClient();
|
|
77
|
-
const { data: { user }, error: authError } = await supabase.auth.getUser();
|
|
75
|
+
const { data: { user }, error: authError, } = await supabase.auth.getUser();
|
|
78
76
|
if (authError || !user) {
|
|
79
77
|
return jsonResponse({ error: "Non authentifié" }, 401);
|
|
80
78
|
}
|
|
@@ -83,10 +81,7 @@ export async function DELETE(request) {
|
|
|
83
81
|
if (!id) {
|
|
84
82
|
return jsonResponse({ error: "ID requis pour la suppression" }, 400);
|
|
85
83
|
}
|
|
86
|
-
const { error } = await supabase
|
|
87
|
-
.from("user_prompts")
|
|
88
|
-
.delete()
|
|
89
|
-
.eq("id", id);
|
|
84
|
+
const { error } = await supabase.from("user_prompts").delete().eq("id", id);
|
|
90
85
|
if (error) {
|
|
91
86
|
return jsonResponse({ error: error.message }, 400);
|
|
92
87
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* GET - Liste tous les enregistrements de user_token_ledger
|
|
3
3
|
*/
|
|
4
|
-
export declare function GET(
|
|
4
|
+
export declare function GET(_request: Request): Promise<Response>;
|
|
5
5
|
/**
|
|
6
6
|
* POST - Crée un nouvel enregistrement dans user_token_ledger
|
|
7
7
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user_token_ledger.d.ts","sourceRoot":"","sources":["../../../src/api/admin/user_token_ledger.ts"],"names":[],"mappings":"AAWA;;GAEG;AACH,wBAAsB,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"user_token_ledger.d.ts","sourceRoot":"","sources":["../../../src/api/admin/user_token_ledger.ts"],"names":[],"mappings":"AAWA;;GAEG;AACH,wBAAsB,GAAG,CAAC,QAAQ,EAAE,OAAO,qBAkB1C;AAED;;GAEG;AACH,wBAAsB,IAAI,CAAC,OAAO,EAAE,OAAO,qBAwB1C;AAED;;GAEG;AACH,wBAAsB,GAAG,CAAC,OAAO,EAAE,OAAO,qBA8BzC;AAED;;GAEG;AACH,wBAAsB,MAAM,CAAC,OAAO,EAAE,OAAO,qBA4B5C"}
|
|
@@ -2,23 +2,21 @@ import { getSupabaseServerClient } from "@lastbrain/core/server";
|
|
|
2
2
|
const jsonResponse = (payload, status = 200) => {
|
|
3
3
|
return new Response(JSON.stringify(payload), {
|
|
4
4
|
headers: {
|
|
5
|
-
"content-type": "application/json"
|
|
5
|
+
"content-type": "application/json",
|
|
6
6
|
},
|
|
7
|
-
status
|
|
7
|
+
status,
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
/**
|
|
11
11
|
* GET - Liste tous les enregistrements de user_token_ledger
|
|
12
12
|
*/
|
|
13
|
-
export async function GET(
|
|
13
|
+
export async function GET(_request) {
|
|
14
14
|
const supabase = await getSupabaseServerClient();
|
|
15
|
-
const { data: { user }, error: authError } = await supabase.auth.getUser();
|
|
15
|
+
const { data: { user }, error: authError, } = await supabase.auth.getUser();
|
|
16
16
|
if (authError || !user) {
|
|
17
17
|
return jsonResponse({ error: "Non authentifié" }, 401);
|
|
18
18
|
}
|
|
19
|
-
const { data, error } = await supabase
|
|
20
|
-
.from("user_token_ledger")
|
|
21
|
-
.select("*");
|
|
19
|
+
const { data, error } = await supabase.from("user_token_ledger").select("*");
|
|
22
20
|
if (error) {
|
|
23
21
|
return jsonResponse({ error: error.message }, 400);
|
|
24
22
|
}
|
|
@@ -29,7 +27,7 @@ export async function GET(request) {
|
|
|
29
27
|
*/
|
|
30
28
|
export async function POST(request) {
|
|
31
29
|
const supabase = await getSupabaseServerClient();
|
|
32
|
-
const { data: { user }, error: authError } = await supabase.auth.getUser();
|
|
30
|
+
const { data: { user }, error: authError, } = await supabase.auth.getUser();
|
|
33
31
|
if (authError || !user) {
|
|
34
32
|
return jsonResponse({ error: "Non authentifié" }, 401);
|
|
35
33
|
}
|
|
@@ -49,7 +47,7 @@ export async function POST(request) {
|
|
|
49
47
|
*/
|
|
50
48
|
export async function PUT(request) {
|
|
51
49
|
const supabase = await getSupabaseServerClient();
|
|
52
|
-
const { data: { user }, error: authError } = await supabase.auth.getUser();
|
|
50
|
+
const { data: { user }, error: authError, } = await supabase.auth.getUser();
|
|
53
51
|
if (authError || !user) {
|
|
54
52
|
return jsonResponse({ error: "Non authentifié" }, 401);
|
|
55
53
|
}
|
|
@@ -74,7 +72,7 @@ export async function PUT(request) {
|
|
|
74
72
|
*/
|
|
75
73
|
export async function DELETE(request) {
|
|
76
74
|
const supabase = await getSupabaseServerClient();
|
|
77
|
-
const { data: { user }, error: authError } = await supabase.auth.getUser();
|
|
75
|
+
const { data: { user }, error: authError, } = await supabase.auth.getUser();
|
|
78
76
|
if (authError || !user) {
|
|
79
77
|
return jsonResponse({ error: "Non authentifié" }, 401);
|
|
80
78
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-image.d.ts","sourceRoot":"","sources":["../../../src/api/auth/generate-image.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAoCxD,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW;;;;;;;;
|
|
1
|
+
{"version":3,"file":"generate-image.d.ts","sourceRoot":"","sources":["../../../src/api/auth/generate-image.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAoCxD,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW;;;;;;;;IA4H9C"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NextResponse } from "next/server";
|
|
2
2
|
import { getSupabaseServerClient } from "@lastbrain/core/server";
|
|
3
|
-
import {
|
|
3
|
+
import { deductTokens, getTokenBalance } from "../../server";
|
|
4
4
|
import OpenAI from "openai";
|
|
5
5
|
const openai = new OpenAI({
|
|
6
6
|
apiKey: process.env.OPENAI_API_KEY,
|
|
@@ -27,19 +27,15 @@ export async function POST(request) {
|
|
|
27
27
|
try {
|
|
28
28
|
const supabase = await getSupabaseServerClient();
|
|
29
29
|
// Vérifier l'authentification
|
|
30
|
-
const { data: { user },
|
|
31
|
-
|
|
32
|
-
return NextResponse.json({ error: "Non autorisé" }, { status: 401 });
|
|
33
|
-
}
|
|
30
|
+
const { data: { user }, } = await supabase.auth.getUser();
|
|
31
|
+
// L'utilisateur est déjà authentifié grâce au middleware
|
|
34
32
|
const body = await request.json();
|
|
35
33
|
const { prompt, model = "dall-e-3", size = "1024x1024", quality = "standard", } = body;
|
|
36
34
|
if (!prompt) {
|
|
37
35
|
return NextResponse.json({ error: "Le prompt est requis" }, { status: 400 });
|
|
38
36
|
}
|
|
39
37
|
// Calculer le coût et les tokens
|
|
40
|
-
const costKey = model === "dall-e-3"
|
|
41
|
-
? `${model}-${size}-${quality}`
|
|
42
|
-
: `${model}-${size}`;
|
|
38
|
+
const costKey = model === "dall-e-3" ? `${model}-${size}-${quality}` : `${model}-${size}`;
|
|
43
39
|
const cost = IMAGE_COSTS[costKey] || 0.04;
|
|
44
40
|
const tokenKey = model === "dall-e-3" ? `${model}-${quality}` : model;
|
|
45
41
|
const tokensRequired = TOKENS_PER_IMAGE[tokenKey] || 1000;
|
|
@@ -74,14 +70,16 @@ export async function POST(request) {
|
|
|
74
70
|
throw new Error("Aucune image générée");
|
|
75
71
|
}
|
|
76
72
|
// Déduire les tokens utilisés
|
|
77
|
-
const tokenResult = await
|
|
73
|
+
const tokenResult = await deductTokens(user.id, tokensRequired, model, prompt, {
|
|
78
74
|
size,
|
|
79
75
|
quality,
|
|
80
76
|
cost,
|
|
81
77
|
imageUrl,
|
|
82
78
|
});
|
|
83
79
|
if (!tokenResult.success) {
|
|
84
|
-
return NextResponse.json({
|
|
80
|
+
return NextResponse.json({
|
|
81
|
+
error: tokenResult.error || "Erreur lors de la déduction des tokens",
|
|
82
|
+
}, { status: 500 });
|
|
85
83
|
}
|
|
86
84
|
return NextResponse.json({
|
|
87
85
|
imageUrl,
|
|
@@ -93,10 +91,10 @@ export async function POST(request) {
|
|
|
93
91
|
}
|
|
94
92
|
catch (error) {
|
|
95
93
|
console.error("Erreur de génération d'image:", error);
|
|
96
|
-
if (error.code ===
|
|
94
|
+
if (error.code === "insufficient_quota") {
|
|
97
95
|
return NextResponse.json({ error: "Quota OpenAI dépassé. Contactez l'administrateur." }, { status: 503 });
|
|
98
96
|
}
|
|
99
|
-
if (error.code ===
|
|
97
|
+
if (error.code === "content_policy_violation") {
|
|
100
98
|
return NextResponse.json({ error: "Le prompt viole la politique de contenu d'OpenAI." }, { status: 400 });
|
|
101
99
|
}
|
|
102
100
|
return NextResponse.json({ error: error.message || "Erreur lors de la génération de l'image" }, { status: 500 });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-text.d.ts","sourceRoot":"","sources":["../../../src/api/auth/generate-text.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAiBxD,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW;;;;;;;;
|
|
1
|
+
{"version":3,"file":"generate-text.d.ts","sourceRoot":"","sources":["../../../src/api/auth/generate-text.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAiBxD,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW;;;;;;;;IAoI9C"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NextResponse } from "next/server";
|
|
2
2
|
import { getSupabaseServerClient } from "@lastbrain/core/server";
|
|
3
|
-
import {
|
|
3
|
+
import { deductTokens, getTokenBalance } from "../../server";
|
|
4
4
|
import OpenAI from "openai";
|
|
5
5
|
const openai = new OpenAI({
|
|
6
6
|
apiKey: process.env.OPENAI_API_KEY,
|
|
@@ -9,10 +9,8 @@ export async function POST(request) {
|
|
|
9
9
|
try {
|
|
10
10
|
const supabase = await getSupabaseServerClient();
|
|
11
11
|
// Vérifier l'authentification
|
|
12
|
-
const { data: { user },
|
|
13
|
-
|
|
14
|
-
return NextResponse.json({ error: "Non autorisé" }, { status: 401 });
|
|
15
|
-
}
|
|
12
|
+
const { data: { user }, } = await supabase.auth.getUser();
|
|
13
|
+
// L'utilisateur est déjà authentifié grâce au middleware
|
|
16
14
|
const body = await request.json();
|
|
17
15
|
const { prompt, model = "gpt-4o-mini", context, maxTokens = 2000, temperature = 0.7, } = body;
|
|
18
16
|
if (!prompt) {
|
|
@@ -57,7 +55,8 @@ export async function POST(request) {
|
|
|
57
55
|
const outputTokens = completion.usage?.completion_tokens || 0;
|
|
58
56
|
let cost = 0;
|
|
59
57
|
if (model.includes("gpt-4o-mini")) {
|
|
60
|
-
cost =
|
|
58
|
+
cost =
|
|
59
|
+
(inputTokens / 1_000_000) * 0.15 + (outputTokens / 1_000_000) * 0.6;
|
|
61
60
|
}
|
|
62
61
|
else if (model.includes("gpt-4o")) {
|
|
63
62
|
cost = (inputTokens / 1_000_000) * 2.5 + (outputTokens / 1_000_000) * 10;
|
|
@@ -69,14 +68,16 @@ export async function POST(request) {
|
|
|
69
68
|
cost = (tokensUsed / 1_000_000) * 2; // Fallback
|
|
70
69
|
}
|
|
71
70
|
// Déduire les tokens utilisés
|
|
72
|
-
const tokenResult = await
|
|
71
|
+
const tokenResult = await deductTokens(user.id, tokensUsed, model, prompt, {
|
|
73
72
|
inputTokens,
|
|
74
73
|
outputTokens,
|
|
75
74
|
cost,
|
|
76
75
|
generatedText: generatedText.substring(0, 500), // Stocker un extrait
|
|
77
76
|
});
|
|
78
77
|
if (!tokenResult.success) {
|
|
79
|
-
return NextResponse.json({
|
|
78
|
+
return NextResponse.json({
|
|
79
|
+
error: tokenResult.error || "Erreur lors de la déduction des tokens",
|
|
80
|
+
}, { status: 500 });
|
|
80
81
|
}
|
|
81
82
|
return NextResponse.json({
|
|
82
83
|
text: generatedText,
|
|
@@ -88,7 +89,7 @@ export async function POST(request) {
|
|
|
88
89
|
}
|
|
89
90
|
catch (error) {
|
|
90
91
|
console.error("Erreur de génération:", error);
|
|
91
|
-
if (error.code ===
|
|
92
|
+
if (error.code === "insufficient_quota") {
|
|
92
93
|
return NextResponse.json({ error: "Quota OpenAI dépassé. Contactez l'administrateur." }, { status: 503 });
|
|
93
94
|
}
|
|
94
95
|
return NextResponse.json({ error: error.message || "Erreur lors de la génération" }, { status: 500 });
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* GET - Liste tous les enregistrements de user_prompts
|
|
3
3
|
*/
|
|
4
|
-
export declare function GET(
|
|
4
|
+
export declare function GET(_request: Request): Promise<Response>;
|
|
5
5
|
/**
|
|
6
6
|
* POST - Crée un nouvel enregistrement dans user_prompts
|
|
7
7
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user_prompts.d.ts","sourceRoot":"","sources":["../../../src/api/auth/user_prompts.ts"],"names":[],"mappings":"AAWA;;GAEG;AACH,wBAAsB,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"user_prompts.d.ts","sourceRoot":"","sources":["../../../src/api/auth/user_prompts.ts"],"names":[],"mappings":"AAWA;;GAEG;AACH,wBAAsB,GAAG,CAAC,QAAQ,EAAE,OAAO,qBAkB1C;AAED;;GAEG;AACH,wBAAsB,IAAI,CAAC,OAAO,EAAE,OAAO,qBAwB1C;AAED;;GAEG;AACH,wBAAsB,GAAG,CAAC,OAAO,EAAE,OAAO,qBA8BzC;AAED;;GAEG;AACH,wBAAsB,MAAM,CAAC,OAAO,EAAE,OAAO,qBAyB5C"}
|
|
@@ -2,23 +2,21 @@ import { getSupabaseServerClient } from "@lastbrain/core/server";
|
|
|
2
2
|
const jsonResponse = (payload, status = 200) => {
|
|
3
3
|
return new Response(JSON.stringify(payload), {
|
|
4
4
|
headers: {
|
|
5
|
-
"content-type": "application/json"
|
|
5
|
+
"content-type": "application/json",
|
|
6
6
|
},
|
|
7
|
-
status
|
|
7
|
+
status,
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
/**
|
|
11
11
|
* GET - Liste tous les enregistrements de user_prompts
|
|
12
12
|
*/
|
|
13
|
-
export async function GET(
|
|
13
|
+
export async function GET(_request) {
|
|
14
14
|
const supabase = await getSupabaseServerClient();
|
|
15
|
-
const { data: { user }, error: authError } = await supabase.auth.getUser();
|
|
15
|
+
const { data: { user }, error: authError, } = await supabase.auth.getUser();
|
|
16
16
|
if (authError || !user) {
|
|
17
17
|
return jsonResponse({ error: "Non authentifié" }, 401);
|
|
18
18
|
}
|
|
19
|
-
const { data, error } = await supabase
|
|
20
|
-
.from("user_prompts")
|
|
21
|
-
.select("*");
|
|
19
|
+
const { data, error } = await supabase.from("user_prompts").select("*");
|
|
22
20
|
if (error) {
|
|
23
21
|
return jsonResponse({ error: error.message }, 400);
|
|
24
22
|
}
|
|
@@ -29,7 +27,7 @@ export async function GET(request) {
|
|
|
29
27
|
*/
|
|
30
28
|
export async function POST(request) {
|
|
31
29
|
const supabase = await getSupabaseServerClient();
|
|
32
|
-
const { data: { user }, error: authError } = await supabase.auth.getUser();
|
|
30
|
+
const { data: { user }, error: authError, } = await supabase.auth.getUser();
|
|
33
31
|
if (authError || !user) {
|
|
34
32
|
return jsonResponse({ error: "Non authentifié" }, 401);
|
|
35
33
|
}
|
|
@@ -49,7 +47,7 @@ export async function POST(request) {
|
|
|
49
47
|
*/
|
|
50
48
|
export async function PUT(request) {
|
|
51
49
|
const supabase = await getSupabaseServerClient();
|
|
52
|
-
const { data: { user }, error: authError } = await supabase.auth.getUser();
|
|
50
|
+
const { data: { user }, error: authError, } = await supabase.auth.getUser();
|
|
53
51
|
if (authError || !user) {
|
|
54
52
|
return jsonResponse({ error: "Non authentifié" }, 401);
|
|
55
53
|
}
|
|
@@ -74,7 +72,7 @@ export async function PUT(request) {
|
|
|
74
72
|
*/
|
|
75
73
|
export async function DELETE(request) {
|
|
76
74
|
const supabase = await getSupabaseServerClient();
|
|
77
|
-
const { data: { user }, error: authError } = await supabase.auth.getUser();
|
|
75
|
+
const { data: { user }, error: authError, } = await supabase.auth.getUser();
|
|
78
76
|
if (authError || !user) {
|
|
79
77
|
return jsonResponse({ error: "Non authentifié" }, 401);
|
|
80
78
|
}
|
|
@@ -83,10 +81,7 @@ export async function DELETE(request) {
|
|
|
83
81
|
if (!id) {
|
|
84
82
|
return jsonResponse({ error: "ID requis pour la suppression" }, 400);
|
|
85
83
|
}
|
|
86
|
-
const { error } = await supabase
|
|
87
|
-
.from("user_prompts")
|
|
88
|
-
.delete()
|
|
89
|
-
.eq("id", id);
|
|
84
|
+
const { error } = await supabase.from("user_prompts").delete().eq("id", id);
|
|
90
85
|
if (error) {
|
|
91
86
|
return jsonResponse({ error: error.message }, 400);
|
|
92
87
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* GET - Liste tous les enregistrements de user_token_ledger
|
|
3
3
|
*/
|
|
4
|
-
export declare function GET(
|
|
4
|
+
export declare function GET(_request: Request): Promise<Response>;
|
|
5
5
|
/**
|
|
6
6
|
* POST - Crée un nouvel enregistrement dans user_token_ledger
|
|
7
7
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user_token_ledger.d.ts","sourceRoot":"","sources":["../../../src/api/auth/user_token_ledger.ts"],"names":[],"mappings":"AAWA;;GAEG;AACH,wBAAsB,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"user_token_ledger.d.ts","sourceRoot":"","sources":["../../../src/api/auth/user_token_ledger.ts"],"names":[],"mappings":"AAWA;;GAEG;AACH,wBAAsB,GAAG,CAAC,QAAQ,EAAE,OAAO,qBAkB1C;AAED;;GAEG;AACH,wBAAsB,IAAI,CAAC,OAAO,EAAE,OAAO,qBAwB1C;AAED;;GAEG;AACH,wBAAsB,GAAG,CAAC,OAAO,EAAE,OAAO,qBA8BzC;AAED;;GAEG;AACH,wBAAsB,MAAM,CAAC,OAAO,EAAE,OAAO,qBA4B5C"}
|
|
@@ -2,23 +2,21 @@ import { getSupabaseServerClient } from "@lastbrain/core/server";
|
|
|
2
2
|
const jsonResponse = (payload, status = 200) => {
|
|
3
3
|
return new Response(JSON.stringify(payload), {
|
|
4
4
|
headers: {
|
|
5
|
-
"content-type": "application/json"
|
|
5
|
+
"content-type": "application/json",
|
|
6
6
|
},
|
|
7
|
-
status
|
|
7
|
+
status,
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
/**
|
|
11
11
|
* GET - Liste tous les enregistrements de user_token_ledger
|
|
12
12
|
*/
|
|
13
|
-
export async function GET(
|
|
13
|
+
export async function GET(_request) {
|
|
14
14
|
const supabase = await getSupabaseServerClient();
|
|
15
|
-
const { data: { user }, error: authError } = await supabase.auth.getUser();
|
|
15
|
+
const { data: { user }, error: authError, } = await supabase.auth.getUser();
|
|
16
16
|
if (authError || !user) {
|
|
17
17
|
return jsonResponse({ error: "Non authentifié" }, 401);
|
|
18
18
|
}
|
|
19
|
-
const { data, error } = await supabase
|
|
20
|
-
.from("user_token_ledger")
|
|
21
|
-
.select("*");
|
|
19
|
+
const { data, error } = await supabase.from("user_token_ledger").select("*");
|
|
22
20
|
if (error) {
|
|
23
21
|
return jsonResponse({ error: error.message }, 400);
|
|
24
22
|
}
|
|
@@ -29,7 +27,7 @@ export async function GET(request) {
|
|
|
29
27
|
*/
|
|
30
28
|
export async function POST(request) {
|
|
31
29
|
const supabase = await getSupabaseServerClient();
|
|
32
|
-
const { data: { user }, error: authError } = await supabase.auth.getUser();
|
|
30
|
+
const { data: { user }, error: authError, } = await supabase.auth.getUser();
|
|
33
31
|
if (authError || !user) {
|
|
34
32
|
return jsonResponse({ error: "Non authentifié" }, 401);
|
|
35
33
|
}
|
|
@@ -49,7 +47,7 @@ export async function POST(request) {
|
|
|
49
47
|
*/
|
|
50
48
|
export async function PUT(request) {
|
|
51
49
|
const supabase = await getSupabaseServerClient();
|
|
52
|
-
const { data: { user }, error: authError } = await supabase.auth.getUser();
|
|
50
|
+
const { data: { user }, error: authError, } = await supabase.auth.getUser();
|
|
53
51
|
if (authError || !user) {
|
|
54
52
|
return jsonResponse({ error: "Non authentifié" }, 401);
|
|
55
53
|
}
|
|
@@ -74,7 +72,7 @@ export async function PUT(request) {
|
|
|
74
72
|
*/
|
|
75
73
|
export async function DELETE(request) {
|
|
76
74
|
const supabase = await getSupabaseServerClient();
|
|
77
|
-
const { data: { user }, error: authError } = await supabase.auth.getUser();
|
|
75
|
+
const { data: { user }, error: authError, } = await supabase.auth.getUser();
|
|
78
76
|
if (authError || !user) {
|
|
79
77
|
return jsonResponse({ error: "Non authentifié" }, 401);
|
|
80
78
|
}
|
package/dist/components/Doc.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Card, CardBody, CardHeader, Snippet, Chip, TableStructure, } from "@lastbrain/ui";
|
|
3
3
|
export function AiModuleDoc() {
|
|
4
|
-
return (_jsxs("div", { className: "space-y-6", children: [_jsxs("div", { className: "flex items-start justify-between", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-3xl font-bold mb-2", children: "Module AI" }), _jsx("p", { className: "text-slate-600 dark:text-slate-400", children: "G\u00E9n\u00E9ration IA (texte et images) avec syst\u00E8me de tokens et gestion des co\u00FBts" })] }), _jsx(Chip, { color: "primary", variant: "flat", children: "v0.1.0" })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx("h3", { className: "text-xl font-semibold", children: "\uD83D\uDCDD Informations" }) }), _jsxs(CardBody, { className: "space-y-2", children: [_jsxs("div", { children: [_jsx("span", { className: "font-semibold", children: "Auteur:" }), " LastBrain Team"] }), _jsxs("div", { children: [_jsx("span", { className: "font-semibold", children: "Package:" }), " @lastbrain/module-ai"] }), _jsxs("div", { children: [_jsx("span", { className: "font-semibold", children: "Derni\u00E8re mise \u00E0 jour:" }), " 21 novembre 2025"] })] })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx("h3", { className: "text-xl font-semibold", children: "\uD83C\uDFA8 Composants Disponibles" }) }), _jsxs(CardBody, { className: "space-y-3", children: [_jsxs("div", { children: [_jsx("h4", { className: "font-semibold mb-2", children: "TextareaGenerative" }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400 mb-2", children: "Textarea avec g\u00E9n\u00E9ration de texte IA int\u00E9gr\u00E9e. Bouton de g\u00E9n\u00E9ration avec s\u00E9lection de prompts." }), _jsx(Snippet, { symbol: "", color: "default", size: "sm", hideSymbol: true, children: _jsxs("div", { className: "flex flex-col gap-1", children: [_jsxs("span", { children: ["import ", "{ TextareaGenerative }", " from \"@lastbrain/module-ai\";"] }), _jsx("span", {}), _jsx("span", { children: "<TextareaGenerative" }), _jsx("span", { children: " label=\"Description\"" }), _jsx("span", { children: " placeholder=\"Entrez une description...\"" }), _jsxs("span", { children: [" value=", "{value}"] }), _jsxs("span", { children: [" onChange=", "{setValue}"] }), _jsx("span", { children: "/>" })] }) })] }), _jsxs("div", { children: [_jsx("h4", { className: "font-semibold mb-2 mt-4", children: "ImageGenerative" }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400 mb-2", children: "Composant de g\u00E9n\u00E9ration d'images avec DALL-E. Upload ou g\u00E9n\u00E9ration IA." }), _jsx(Snippet, { symbol: "", color: "default", size: "sm", hideSymbol: true, children: _jsxs("div", { className: "flex flex-col gap-1", children: [_jsxs("span", { children: ["import ", "{ ImageGenerative }", " from \"@lastbrain/module-ai\";"] }), _jsx("span", {}), _jsx("span", { children: "<ImageGenerative" }), _jsx("span", { children: " label=\"Image du produit\"" }), _jsxs("span", { children: [" value=", "{imageUrl}"] }), _jsxs("span", { children: [" onChange=", "{setImageUrl}"] }), _jsx("span", { children: "/>" })] }) })] })] })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx("h3", { className: "text-xl font-semibold", children: "\uD83D\uDCC4 Pages Disponibles" }) }), _jsxs(CardBody, { className: "space-y-3", children: [_jsxs("div", { children: [_jsx("h4", { className: "font-semibold mb-2", children: "Pages Prot\u00E9g\u00E9es (Auth)" }), _jsx("div", { className: "space-y-2", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Chip, { size: "sm", color: "primary", variant: "flat", children: "GET" }), _jsx("code", { className: "text-sm", children: "/auth/token" }), _jsx("span", { className: "text-slate-600 dark:text-slate-400", children: "- Historique et balance des tokens" })] }) })] }), _jsxs("div", { children: [_jsx("h4", { className: "font-semibold mb-2", children: "Pages Admin" }), _jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Chip, { size: "sm", color: "danger", variant: "flat", children: "GET" }), _jsx("code", { className: "text-sm", children: "/admin/user-token" }), _jsx("span", { className: "text-slate-600 dark:text-slate-400", children: "- Gestion des tokens utilisateurs" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Chip, { size: "sm", color: "danger", variant: "flat", children: "GET" }), _jsx("code", { className: "text-sm", children: "/admin/user-token/[id]" }), _jsx("span", { className: "text-slate-600 dark:text-slate-400", children: "- D\u00E9tail d'un utilisateur" })] })] })] })] })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx("h3", { className: "text-xl font-semibold", children: "\uD83D\uDD0C Routes API" }) }), _jsxs(CardBody, { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Chip, { size: "sm", color: "warning", variant: "flat", children: "POST" }), _jsx("code", { className: "text-sm", children: "/api/auth/generate-text" }), _jsx("span", { className: "text-slate-600 dark:text-slate-400", children: "- G\u00E9n\u00E9ration de texte" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Chip, { size: "sm", color: "warning", variant: "flat", children: "POST" }), _jsx("code", { className: "text-sm", children: "/api/auth/generate-image" }), _jsx("span", { className: "text-slate-600 dark:text-slate-400", children: "- G\u00E9n\u00E9ration d'image" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Chip, { size: "sm", color: "success", variant: "flat", children: "GET" }), _jsx("code", { className: "text-sm", children: "/api/admin/user-token" }), _jsx("span", { className: "text-slate-600 dark:text-slate-400", children: "- Liste des tokens utilisateurs" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Chip, { size: "sm", color: "warning", variant: "flat", children: "POST" }), _jsx("code", { className: "text-sm", children: "/api/admin/user-token" }), _jsx("span", { className: "text-slate-600 dark:text-slate-400", children: "- Cr\u00E9er/modifier des tokens" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Chip, { size: "sm", color: "success", variant: "flat", children: "GET" }), _jsx("code", { className: "text-sm", children: "/api/admin/user-token/[id]" }), _jsx("span", { className: "text-slate-600 dark:text-slate-400", children: "- D\u00E9tails tokens utilisateur" })] })] })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx("h3", { className: "text-xl font-semibold", children: "\uD83D\uDCC1 Structure" }) }), _jsx(CardBody, { children: _jsx(Snippet, { symbol: "", color: "default", size: "sm", hideSymbol: true, children: _jsxs("div", { className: "flex flex-col gap-1 text-xs font-mono", children: [_jsx("span", { children: "module-ai/" }), _jsx("span", { children: "\u251C\u2500\u2500 src/" }), _jsx("span", { children: "\u2502 \u251C\u2500\u2500 web/" }), _jsx("span", { children: "\u2502 \u2502 \u251C\u2500\u2500 TextareaGenerative.tsx" }), _jsx("span", { children: "\u2502 \u2502 \u2514\u2500\u2500 ImageGenerative.tsx" }), _jsx("span", { children: "\u2502 \u251C\u2500\u2500 api/" }), _jsx("span", { children: "\u2502 \u2502 \u251C\u2500\u2500 generate-text.ts" }), _jsx("span", { children: "\u2502 \u2502 \u251C\u2500\u2500 generate-image.ts" }), _jsx("span", { children: "\u2502 \u2502 \u251C\u2500\u2500 prompts.ts" }), _jsx("span", { children: "\u2502 \u2502 \u2514\u2500\u2500 balance.ts" }), _jsx("span", { children: "\u2502 \u251C\u2500\u2500 components/" }), _jsx("span", { children: "\u2502 \u2502 \u2514\u2500\u2500 Doc.tsx" }), _jsx("span", { children: "\u2502 \u2514\u2500\u2500 ai.build.config.ts" }), _jsx("span", { children: "\u2514\u2500\u2500 supabase/" }), _jsx("span", { children: " \u2514\u2500\u2500 migrations/" }), _jsx("span", { children: " \u251C\u2500\u2500 20251121000000_ai_tokens.sql" }), _jsx("span", { children: " \u2514\u2500\u2500 20251121093113_module-ai_init.sql" })] }) }) })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx("h3", { className: "text-xl font-semibold", children: "\uD83D\uDDC4\uFE0F Tables de Donn\u00E9es" }) }), _jsxs(CardBody, { className: "space-y-4", children: [_jsx(TableStructure, { tableName: "user_token_ledger", title: "user_token_ledger", description: "Comptabilit\u00E9 des tokens (cr\u00E9dits, d\u00E9bits, balance). Vue user_token_balance pour le solde actuel." }), _jsx(TableStructure, { tableName: "user_prompts", title: "user_prompts", description: "Biblioth\u00E8que de prompts r\u00E9utilisables par utilisateur (titre, contenu, type)." })] })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx("h3", { className: "text-xl font-semibold", children: "\uD83D\uDCE6 Installation" }) }), _jsxs(CardBody, { className: "space-y-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Snippet, { symbol: "", color: "default", size: "sm", children: "pnpm lastbrain add-module ai" }), _jsx(Snippet, { symbol: "", color: "default", size: "sm", children: "pnpm build:modules" }), _jsx(Snippet, { symbol: "", color: "default", size: "sm", children: "supabase migration up" })] }), _jsxs("div", { className: "border-2 border-danger rounded-lg p-4 mt-6", children: [_jsx("h4", { className: "text-lg font-semibold text-danger mb-3", children: "\u26A0\uFE0F Danger Zone" }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400 mb-3", children: "La suppression du module supprimera toutes les pages, routes API et migrations associ\u00E9es. Cette action est irr\u00E9versible." }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Snippet, { symbol: "", color: "danger", size: "sm", children: "pnpm lastbrain remove-module ai" }), _jsx(Snippet, { symbol: "", color: "danger", size: "sm", children: "pnpm build:modules" })] })] })] })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx("h3", { className: "text-xl font-semibold", children: "\u2699\uFE0F Configuration" }) }), _jsxs(CardBody, { className: "space-y-3", children: [_jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Ajoutez votre cl\u00E9 API OpenAI dans vos variables d'environnement :" }), _jsx(Snippet, { symbol: "", color: "default", size: "sm", children: "OPENAI_API_KEY=sk-..." })] })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx("h3", { className: "text-xl font-semibold", children: "\uD83D\uDCB0 Syst\u00E8me de Tokens" }) }), _jsxs(CardBody, { className: "space-y-3", children: [_jsxs("div", { children: [_jsx("h4", { className: "font-semibold mb-2", children: "Co\u00FBts" }), _jsxs("ul", { className: "text-sm text-slate-600 dark:text-slate-400 space-y-1", children: [_jsx("li", { children: "\u2022 G\u00E9n\u00E9ration de texte : 10 tokens" }), _jsx("li", { children: "\u2022 G\u00E9n\u00E9ration d'image : 50 tokens" })] })] }), _jsxs("div", { children: [_jsx("h4", { className: "font-semibold mb-2 mt-4", children: "Trigger de validation" }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Un trigger emp\u00EAche les transactions si le solde devient n\u00E9gatif." })] }), _jsxs("div", { children: [_jsx("h4", { className: "font-semibold mb-2 mt-4", children: "Ajouter des tokens" }), _jsx(Snippet, { symbol: "", color: "default", size: "sm", hideSymbol: true, children: _jsxs("div", { className: "flex flex-col gap-1", children: [_jsx("span", { children: "INSERT INTO user_token_ledger" }), _jsx("span", { children: "(user_id, amount, transaction_type, description)" }), _jsx("span", { children: "VALUES" }), _jsx("span", { children: "(\"('user-uuid', 1000, 'credit', 'Achat de tokens');\")" })] }) })] })] })] })] }));
|
|
4
|
+
return (_jsxs("div", { className: "space-y-6", children: [_jsxs("div", { className: "flex items-start justify-between", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-3xl font-bold mb-2", children: "Module AI" }), _jsx("p", { className: "text-slate-600 dark:text-slate-400", children: "G\u00E9n\u00E9ration IA (texte et images) avec syst\u00E8me de tokens et gestion des co\u00FBts" })] }), _jsx(Chip, { color: "primary", variant: "flat", children: "v0.1.0" })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx("h3", { className: "text-xl font-semibold", children: "\uD83D\uDCDD Informations" }) }), _jsxs(CardBody, { className: "space-y-2", children: [_jsxs("div", { children: [_jsx("span", { className: "font-semibold", children: "Auteur:" }), " LastBrain Team"] }), _jsxs("div", { children: [_jsx("span", { className: "font-semibold", children: "Package:" }), " @lastbrain/module-ai"] }), _jsxs("div", { children: [_jsx("span", { className: "font-semibold", children: "Derni\u00E8re mise \u00E0 jour:" }), " 21 novembre 2025"] })] })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx("h3", { className: "text-xl font-semibold", children: "\uD83C\uDFA8 Composants Disponibles" }) }), _jsxs(CardBody, { className: "space-y-3", children: [_jsxs("div", { children: [_jsx("h4", { className: "font-semibold mb-2", children: "TextareaGenerative" }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400 mb-2", children: "Textarea avec g\u00E9n\u00E9ration de texte IA int\u00E9gr\u00E9e. Bouton de g\u00E9n\u00E9ration avec s\u00E9lection de prompts." }), _jsx(Snippet, { symbol: "", color: "default", size: "sm", hideSymbol: true, children: _jsxs("div", { className: "flex flex-col gap-1", children: [_jsxs("span", { children: ["import ", "{ TextareaGenerative }", " from \"@lastbrain/module-ai\";"] }), _jsx("span", {}), _jsx("span", { children: "<TextareaGenerative" }), _jsx("span", { children: " label=\"Description\"" }), _jsx("span", { children: " placeholder=\"Entrez une description...\"" }), _jsxs("span", { children: [" value=", "{value}"] }), _jsxs("span", { children: [" onChange=", "{setValue}"] }), _jsx("span", { children: "/>" })] }) })] }), _jsxs("div", { children: [_jsx("h4", { className: "font-semibold mb-2 mt-4", children: "ImageGenerative" }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400 mb-2", children: "Composant de g\u00E9n\u00E9ration d'images avec DALL-E. Upload ou g\u00E9n\u00E9ration IA." }), _jsx(Snippet, { symbol: "", color: "default", size: "sm", hideSymbol: true, children: _jsxs("div", { className: "flex flex-col gap-1", children: [_jsxs("span", { children: ["import ", "{ ImageGenerative }", " from \"@lastbrain/module-ai\";"] }), _jsx("span", {}), _jsx("span", { children: "<ImageGenerative" }), _jsx("span", { children: " label=\"Image du produit\"" }), _jsxs("span", { children: [" value=", "{imageUrl}"] }), _jsxs("span", { children: [" onChange=", "{setImageUrl}"] }), _jsx("span", { children: "/>" })] }) })] })] })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx("h3", { className: "text-xl font-semibold", children: "\uD83D\uDCC4 Pages Disponibles" }) }), _jsxs(CardBody, { className: "space-y-3", children: [_jsxs("div", { children: [_jsx("h4", { className: "font-semibold mb-2", children: "Pages Prot\u00E9g\u00E9es (Auth)" }), _jsx("div", { className: "space-y-2", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Chip, { size: "sm", color: "primary", variant: "flat", children: "GET" }), _jsx("code", { className: "text-sm", children: "/auth/token" }), _jsx("span", { className: "text-slate-600 dark:text-slate-400", children: "- Historique et balance des tokens" })] }) })] }), _jsxs("div", { children: [_jsx("h4", { className: "font-semibold mb-2", children: "Pages Admin" }), _jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Chip, { size: "sm", color: "danger", variant: "flat", children: "GET" }), _jsx("code", { className: "text-sm", children: "/admin/user-token" }), _jsx("span", { className: "text-slate-600 dark:text-slate-400", children: "- Gestion des tokens utilisateurs" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Chip, { size: "sm", color: "danger", variant: "flat", children: "GET" }), _jsx("code", { className: "text-sm", children: "/admin/user-token/[id]" }), _jsx("span", { className: "text-slate-600 dark:text-slate-400", children: "- D\u00E9tail d'un utilisateur" })] })] })] })] })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx("h3", { className: "text-xl font-semibold", children: "\uD83D\uDD0C Routes API" }) }), _jsxs(CardBody, { className: "space-y-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Chip, { size: "sm", color: "warning", variant: "flat", children: "POST" }), _jsx("code", { className: "text-sm", children: "/api/ai/generate-text" }), _jsx("span", { className: "text-slate-600 dark:text-slate-400", children: "- G\u00E9n\u00E9ration de texte" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Chip, { size: "sm", color: "warning", variant: "flat", children: "POST" }), _jsx("code", { className: "text-sm", children: "/api/ai/generate-image" }), _jsx("span", { className: "text-slate-600 dark:text-slate-400", children: "- G\u00E9n\u00E9ration d'image" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Chip, { size: "sm", color: "success", variant: "flat", children: "GET" }), _jsx("code", { className: "text-sm", children: "/api/ai/admin/user-token" }), _jsx("span", { className: "text-slate-600 dark:text-slate-400", children: "- Liste des tokens utilisateurs" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Chip, { size: "sm", color: "warning", variant: "flat", children: "POST" }), _jsx("code", { className: "text-sm", children: "/api/ai/admin/user-token" }), _jsx("span", { className: "text-slate-600 dark:text-slate-400", children: "- Cr\u00E9er/modifier des tokens" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Chip, { size: "sm", color: "success", variant: "flat", children: "GET" }), _jsx("code", { className: "text-sm", children: "/api/ai/admin/user-token/[id]" }), _jsx("span", { className: "text-slate-600 dark:text-slate-400", children: "- D\u00E9tails tokens utilisateur" })] })] })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx("h3", { className: "text-xl font-semibold", children: "\uD83D\uDCC1 Structure" }) }), _jsx(CardBody, { children: _jsx(Snippet, { symbol: "", color: "default", size: "sm", hideSymbol: true, children: _jsxs("div", { className: "flex flex-col gap-1 text-xs font-mono", children: [_jsx("span", { children: "module-ai/" }), _jsx("span", { children: "\u251C\u2500\u2500 src/" }), _jsx("span", { children: "\u2502 \u251C\u2500\u2500 web/" }), _jsx("span", { children: "\u2502 \u2502 \u251C\u2500\u2500 TextareaGenerative.tsx" }), _jsx("span", { children: "\u2502 \u2502 \u2514\u2500\u2500 ImageGenerative.tsx" }), _jsx("span", { children: "\u2502 \u251C\u2500\u2500 api/" }), _jsx("span", { children: "\u2502 \u2502 \u251C\u2500\u2500 generate-text.ts" }), _jsx("span", { children: "\u2502 \u2502 \u251C\u2500\u2500 generate-image.ts" }), _jsx("span", { children: "\u2502 \u2502 \u251C\u2500\u2500 prompts.ts" }), _jsx("span", { children: "\u2502 \u2502 \u2514\u2500\u2500 balance.ts" }), _jsx("span", { children: "\u2502 \u251C\u2500\u2500 components/" }), _jsx("span", { children: "\u2502 \u2502 \u2514\u2500\u2500 Doc.tsx" }), _jsx("span", { children: "\u2502 \u2514\u2500\u2500 ai.build.config.ts" }), _jsx("span", { children: "\u2514\u2500\u2500 supabase/" }), _jsx("span", { children: " \u2514\u2500\u2500 migrations/" }), _jsx("span", { children: " \u251C\u2500\u2500 20251121000000_ai_tokens.sql" }), _jsx("span", { children: " \u2514\u2500\u2500 20251121093113_module-ai_init.sql" })] }) }) })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx("h3", { className: "text-xl font-semibold", children: "\uD83D\uDDC4\uFE0F Tables de Donn\u00E9es" }) }), _jsxs(CardBody, { className: "space-y-4", children: [_jsx(TableStructure, { tableName: "user_token_ledger", title: "user_token_ledger", description: "Comptabilit\u00E9 des tokens (cr\u00E9dits, d\u00E9bits, balance). Vue user_token_balance pour le solde actuel." }), _jsx(TableStructure, { tableName: "user_prompts", title: "user_prompts", description: "Biblioth\u00E8que de prompts r\u00E9utilisables par utilisateur (titre, contenu, type)." })] })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx("h3", { className: "text-xl font-semibold", children: "\uD83D\uDCE6 Installation" }) }), _jsxs(CardBody, { className: "space-y-4", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Snippet, { symbol: "", color: "default", size: "sm", children: "pnpm lastbrain add-module ai" }), _jsx(Snippet, { symbol: "", color: "default", size: "sm", children: "pnpm build:modules" }), _jsx(Snippet, { symbol: "", color: "default", size: "sm", children: "supabase migration up" })] }), _jsxs("div", { className: "border-2 border-danger rounded-lg p-4 mt-6", children: [_jsx("h4", { className: "text-lg font-semibold text-danger mb-3", children: "\u26A0\uFE0F Danger Zone" }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400 mb-3", children: "La suppression du module supprimera toutes les pages, routes API et migrations associ\u00E9es. Cette action est irr\u00E9versible." }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Snippet, { symbol: "", color: "danger", size: "sm", children: "pnpm lastbrain remove-module ai" }), _jsx(Snippet, { symbol: "", color: "danger", size: "sm", children: "pnpm build:modules" })] })] })] })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx("h3", { className: "text-xl font-semibold", children: "\u2699\uFE0F Configuration" }) }), _jsxs(CardBody, { className: "space-y-3", children: [_jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Ajoutez votre cl\u00E9 API OpenAI dans vos variables d'environnement :" }), _jsx(Snippet, { symbol: "", color: "default", size: "sm", children: "OPENAI_API_KEY=sk-..." })] })] }), _jsxs(Card, { children: [_jsx(CardHeader, { children: _jsx("h3", { className: "text-xl font-semibold", children: "\uD83D\uDCB0 Syst\u00E8me de Tokens" }) }), _jsxs(CardBody, { className: "space-y-3", children: [_jsxs("div", { children: [_jsx("h4", { className: "font-semibold mb-2", children: "Co\u00FBts" }), _jsxs("ul", { className: "text-sm text-slate-600 dark:text-slate-400 space-y-1", children: [_jsx("li", { children: "\u2022 G\u00E9n\u00E9ration de texte : 10 tokens" }), _jsx("li", { children: "\u2022 G\u00E9n\u00E9ration d'image : 50 tokens" })] })] }), _jsxs("div", { children: [_jsx("h4", { className: "font-semibold mb-2 mt-4", children: "Trigger de validation" }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400", children: "Un trigger emp\u00EAche les transactions si le solde devient n\u00E9gatif." })] }), _jsxs("div", { children: [_jsx("h4", { className: "font-semibold mb-2 mt-4", children: "Ajouter des tokens" }), _jsx(Snippet, { symbol: "", color: "default", size: "sm", hideSymbol: true, children: _jsxs("div", { className: "flex flex-col gap-1", children: [_jsx("span", { children: "INSERT INTO user_token_ledger" }), _jsx("span", { children: "(user_id, amount, transaction_type, description)" }), _jsx("span", { children: "VALUES" }), _jsx("span", { children: "(\"('user-uuid', 1000, 'credit', 'Achat de tokens');\")" })] }) })] })] })] })] }));
|
|
5
5
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export { TokenPage } from "./web/auth/TokenPage.js";
|
|
|
4
4
|
export { UserTokenPage } from "./web/admin/UserTokenPage.js";
|
|
5
5
|
export { UserTokenIdPage } from "./web/admin/UserTokenIdPage.js";
|
|
6
6
|
export { AiModuleDoc } from "./components/Doc.js";
|
|
7
|
-
export type { GenerativeResponse, TextareaGenerativeProps } from "./web/components/TextareaGenerative.js";
|
|
8
|
-
export type { GenerativeImageResponse, ImageGenerativeProps } from "./web/components/ImageGenerative.js";
|
|
7
|
+
export type { GenerativeResponse, TextareaGenerativeProps, } from "./web/components/TextareaGenerative.js";
|
|
8
|
+
export type { GenerativeImageResponse, ImageGenerativeProps, } from "./web/components/ImageGenerative.js";
|
|
9
9
|
export { default as buildConfig } from "./ai.build.config.js";
|
|
10
10
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAGtE,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAGpD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAGjE,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGlD,YAAY,EACV,kBAAkB,EAClB,uBAAuB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAGtE,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAGpD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAGjE,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGlD,YAAY,EACV,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,wCAAwC,CAAC;AAEhD,YAAY,EACV,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,qCAAqC,CAAC;AAG7C,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/server.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export interface TokenLedgerEntry {
|
|
|
13
13
|
id: string;
|
|
14
14
|
owner_id: string;
|
|
15
15
|
ts: string;
|
|
16
|
-
type:
|
|
16
|
+
type: "purchase" | "gift" | "use" | "adjust";
|
|
17
17
|
amount: number;
|
|
18
18
|
model?: string;
|
|
19
19
|
prompt?: string;
|
|
@@ -24,11 +24,11 @@ export interface TokenLedgerEntry {
|
|
|
24
24
|
/**
|
|
25
25
|
* Ajoute des tokens au compte d'un utilisateur
|
|
26
26
|
*/
|
|
27
|
-
export declare function addTokens(userId: string, amount: number, type?:
|
|
27
|
+
export declare function addTokens(userId: string, amount: number, type?: "purchase" | "gift" | "adjust", meta?: Record<string, any>, createdBy?: string): Promise<TokenOperationResult>;
|
|
28
28
|
/**
|
|
29
29
|
* Utilise des tokens du compte d'un utilisateur
|
|
30
30
|
*/
|
|
31
|
-
export declare function
|
|
31
|
+
export declare function deductTokens(userId: string, amount: number, model?: string, prompt?: string, meta?: Record<string, any>): Promise<TokenOperationResult>;
|
|
32
32
|
/**
|
|
33
33
|
* Récupère le solde de tokens d'un utilisateur
|
|
34
34
|
*/
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,UAAU,GAAG,MAAM,GAAG,QAAiB,EAC7C,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,EAC9B,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,oBAAoB,CAAC,
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,UAAU,GAAG,MAAM,GAAG,QAAiB,EAC7C,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,EAC9B,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,oBAAoB,CAAC,CA+B/B;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,EACf,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CAoD/B;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAoBrE;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,OAAO,CAAC,CAGlB;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,KAAK,GAAE,MAAW,EAClB,MAAM,GAAE,MAAU,GACjB,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAiB7B;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM;;;;;;GA4CjD;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,KAAK,GAAE,MAAW,EAClB,MAAM,GAAE,MAAU;;;KAiBnB"}
|
package/dist/server.js
CHANGED
|
@@ -3,14 +3,22 @@ import { getSupabaseServerClient } from "@lastbrain/core/server";
|
|
|
3
3
|
/**
|
|
4
4
|
* Ajoute des tokens au compte d'un utilisateur
|
|
5
5
|
*/
|
|
6
|
-
export async function addTokens(userId, amount, type =
|
|
6
|
+
export async function addTokens(userId, amount, type = "gift", meta = {}, createdBy) {
|
|
7
7
|
if (amount <= 0) {
|
|
8
|
-
return {
|
|
8
|
+
return {
|
|
9
|
+
success: false,
|
|
10
|
+
balance: 0,
|
|
11
|
+
error: "Le montant doit être positif",
|
|
12
|
+
};
|
|
9
13
|
}
|
|
10
14
|
const supabase = await getSupabaseServerClient();
|
|
11
15
|
try {
|
|
12
|
-
const { error } = await supabase.from(
|
|
13
|
-
owner_id: userId,
|
|
16
|
+
const { error } = await supabase.from("user_token_ledger").insert({
|
|
17
|
+
owner_id: userId,
|
|
18
|
+
type,
|
|
19
|
+
amount,
|
|
20
|
+
meta,
|
|
21
|
+
created_by: createdBy,
|
|
14
22
|
});
|
|
15
23
|
if (error)
|
|
16
24
|
throw error;
|
|
@@ -18,16 +26,24 @@ export async function addTokens(userId, amount, type = 'gift', meta = {}, create
|
|
|
18
26
|
return { success: true, balance };
|
|
19
27
|
}
|
|
20
28
|
catch (error) {
|
|
21
|
-
console.error(
|
|
22
|
-
return {
|
|
29
|
+
console.error("[addTokens] Error:", error);
|
|
30
|
+
return {
|
|
31
|
+
success: false,
|
|
32
|
+
balance: 0,
|
|
33
|
+
error: error.message || "Erreur lors de l'ajout de tokens",
|
|
34
|
+
};
|
|
23
35
|
}
|
|
24
36
|
}
|
|
25
37
|
/**
|
|
26
38
|
* Utilise des tokens du compte d'un utilisateur
|
|
27
39
|
*/
|
|
28
|
-
export async function
|
|
40
|
+
export async function deductTokens(userId, amount, model, prompt, meta = {}) {
|
|
29
41
|
if (amount <= 0) {
|
|
30
|
-
return {
|
|
42
|
+
return {
|
|
43
|
+
success: false,
|
|
44
|
+
balance: 0,
|
|
45
|
+
error: "Le montant doit être positif",
|
|
46
|
+
};
|
|
31
47
|
}
|
|
32
48
|
const supabase = await getSupabaseServerClient();
|
|
33
49
|
try {
|
|
@@ -36,24 +52,24 @@ export async function useTokens(userId, amount, model, prompt, meta = {}) {
|
|
|
36
52
|
return {
|
|
37
53
|
success: false,
|
|
38
54
|
balance: currentBalance,
|
|
39
|
-
error: `Solde insuffisant. Disponible: ${currentBalance}, requis: ${amount}
|
|
55
|
+
error: `Solde insuffisant. Disponible: ${currentBalance}, requis: ${amount}`,
|
|
40
56
|
};
|
|
41
57
|
}
|
|
42
|
-
const { error } = await supabase.from(
|
|
58
|
+
const { error } = await supabase.from("user_token_ledger").insert({
|
|
43
59
|
owner_id: userId,
|
|
44
|
-
type:
|
|
60
|
+
type: "use",
|
|
45
61
|
amount: -amount,
|
|
46
62
|
model,
|
|
47
63
|
prompt,
|
|
48
|
-
meta
|
|
64
|
+
meta,
|
|
49
65
|
});
|
|
50
66
|
if (error) {
|
|
51
|
-
if (error.message?.includes(
|
|
67
|
+
if (error.message?.includes("INSUFFICIENT_TOKEN_BALANCE")) {
|
|
52
68
|
const currentBalance = await getTokenBalance(userId);
|
|
53
69
|
return {
|
|
54
70
|
success: false,
|
|
55
71
|
balance: currentBalance,
|
|
56
|
-
error: `Solde insuffisant. Disponible: ${currentBalance}, requis: ${amount}
|
|
72
|
+
error: `Solde insuffisant. Disponible: ${currentBalance}, requis: ${amount}`,
|
|
57
73
|
};
|
|
58
74
|
}
|
|
59
75
|
throw error;
|
|
@@ -62,8 +78,12 @@ export async function useTokens(userId, amount, model, prompt, meta = {}) {
|
|
|
62
78
|
return { success: true, balance };
|
|
63
79
|
}
|
|
64
80
|
catch (error) {
|
|
65
|
-
console.error(
|
|
66
|
-
return {
|
|
81
|
+
console.error("[deductTokens] Error:", error);
|
|
82
|
+
return {
|
|
83
|
+
success: false,
|
|
84
|
+
balance: 0,
|
|
85
|
+
error: error.message || "Erreur lors de l'utilisation de tokens",
|
|
86
|
+
};
|
|
67
87
|
}
|
|
68
88
|
}
|
|
69
89
|
/**
|
|
@@ -73,19 +93,19 @@ export async function getTokenBalance(userId) {
|
|
|
73
93
|
const supabase = await getSupabaseServerClient();
|
|
74
94
|
try {
|
|
75
95
|
const { data, error } = await supabase
|
|
76
|
-
.from(
|
|
77
|
-
.select(
|
|
78
|
-
.eq(
|
|
96
|
+
.from("user_token_balance_v")
|
|
97
|
+
.select("balance")
|
|
98
|
+
.eq("owner_id", userId)
|
|
79
99
|
.single();
|
|
80
100
|
if (error) {
|
|
81
|
-
if (error.code ===
|
|
101
|
+
if (error.code === "PGRST116")
|
|
82
102
|
return 0;
|
|
83
103
|
throw error;
|
|
84
104
|
}
|
|
85
105
|
return data?.balance || 0;
|
|
86
106
|
}
|
|
87
107
|
catch (error) {
|
|
88
|
-
console.error(
|
|
108
|
+
console.error("[getTokenBalance] Error:", error);
|
|
89
109
|
return 0;
|
|
90
110
|
}
|
|
91
111
|
}
|
|
@@ -103,17 +123,17 @@ export async function getTokenHistory(userId, limit = 50, offset = 0) {
|
|
|
103
123
|
const supabase = await getSupabaseServerClient();
|
|
104
124
|
try {
|
|
105
125
|
const { data, error } = await supabase
|
|
106
|
-
.from(
|
|
107
|
-
.select(
|
|
108
|
-
.eq(
|
|
109
|
-
.order(
|
|
126
|
+
.from("user_token_ledger")
|
|
127
|
+
.select("*")
|
|
128
|
+
.eq("owner_id", userId)
|
|
129
|
+
.order("ts", { ascending: false })
|
|
110
130
|
.range(offset, offset + limit - 1);
|
|
111
131
|
if (error)
|
|
112
132
|
throw error;
|
|
113
133
|
return data || [];
|
|
114
134
|
}
|
|
115
135
|
catch (error) {
|
|
116
|
-
console.error(
|
|
136
|
+
console.error("[getTokenHistory] Error:", error);
|
|
117
137
|
return [];
|
|
118
138
|
}
|
|
119
139
|
}
|
|
@@ -124,9 +144,9 @@ export async function getTokenStats(userId) {
|
|
|
124
144
|
const supabase = await getSupabaseServerClient();
|
|
125
145
|
try {
|
|
126
146
|
const { data, error } = await supabase
|
|
127
|
-
.from(
|
|
128
|
-
.select(
|
|
129
|
-
.eq(
|
|
147
|
+
.from("user_token_ledger")
|
|
148
|
+
.select("type, amount")
|
|
149
|
+
.eq("owner_id", userId);
|
|
130
150
|
if (error)
|
|
131
151
|
throw error;
|
|
132
152
|
const stats = {
|
|
@@ -134,33 +154,33 @@ export async function getTokenStats(userId) {
|
|
|
134
154
|
totalPurchased: 0,
|
|
135
155
|
totalGifted: 0,
|
|
136
156
|
totalUsed: 0,
|
|
137
|
-
totalAdjusted: 0
|
|
157
|
+
totalAdjusted: 0,
|
|
138
158
|
};
|
|
139
159
|
data?.forEach((entry) => {
|
|
140
160
|
stats.balance += entry.amount;
|
|
141
|
-
if (entry.type ===
|
|
161
|
+
if (entry.type === "purchase" && entry.amount > 0) {
|
|
142
162
|
stats.totalPurchased += entry.amount;
|
|
143
163
|
}
|
|
144
|
-
else if (entry.type ===
|
|
164
|
+
else if (entry.type === "gift" && entry.amount > 0) {
|
|
145
165
|
stats.totalGifted += entry.amount;
|
|
146
166
|
}
|
|
147
|
-
else if (entry.type ===
|
|
167
|
+
else if (entry.type === "use" && entry.amount < 0) {
|
|
148
168
|
stats.totalUsed += Math.abs(entry.amount);
|
|
149
169
|
}
|
|
150
|
-
else if (entry.type ===
|
|
170
|
+
else if (entry.type === "adjust") {
|
|
151
171
|
stats.totalAdjusted += entry.amount;
|
|
152
172
|
}
|
|
153
173
|
});
|
|
154
174
|
return stats;
|
|
155
175
|
}
|
|
156
176
|
catch (error) {
|
|
157
|
-
console.error(
|
|
177
|
+
console.error("[getTokenStats] Error:", error);
|
|
158
178
|
return {
|
|
159
179
|
balance: 0,
|
|
160
180
|
totalPurchased: 0,
|
|
161
181
|
totalGifted: 0,
|
|
162
182
|
totalUsed: 0,
|
|
163
|
-
totalAdjusted: 0
|
|
183
|
+
totalAdjusted: 0,
|
|
164
184
|
};
|
|
165
185
|
}
|
|
166
186
|
}
|
|
@@ -171,16 +191,16 @@ export async function getAllUsersTokenBalance(limit = 50, offset = 0) {
|
|
|
171
191
|
const supabase = await getSupabaseServerClient();
|
|
172
192
|
try {
|
|
173
193
|
const { data, error } = await supabase
|
|
174
|
-
.from(
|
|
175
|
-
.select(
|
|
176
|
-
.order(
|
|
194
|
+
.from("user_token_balance_v")
|
|
195
|
+
.select("owner_id, balance")
|
|
196
|
+
.order("balance", { ascending: false })
|
|
177
197
|
.range(offset, offset + limit - 1);
|
|
178
198
|
if (error)
|
|
179
199
|
throw error;
|
|
180
200
|
return data || [];
|
|
181
201
|
}
|
|
182
202
|
catch (error) {
|
|
183
|
-
console.error(
|
|
203
|
+
console.error("[getAllUsersTokenBalance] Error:", error);
|
|
184
204
|
return [];
|
|
185
205
|
}
|
|
186
206
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageGenerative.d.ts","sourceRoot":"","sources":["../../../src/web/components/ImageGenerative.tsx"],"names":[],"mappings":"AAOA,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,CAAC;IACvE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC5B,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,uBAAuB,KAAK,IAAI,CAAC;IACvD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,wBAAgB,eAAe,CAAC,EAC9B,MAAM,EACN,KAAkB,EAClB,IAAkB,EAClB,OAAoB,EACpB,QAAQ,EACR,OAAO,EACP,SAAS,EACT,QAAgB,EAChB,
|
|
1
|
+
{"version":3,"file":"ImageGenerative.d.ts","sourceRoot":"","sources":["../../../src/web/components/ImageGenerative.tsx"],"names":[],"mappings":"AAOA,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,CAAC;IACvE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC5B,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,uBAAuB,KAAK,IAAI,CAAC;IACvD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,wBAAgB,eAAe,CAAC,EAC9B,MAAM,EACN,KAAkB,EAClB,IAAkB,EAClB,OAAoB,EACpB,QAAQ,EACR,OAAO,EACP,SAAS,EACT,QAAgB,EAChB,WAAsC,EACtC,gBAAuB,GACxB,EAAE,oBAAoB,2CA6LtB"}
|
|
@@ -4,7 +4,7 @@ import { useState, useCallback } from "react";
|
|
|
4
4
|
import { Button, Chip, Progress, Card, CardBody } from "@lastbrain/ui";
|
|
5
5
|
import { Sparkles, Loader2, AlertCircle, Download } from "lucide-react";
|
|
6
6
|
import Image from "next/image";
|
|
7
|
-
export function ImageGenerative({ prompt, model = "dall-e-3", size = "1024x1024", quality = "standard", onChange, onError, className, disabled = false, apiEndpoint = "/api/
|
|
7
|
+
export function ImageGenerative({ prompt, model = "dall-e-3", size = "1024x1024", quality = "standard", onChange, onError, className, disabled = false, apiEndpoint = "/api/ai/generate-image", showTokenBalance = true, }) {
|
|
8
8
|
const [isGenerating, setIsGenerating] = useState(false);
|
|
9
9
|
const [generatedImage, setGeneratedImage] = useState(null);
|
|
10
10
|
const [error, setError] = useState(null);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextareaGenerative.d.ts","sourceRoot":"","sources":["../../../src/web/components/TextareaGenerative.tsx"],"names":[],"mappings":"AAMA,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAClD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,wBAAgB,kBAAkB,CAAC,EACjC,MAAM,EACN,KAAqB,EACrB,WAAmC,EACnC,YAAiB,EACjB,QAAQ,EACR,OAAO,EACP,SAAS,EACT,QAAgB,EAChB,OAAW,EACX,OAAY,EACZ,
|
|
1
|
+
{"version":3,"file":"TextareaGenerative.d.ts","sourceRoot":"","sources":["../../../src/web/components/TextareaGenerative.tsx"],"names":[],"mappings":"AAMA,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAClD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,wBAAgB,kBAAkB,CAAC,EACjC,MAAM,EACN,KAAqB,EACrB,WAAmC,EACnC,YAAiB,EACjB,QAAQ,EACR,OAAO,EACP,SAAS,EACT,QAAgB,EAChB,OAAW,EACX,OAAY,EACZ,WAAqC,EACrC,gBAAuB,GACxB,EAAE,uBAAuB,2CAwIzB"}
|
|
@@ -3,7 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { useState, useCallback } from "react";
|
|
4
4
|
import { Textarea, Button, Chip, Progress } from "@lastbrain/ui";
|
|
5
5
|
import { Sparkles, Loader2, AlertCircle } from "lucide-react";
|
|
6
|
-
export function TextareaGenerative({ prompt, model = "gpt-4o-mini", placeholder = "Générer du texte...", defaultValue = "", onChange, onError, className, disabled = false, minRows = 4, maxRows = 20, apiEndpoint = "/api/
|
|
6
|
+
export function TextareaGenerative({ prompt, model = "gpt-4o-mini", placeholder = "Générer du texte...", defaultValue = "", onChange, onError, className, disabled = false, minRows = 4, maxRows = 20, apiEndpoint = "/api/ai/generate-text", showTokenBalance = true, }) {
|
|
7
7
|
const [value, setValue] = useState(defaultValue);
|
|
8
8
|
const [isGenerating, setIsGenerating] = useState(false);
|
|
9
9
|
const [lastResponse, setLastResponse] = useState(null);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lastbrain/module-ai",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Module de génération IA (texte et images) avec gestion de tokens pour LastBrain",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -37,8 +37,9 @@
|
|
|
37
37
|
"openai": "^4.76.0",
|
|
38
38
|
"react": "^19.0.0",
|
|
39
39
|
"react-dom": "^19.0.0",
|
|
40
|
-
"
|
|
41
|
-
"@lastbrain/
|
|
40
|
+
"zod": "^3.23.8",
|
|
41
|
+
"@lastbrain/core": "0.1.3",
|
|
42
|
+
"@lastbrain/ui": "0.1.7"
|
|
42
43
|
},
|
|
43
44
|
"peerDependencies": {
|
|
44
45
|
"next": ">=15.0.0"
|
|
@@ -67,6 +68,7 @@
|
|
|
67
68
|
"sideEffects": false,
|
|
68
69
|
"scripts": {
|
|
69
70
|
"build": "tsc -p tsconfig.json",
|
|
70
|
-
"dev": "tsc -p tsconfig.json --watch"
|
|
71
|
+
"dev": "tsc -p tsconfig.json --watch",
|
|
72
|
+
"lint": "eslint ."
|
|
71
73
|
}
|
|
72
74
|
}
|