bibest-code 2.0.0 → 2.0.1
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/bibest-code.js +325 -245
- package/package.json +13 -4
package/bibest-code.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// ============================================================
|
|
3
|
-
// BIBEST CODE
|
|
3
|
+
// BIBEST CODE v3.0.0 — Agent CLI propulsé par Claude
|
|
4
|
+
// Supabase + Stripe + Quota + Licence
|
|
4
5
|
// © BIBI ONDOUA — Tous droits réservés
|
|
5
6
|
// ============================================================
|
|
6
7
|
|
|
7
8
|
import Anthropic from "@anthropic-ai/sdk";
|
|
9
|
+
import { createClient } from "@supabase/supabase-js";
|
|
10
|
+
import ws from "ws";
|
|
8
11
|
import * as readline from "readline";
|
|
9
12
|
import * as fs from "fs";
|
|
10
13
|
import * as path from "path";
|
|
@@ -12,102 +15,148 @@ import { exec } from "child_process";
|
|
|
12
15
|
import { promisify } from "util";
|
|
13
16
|
|
|
14
17
|
const execAsync = promisify(exec);
|
|
15
|
-
const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
|
|
16
18
|
|
|
17
|
-
// ──
|
|
19
|
+
// ── Config ─────────────────────────────────────────────────
|
|
20
|
+
const SUPABASE_URL = process.env.SUPABASE_URL || "https://fkkhzvstilmgtvkbbjxz.supabase.co";
|
|
21
|
+
const SUPABASE_ANON_KEY = process.env.SUPABASE_ANON_KEY || "";
|
|
22
|
+
const ANTHROPIC_KEY = process.env.ANTHROPIC_API_KEY || "";
|
|
23
|
+
|
|
24
|
+
const PLANS = {
|
|
25
|
+
free: { name: "Free", tokens: 5000, price: 0 },
|
|
26
|
+
starter: { name: "Starter", tokens: 500000, price: 9 },
|
|
27
|
+
pro: { name: "Pro", tokens: 2000000, price: 29 },
|
|
28
|
+
business: { name: "Business", tokens: 10000000, price: 79 },
|
|
29
|
+
enterprise: { name: "Enterprise", tokens: -1, price: 199 },
|
|
30
|
+
founder: { name: "Founder", tokens: -1, price: 0 },
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// ── Couleurs ────────────────────────────────────────────────
|
|
18
34
|
const C = {
|
|
19
|
-
reset: "\x1b[0m",
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
greenBright: "\x1b[92m",
|
|
28
|
-
yellow: "\x1b[33m",
|
|
29
|
-
yellowBright: "\x1b[93m",
|
|
30
|
-
red: "\x1b[31m",
|
|
31
|
-
redBright: "\x1b[91m",
|
|
32
|
-
magenta: "\x1b[35m",
|
|
33
|
-
magentaBright: "\x1b[95m",
|
|
34
|
-
blue: "\x1b[34m",
|
|
35
|
-
blueBright: "\x1b[94m",
|
|
36
|
-
white: "\x1b[37m",
|
|
37
|
-
whiteBright: "\x1b[97m",
|
|
35
|
+
reset: "\x1b[0m", bold: "\x1b[1m", dim: "\x1b[2m",
|
|
36
|
+
cyan: "\x1b[36m", cyanBright: "\x1b[96m",
|
|
37
|
+
green: "\x1b[32m", greenBright: "\x1b[92m",
|
|
38
|
+
yellow: "\x1b[33m", yellowBright: "\x1b[93m",
|
|
39
|
+
red: "\x1b[31m", redBright: "\x1b[91m",
|
|
40
|
+
magenta: "\x1b[35m", magentaBright: "\x1b[95m",
|
|
41
|
+
blue: "\x1b[34m", blueBright: "\x1b[94m",
|
|
42
|
+
white: "\x1b[37m", whiteBright: "\x1b[97m",
|
|
38
43
|
gray: "\x1b[90m",
|
|
39
|
-
bgCyan: "\x1b[46m",
|
|
40
|
-
bgBlue: "\x1b[44m",
|
|
41
|
-
bgGreen: "\x1b[42m",
|
|
42
|
-
bgRed: "\x1b[41m",
|
|
43
|
-
bgMagenta: "\x1b[45m",
|
|
44
|
-
bgYellow: "\x1b[43m",
|
|
45
44
|
};
|
|
46
45
|
|
|
47
46
|
const W = process.stdout.columns || 80;
|
|
48
|
-
const
|
|
49
|
-
const pad = (
|
|
50
|
-
const
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
console.log(
|
|
60
|
-
lines.forEach(l => {
|
|
61
|
-
const padded = pad(l, maxLen);
|
|
62
|
-
console.log(borderColor + "║ " + C.reset + padded + " " + borderColor + "║" + C.reset);
|
|
63
|
-
});
|
|
64
|
-
console.log(borderColor + "╚" + "═".repeat(w) + "╝" + C.reset);
|
|
47
|
+
const stripAnsi = (s) => s.replace(/\x1b\[[0-9;]*m/g, "");
|
|
48
|
+
const pad = (t, w) => t + " ".repeat(Math.max(0, w - stripAnsi(t).length));
|
|
49
|
+
const center = (t, c = "") => { const l = stripAnsi(t).length; const s = Math.max(0, Math.floor((W - l) / 2)); return " ".repeat(s) + c + t + C.reset; };
|
|
50
|
+
const line = (ch = "─", c = C.gray) => c + ch.repeat(W) + C.reset;
|
|
51
|
+
const println = (c, t) => console.log(c + t + C.reset);
|
|
52
|
+
|
|
53
|
+
const box = (lines, bc = C.cyanBright) => {
|
|
54
|
+
const max = Math.max(...lines.map(l => stripAnsi(l).length));
|
|
55
|
+
const w = max + 4;
|
|
56
|
+
console.log(bc + "╔" + "═".repeat(w) + "╗" + C.reset);
|
|
57
|
+
lines.forEach(l => console.log(bc + "║ " + C.reset + pad(l, max) + " " + bc + "║" + C.reset));
|
|
58
|
+
console.log(bc + "╚" + "═".repeat(w) + "╝" + C.reset);
|
|
65
59
|
};
|
|
66
60
|
|
|
67
|
-
// ── État
|
|
68
|
-
let
|
|
61
|
+
// ── État ────────────────────────────────────────────────────
|
|
62
|
+
let currentUser = null;
|
|
69
63
|
let currentModel = "claude-sonnet-4-6";
|
|
64
|
+
let sessionTokens = 0;
|
|
70
65
|
let sessionStart = new Date();
|
|
66
|
+
let sessionMsgs = 0;
|
|
71
67
|
const HISTORY_FILE = path.join(process.env.USERPROFILE || process.env.HOME || ".", ".bibest-code-history.json");
|
|
72
68
|
|
|
73
|
-
// ──
|
|
69
|
+
// ── Supabase ────────────────────────────────────────────────
|
|
70
|
+
let supabase = null;
|
|
71
|
+
function getSupabase() {
|
|
72
|
+
if (!supabase && SUPABASE_URL && SUPABASE_ANON_KEY) {
|
|
73
|
+
supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY, { realtime: { transport: ws } });
|
|
74
|
+
}
|
|
75
|
+
return supabase;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async function loadUser(email) {
|
|
79
|
+
const sb = getSupabase();
|
|
80
|
+
if (!sb) return null;
|
|
81
|
+
const { data } = await sb.from("users").select("*, plans(*)").eq("email", email).single();
|
|
82
|
+
return data;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async function logUsage(userId, tokens, model) {
|
|
86
|
+
const sb = getSupabase();
|
|
87
|
+
if (!sb || !userId) return;
|
|
88
|
+
await sb.from("usage_logs").insert({ user_id: userId, tokens_used: tokens, model });
|
|
89
|
+
await sb.from("users").update({ tokens_used: supabase.rpc ? undefined : undefined }).eq("id", userId);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async function checkQuota(user) {
|
|
93
|
+
if (!user) return { ok: true, remaining: 5000, plan: "free" };
|
|
94
|
+
const planId = user.plan_id || "free";
|
|
95
|
+
const plan = PLANS[planId];
|
|
96
|
+
if (plan.tokens === -1) return { ok: true, remaining: -1, plan: planId };
|
|
97
|
+
const sb = getSupabase();
|
|
98
|
+
if (!sb) return { ok: true, remaining: plan.tokens, plan: planId };
|
|
99
|
+
const startOfMonth = new Date(); startOfMonth.setDate(1); startOfMonth.setHours(0, 0, 0, 0);
|
|
100
|
+
const { data } = await sb.from("usage_logs").select("tokens_used").eq("user_id", user.id).gte("created_at", startOfMonth.toISOString());
|
|
101
|
+
const used = data ? data.reduce((s, r) => s + r.tokens_used, 0) : 0;
|
|
102
|
+
const remaining = plan.tokens - used;
|
|
103
|
+
return { ok: remaining > 0, remaining, plan: planId, used, limit: plan.tokens };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// ── Header ──────────────────────────────────────────────────
|
|
74
107
|
function showHeader() {
|
|
75
108
|
console.clear();
|
|
76
109
|
console.log();
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
110
|
+
println(C.cyanBright + C.bold, center("██████╗ ██╗██████╗ ███████╗███████╗████████╗"));
|
|
111
|
+
println(C.cyanBright + C.bold, center("██╔══██╗██║██╔══██╗██╔════╝██╔════╝╚══██╔══╝"));
|
|
112
|
+
println(C.cyan + C.bold, center("██████╔╝██║██████╔╝█████╗ ███████╗ ██║ "));
|
|
113
|
+
println(C.blue + C.bold, center("██╔══██╗██║██╔══██╗██╔══╝ ╚════██║ ██║ "));
|
|
114
|
+
println(C.blueBright + C.bold, center("██████╔╝██║██████╔╝███████╗███████║ ██║ "));
|
|
115
|
+
println(C.gray + C.bold, center("╚═════╝ ╚═╝╚═════╝ ╚══════╝╚══════╝ ╚═╝ "));
|
|
116
|
+
println(C.magentaBright + C.bold, center("██████╗ ██████╗ ██████╗ ███████╗"));
|
|
117
|
+
println(C.magenta + C.bold, center("██╔════╝██╔═══██╗██╔══██╗██╔════╝"));
|
|
118
|
+
println(C.magentaBright + C.bold, center("██║ ██║ ██║██║ ██║█████╗ "));
|
|
119
|
+
println(C.magenta + C.bold, center("██║ ██║ ██║██║ ██║██╔══╝ "));
|
|
120
|
+
println(C.magentaBright + C.bold, center("╚██████╗╚██████╔╝██████╔╝███████╗"));
|
|
121
|
+
println(C.gray + C.bold, center(" ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝"));
|
|
89
122
|
console.log();
|
|
90
123
|
console.log(line("═", C.cyanBright));
|
|
91
|
-
|
|
92
|
-
|
|
124
|
+
println(C.whiteBright + C.bold, center("🤖 Agent CLI de développement propulsé par Claude AI 🚀"));
|
|
125
|
+
println(C.gray, center("© BIBI ONDOUA — Tous droits réservés — v3.0.0"));
|
|
93
126
|
console.log(line("═", C.cyanBright));
|
|
94
127
|
console.log();
|
|
95
128
|
}
|
|
96
129
|
|
|
97
|
-
// ── Barre de statut
|
|
98
|
-
function showStatus() {
|
|
130
|
+
// ── Barre de statut ─────────────────────────────────────────
|
|
131
|
+
async function showStatus() {
|
|
99
132
|
const now = new Date();
|
|
100
133
|
const uptime = Math.floor((now - sessionStart) / 1000);
|
|
101
|
-
const
|
|
102
|
-
const
|
|
103
|
-
const cwd = process.cwd().replace(process.env.USERPROFILE || "", "~");
|
|
134
|
+
const mm = Math.floor(uptime / 60).toString().padStart(2, "0");
|
|
135
|
+
const ss = (uptime % 60).toString().padStart(2, "0");
|
|
136
|
+
const cwd = process.cwd().replace(process.env.USERPROFILE || "", "~").slice(-30);
|
|
137
|
+
|
|
138
|
+
let quotaStr = "";
|
|
139
|
+
if (currentUser) {
|
|
140
|
+
const q = await checkQuota(currentUser);
|
|
141
|
+
const planName = PLANS[currentUser.plan_id || "free"].name;
|
|
142
|
+
if (q.remaining === -1) {
|
|
143
|
+
quotaStr = `${C.greenBright}∞ illimité${C.reset}`;
|
|
144
|
+
} else {
|
|
145
|
+
const pct = Math.round((q.remaining / q.limit) * 100);
|
|
146
|
+
const color = pct > 50 ? C.greenBright : pct > 20 ? C.yellowBright : C.redBright;
|
|
147
|
+
quotaStr = `${color}${q.remaining.toLocaleString()} tokens${C.reset}`;
|
|
148
|
+
}
|
|
149
|
+
} else {
|
|
150
|
+
quotaStr = `${C.yellowBright}5K tokens Free${C.reset}`;
|
|
151
|
+
}
|
|
104
152
|
|
|
105
153
|
const items = [
|
|
106
154
|
`${C.greenBright}●${C.reset} ${C.gray}Connecté${C.reset}`,
|
|
107
|
-
`${C.cyan}⚡${C.reset} ${C.whiteBright}${currentModel}${C.reset}`,
|
|
155
|
+
`${C.cyan}⚡${C.reset} ${C.whiteBright}${currentModel.replace("claude-", "")}${C.reset}`,
|
|
108
156
|
`${C.yellow}📁${C.reset} ${C.gray}${cwd}${C.reset}`,
|
|
109
|
-
`${C.magenta}⏱${C.reset} ${C.gray}${
|
|
110
|
-
`${C.blue}💬${C.reset} ${C.gray}${
|
|
157
|
+
`${C.magenta}⏱${C.reset} ${C.gray}${mm}:${ss}${C.reset}`,
|
|
158
|
+
`${C.blue}💬${C.reset} ${C.gray}${sessionMsgs} msgs${C.reset}`,
|
|
159
|
+
`${C.cyan}🔋${C.reset} ${quotaStr}`,
|
|
111
160
|
];
|
|
112
161
|
|
|
113
162
|
console.log(line("─", C.gray));
|
|
@@ -115,80 +164,165 @@ function showStatus() {
|
|
|
115
164
|
console.log(line("─", C.gray));
|
|
116
165
|
}
|
|
117
166
|
|
|
118
|
-
// ──
|
|
167
|
+
// ── Login ───────────────────────────────────────────────────
|
|
168
|
+
async function loginFlow(rl) {
|
|
169
|
+
console.log();
|
|
170
|
+
box([
|
|
171
|
+
`${C.yellowBright + C.bold}🔑 Connexion à BIBEST CODE${C.reset}`,
|
|
172
|
+
"",
|
|
173
|
+
`${C.gray}Entrez votre email pour accéder à votre compte.${C.reset}`,
|
|
174
|
+
`${C.gray}Nouveau ? Un compte Free sera créé automatiquement.${C.reset}`,
|
|
175
|
+
], C.yellowBright);
|
|
176
|
+
|
|
177
|
+
return new Promise((resolve) => {
|
|
178
|
+
process.stdout.write(`\n${C.cyan}Email : ${C.reset}`);
|
|
179
|
+
rl.once("line", async (email) => {
|
|
180
|
+
email = email.trim().toLowerCase();
|
|
181
|
+
if (!email || !email.includes("@")) {
|
|
182
|
+
println(C.gray, "\n Mode anonyme — plan Free (5K tokens)\n");
|
|
183
|
+
resolve(null);
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const sb = getSupabase();
|
|
188
|
+
if (!sb) { resolve(null); return; }
|
|
189
|
+
|
|
190
|
+
let user = await loadUser(email);
|
|
191
|
+
if (!user) {
|
|
192
|
+
// Créer le compte
|
|
193
|
+
const { data, error } = await sb.from("users").insert({
|
|
194
|
+
email, name: email.split("@")[0], plan_id: "free"
|
|
195
|
+
}).select("*, plans(*)").single();
|
|
196
|
+
user = data;
|
|
197
|
+
if (!error) println(C.greenBright, `\n ✅ Compte créé ! Bienvenue sur BIBEST CODE (plan Free)\n`);
|
|
198
|
+
} else {
|
|
199
|
+
const planName = PLANS[user.plan_id || "free"].name;
|
|
200
|
+
println(C.greenBright, `\n ✅ Bonjour ${user.name || email} ! Plan : ${C.bold}${planName}${C.reset}\n`);
|
|
201
|
+
}
|
|
202
|
+
resolve(user);
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// ── Help ────────────────────────────────────────────────────
|
|
119
208
|
function showHelp() {
|
|
120
209
|
console.log();
|
|
121
210
|
box([
|
|
122
|
-
`${C.yellowBright + C.bold}BIBEST CODE — Commandes
|
|
211
|
+
`${C.yellowBright + C.bold}BIBEST CODE — Commandes${C.reset}`,
|
|
123
212
|
"",
|
|
124
|
-
`${C.cyanBright}/help${C.reset} ${C.gray}
|
|
213
|
+
`${C.cyanBright}/help${C.reset} ${C.gray}Cette aide${C.reset}`,
|
|
125
214
|
`${C.cyanBright}/clear${C.reset} ${C.gray}Effacer l'écran${C.reset}`,
|
|
126
|
-
`${C.cyanBright}/
|
|
127
|
-
`${C.cyanBright}/
|
|
215
|
+
`${C.cyanBright}/stats${C.reset} ${C.gray}Statistiques session${C.reset}`,
|
|
216
|
+
`${C.cyanBright}/quota${C.reset} ${C.gray}Voir votre quota tokens${C.reset}`,
|
|
217
|
+
`${C.cyanBright}/upgrade${C.reset} ${C.gray}Voir les plans et upgrader${C.reset}`,
|
|
128
218
|
`${C.cyanBright}/model${C.reset} ${C.gray}Changer de modèle Claude${C.reset}`,
|
|
129
219
|
`${C.cyanBright}/cd <dossier>${C.reset} ${C.gray}Changer de répertoire${C.reset}`,
|
|
130
|
-
`${C.cyanBright}/ls${C.reset} ${C.gray}Lister le répertoire
|
|
131
|
-
`${C.cyanBright}/reset${C.reset} ${C.gray}Réinitialiser
|
|
132
|
-
`${C.cyanBright}/
|
|
133
|
-
|
|
134
|
-
`${C.gray}Exemples de tâches :${C.reset}`,
|
|
135
|
-
`${C.green}▶${C.reset} ${C.italic}crée une API REST en Express${C.reset}`,
|
|
136
|
-
`${C.green}▶${C.reset} ${C.italic}analyse et corrige les bugs de mon projet${C.reset}`,
|
|
137
|
-
`${C.green}▶${C.reset} ${C.italic}écris des tests unitaires pour app.js${C.reset}`,
|
|
138
|
-
`${C.green}▶${C.reset} ${C.italic}optimise les performances de ce code${C.reset}`,
|
|
220
|
+
`${C.cyanBright}/ls${C.reset} ${C.gray}Lister le répertoire${C.reset}`,
|
|
221
|
+
`${C.cyanBright}/reset${C.reset} ${C.gray}Réinitialiser conversation${C.reset}`,
|
|
222
|
+
`${C.cyanBright}/history${C.reset} ${C.gray}Historique sessions${C.reset}`,
|
|
223
|
+
`${C.cyanBright}/exit${C.reset} ${C.gray}Quitter${C.reset}`,
|
|
139
224
|
], C.cyanBright);
|
|
140
225
|
console.log();
|
|
141
226
|
}
|
|
142
227
|
|
|
143
|
-
// ──
|
|
228
|
+
// ── Quota ────────────────────────────────────────────────────
|
|
229
|
+
async function showQuota() {
|
|
230
|
+
console.log();
|
|
231
|
+
const q = await checkQuota(currentUser);
|
|
232
|
+
const planId = currentUser?.plan_id || "free";
|
|
233
|
+
const plan = PLANS[planId];
|
|
234
|
+
|
|
235
|
+
if (q.remaining === -1) {
|
|
236
|
+
box([
|
|
237
|
+
`${C.greenBright + C.bold}🔋 Quota — Plan ${plan.name}${C.reset}`,
|
|
238
|
+
"",
|
|
239
|
+
`${C.greenBright}✨ Tokens illimités${C.reset}`,
|
|
240
|
+
`${C.gray}Session actuelle : ${sessionTokens.toLocaleString()} tokens utilisés${C.reset}`,
|
|
241
|
+
], C.greenBright);
|
|
242
|
+
} else {
|
|
243
|
+
const pct = Math.round((q.used / q.limit) * 100);
|
|
244
|
+
const bar = Math.round(pct / 5);
|
|
245
|
+
const barFull = "█".repeat(bar) + "░".repeat(20 - bar);
|
|
246
|
+
const color = pct < 50 ? C.greenBright : pct < 80 ? C.yellowBright : C.redBright;
|
|
247
|
+
box([
|
|
248
|
+
`${C.yellowBright + C.bold}🔋 Quota mensuel — Plan ${plan.name}${C.reset}`,
|
|
249
|
+
"",
|
|
250
|
+
`${color}${barFull} ${pct}%${C.reset}`,
|
|
251
|
+
`${C.gray}Utilisé : ${(q.used || 0).toLocaleString()} tokens${C.reset}`,
|
|
252
|
+
`${C.gray}Restant : ${q.remaining.toLocaleString()} tokens${C.reset}`,
|
|
253
|
+
`${C.gray}Total : ${q.limit.toLocaleString()} tokens/mois${C.reset}`,
|
|
254
|
+
"",
|
|
255
|
+
q.remaining < 1000 ? `${C.redBright}⚠️ Quota presque épuisé — tapez /upgrade${C.reset}` : `${C.greenBright}✅ Quota suffisant${C.reset}`,
|
|
256
|
+
], color);
|
|
257
|
+
}
|
|
258
|
+
console.log();
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// ── Upgrade ──────────────────────────────────────────────────
|
|
262
|
+
function showUpgrade() {
|
|
263
|
+
console.log();
|
|
264
|
+
box([
|
|
265
|
+
`${C.yellowBright + C.bold}🚀 Plans BIBEST CODE${C.reset}`,
|
|
266
|
+
"",
|
|
267
|
+
`${C.gray}Plan Prix Tokens/mois${C.reset}`,
|
|
268
|
+
`${C.gray}─────────────────────────────────${C.reset}`,
|
|
269
|
+
`${C.white}Free 0€ 5 000${C.reset} ${C.gray}← actuel${C.reset}`,
|
|
270
|
+
`${C.cyanBright}Starter 9€/mois 500 000${C.reset}`,
|
|
271
|
+
`${C.blueBright}Pro 29€/mois 2 000 000${C.reset}`,
|
|
272
|
+
`${C.magentaBright}Business 79€/mois 10 000 000${C.reset}`,
|
|
273
|
+
`${C.yellowBright}Enterprise 199€/mois Illimité${C.reset}`,
|
|
274
|
+
"",
|
|
275
|
+
`${C.gray}Contactez : b.ondoua00@gmail.com${C.reset}`,
|
|
276
|
+
`${C.gray}ou visitez : npmjs.com/package/bibest-code${C.reset}`,
|
|
277
|
+
], C.yellowBright);
|
|
278
|
+
console.log();
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// ── Stats ────────────────────────────────────────────────────
|
|
144
282
|
function showStats() {
|
|
145
283
|
console.log();
|
|
146
284
|
box([
|
|
147
|
-
`${C.yellowBright + C.bold}📊 Statistiques
|
|
285
|
+
`${C.yellowBright + C.bold}📊 Statistiques session${C.reset}`,
|
|
148
286
|
"",
|
|
149
|
-
`${C.cyan}Messages
|
|
150
|
-
`${C.cyan}
|
|
151
|
-
`${C.cyan}
|
|
152
|
-
`${C.cyan}
|
|
153
|
-
`${C.cyan}
|
|
287
|
+
`${C.cyan}Messages :${C.reset} ${C.whiteBright}${sessionMsgs}${C.reset}`,
|
|
288
|
+
`${C.cyan}Tokens session :${C.reset} ${C.whiteBright}${sessionTokens.toLocaleString()}${C.reset}`,
|
|
289
|
+
`${C.cyan}Modèle :${C.reset} ${C.magentaBright}${currentModel}${C.reset}`,
|
|
290
|
+
`${C.cyan}Utilisateur :${C.reset} ${C.whiteBright}${currentUser?.email || "Anonyme"}${C.reset}`,
|
|
291
|
+
`${C.cyan}Plan :${C.reset} ${C.greenBright}${PLANS[currentUser?.plan_id || "free"].name}${C.reset}`,
|
|
154
292
|
], C.yellowBright);
|
|
155
293
|
console.log();
|
|
156
294
|
}
|
|
157
295
|
|
|
158
|
-
// ── Sélecteur
|
|
296
|
+
// ── Sélecteur modèle ─────────────────────────────────────────
|
|
159
297
|
async function selectModel(rl) {
|
|
160
298
|
const models = [
|
|
161
|
-
{ id: "claude-opus-4-6",
|
|
162
|
-
{ id: "claude-sonnet-4-6", label: "Claude Sonnet 4.6", desc: "
|
|
163
|
-
{ id: "claude-haiku-4-5",
|
|
299
|
+
{ id: "claude-opus-4-6", label: "Claude Opus 4.6", desc: "Le plus puissant" },
|
|
300
|
+
{ id: "claude-sonnet-4-6", label: "Claude Sonnet 4.6", desc: "Recommandé ✓" },
|
|
301
|
+
{ id: "claude-haiku-4-5", label: "Claude Haiku 4.5", desc: "Ultra rapide" },
|
|
164
302
|
];
|
|
165
|
-
|
|
166
303
|
console.log();
|
|
167
304
|
box([
|
|
168
|
-
`${C.yellowBright + C.bold}🤖 Choisir un modèle
|
|
305
|
+
`${C.yellowBright + C.bold}🤖 Choisir un modèle${C.reset}`,
|
|
169
306
|
"",
|
|
170
307
|
...models.map((m, i) => `${C.cyanBright}${i + 1}.${C.reset} ${C.whiteBright}${m.label}${C.reset} ${C.gray}${m.desc}${C.reset}${m.id === currentModel ? ` ${C.greenBright}← actuel${C.reset}` : ""}`),
|
|
171
308
|
], C.yellowBright);
|
|
172
|
-
|
|
173
309
|
return new Promise((resolve) => {
|
|
174
310
|
process.stdout.write(`\n${C.yellow}Choix (1-3) : ${C.reset}`);
|
|
175
311
|
rl.once("line", (input) => {
|
|
176
312
|
const idx = parseInt(input.trim()) - 1;
|
|
177
313
|
if (idx >= 0 && idx < models.length) {
|
|
178
314
|
currentModel = models[idx].id;
|
|
179
|
-
|
|
180
|
-
} else {
|
|
181
|
-
console.log(`\n${C.gray}Annulé.${C.reset}\n`);
|
|
315
|
+
println(C.greenBright, `\n ✅ Modèle → ${models[idx].label}\n`);
|
|
182
316
|
}
|
|
183
317
|
resolve();
|
|
184
318
|
});
|
|
185
319
|
});
|
|
186
320
|
}
|
|
187
321
|
|
|
188
|
-
// ── Historique
|
|
322
|
+
// ── Historique ────────────────────────────────────────────────
|
|
189
323
|
function saveHistory(history) {
|
|
190
324
|
try {
|
|
191
|
-
const data = { date: new Date().toISOString(), model: currentModel,
|
|
325
|
+
const data = { date: new Date().toISOString(), model: currentModel, tokens: sessionTokens, messages: history.slice(-10) };
|
|
192
326
|
let all = [];
|
|
193
327
|
if (fs.existsSync(HISTORY_FILE)) all = JSON.parse(fs.readFileSync(HISTORY_FILE, "utf8"));
|
|
194
328
|
all.unshift(data);
|
|
@@ -200,115 +334,91 @@ function saveHistory(history) {
|
|
|
200
334
|
function showHistory() {
|
|
201
335
|
console.log();
|
|
202
336
|
try {
|
|
203
|
-
if (!fs.existsSync(HISTORY_FILE)) {
|
|
337
|
+
if (!fs.existsSync(HISTORY_FILE)) { println(C.gray, " Aucun historique."); return; }
|
|
204
338
|
const all = JSON.parse(fs.readFileSync(HISTORY_FILE, "utf8"));
|
|
205
339
|
box([
|
|
206
|
-
`${C.yellowBright + C.bold}📜 Historique
|
|
340
|
+
`${C.yellowBright + C.bold}📜 Historique${C.reset}`,
|
|
207
341
|
"",
|
|
208
342
|
...all.map((s, i) => {
|
|
209
343
|
const d = new Date(s.date).toLocaleString("fr-FR");
|
|
210
|
-
return `${C.cyanBright}${i + 1}.${C.reset} ${C.whiteBright}${d}${C.reset} ${C.gray}${s.
|
|
344
|
+
return `${C.cyanBright}${i + 1}.${C.reset} ${C.whiteBright}${d}${C.reset} ${C.gray}${s.tokens?.toLocaleString() || 0} tokens${C.reset}`;
|
|
211
345
|
}),
|
|
212
346
|
], C.blueBright);
|
|
213
|
-
} catch {
|
|
347
|
+
} catch {}
|
|
214
348
|
console.log();
|
|
215
349
|
}
|
|
216
350
|
|
|
217
|
-
// ── Outils
|
|
351
|
+
// ── Outils ───────────────────────────────────────────────────
|
|
218
352
|
const tools = [
|
|
219
|
-
{ name: "read_file",
|
|
220
|
-
{ name: "write_file",
|
|
221
|
-
{ name: "list_files",
|
|
222
|
-
{ name: "run_command",
|
|
223
|
-
{ name: "delete_file",
|
|
224
|
-
{ name: "create_directory", description: "Créer un dossier",
|
|
353
|
+
{ name: "read_file", description: "Lire un fichier", input_schema: { type: "object", properties: { path: { type: "string" } }, required: ["path"] } },
|
|
354
|
+
{ name: "write_file", description: "Écrire un fichier", input_schema: { type: "object", properties: { path: { type: "string" }, content: { type: "string" } }, required: ["path", "content"] } },
|
|
355
|
+
{ name: "list_files", description: "Lister un répertoire", input_schema: { type: "object", properties: { path: { type: "string" } }, required: ["path"] } },
|
|
356
|
+
{ name: "run_command", description: "Exécuter une commande", input_schema: { type: "object", properties: { command: { type: "string" } }, required: ["command"] } },
|
|
357
|
+
{ name: "delete_file", description: "Supprimer un fichier", input_schema: { type: "object", properties: { path: { type: "string" } }, required: ["path"] } },
|
|
358
|
+
{ name: "create_directory", description: "Créer un dossier", input_schema: { type: "object", properties: { path: { type: "string" } }, required: ["path"] } },
|
|
225
359
|
];
|
|
226
360
|
|
|
227
361
|
const toolIcons = { read_file: "📄", write_file: "✏️ ", list_files: "📁", run_command: "⚡", delete_file: "🗑️ ", create_directory: "📂" };
|
|
228
362
|
|
|
229
363
|
async function executeTool(name, input) {
|
|
230
364
|
try {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
case "write_file": {
|
|
239
|
-
const dir = path.dirname(input.path);
|
|
240
|
-
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
241
|
-
fs.writeFileSync(input.path, input.content, "utf8");
|
|
242
|
-
sessionStats.filesCreated++;
|
|
243
|
-
console.log(` ${C.greenBright}└─${C.reset} ${C.gray}${input.path}${C.reset}`);
|
|
244
|
-
return `Fichier écrit: ${input.path}`;
|
|
245
|
-
}
|
|
246
|
-
case "list_files": {
|
|
247
|
-
const files = fs.readdirSync(input.path);
|
|
248
|
-
console.log(` ${C.blueBright}└─${C.reset} ${C.gray}${files.length} entrées${C.reset}`);
|
|
249
|
-
return files.map(f => {
|
|
250
|
-
const full = path.join(input.path, f);
|
|
251
|
-
const stat = fs.statSync(full);
|
|
252
|
-
return `${stat.isDirectory() ? "[DIR] " : " "}${f}`;
|
|
253
|
-
}).join("\n");
|
|
254
|
-
}
|
|
255
|
-
case "run_command": {
|
|
256
|
-
sessionStats.commandsRun++;
|
|
257
|
-
console.log(` ${C.yellowBright}└─${C.reset} ${C.gray}${input.command}${C.reset}`);
|
|
258
|
-
const { stdout, stderr } = await execAsync(input.command, { timeout: 30000, cwd: process.cwd() });
|
|
259
|
-
return (stdout + (stderr ? "\nSTDERR: " + stderr : "")).trim() || "(aucune sortie)";
|
|
260
|
-
}
|
|
261
|
-
case "delete_file": {
|
|
262
|
-
fs.unlinkSync(input.path);
|
|
263
|
-
console.log(` ${C.redBright}└─${C.reset} ${C.gray}${input.path}${C.reset}`);
|
|
264
|
-
return `Supprimé: ${input.path}`;
|
|
265
|
-
}
|
|
266
|
-
case "create_directory": {
|
|
267
|
-
fs.mkdirSync(input.path, { recursive: true });
|
|
268
|
-
console.log(` ${C.greenBright}└─${C.reset} ${C.gray}${input.path}${C.reset}`);
|
|
269
|
-
return `Dossier créé: ${input.path}`;
|
|
270
|
-
}
|
|
271
|
-
default: return `Outil inconnu: ${name}`;
|
|
272
|
-
}
|
|
365
|
+
if (name === "read_file") { const c = fs.readFileSync(input.path, "utf8"); println(C.blueBright, ` └─ ${C.gray}${input.path}${C.reset}`); return c; }
|
|
366
|
+
if (name === "write_file") { fs.mkdirSync(path.dirname(input.path), { recursive: true }); fs.writeFileSync(input.path, input.content, "utf8"); println(C.greenBright, ` └─ ${C.gray}${input.path}${C.reset}`); return "OK"; }
|
|
367
|
+
if (name === "list_files") { return fs.readdirSync(input.path).map(f => { const s = fs.statSync(path.join(input.path, f)); return `${s.isDirectory() ? "[DIR] " : " "}${f}`; }).join("\n"); }
|
|
368
|
+
if (name === "run_command") { println(C.yellowBright, ` └─ ${C.gray}${input.command}${C.reset}`); const { stdout, stderr } = await execAsync(input.command, { timeout: 30000, cwd: process.cwd() }); return (stdout + (stderr ? "\n" + stderr : "")).trim() || "(aucune sortie)"; }
|
|
369
|
+
if (name === "delete_file") { fs.unlinkSync(input.path); return `Supprimé: ${input.path}`; }
|
|
370
|
+
if (name === "create_directory") { fs.mkdirSync(input.path, { recursive: true }); return `Créé: ${input.path}`; }
|
|
371
|
+
return "Outil inconnu";
|
|
273
372
|
} catch (e) { return `ERREUR: ${e.message}`; }
|
|
274
373
|
}
|
|
275
374
|
|
|
276
|
-
// ──
|
|
375
|
+
// ── Spinner ───────────────────────────────────────────────────
|
|
277
376
|
function startSpinner(text) {
|
|
278
|
-
const frames = ["⠋",
|
|
377
|
+
const frames = ["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"];
|
|
279
378
|
let i = 0;
|
|
280
|
-
const
|
|
281
|
-
|
|
282
|
-
i++;
|
|
283
|
-
}, 80);
|
|
284
|
-
return () => { clearInterval(timer); process.stdout.write("\r" + " ".repeat(60) + "\r"); };
|
|
379
|
+
const t = setInterval(() => { process.stdout.write(`\r ${C.cyanBright}${frames[i++ % frames.length]}${C.reset} ${C.gray}${text}${C.reset} `); }, 80);
|
|
380
|
+
return () => { clearInterval(t); process.stdout.write("\r" + " ".repeat(60) + "\r"); };
|
|
285
381
|
}
|
|
286
382
|
|
|
287
|
-
// ── Agent
|
|
383
|
+
// ── Agent ─────────────────────────────────────────────────────
|
|
384
|
+
const client = new Anthropic({ apiKey: ANTHROPIC_KEY });
|
|
385
|
+
|
|
288
386
|
async function runAgent(userMessage, history) {
|
|
289
|
-
|
|
290
|
-
|
|
387
|
+
// Vérif quota
|
|
388
|
+
const quota = await checkQuota(currentUser);
|
|
389
|
+
if (!quota.ok) {
|
|
390
|
+
console.log();
|
|
391
|
+
box([
|
|
392
|
+
`${C.redBright + C.bold}⛔ Quota épuisé${C.reset}`,
|
|
393
|
+
"",
|
|
394
|
+
`${C.gray}Vous avez atteint la limite de votre plan ${PLANS[currentUser?.plan_id || "free"].name}.${C.reset}`,
|
|
395
|
+
`${C.yellowBright}Tapez /upgrade pour voir les plans disponibles.${C.reset}`,
|
|
396
|
+
], C.redBright);
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
291
399
|
|
|
400
|
+
sessionMsgs++;
|
|
401
|
+
history.push({ role: "user", content: userMessage });
|
|
292
402
|
const stopSpinner = startSpinner("BIBEST CODE réfléchit...");
|
|
293
403
|
|
|
294
404
|
try {
|
|
295
405
|
while (true) {
|
|
296
406
|
const response = await client.messages.create({
|
|
297
|
-
model: currentModel,
|
|
298
|
-
max_tokens: 8096,
|
|
407
|
+
model: currentModel, max_tokens: 8096,
|
|
299
408
|
system: `Tu es BIBEST CODE, un agent de développement expert créé par BIBI ONDOUA.
|
|
300
|
-
Tu peux lire/écrire des fichiers, exécuter des commandes
|
|
301
|
-
Répertoire
|
|
302
|
-
|
|
303
|
-
Sois efficace, précis et professionnel. Utilise les outils pour accomplir les tâches concrètement.
|
|
304
|
-
Après chaque action, donne un résumé clair de ce qui a été fait.`,
|
|
305
|
-
tools,
|
|
306
|
-
messages: history,
|
|
409
|
+
Tu peux lire/écrire des fichiers, exécuter des commandes, créer des projets complets.
|
|
410
|
+
Répertoire: ${process.cwd()}. Réponds en français. Sois efficace et précis.`,
|
|
411
|
+
tools, messages: history,
|
|
307
412
|
});
|
|
308
413
|
|
|
309
414
|
stopSpinner();
|
|
310
|
-
history.push({ role: "assistant", content: response.content });
|
|
311
415
|
|
|
416
|
+
// Comptage tokens
|
|
417
|
+
const tokensUsed = response.usage?.input_tokens + response.usage?.output_tokens || 0;
|
|
418
|
+
sessionTokens += tokensUsed;
|
|
419
|
+
if (currentUser) await logUsage(currentUser.id, tokensUsed, currentModel);
|
|
420
|
+
|
|
421
|
+
history.push({ role: "assistant", content: response.content });
|
|
312
422
|
let hasToolUse = false;
|
|
313
423
|
const toolResults = [];
|
|
314
424
|
|
|
@@ -316,66 +426,60 @@ Après chaque action, donne un résumé clair de ce qui a été fait.`,
|
|
|
316
426
|
if (block.type === "text" && block.text) {
|
|
317
427
|
console.log();
|
|
318
428
|
console.log(line("─", C.gray));
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
if (l.startsWith("
|
|
322
|
-
else if (l.startsWith("
|
|
323
|
-
else if (l.
|
|
324
|
-
else
|
|
325
|
-
else if (l.trim() === "") console.log();
|
|
326
|
-
else console.log(` ${C.whiteBright}${l}${C.reset}`);
|
|
429
|
+
block.text.split("\n").forEach(l => {
|
|
430
|
+
if (l.startsWith("# ")) println(C.yellowBright + C.bold, " " + l.substring(2));
|
|
431
|
+
else if (l.startsWith("## ")) println(C.cyanBright + C.bold, " " + l.substring(3));
|
|
432
|
+
else if (l.startsWith("- ") || l.startsWith("• ")) println(C.reset, ` ${C.cyan}▸${C.reset} ${C.whiteBright}${l.substring(2)}${C.reset}`);
|
|
433
|
+
else if (l.trim() === "") console.log();
|
|
434
|
+
else println(C.whiteBright, " " + l);
|
|
327
435
|
});
|
|
328
436
|
console.log(line("─", C.gray));
|
|
329
437
|
}
|
|
330
438
|
if (block.type === "tool_use") {
|
|
331
439
|
hasToolUse = true;
|
|
332
|
-
|
|
333
|
-
console.log(`\n ${icon} ${C.magentaBright + C.bold}${block.name}${C.reset} ${C.gray}en cours...${C.reset}`);
|
|
440
|
+
println(C.magentaBright, `\n ${toolIcons[block.name] || "🔧"} ${C.bold}${block.name}${C.reset}`);
|
|
334
441
|
const result = await executeTool(block.name, block.input);
|
|
335
442
|
toolResults.push({ type: "tool_result", tool_use_id: block.id, content: result });
|
|
336
443
|
}
|
|
337
444
|
}
|
|
338
445
|
|
|
339
|
-
if (hasToolUse) {
|
|
340
|
-
history.push({ role: "user", content: toolResults });
|
|
341
|
-
const stop2 = startSpinner("Traitement des résultats...");
|
|
342
|
-
setTimeout(stop2, 100);
|
|
343
|
-
continue;
|
|
344
|
-
}
|
|
446
|
+
if (hasToolUse) { history.push({ role: "user", content: toolResults }); continue; }
|
|
345
447
|
break;
|
|
346
448
|
}
|
|
347
|
-
} catch (e) {
|
|
348
|
-
stopSpinner();
|
|
349
|
-
throw e;
|
|
350
|
-
}
|
|
449
|
+
} catch (e) { stopSpinner(); throw e; }
|
|
351
450
|
}
|
|
352
451
|
|
|
353
|
-
// ── Prompt
|
|
452
|
+
// ── Prompt ────────────────────────────────────────────────────
|
|
354
453
|
function showPrompt() {
|
|
454
|
+
const planColor = { free: C.gray, starter: C.cyanBright, pro: C.blueBright, business: C.magentaBright, enterprise: C.yellowBright, founder: C.greenBright };
|
|
455
|
+
const planId = currentUser?.plan_id || "free";
|
|
456
|
+
const pc = planColor[planId] || C.gray;
|
|
457
|
+
const planBadge = `${pc}[${PLANS[planId].name}]${C.reset}`;
|
|
355
458
|
const cwd = path.basename(process.cwd());
|
|
356
|
-
process.stdout.write(
|
|
357
|
-
`\n ${C.gray}[${C.cyanBright}${cwd}${C.gray}]${C.reset} ${C.yellowBright + C.bold}❯${C.reset} `
|
|
358
|
-
);
|
|
459
|
+
process.stdout.write(`\n ${C.gray}[${C.cyanBright}${cwd}${C.gray}]${C.reset} ${planBadge} ${C.yellowBright + C.bold}❯${C.reset} `);
|
|
359
460
|
}
|
|
360
461
|
|
|
361
|
-
// ── Main
|
|
462
|
+
// ── Main ──────────────────────────────────────────────────────
|
|
362
463
|
async function main() {
|
|
363
464
|
showHeader();
|
|
364
465
|
|
|
365
|
-
if (!
|
|
366
|
-
box([
|
|
367
|
-
`${C.redBright + C.bold}❌ Clé API manquante${C.reset}`,
|
|
368
|
-
"",
|
|
369
|
-
`Lance cette commande d'abord :`,
|
|
370
|
-
`${C.yellowBright}$env:ANTHROPIC_API_KEY="sk-ant-..."${C.reset}`,
|
|
371
|
-
], C.redBright);
|
|
466
|
+
if (!ANTHROPIC_KEY) {
|
|
467
|
+
box([`${C.redBright}❌ ANTHROPIC_API_KEY manquante${C.reset}`, "", `${C.yellow}$env:ANTHROPIC_API_KEY="sk-ant-..."${C.reset}`], C.redBright);
|
|
372
468
|
process.exit(1);
|
|
373
469
|
}
|
|
374
470
|
|
|
375
|
-
|
|
471
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
472
|
+
|
|
473
|
+
// Login
|
|
474
|
+
if (SUPABASE_ANON_KEY) {
|
|
475
|
+
currentUser = await loginFlow(rl);
|
|
476
|
+
} else {
|
|
477
|
+
println(C.yellow, " ⚠️ Mode hors-ligne (SUPABASE_ANON_KEY non configurée)\n");
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
await showStatus();
|
|
376
481
|
showHelp();
|
|
377
482
|
|
|
378
|
-
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
379
483
|
const history = [];
|
|
380
484
|
|
|
381
485
|
const prompt = () => {
|
|
@@ -384,49 +488,25 @@ async function main() {
|
|
|
384
488
|
const t = input.trim();
|
|
385
489
|
if (!t) return prompt();
|
|
386
490
|
|
|
387
|
-
// Commandes internes
|
|
388
491
|
if (t === "/exit" || t === "exit") {
|
|
389
492
|
saveHistory(history);
|
|
390
493
|
console.log();
|
|
391
|
-
box([
|
|
392
|
-
`${C.cyanBright + C.bold}👋 Merci d'avoir utilisé BIBEST CODE${C.reset}`,
|
|
393
|
-
"",
|
|
394
|
-
`${C.gray}Session sauvegardée — À bientôt !${C.reset}`,
|
|
395
|
-
`${C.gray}© BIBI ONDOUA — Tous droits réservés${C.reset}`,
|
|
396
|
-
], C.cyanBright);
|
|
397
|
-
console.log();
|
|
494
|
+
box([`${C.cyanBright + C.bold}👋 Au revoir !${C.reset}`, "", `${C.gray}© BIBI ONDOUA — Tous droits réservés${C.reset}`], C.cyanBright);
|
|
398
495
|
process.exit(0);
|
|
399
496
|
}
|
|
400
|
-
if (t === "/help")
|
|
401
|
-
if (t === "/clear")
|
|
402
|
-
if (t === "/stats")
|
|
497
|
+
if (t === "/help") { showHelp(); return prompt(); }
|
|
498
|
+
if (t === "/clear") { showHeader(); await showStatus(); return prompt(); }
|
|
499
|
+
if (t === "/stats") { showStats(); return prompt(); }
|
|
500
|
+
if (t === "/quota") { await showQuota(); return prompt(); }
|
|
501
|
+
if (t === "/upgrade") { showUpgrade(); return prompt(); }
|
|
403
502
|
if (t === "/history") { showHistory(); return prompt(); }
|
|
404
|
-
if (t === "/reset")
|
|
405
|
-
if (t === "/ls") {
|
|
406
|
-
|
|
407
|
-
console.log();
|
|
408
|
-
files.forEach(f => {
|
|
409
|
-
const stat = fs.statSync(f);
|
|
410
|
-
console.log(` ${stat.isDirectory() ? C.blueBright + "📁" : C.gray + "📄"} ${C.whiteBright}${f}${C.reset}`);
|
|
411
|
-
});
|
|
412
|
-
console.log();
|
|
413
|
-
return prompt();
|
|
414
|
-
}
|
|
415
|
-
if (t.startsWith("/cd ")) {
|
|
416
|
-
const dir = t.substring(4).trim();
|
|
417
|
-
try { process.chdir(dir); console.log(`\n ${C.greenBright}✅ Répertoire: ${process.cwd()}${C.reset}\n`); }
|
|
418
|
-
catch { console.log(`\n ${C.redBright}❌ Dossier introuvable: ${dir}${C.reset}\n`); }
|
|
419
|
-
return prompt();
|
|
420
|
-
}
|
|
503
|
+
if (t === "/reset") { history.length = 0; println(C.greenBright, "\n ✅ Conversation réinitialisée\n"); return prompt(); }
|
|
504
|
+
if (t === "/ls") { fs.readdirSync(process.cwd()).forEach(f => { const s = fs.statSync(f); println(s.isDirectory() ? C.blueBright : C.gray, ` ${s.isDirectory() ? "📁" : "📄"} ${C.whiteBright}${f}${C.reset}`); }); return prompt(); }
|
|
505
|
+
if (t.startsWith("/cd ")) { try { process.chdir(t.substring(4).trim()); println(C.greenBright, `\n ✅ ${process.cwd()}\n`); } catch { println(C.redBright, "\n ❌ Dossier introuvable\n"); } return prompt(); }
|
|
421
506
|
if (t.startsWith("/model")) { await selectModel(rl); return prompt(); }
|
|
422
507
|
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
await runAgent(t, history);
|
|
426
|
-
} catch (e) {
|
|
427
|
-
console.log();
|
|
428
|
-
box([`${C.redBright}❌ Erreur: ${e.message}${C.reset}`], C.redBright);
|
|
429
|
-
}
|
|
508
|
+
try { await runAgent(t, history); }
|
|
509
|
+
catch (e) { box([`${C.redBright}❌ ${e.message}${C.reset}`], C.redBright); }
|
|
430
510
|
prompt();
|
|
431
511
|
});
|
|
432
512
|
};
|
package/package.json
CHANGED
|
@@ -1,17 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bibest-code",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "Agent CLI de developpement propulse par Claude AI",
|
|
5
5
|
"main": "bibest-code.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
8
8
|
"bibest-code": "./bibest-code.js"
|
|
9
9
|
},
|
|
10
|
-
"keywords": [
|
|
10
|
+
"keywords": [
|
|
11
|
+
"ai",
|
|
12
|
+
"cli",
|
|
13
|
+
"claude",
|
|
14
|
+
"agent",
|
|
15
|
+
"developer-tools"
|
|
16
|
+
],
|
|
11
17
|
"author": "BIBI ONDOUA <b.ondoua00@gmail.com>",
|
|
12
18
|
"license": "ISC",
|
|
13
19
|
"dependencies": {
|
|
14
20
|
"@anthropic-ai/sdk": "^0.39.0",
|
|
15
|
-
"
|
|
21
|
+
"@supabase/supabase-js": "^2.108.2",
|
|
22
|
+
"readline-sync": "^1.4.10",
|
|
23
|
+
"stripe": "^22.3.0",
|
|
24
|
+
"ws": "^8.21.0"
|
|
16
25
|
}
|
|
17
|
-
}
|
|
26
|
+
}
|