create-byan-agent 2.6.0 → 2.6.2

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/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "create-byan-agent",
3
- "version": "2.6.0",
4
- "description": "BYAN v2.6.0 - Intelligent AI agent creator with ELO trust system + scientific fact-check + Hermes universal dispatcher. Multi-platform (Copilot CLI, Claude Code, Codex). Merise Agile + TDD + 64 Mantras. ~54% LLM cost savings.",
3
+ "version": "2.6.2",
4
+ "description": "BYAN v2.6.1 - Intelligent AI agent creator with ELO trust system + scientific fact-check + Hermes universal dispatcher. Multi-platform (Copilot CLI, Claude Code, Codex). Merise Agile + TDD + 64 Mantras. ~54% LLM cost savings.",
5
5
  "main": "src/index.js",
6
6
  "bin": {
7
7
  "create-byan-agent": "./install/bin/create-byan-agent-v2.js",
8
- "byan-v2": "./install/bin/create-byan-agent-v2.js"
8
+ "byan-v2": "./install/bin/create-byan-agent-v2.js",
9
+ "update-byan-agent": "./update-byan-agent/bin/update-byan-agent.js"
9
10
  },
10
11
  "scripts": {
11
12
  "test": "jest",
@@ -0,0 +1,165 @@
1
+ # BYAN Update Agent
2
+
3
+ Mécanisme de mise à jour fonctionnel pour BYAN installé via `npx create-byan-agent`.
4
+
5
+ ## Problème Résolu
6
+
7
+ Les utilisateurs qui ont installé BYAN avec une version antérieure n'avaient aucun moyen de mettre à jour leurs fichiers `_byan/` lorsqu'une nouvelle version était publiée sur npm.
8
+
9
+ ## Fonctionnalités
10
+
11
+ ### 1. Vérification de Version
12
+ ```bash
13
+ npx create-byan-agent check
14
+ # ou
15
+ npx update-byan-agent check
16
+ ```
17
+
18
+ Affiche :
19
+ - Version actuelle (depuis `_byan/bmb/config.yaml`)
20
+ - Dernière version npm (depuis registry.npmjs.org)
21
+ - Statut : à jour / mise à jour disponible / version dev
22
+
23
+ ### 2. Mise à Jour
24
+ ```bash
25
+ npx create-byan-agent update
26
+ # ou
27
+ npx update-byan-agent update
28
+ ```
29
+
30
+ Processus :
31
+ 1. Vérifie la version actuelle vs npm
32
+ 2. Demande confirmation
33
+ 3. Détecte les personnalisations
34
+ 4. Crée un backup automatique
35
+ 5. Télécharge la dernière version
36
+ 6. Préserve les fichiers utilisateur :
37
+ - `_byan/bmb/config.yaml`
38
+ - `_byan/_memory/`
39
+ - `_byan-output/`
40
+ 7. Restaure les personnalisations
41
+ 8. Met à jour `byan_version` dans config.yaml
42
+
43
+ Options :
44
+ - `--dry-run` : Analyse sans appliquer
45
+ - `--force` : Forcer même si déjà à jour
46
+
47
+ ### 3. Backup Manuel
48
+ ```bash
49
+ npx update-byan-agent backup
50
+ ```
51
+
52
+ Crée un backup horodaté dans `_byan.backup/backup-YYYY-MM-DD_HH-MM-SS/`
53
+
54
+ ### 4. Restauration
55
+ ```bash
56
+ npx create-byan-agent restore
57
+ # ou
58
+ npx update-byan-agent restore [--path /chemin/backup]
59
+ ```
60
+
61
+ Restaure depuis le dernier backup ou un backup spécifique.
62
+
63
+ ### 5. Lister Backups
64
+ ```bash
65
+ npx update-byan-agent list-backups
66
+ ```
67
+
68
+ Affiche tous les backups disponibles avec date et taille.
69
+
70
+ ## Architecture
71
+
72
+ ### Modules
73
+
74
+ #### `lib/analyzer.js`
75
+ - `checkCurrentVersion()` : Lit `byan_version` depuis config.yaml
76
+ - `fetchLatestVersion()` : Récupère dernière version npm via HTTPS
77
+ - `compare(current, latest)` : Comparaison semver
78
+ - `checkVersion()` : Combine tout pour retourner `{current, latest, needsUpdate}`
79
+
80
+ #### `lib/backup.js`
81
+ - `create()` : Copie `_byan/` vers `_byan.backup/backup-{timestamp}/`
82
+ - `restore(backupPath)` : Restaure depuis backup
83
+ - `getLatestBackup()` : Trouve dernier backup par date
84
+ - `listBackups()` : Liste tous les backups avec métadonnées
85
+
86
+ #### `lib/customization-detector.js`
87
+ - `detectCustomizations()` : Identifie fichiers à préserver
88
+ - `isModified(filePath)` : Vérifie si fichier modifié récemment
89
+
90
+ #### `bin/update-byan-agent.js`
91
+ Commandes CLI :
92
+ - `check` : Vérification version
93
+ - `update` : Mise à jour complète
94
+ - `backup` : Backup manuel
95
+ - `restore` : Restauration
96
+ - `list-backups` : Lister backups
97
+
98
+ ### Intégration
99
+
100
+ Le binaire principal `install/bin/create-byan-agent-v2.js` expose maintenant :
101
+ - `npx create-byan-agent` : Installation initiale
102
+ - `npx create-byan-agent check` : Vérification version
103
+ - `npx create-byan-agent update` : Mise à jour
104
+ - `npx create-byan-agent restore` : Restauration
105
+
106
+ ## Sécurité
107
+
108
+ ### Trust But Verify (Mantra IA-1)
109
+ - Validation de la version npm avant téléchargement
110
+ - Backup automatique avant toute modification
111
+ - Rollback automatique en cas d'erreur
112
+ - Préservation des personnalisations utilisateur
113
+
114
+ ### Zero Emoji dans Code (Mantra IA-23)
115
+ Tous les messages utilisateur utilisent des symboles textuels.
116
+
117
+ ### Dépendances
118
+ Utilise uniquement les modules déjà présents dans BYAN :
119
+ - `https` : Requêtes npm registry (built-in)
120
+ - `fs` / `fs-extra` : Opérations fichiers
121
+ - `path` : Manipulation chemins
122
+ - `js-yaml` : Parsing config.yaml
123
+ - `chalk`, `ora`, `inquirer` : UI
124
+
125
+ ## Workflow Utilisateur
126
+
127
+ ### Scénario Typique
128
+
129
+ ```bash
130
+ # 1. Installation initiale (v2.6.0)
131
+ npx create-byan-agent
132
+
133
+ # 2. Quelques semaines plus tard, nouvelle version disponible (v2.6.1)
134
+ npx create-byan-agent check
135
+ # → Affiche: Version actuelle: 2.6.0, npm: 2.6.1
136
+ # → Suggère: npx create-byan-agent update
137
+
138
+ # 3. Mise à jour
139
+ npx create-byan-agent update
140
+ # → Backup créé
141
+ # → Télécharge v2.6.1
142
+ # → Préserve config.yaml, _memory/, _byan-output/
143
+ # → Succès!
144
+
145
+ # 4. En cas de problème
146
+ npx create-byan-agent restore
147
+ # → Restaure backup automatiquement
148
+ ```
149
+
150
+ ## Mantras Applied
151
+ - IA-1: Trust But Verify
152
+ - IA-16: Challenge Before Confirm
153
+ - IA-23: Zero Emoji in Code
154
+ - #3: KISS (Keep It Simple)
155
+ - #4: YAGNI (You Aren't Gonna Need It)
156
+ - #39: Evaluate Consequences
157
+
158
+ ## License
159
+ MIT
160
+
161
+ ---
162
+
163
+ **Implémenté par:** Rachid (NPM/NPX Deployment Specialist)
164
+ **Version:** 1.0.0
165
+ **Date:** 2025-01-20
@@ -0,0 +1,303 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { program } = require('commander');
4
+ const chalk = require('chalk');
5
+ const ora = require('ora');
6
+ const inquirer = require('inquirer');
7
+ const path = require('path');
8
+ const fs = require('fs');
9
+ const { execSync } = require('child_process');
10
+
11
+ const Analyzer = require('../lib/analyzer');
12
+ const Backup = require('../lib/backup');
13
+ const CustomizationDetector = require('../lib/customization-detector');
14
+
15
+ program
16
+ .name('update-byan-agent')
17
+ .description('Gestion des mises a jour BYAN avec detection de conflits')
18
+ .version('2.6.1');
19
+
20
+ program
21
+ .command('check')
22
+ .description('Verifier version actuelle vs derniere version npm')
23
+ .action(async () => {
24
+ const spinner = ora('Verification version BYAN...').start();
25
+
26
+ try {
27
+ const installPath = process.cwd();
28
+ const analyzer = new Analyzer(installPath);
29
+
30
+ const versionInfo = await analyzer.checkVersion();
31
+
32
+ spinner.succeed('Verification terminee');
33
+
34
+ console.log('');
35
+ console.log(chalk.bold('Informations de version:'));
36
+ console.log(chalk.gray(' Version actuelle: ') + chalk.cyan(versionInfo.current));
37
+ console.log(chalk.gray(' Version npm: ') + chalk.cyan(versionInfo.latest));
38
+ console.log('');
39
+
40
+ if (versionInfo.upToDate) {
41
+ console.log(chalk.green(' BYAN est a jour!'));
42
+ } else if (versionInfo.needsUpdate) {
43
+ console.log(chalk.yellow(' Une mise a jour est disponible'));
44
+ console.log(chalk.gray(' Executer: npx update-byan-agent update'));
45
+ } else if (versionInfo.ahead) {
46
+ console.log(chalk.blue(' Vous utilisez une version dev en avance sur npm'));
47
+ }
48
+
49
+ } catch (error) {
50
+ spinner.fail('Erreur verification version');
51
+ console.error(chalk.red(` ${error.message}`));
52
+ process.exit(1);
53
+ }
54
+ });
55
+
56
+ program
57
+ .command('update')
58
+ .description('Mettre a jour installation BYAN')
59
+ .option('--dry-run', 'Analyser sans appliquer les changements')
60
+ .option('--force', 'Forcer la mise a jour meme si deja a jour')
61
+ .action(async (options) => {
62
+ const installPath = process.cwd();
63
+
64
+ try {
65
+ // Step 1: Check version
66
+ const spinner = ora('Verification version...').start();
67
+ const analyzer = new Analyzer(installPath);
68
+ const versionInfo = await analyzer.checkVersion();
69
+ spinner.succeed(`Version actuelle: ${versionInfo.current}, npm: ${versionInfo.latest}`);
70
+
71
+ if (versionInfo.upToDate && !options.force) {
72
+ console.log(chalk.green('\nBYAN est deja a jour!'));
73
+ return;
74
+ }
75
+
76
+ if (options.dryRun) {
77
+ console.log(chalk.cyan('\nMode dry-run: Aucune modification appliquee'));
78
+ return;
79
+ }
80
+
81
+ // Step 2: Confirm update
82
+ const { confirmUpdate } = await inquirer.prompt([{
83
+ type: 'confirm',
84
+ name: 'confirmUpdate',
85
+ message: `Mettre a jour BYAN ${versionInfo.current} -> ${versionInfo.latest}?`,
86
+ default: true
87
+ }]);
88
+
89
+ if (!confirmUpdate) {
90
+ console.log(chalk.yellow('Mise a jour annulee'));
91
+ return;
92
+ }
93
+
94
+ // Step 3: Detect customizations
95
+ const detectorSpinner = ora('Detection des personnalisations...').start();
96
+ const detector = new CustomizationDetector(installPath);
97
+ const customizations = await detector.detectCustomizations();
98
+ detectorSpinner.succeed(`${customizations.length} fichiers a preserver detectes`);
99
+
100
+ // Step 4: Create backup
101
+ const backupSpinner = ora('Creation backup...').start();
102
+ const backup = new Backup(installPath);
103
+ const backupPath = await backup.create();
104
+ backupSpinner.succeed(`Backup cree: ${path.basename(backupPath)}`);
105
+
106
+ // Step 5: Preserve customizations
107
+ const preserveSpinner = ora('Sauvegarde des personnalisations...').start();
108
+ const tempDir = path.join(installPath, '.byan-update-temp');
109
+ if (fs.existsSync(tempDir)) {
110
+ fs.rmSync(tempDir, { recursive: true, force: true });
111
+ }
112
+ fs.mkdirSync(tempDir, { recursive: true });
113
+
114
+ for (const custom of customizations) {
115
+ if (fs.existsSync(custom.path)) {
116
+ const relativePath = path.relative(installPath, custom.path);
117
+ const tempPath = path.join(tempDir, relativePath);
118
+ const tempParent = path.dirname(tempPath);
119
+
120
+ if (!fs.existsSync(tempParent)) {
121
+ fs.mkdirSync(tempParent, { recursive: true });
122
+ }
123
+
124
+ if (fs.statSync(custom.path).isDirectory()) {
125
+ copyRecursive(custom.path, tempPath);
126
+ } else {
127
+ fs.copyFileSync(custom.path, tempPath);
128
+ }
129
+ }
130
+ }
131
+ preserveSpinner.succeed('Personnalisations sauvegardees');
132
+
133
+ // Step 6: Download and install latest version
134
+ const updateSpinner = ora('Telechargement derniere version...').start();
135
+ try {
136
+ // Remove current _byan directory
137
+ const byanDir = path.join(installPath, '_byan');
138
+ if (fs.existsSync(byanDir)) {
139
+ fs.rmSync(byanDir, { recursive: true, force: true });
140
+ }
141
+
142
+ // Run npm install to get latest create-byan-agent
143
+ execSync('npm install --no-save create-byan-agent@latest', {
144
+ cwd: installPath,
145
+ stdio: 'pipe'
146
+ });
147
+
148
+ // Copy _byan from node_modules to project root
149
+ const nodeModulesByan = path.join(installPath, 'node_modules', 'create-byan-agent', '_byan');
150
+ if (fs.existsSync(nodeModulesByan)) {
151
+ copyRecursive(nodeModulesByan, byanDir);
152
+ } else {
153
+ throw new Error('_byan directory not found in npm package');
154
+ }
155
+
156
+ updateSpinner.succeed('Derniere version installee');
157
+ } catch (error) {
158
+ updateSpinner.fail('Erreur installation');
159
+
160
+ // Rollback
161
+ const rollbackSpinner = ora('Restauration backup...').start();
162
+ await backup.restore(backupPath);
163
+ rollbackSpinner.succeed('Backup restaure');
164
+
165
+ throw error;
166
+ }
167
+
168
+ // Step 7: Restore customizations
169
+ const restoreSpinner = ora('Restauration personnalisations...').start();
170
+ for (const custom of customizations) {
171
+ const relativePath = path.relative(installPath, custom.path);
172
+ const tempPath = path.join(tempDir, relativePath);
173
+
174
+ if (fs.existsSync(tempPath)) {
175
+ const targetParent = path.dirname(custom.path);
176
+
177
+ if (!fs.existsSync(targetParent)) {
178
+ fs.mkdirSync(targetParent, { recursive: true });
179
+ }
180
+
181
+ if (fs.statSync(tempPath).isDirectory()) {
182
+ copyRecursive(tempPath, custom.path);
183
+ } else {
184
+ fs.copyFileSync(tempPath, custom.path);
185
+ }
186
+ }
187
+ }
188
+ restoreSpinner.succeed('Personnalisations restaurees');
189
+
190
+ // Cleanup temp directory
191
+ if (fs.existsSync(tempDir)) {
192
+ fs.rmSync(tempDir, { recursive: true, force: true });
193
+ }
194
+
195
+ console.log('');
196
+ console.log(chalk.green.bold('Mise a jour terminee avec succes!'));
197
+ console.log(chalk.gray(` ${versionInfo.current} -> ${versionInfo.latest}`));
198
+ console.log('');
199
+
200
+ } catch (error) {
201
+ console.error('');
202
+ console.error(chalk.red.bold('Erreur lors de la mise a jour:'));
203
+ console.error(chalk.red(` ${error.message}`));
204
+ console.error('');
205
+ console.error(chalk.yellow('Le backup est disponible dans _byan.backup/'));
206
+ process.exit(1);
207
+ }
208
+ });
209
+
210
+ program
211
+ .command('backup')
212
+ .description('Creer backup manuel de _byan')
213
+ .action(async () => {
214
+ const spinner = ora('Creation backup...').start();
215
+
216
+ try {
217
+ const installPath = process.cwd();
218
+ const backup = new Backup(installPath);
219
+ const backupPath = await backup.create();
220
+
221
+ spinner.succeed('Backup cree avec succes');
222
+ console.log(chalk.gray(` Chemin: ${backupPath}`));
223
+
224
+ } catch (error) {
225
+ spinner.fail('Erreur creation backup');
226
+ console.error(chalk.red(` ${error.message}`));
227
+ process.exit(1);
228
+ }
229
+ });
230
+
231
+ program
232
+ .command('restore')
233
+ .description('Restaurer depuis backup')
234
+ .option('-p, --path <path>', 'Chemin du backup (dernier par defaut)')
235
+ .action(async (options) => {
236
+ const spinner = ora('Restauration backup...').start();
237
+
238
+ try {
239
+ const installPath = process.cwd();
240
+ const backup = new Backup(installPath);
241
+
242
+ await backup.restore(options.path);
243
+
244
+ spinner.succeed('Backup restaure avec succes');
245
+
246
+ } catch (error) {
247
+ spinner.fail('Erreur restauration backup');
248
+ console.error(chalk.red(` ${error.message}`));
249
+ process.exit(1);
250
+ }
251
+ });
252
+
253
+ program
254
+ .command('list-backups')
255
+ .description('Lister les backups disponibles')
256
+ .action(async () => {
257
+ try {
258
+ const installPath = process.cwd();
259
+ const backup = new Backup(installPath);
260
+ const backups = await backup.listBackups();
261
+
262
+ if (backups.length === 0) {
263
+ console.log(chalk.yellow('Aucun backup disponible'));
264
+ return;
265
+ }
266
+
267
+ console.log(chalk.bold('\nBackups disponibles:'));
268
+ backups.forEach((b, i) => {
269
+ const size = (b.size / 1024).toFixed(2);
270
+ console.log(` ${i + 1}. ${chalk.cyan(b.name)}`);
271
+ console.log(` ${chalk.gray('Date:')} ${new Date(b.timestamp).toLocaleString()}`);
272
+ console.log(` ${chalk.gray('Taille:')} ${size} KB`);
273
+ });
274
+
275
+ } catch (error) {
276
+ console.error(chalk.red(`Erreur: ${error.message}`));
277
+ process.exit(1);
278
+ }
279
+ });
280
+
281
+ /**
282
+ * Helper function to copy directory recursively
283
+ */
284
+ function copyRecursive(src, dest) {
285
+ if (!fs.existsSync(dest)) {
286
+ fs.mkdirSync(dest, { recursive: true });
287
+ }
288
+
289
+ const entries = fs.readdirSync(src, { withFileTypes: true });
290
+
291
+ for (const entry of entries) {
292
+ const srcPath = path.join(src, entry.name);
293
+ const destPath = path.join(dest, entry.name);
294
+
295
+ if (entry.isDirectory()) {
296
+ copyRecursive(srcPath, destPath);
297
+ } else {
298
+ fs.copyFileSync(srcPath, destPath);
299
+ }
300
+ }
301
+ }
302
+
303
+ program.parse();