@lastbrain/module-ai 2.0.18 → 2.0.26
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/api/auth/generate-text.d.ts +0 -1
- package/dist/api/auth/generate-text.d.ts.map +1 -1
- package/dist/api/auth/generate-text.js +6 -4
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/web/components/ButtonGenerative.d.ts +24 -0
- package/dist/web/components/ButtonGenerative.d.ts.map +1 -0
- package/dist/web/components/ButtonGenerative.js +91 -0
- package/dist/web/components/ImageGenerative.d.ts.map +1 -1
- package/dist/web/components/ImageGenerative.js +102 -1
- package/dist/web/components/TextareaGenerative.d.ts.map +1 -1
- package/dist/web/components/TextareaGenerative.js +4 -2
- package/package.json +4 -4
|
@@ -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;AAwBxD,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;AAwBxD,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW;;;;;;;IAuI9C"}
|
|
@@ -22,12 +22,15 @@ export async function POST(request) {
|
|
|
22
22
|
if (!prompt) {
|
|
23
23
|
return NextResponse.json({ error: "Le prompt est requis" }, { status: 400 });
|
|
24
24
|
}
|
|
25
|
+
if (!user) {
|
|
26
|
+
return NextResponse.json({ error: "Non authentifié" }, { status: 401 });
|
|
27
|
+
}
|
|
25
28
|
// Vérifier le solde de tokens
|
|
26
29
|
const currentBalance = await getTokenBalance(user.id);
|
|
27
|
-
const estimatedCost = Math.ceil(prompt.length / 4) + maxTokens; // Estimation approximative
|
|
28
|
-
if (currentBalance < estimatedCost) {
|
|
30
|
+
const estimatedCost = 0; //Math.ceil(prompt.length / 4) + maxTokens; // Estimation approximative
|
|
31
|
+
if (currentBalance < estimatedCost || currentBalance <= 0) {
|
|
29
32
|
return NextResponse.json({
|
|
30
|
-
error: `Solde insuffisant. Disponible: ${currentBalance}
|
|
33
|
+
error: `Solde insuffisant. Disponible: ${currentBalance}`,
|
|
31
34
|
}, { status: 402 });
|
|
32
35
|
}
|
|
33
36
|
// Construire les messages
|
|
@@ -91,7 +94,6 @@ export async function POST(request) {
|
|
|
91
94
|
tokensUsed,
|
|
92
95
|
tokensRemaining: tokenResult.balance,
|
|
93
96
|
model,
|
|
94
|
-
cost,
|
|
95
97
|
});
|
|
96
98
|
}
|
|
97
99
|
catch (error) {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { TextareaGenerative } from "./web/components/TextareaGenerative";
|
|
2
2
|
export { ImageGenerative } from "./web/components/ImageGenerative";
|
|
3
|
+
export { ButtonGenerative } from "./web/components/ButtonGenerative";
|
|
3
4
|
export { TokenPage } from "./web/auth/TokenPage";
|
|
4
5
|
export { UserTokenPage } from "./web/admin/UserTokenPage";
|
|
5
6
|
export { AdminTokenPacksPage } from "./web/admin/AdminTokenPacksPage";
|
|
@@ -8,5 +9,6 @@ export { Doc } from "./components/Doc";
|
|
|
8
9
|
export { Doc as AiModuleDoc } from "./components/Doc";
|
|
9
10
|
export type { GenerativeResponse, TextareaGenerativeProps, } from "./web/components/TextareaGenerative";
|
|
10
11
|
export type { GenerativeImageResponse, ImageGenerativeProps, } from "./web/components/ImageGenerative";
|
|
12
|
+
export type { ButtonGenerativeResponse, ButtonGenerativeProps, } from "./web/components/ButtonGenerative";
|
|
11
13
|
export { default as buildConfig } from "./ai.build.config";
|
|
12
14
|
//# 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,qCAAqC,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAGrE,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAGjD,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAGtE,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAG/D,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,GAAG,IAAI,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGtD,YAAY,EACV,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,qCAAqC,CAAC;AAE7C,YAAY,EACV,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,kCAAkC,CAAC;AAE1C,YAAY,EACV,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Client Components - Composants réutilisables
|
|
2
2
|
export { TextareaGenerative } from "./web/components/TextareaGenerative";
|
|
3
3
|
export { ImageGenerative } from "./web/components/ImageGenerative";
|
|
4
|
+
export { ButtonGenerative } from "./web/components/ButtonGenerative";
|
|
4
5
|
// Pages Auth
|
|
5
6
|
export { TokenPage } from "./web/auth/TokenPage";
|
|
6
7
|
// Pages Admin
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface ButtonGenerativeResponse {
|
|
2
|
+
text: string;
|
|
3
|
+
tokensUsed: number;
|
|
4
|
+
tokensRemaining: number;
|
|
5
|
+
model: string;
|
|
6
|
+
cost?: number;
|
|
7
|
+
}
|
|
8
|
+
export interface ButtonGenerativeProps {
|
|
9
|
+
label: string;
|
|
10
|
+
size?: "sm" | "md" | "lg";
|
|
11
|
+
className?: string;
|
|
12
|
+
prompt: string;
|
|
13
|
+
model?: string;
|
|
14
|
+
onResult: (response: ButtonGenerativeResponse) => void;
|
|
15
|
+
onError?: (error: Error) => void;
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
apiEndpoint?: string;
|
|
18
|
+
showTokenBalance?: boolean;
|
|
19
|
+
maxTokens?: number;
|
|
20
|
+
temperature?: number;
|
|
21
|
+
skeleton?: boolean;
|
|
22
|
+
}
|
|
23
|
+
export declare function ButtonGenerative({ label, size, className, prompt, model, onResult, onError, disabled, apiEndpoint, showTokenBalance, maxTokens, temperature, skeleton, }: ButtonGenerativeProps): import("react/jsx-runtime").JSX.Element;
|
|
24
|
+
//# sourceMappingURL=ButtonGenerative.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ButtonGenerative.d.ts","sourceRoot":"","sources":["../../../src/web/components/ButtonGenerative.tsx"],"names":[],"mappings":"AAOA,MAAM,WAAW,wBAAwB;IACvC,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,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,CAAC,QAAQ,EAAE,wBAAwB,KAAK,IAAI,CAAC;IACvD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,KAAK,EACL,IAAW,EACX,SAAc,EACd,MAAM,EACN,KAAqB,EACrB,QAAQ,EACR,OAAO,EACP,QAAgB,EAChB,WAAqC,EACrC,gBAAuB,EACvB,SAAgB,EAChB,WAAiB,EACjB,QAAe,GAChB,EAAE,qBAAqB,2CA+JvB"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState, useCallback } from "react";
|
|
4
|
+
import { useModuleTranslation } from "@lastbrain/core";
|
|
5
|
+
import { Button, Chip, Progress, Skeleton, addToast } from "@lastbrain/ui";
|
|
6
|
+
import { Sparkles, AlertCircle } from "lucide-react";
|
|
7
|
+
export function ButtonGenerative({ label, size = "md", className = "", prompt, model = "gpt-4o-mini", onResult, onError, disabled = false, apiEndpoint = "/api/ai/generate-text", showTokenBalance = true, maxTokens = 3000, temperature = 0.7, skeleton = true, }) {
|
|
8
|
+
const t = useModuleTranslation("ai");
|
|
9
|
+
const [isGenerating, setIsGenerating] = useState(false);
|
|
10
|
+
const [tokenBalance, setTokenBalance] = useState(null);
|
|
11
|
+
const [error, setError] = useState(null);
|
|
12
|
+
const handleGenerate = useCallback(async () => {
|
|
13
|
+
if (!prompt || isGenerating) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
setIsGenerating(true);
|
|
17
|
+
setError(null);
|
|
18
|
+
try {
|
|
19
|
+
const response = await fetch(apiEndpoint, {
|
|
20
|
+
method: "POST",
|
|
21
|
+
headers: { "Content-Type": "application/json" },
|
|
22
|
+
body: JSON.stringify({
|
|
23
|
+
prompt,
|
|
24
|
+
model,
|
|
25
|
+
maxTokens,
|
|
26
|
+
temperature,
|
|
27
|
+
}),
|
|
28
|
+
});
|
|
29
|
+
if (!response.ok) {
|
|
30
|
+
const errorData = await response.json();
|
|
31
|
+
// Handle specific error codes
|
|
32
|
+
if (response.status === 402) {
|
|
33
|
+
throw new Error(errorData.error ||
|
|
34
|
+
t("error.insufficient_tokens") ||
|
|
35
|
+
"Solde insuffisant");
|
|
36
|
+
}
|
|
37
|
+
throw new Error(errorData.error ||
|
|
38
|
+
t("error.generation_failed") ||
|
|
39
|
+
"Erreur lors de la génération");
|
|
40
|
+
}
|
|
41
|
+
const data = await response.json();
|
|
42
|
+
const generativeResponse = {
|
|
43
|
+
text: data.text,
|
|
44
|
+
tokensUsed: data.tokensUsed || 0,
|
|
45
|
+
tokensRemaining: data.tokensRemaining || 0,
|
|
46
|
+
model: data.model || model,
|
|
47
|
+
cost: data.cost,
|
|
48
|
+
};
|
|
49
|
+
setTokenBalance(data.tokensRemaining);
|
|
50
|
+
// Show success toast with credit info
|
|
51
|
+
addToast({
|
|
52
|
+
color: "success",
|
|
53
|
+
title: t("toast.generation_success") || "Génération réussie",
|
|
54
|
+
description: `${generativeResponse.tokensUsed} ${t("toast.tokens_used") || "tokens utilisés"} - ${t("toast.remaining") || "Restants"}: ${generativeResponse.tokensRemaining}`,
|
|
55
|
+
});
|
|
56
|
+
onResult(generativeResponse);
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
const errorMessage = err instanceof Error ? err.message : "Erreur inconnue";
|
|
60
|
+
setError(errorMessage);
|
|
61
|
+
// Show error toast
|
|
62
|
+
addToast({
|
|
63
|
+
color: "danger",
|
|
64
|
+
title: t("toast.generation_error") || "Erreur de génération",
|
|
65
|
+
description: errorMessage,
|
|
66
|
+
});
|
|
67
|
+
if (onError) {
|
|
68
|
+
if (err instanceof Error) {
|
|
69
|
+
onError(err);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
onError(new Error(errorMessage));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
setIsGenerating(false);
|
|
78
|
+
}
|
|
79
|
+
}, [
|
|
80
|
+
prompt,
|
|
81
|
+
model,
|
|
82
|
+
isGenerating,
|
|
83
|
+
maxTokens,
|
|
84
|
+
temperature,
|
|
85
|
+
apiEndpoint,
|
|
86
|
+
onResult,
|
|
87
|
+
onError,
|
|
88
|
+
t,
|
|
89
|
+
]);
|
|
90
|
+
return (_jsx("div", { className: className, children: _jsxs("div", { className: "flex flex-col gap-2", children: [isGenerating && skeleton && (_jsxs("div", { className: "w-full border border-default-200 p-4 rounded-xl", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Skeleton, { className: "w-lg bg-content-2 h-6 rounded-lg" }), _jsx(Skeleton, { className: "w-md bg-content-2 h-3 rounded-lg" }), _jsx(Skeleton, { className: "w-sm bg-content-2 h-3 rounded-lg" })] }), _jsx("div", { className: "mt-2", children: _jsx(Progress, { size: "sm", isIndeterminate: true, "aria-label": t("progress.generating") || "Génération en cours...", label: t("progress.generating") || "Génération en cours..." }) })] })), _jsx(Button, { color: "primary", size: size, variant: "flat", startContent: _jsx(Sparkles, { size: 16 }), onPress: handleGenerate, disabled: disabled || isGenerating || !prompt.trim(), title: label, isLoading: isGenerating, className: "w-full sm:w-auto", children: label }), showTokenBalance && tokenBalance !== null && (_jsx("div", { className: "flex items-center gap-2", children: _jsxs(Chip, { size: "sm", variant: "flat", color: "success", children: [tokenBalance.toLocaleString(), " ", t("chip.tokens_remaining") || "tokens restants"] }) })), error && (_jsxs("div", { className: "flex items-center gap-2 text-danger text-sm p-2 bg-danger-50 rounded-md", children: [_jsx(AlertCircle, { size: 16 }), _jsx("span", { children: error })] }))] }) }));
|
|
91
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageGenerative.d.ts","sourceRoot":"","sources":["../../../src/web/components/ImageGenerative.tsx"],"names":[],"mappings":"AA0CA,MAAM,WAAW,uBAAuB;IACtC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,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;
|
|
1
|
+
{"version":3,"file":"ImageGenerative.d.ts","sourceRoot":"","sources":["../../../src/web/components/ImageGenerative.tsx"],"names":[],"mappings":"AA0CA,MAAM,WAAW,uBAAuB;IACtC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,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;AAsID,MAAM,WAAW,oBAAoB;IACnC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,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,CACT,gBAAgB,EAAE,MAAM,EACxB,QAAQ,CAAC,EAAE,uBAAuB,KAC/B,IAAI,CAAC;IACV,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;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,eAAe,CAAC,EAC9B,aAAkB,EAClB,KAAkB,EAClB,IAAkB,EAClB,OAAoB,EACpB,QAAQ,EACR,OAAO,EACP,SAAS,EACT,QAAgB,EAChB,WAAsC,EACtC,gBAAuB,EACvB,KAAK,EACL,WAAW,EACX,YAA0B,EAC1B,eAAuB,EACvB,UAAU,EACV,OAAc,EACd,MAAc,GACf,EAAE,oBAAoB,2CA0lBtB"}
|
|
@@ -46,6 +46,107 @@ const imageStyles = [
|
|
|
46
46
|
description: "Peinture à l'aquarelle",
|
|
47
47
|
},
|
|
48
48
|
{ key: "pop-art", label: "Pop Art", description: "Style pop art vibrant" },
|
|
49
|
+
// 🔥 Styles ajoutés
|
|
50
|
+
{
|
|
51
|
+
key: "oil-painting",
|
|
52
|
+
label: "Peinture à l'huile",
|
|
53
|
+
description: "Textures riches, style classique",
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
key: "pixel-art",
|
|
57
|
+
label: "Pixel Art",
|
|
58
|
+
description: "Graphismes rétro pixelisés",
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
key: "low-poly",
|
|
62
|
+
label: "Low Poly",
|
|
63
|
+
description: "Modélisation simple en polygones",
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
key: "cyberpunk",
|
|
67
|
+
label: "Cyberpunk",
|
|
68
|
+
description: "Esthétique futuriste néon sombre",
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
key: "noir",
|
|
72
|
+
label: "Film Noir",
|
|
73
|
+
description: "Ambiance dramatique noir et blanc",
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
key: "vaporwave",
|
|
77
|
+
label: "Vaporwave",
|
|
78
|
+
description: "Style rétro futur rose/bleu pastel",
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
key: "fantasy",
|
|
82
|
+
label: "Fantasy",
|
|
83
|
+
description: "Univers magique et héros épiques",
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
key: "comic-book",
|
|
87
|
+
label: "Comic Book",
|
|
88
|
+
description: "Style bande dessinée américaine",
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
key: "flat-design",
|
|
92
|
+
label: "Flat Design",
|
|
93
|
+
description: "Illustration minimaliste sans ombres",
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
key: "isometric",
|
|
97
|
+
label: "Isométrique",
|
|
98
|
+
description: "Perspective 3D isométrique",
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
key: "steampunk",
|
|
102
|
+
label: "Steampunk",
|
|
103
|
+
description: "Univers mécanique rétro industriel",
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
key: "cinematic",
|
|
107
|
+
label: "Cinematic",
|
|
108
|
+
description: "Style film avec mise en scène dramatique",
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
key: "retro",
|
|
112
|
+
label: "Rétro",
|
|
113
|
+
description: "Style années 80/90",
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
key: "minimalist",
|
|
117
|
+
label: "Minimaliste",
|
|
118
|
+
description: "Formes simples, ambiance épurée",
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
key: "neon",
|
|
122
|
+
label: "Néon",
|
|
123
|
+
description: "Glow électrique et couleurs vibrantes",
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
key: "line-art",
|
|
127
|
+
label: "Line Art",
|
|
128
|
+
description: "Illustration en lignes fines",
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
key: "pastel",
|
|
132
|
+
label: "Pastel",
|
|
133
|
+
description: "Couleurs douces et lumineuses",
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
key: "dark-fantasy",
|
|
137
|
+
label: "Dark Fantasy",
|
|
138
|
+
description: "Fantasy sombre, atmosphère dramatique",
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
key: "surreal",
|
|
142
|
+
label: "Surréaliste",
|
|
143
|
+
description: "Style rêve éveillé, étrange",
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
key: "photographic-food",
|
|
147
|
+
label: "Gastronomique",
|
|
148
|
+
description: "Photo culinaire professionnelle",
|
|
149
|
+
},
|
|
49
150
|
];
|
|
50
151
|
export function ImageGenerative({ defaultPrompt = "", model = "dall-e-3", size = "1024x1024", quality = "standard", onChange, onError, className, disabled = false, apiEndpoint = "/api/ai/generate-image", showTokenBalance = true, label, description, defaultStyle = "realistic", hideStyleEditor = false, uploadPath, preview = true, inline = false, }) {
|
|
51
152
|
const t = useModuleTranslation("ai");
|
|
@@ -183,7 +284,7 @@ export function ImageGenerative({ defaultPrompt = "", model = "dall-e-3", size =
|
|
|
183
284
|
"Tailles disponibles selon le modèle", children: selectedModel === "dall-e-2" ? (_jsxs(_Fragment, { children: [_jsx(SelectItem, { children: "256\u00D7256 (3000 tokens)" }, "256x256"), _jsx(SelectItem, { children: "512\u00D7512 (4000 tokens)" }, "512x512"), _jsx(SelectItem, { children: "1024\u00D71024 (5000 tokens)" }, "1024x1024")] })) : (_jsxs(_Fragment, { children: [_jsx(SelectItem, { children: "1024\u00D71024 (6000-8000 tokens)" }, "1024x1024"), _jsx(SelectItem, { children: "1024\u00D71792 Portrait (8000-10000 tokens)" }, "1024x1792"), _jsx(SelectItem, { children: "1792\u00D71024 Paysage (8000-10000 tokens)" }, "1792x1024")] })) }), selectedModel === "dall-e-3" && (_jsxs(Select, { label: t("image.quality_label") || "Qualité", selectedKeys: [selectedQuality], onSelectionChange: (keys) => setSelectedQuality(Array.from(keys)[0]), description: t("image.quality_description") ||
|
|
184
285
|
"HD offre plus de détails mais coûte plus de tokens", children: [_jsx(SelectItem, { children: t("image.quality_standard") || "Standard" }, "standard"), _jsx(SelectItem, { children: t("image.quality_hd") || "HD (Haute Définition)" }, "hd")] })), _jsx("div", { className: "p-3 bg-primary-50 dark:bg-primary-900/20 rounded-lg", children: _jsxs("p", { className: "text-sm font-medium text-primary-700 dark:text-primary-300", children: [t("image.estimated_cost") || "Coût estimé:", " ", estimatedCost().toLocaleString(), " ", t("chip.tokens") || "tokens"] }) })] })), _jsx(Button, { color: "primary", onClick: handleGenerate, disabled: !userPrompt.trim() || disabled || isGenerating, startContent: isGenerating ? (_jsx(Loader2, { className: "animate-spin", size: 16 })) : (_jsx(Wand2, { size: 18 })), className: "w-full", children: isGenerating
|
|
185
286
|
? t("button.generating") || "Génération..."
|
|
186
|
-
: t("button.generate") || "Générer" })] })) : (_jsx(Button, { color: "primary",
|
|
287
|
+
: t("button.generate") || "Générer" })] })) : (_jsx(Button, { color: "primary", onPress: () => setIsModalOpen(true), isDisabled: disabled || isGenerating, startContent: _jsx(Wand2, { size: 18 }), className: "w-full", children: isGenerating
|
|
187
288
|
? t("button.generating") || "Génération..."
|
|
188
289
|
: t("button.generate_image") || "Générer une image" })), _jsxs("div", { className: "flex items-center justify-between gap-2 flex-wrap", children: [_jsx("div", { className: "flex items-center gap-2", children: showTokenBalance && tokenBalance !== null && (_jsxs(Chip, { size: "sm", variant: "flat", color: "success", children: [tokenBalance.toLocaleString(), " ", t("chip.tokens_remaining") || "tokens restants"] })) }), generatedImage && (_jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [_jsxs(Chip, { size: "sm", variant: "flat", children: [generatedImage.tokensUsed, " ", t("chip.tokens_used") || "tokens utilisés"] }), _jsx(Chip, { size: "sm", variant: "flat", color: "primary", children: generatedImage.model }), preview && (_jsx(Button, { size: "sm", variant: "flat", onClick: handleDownload, startContent: _jsx(Download, { size: 16 }), children: t("button.download") || "Télécharger" }))] }))] }), isGenerating && (_jsxs("div", { className: "space-y-2", children: [_jsx(Progress, { size: "sm", isIndeterminate: true, "aria-label": t("progress.generating_image") || "Génération en cours...", className: "max-w-md" }), _jsx("p", { className: "text-sm text-default-500", children: t("progress.image_generation_message") ||
|
|
189
290
|
"Génération de l'image en cours... Cela peut prendre quelques instants." })] })), error && (_jsxs("div", { className: "flex items-center gap-2 text-danger text-sm p-3 bg-danger-50 rounded-md", children: [_jsx(AlertCircle, { size: 16 }), _jsx("span", { children: error })] }))] }), _jsx(Modal, { backdrop: "blur", isOpen: isModalOpen, onClose: () => setIsModalOpen(false), size: "2xl", children: _jsxs(ModalContent, { children: [_jsx(ModalHeader, { children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(ImageIcon, { size: 20 }), _jsx("span", { children: t("modal.image_title") || "Générer une image avec l'IA" })] }) }), _jsx(ModalBody, { children: _jsxs("div", { className: "space-y-4", children: [_jsx(Textarea, { label: t("image.description_label") || "Description de l'image", placeholder: t("image.description_placeholder") ||
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextareaGenerative.d.ts","sourceRoot":"","sources":["../../../src/web/components/TextareaGenerative.tsx"],"names":[],"mappings":"AAqBA,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,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAClE,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;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,wBAAgB,kBAAkB,CAAC,EACjC,aAAkB,EAClB,KAAqB,EACrB,WAA6D,EAC7D,YAAiB,EACjB,QAAQ,EACR,OAAO,EACP,SAAS,EACT,QAAgB,EAChB,OAAW,EACX,OAAY,EACZ,WAAqC,EACrC,gBAAuB,EACvB,KAAK,EACL,WAAW,EACX,gBAAwB,EACxB,sBAA8B,GAC/B,EAAE,uBAAuB,
|
|
1
|
+
{"version":3,"file":"TextareaGenerative.d.ts","sourceRoot":"","sources":["../../../src/web/components/TextareaGenerative.tsx"],"names":[],"mappings":"AAqBA,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,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAClE,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;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,wBAAgB,kBAAkB,CAAC,EACjC,aAAkB,EAClB,KAAqB,EACrB,WAA6D,EAC7D,YAAiB,EACjB,QAAQ,EACR,OAAO,EACP,SAAS,EACT,QAAgB,EAChB,OAAW,EACX,OAAY,EACZ,WAAqC,EACrC,gBAAuB,EACvB,KAAK,EACL,WAAW,EACX,gBAAwB,EACxB,sBAA8B,GAC/B,EAAE,uBAAuB,2CA2TzB"}
|
|
@@ -100,7 +100,7 @@ export function TextareaGenerative({ defaultPrompt = "", model = "gpt-4o-mini",
|
|
|
100
100
|
onChange(newValue);
|
|
101
101
|
}
|
|
102
102
|
};
|
|
103
|
-
return (_jsxs("div", { className: className, children: [_jsxs("div", { className: "flex flex-col gap-2", children: [label && _jsx("label", { className: "text-sm font-medium", children: label }), description && (_jsx("p", { className: "text-sm text-gray-500 mb-2", children: description })), isGenerating && (_jsxs("div", { className: "w-full border border-default-200 p-5 rounded-xl", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Skeleton, { className: "w-
|
|
103
|
+
return (_jsxs("div", { className: className, children: [_jsxs("div", { className: "flex flex-col gap-2", children: [label && _jsx("label", { className: "text-sm font-medium", children: label }), description && (_jsx("p", { className: "text-sm text-gray-500 mb-2", children: description })), isGenerating && (_jsxs("div", { className: "w-full border border-default-200 p-5 rounded-xl", children: [_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(Skeleton, { className: "w-[30%] bg-content-2 h-8 rounded-lg" }), _jsx(Skeleton, { className: "w-[50%] bg-content-2 h-4 rounded-lg" }), _jsx(Skeleton, { className: "w-[40%] bg-content-2 h-4 rounded-lg" })] }), _jsx("div", { className: "mt-2", children: _jsx(Progress, { size: "sm", isIndeterminate: true, "aria-label": t("progress.generating") || "Génération en cours...", label: t("progress.generating") || "Génération en cours..." }) })] })), !isGenerating && (_jsx(Textarea, { value: userInput, onChange: (e) => handleInputChange(e.target.value), placeholder: placeholder ||
|
|
104
104
|
t("textarea.placeholder") ||
|
|
105
105
|
"Saisissez votre texte ou générez avec l'IA...", disabled: disabled || isGenerating, minRows: minRows, maxRows: maxRows, endContent: _jsx(Button, { isIconOnly: true, size: "sm", color: "primary", variant: "light", onPress: () => {
|
|
106
106
|
if (hidePromptEditor) {
|
|
@@ -109,7 +109,9 @@ export function TextareaGenerative({ defaultPrompt = "", model = "gpt-4o-mini",
|
|
|
109
109
|
else {
|
|
110
110
|
setIsModalOpen(true);
|
|
111
111
|
}
|
|
112
|
-
}, disabled: disabled ||
|
|
112
|
+
}, disabled: disabled ||
|
|
113
|
+
isGenerating ||
|
|
114
|
+
(hidePromptEditor && !userInput.trim()), title: t("button.generate_with_ai") || "Générer avec l'IA", children: _jsx(Wand2, { size: 18 }) }) })), _jsxs("div", { className: "flex items-center justify-between gap-2 flex-wrap", children: [_jsx("div", { className: "flex items-center gap-2", children: showTokenBalance && tokenBalance !== null && (_jsxs(Chip, { size: "sm", variant: "flat", color: "success", children: [tokenBalance.toLocaleString(), " ", t("chip.tokens_remaining") || "tokens restants"] })) }), lastResponse && (_jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [_jsxs(Chip, { size: "sm", variant: "flat", children: [lastResponse.tokensUsed, " ", t("chip.tokens_used") || "tokens utilisés"] }), _jsx(Chip, { size: "sm", variant: "flat", color: "primary", children: lastResponse.model }), lastResponse.cost && (_jsxs(Chip, { size: "sm", variant: "flat", color: "warning", children: ["$", lastResponse.cost.toFixed(4)] }))] }))] }), error && (_jsxs("div", { className: "flex items-center gap-2 text-danger text-sm p-2 bg-danger-50 rounded-md", children: [_jsx(AlertCircle, { size: 16 }), _jsx("span", { children: error })] }))] }), !hidePromptEditor && (_jsx(Modal, { isOpen: isModalOpen, onClose: () => setIsModalOpen(false), size: "2xl", backdrop: "blur", children: _jsxs(ModalContent, { children: [_jsx(ModalHeader, { children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Sparkles, { size: 20 }), _jsx("span", { children: t("modal.title") || "Générer du texte avec l'IA" })] }) }), _jsx(ModalBody, { children: _jsxs("div", { className: "space-y-4", children: [_jsx(Textarea, { label: t("modal.prompt_label") || "Prompt de génération", placeholder: t("modal.prompt_placeholder") ||
|
|
113
115
|
"Décrivez ce que vous souhaitez générer...", value: userPrompt, onChange: (e) => setUserPrompt(e.target.value), minRows: 3, description: t("modal.prompt_description") ||
|
|
114
116
|
"Soyez précis pour obtenir de meilleurs résultats" }), _jsxs(Select, { label: t("modal.model_label") || "Modèle IA", selectedKeys: [selectedModel], onSelectionChange: (keys) => setSelectedModel(Array.from(keys)[0]), description: t("modal.model_description") ||
|
|
115
117
|
"GPT-4o-mini est plus rapide et économique", children: [_jsx(SelectItem, { children: t("modal.model_gpt4o_mini") || "GPT-4o Mini (Rapide)" }, "gpt-4o-mini"), _jsx(SelectItem, { children: t("modal.model_gpt4o") || "GPT-4o (Avancé)" }, "gpt-4o"), _jsx(SelectItem, { children: t("modal.model_gpt35") || "GPT-3.5 Turbo (Économique)" }, "gpt-3.5-turbo")] }), userInput && (_jsxs("div", { className: "p-3 bg-gray-50 dark:bg-gray-800 rounded-lg", children: [_jsx("p", { className: "text-sm font-medium mb-1", children: t("modal.current_context") || "Contexte actuel:" }), _jsx("p", { className: "text-xs text-gray-600 dark:text-gray-400 line-clamp-3", children: userInput })] }))] }) }), _jsxs(ModalFooter, { children: [_jsx(Button, { variant: "light", onClick: () => setIsModalOpen(false), children: t("button.cancel") || "Annuler" }), _jsx(Button, { color: "primary", onClick: () => handleGenerate(userPrompt), disabled: !userPrompt.trim() || isGenerating, startContent: isGenerating ? (_jsx(Loader2, { className: "animate-spin", size: 16 })) : (_jsx(Sparkles, { size: 16 })), children: isGenerating
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lastbrain/module-ai",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.26",
|
|
4
4
|
"description": "Module de génération IA (texte et images) avec gestion de tokens pour LastBrain",
|
|
5
5
|
"private": false,
|
|
6
6
|
"release": {
|
|
@@ -35,9 +35,9 @@
|
|
|
35
35
|
"@heroui/react": "^2.4.23",
|
|
36
36
|
"@heroui/system": "^2.4.23",
|
|
37
37
|
"@heroui/theme": "^2.4.23",
|
|
38
|
-
"@lastbrain-labs/module-core-payment-pro": "^2.0.
|
|
39
|
-
"@lastbrain/core": "^2.0.
|
|
40
|
-
"@lastbrain/ui": "^2.0.
|
|
38
|
+
"@lastbrain-labs/module-core-payment-pro": "^2.0.26",
|
|
39
|
+
"@lastbrain/core": "^2.0.27",
|
|
40
|
+
"@lastbrain/ui": "^2.0.27",
|
|
41
41
|
"lucide-react": "^0.554.0",
|
|
42
42
|
"next": "^16.0.7",
|
|
43
43
|
"openai": "^6.9.1",
|