@lastbrain/module-ai 0.1.10 → 0.1.13

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.
Files changed (40) hide show
  1. package/README.md +1 -2
  2. package/dist/ai.build.config.d.ts.map +1 -1
  3. package/dist/ai.build.config.js +24 -6
  4. package/dist/api/admin/user-token/[id].d.ts +6 -1
  5. package/dist/api/admin/user-token/[id].d.ts.map +1 -1
  6. package/dist/api/admin/user-token/[id].js +16 -14
  7. package/dist/api/admin/user-token.d.ts +19 -3
  8. package/dist/api/admin/user-token.d.ts.map +1 -1
  9. package/dist/api/admin/user-token.js +85 -26
  10. package/dist/api/auth/generate-text.js +1 -1
  11. package/dist/api/auth/user-tokens.d.ts +17 -0
  12. package/dist/api/auth/user-tokens.d.ts.map +1 -0
  13. package/dist/api/auth/user-tokens.js +34 -0
  14. package/dist/components/Doc.d.ts.map +1 -1
  15. package/dist/components/Doc.js +2 -5
  16. package/dist/components/DocUsageCustom.d.ts +9 -0
  17. package/dist/components/DocUsageCustom.d.ts.map +1 -0
  18. package/dist/components/DocUsageCustom.js +70 -0
  19. package/dist/components/admin/UserTokenTab.d.ts +6 -0
  20. package/dist/components/admin/UserTokenTab.d.ts.map +1 -0
  21. package/dist/components/admin/UserTokenTab.js +112 -0
  22. package/dist/index.d.ts +1 -1
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +2 -1
  25. package/dist/web/admin/UserTokenPage.d.ts.map +1 -1
  26. package/dist/web/admin/UserTokenPage.js +103 -2
  27. package/dist/web/auth/TokenPage.d.ts.map +1 -1
  28. package/dist/web/auth/TokenPage.js +110 -2
  29. package/dist/web/components/ImageGenerative.d.ts +6 -3
  30. package/dist/web/components/ImageGenerative.d.ts.map +1 -1
  31. package/dist/web/components/ImageGenerative.js +51 -12
  32. package/dist/web/components/TextareaGenerative.d.ts +5 -3
  33. package/dist/web/components/TextareaGenerative.d.ts.map +1 -1
  34. package/dist/web/components/TextareaGenerative.js +33 -12
  35. package/package.json +4 -4
  36. package/supabase/migrations-down/20251125000000_ai_tokens.sql +45 -0
  37. package/supabase/migrations/20251121093113_module-ai_init.sql +0 -122
  38. package/supabase/migrations-down/20251121000000_ai_tokens.sql +0 -23
  39. package/supabase/migrations-down/20251121093113_module-ai_init.sql +0 -11
  40. /package/supabase/migrations/{20251121000000_ai_tokens.sql → 20251125000000_ai_tokens.sql} +0 -0
package/README.md CHANGED
@@ -44,8 +44,7 @@
44
44
 
45
45
  ### Migrations
46
46
 
47
- - `20251121000000_ai_tokens.sql`
48
- - `20251121093113_module-ai_init.sql`
47
+ - `20251125000000_ai_tokens.sql`
49
48
 
50
49
  ## 📦 Installation
51
50
 
@@ -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,iBAoFlB,CAAC;AAEF,eAAe,WAAW,CAAC"}
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"}
@@ -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: ["20251121000000_ai_tokens.sql"],
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, props: {
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,KAAK,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE;;;;;;;;;;;;;;;;;;;;;;IA6D3C"}
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 { getSupabaseServerClient } from "@lastbrain/core/server";
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, props) {
6
- const params = await props.params;
7
- const { id } = params;
5
+ export async function GET(request, context) {
6
+ const { id: userId } = await context.params;
8
7
  try {
9
- const supabase = await getSupabaseServerClient();
8
+ const supabase = getSupabaseServiceClient();
10
9
  // Vérifier l'authentification et les permissions admin
11
- const { data: { user: _user }, } = await supabase.auth.getUser();
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 = id;
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 || !targetUser) {
17
- return NextResponse.json({ error: "Utilisateur non trouvé" }, { status: 404 });
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
- id: targetUser.user.id,
31
- email: targetUser.user.email,
32
- createdAt: targetUser.user.created_at,
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(_request: NextRequest): Promise<NextResponse<{
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
- balance: any;
7
- createdAt: string | undefined;
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,QAAQ,EAAE,WAAW;;;;;;;;;;IA0C9C;AAGD,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW;;;;;;IAqD9C"}
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 { getSupabaseServerClient } from "@lastbrain/core/server";
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(_request) {
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 = await getSupabaseServerClient();
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 avec leur balance
10
- const { data: balances, error: balanceError } = await supabase
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
- // Combiner les données
22
- const usersWithBalance = balances?.map((balance) => {
23
- const userInfo = users.users.find((u) => u.id === balance.owner_id);
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: balance.owner_id,
26
- email: userInfo?.email || "Unknown",
27
- balance: balance.balance,
28
- createdAt: userInfo?.created_at,
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: usersWithBalance,
33
- total: usersWithBalance?.length || 0,
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 = await getSupabaseServerClient();
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", admin_id: user.id }, user.id);
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 = 2000, temperature = 0.7, } = body;
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":"AAgBA;;;;;;GAMG;AACH,wBAAgB,GAAG,4CA4PlB"}
1
+ {"version":3,"file":"Doc.d.ts","sourceRoot":"","sources":["../../src/components/Doc.tsx"],"names":[],"mappings":"AAiBA;;;;;;GAMG;AACH,wBAAgB,GAAG,4CAsOlB"}
@@ -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"] }) }), _jsxs(CardBody, { className: "space-y-4", children: [_jsxs(Alert, { color: "default", className: "mb-4", children: [_jsxs("p", { className: "text-sm", children: ["\uD83D\uDCDD ", _jsx("strong", { children: "Section \u00E0 compl\u00E9ter par l'auteur du module" })] }), _jsx("p", { className: "text-sm text-slate-600 dark:text-slate-400 mt-2", children: "Ajoutez ici des exemples d'utilisation, des configurations sp\u00E9cifiques, et toute information utile pour les d\u00E9veloppeurs utilisant ce module." })] }), _jsxs("div", { children: [_jsx("h3", { className: "text-lg font-semibold mb-2", children: "Exemple d'utilisation" }), _jsx(Alert, { color: "primary", className: "p-4 mb-4", children: _jsx("pre", { className: "whitespace-pre-wrap", children: `// Importez les composants depuis le module
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,6 @@
1
+ interface UserTokenTabProps {
2
+ userId: string;
3
+ }
4
+ export declare function UserTokenTab({ userId }: UserTokenTabProps): import("react/jsx-runtime").JSX.Element;
5
+ export {};
6
+ //# sourceMappingURL=UserTokenTab.d.ts.map
@@ -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"}