create-byan-agent 2.0.1 → 2.1.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/API-BYAN-V2.md +741 -0
- package/BMAD-QUICK-REFERENCE.md +370 -0
- package/CHANGELOG-v2.1.0.md +371 -0
- package/LICENSE +1 -1
- package/MIGRATION-v2.0-to-v2.1.md +430 -0
- package/README-BYAN-V2.md +446 -0
- package/README.md +264 -201
- package/install/.eslintrc.js +20 -0
- package/install/.prettierrc +7 -0
- package/install/BUGFIX-CHALK.md +173 -0
- package/install/BUGFIX-DOCUMENTATION-INDEX.md +299 -0
- package/install/BUGFIX-PATH-RESOLUTION.md +293 -0
- package/install/BUGFIX-QUICKSTART.md +184 -0
- package/install/BUGFIX-SUMMARY.txt +91 -0
- package/install/BUGFIX-VISUAL-SUMMARY.md +253 -0
- package/install/DEPLOYMENT-GUIDE-V2.md +431 -0
- package/install/DOCS-INDEX.md +261 -0
- package/install/GUIDE-INSTALLATION-BYAN-SIMPLE.md +1083 -0
- package/install/INSTALLER-V2-CHANGES.md +472 -0
- package/install/LICENSE +21 -0
- package/install/PUBLICATION-CHECKLIST.md +265 -0
- package/install/PUBLISH-GUIDE.md +190 -0
- package/install/QUICKSTART.md +311 -0
- package/install/README-NPM-PUBLISH.md +298 -0
- package/install/README-NPM-SHORT.md +298 -0
- package/install/README-NPM.md +433 -0
- package/install/README-RACHID.md +302 -0
- package/install/README-V2-INDEX.md +306 -0
- package/install/README.md +298 -0
- package/install/RESUME-EXECUTIF-YAN.md +408 -0
- package/install/UPDATE-SUMMARY.md +205 -0
- package/install/__tests__/integration/detection-flow.test.js +154 -0
- package/install/__tests__/platforms/claude-code.test.js +175 -0
- package/install/__tests__/platforms/codex.test.js +80 -0
- package/install/__tests__/platforms/copilot-cli.test.js +118 -0
- package/install/__tests__/platforms/vscode.test.js +67 -0
- package/install/__tests__/utils/file-utils.test.js +87 -0
- package/install/__tests__/utils/git-detector.test.js +80 -0
- package/install/__tests__/utils/logger.test.js +83 -0
- package/install/__tests__/utils/node-detector.test.js +71 -0
- package/install/__tests__/utils/os-detector.test.js +63 -0
- package/install/__tests__/utils/yaml-utils.test.js +85 -0
- package/install/__tests__/yanstaller/detector.test.js +210 -0
- package/install/coverage/clover.xml +219 -0
- package/install/coverage/coverage-final.json +13 -0
- package/install/coverage/lcov-report/base.css +224 -0
- package/install/coverage/lcov-report/block-navigation.js +87 -0
- package/install/coverage/lcov-report/favicon.png +0 -0
- package/install/coverage/lcov-report/index.html +146 -0
- package/install/coverage/lcov-report/lib/errors.js.html +268 -0
- package/install/coverage/lcov-report/lib/exit-codes.js.html +247 -0
- package/install/coverage/lcov-report/lib/index.html +131 -0
- package/install/coverage/lcov-report/lib/platforms/claude-code.js.html +343 -0
- package/install/coverage/lcov-report/lib/platforms/codex.js.html +361 -0
- package/install/coverage/lcov-report/lib/platforms/copilot-cli.js.html +454 -0
- package/install/coverage/lcov-report/lib/platforms/index.html +176 -0
- package/install/coverage/lcov-report/lib/platforms/index.js.html +127 -0
- package/install/coverage/lcov-report/lib/platforms/vscode.js.html +238 -0
- package/install/coverage/lcov-report/lib/utils/config-loader.js.html +322 -0
- package/install/coverage/lcov-report/lib/utils/file-utils.js.html +397 -0
- package/install/coverage/lcov-report/lib/utils/git-detector.js.html +190 -0
- package/install/coverage/lcov-report/lib/utils/index.html +206 -0
- package/install/coverage/lcov-report/lib/utils/logger.js.html +277 -0
- package/install/coverage/lcov-report/lib/utils/node-detector.js.html +259 -0
- package/install/coverage/lcov-report/lib/utils/os-detector.js.html +307 -0
- package/install/coverage/lcov-report/lib/utils/yaml-utils.js.html +346 -0
- package/install/coverage/lcov-report/lib/yanstaller/backuper.js.html +409 -0
- package/install/coverage/lcov-report/lib/yanstaller/detector.js.html +508 -0
- package/install/coverage/lcov-report/lib/yanstaller/index.html +236 -0
- package/install/coverage/lcov-report/lib/yanstaller/index.js.html +364 -0
- package/install/coverage/lcov-report/lib/yanstaller/installer.js.html +505 -0
- package/install/coverage/lcov-report/lib/yanstaller/interviewer.js.html +349 -0
- package/install/coverage/lcov-report/lib/yanstaller/recommender.js.html +379 -0
- package/install/coverage/lcov-report/lib/yanstaller/troubleshooter.js.html +352 -0
- package/install/coverage/lcov-report/lib/yanstaller/validator.js.html +679 -0
- package/install/coverage/lcov-report/lib/yanstaller/wizard.js.html +412 -0
- package/install/coverage/lcov-report/platforms/claude-code.js.html +343 -0
- package/install/coverage/lcov-report/platforms/codex.js.html +361 -0
- package/install/coverage/lcov-report/platforms/copilot-cli.js.html +454 -0
- package/install/coverage/lcov-report/platforms/index.html +176 -0
- package/install/coverage/lcov-report/platforms/index.js.html +127 -0
- package/install/coverage/lcov-report/platforms/vscode.js.html +238 -0
- package/install/coverage/lcov-report/prettify.css +1 -0
- package/install/coverage/lcov-report/prettify.js +2 -0
- package/install/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/install/coverage/lcov-report/sorter.js +210 -0
- package/install/coverage/lcov-report/utils/file-utils.js.html +397 -0
- package/install/coverage/lcov-report/utils/git-detector.js.html +190 -0
- package/install/coverage/lcov-report/utils/index.html +191 -0
- package/install/coverage/lcov-report/utils/logger.js.html +277 -0
- package/install/coverage/lcov-report/utils/node-detector.js.html +259 -0
- package/install/coverage/lcov-report/utils/os-detector.js.html +307 -0
- package/install/coverage/lcov-report/utils/yaml-utils.js.html +346 -0
- package/install/coverage/lcov-report/yanstaller/detector.js.html +508 -0
- package/install/coverage/lcov-report/yanstaller/index.html +116 -0
- package/install/coverage/lcov.info +414 -0
- package/install/install.sh +239 -0
- package/install/jest.config.js +33 -0
- package/install/lib/errors.js +61 -0
- package/install/lib/exit-codes.js +54 -0
- package/install/lib/platforms/claude-code.js +86 -0
- package/install/lib/platforms/codex.js +92 -0
- package/install/lib/platforms/copilot-cli.js +123 -0
- package/install/lib/platforms/index.js +14 -0
- package/install/lib/platforms/vscode.js +51 -0
- package/install/lib/utils/config-loader.js +79 -0
- package/install/lib/utils/file-utils.js +104 -0
- package/install/lib/utils/git-detector.js +35 -0
- package/install/lib/utils/logger.js +64 -0
- package/install/lib/utils/node-detector.js +58 -0
- package/install/lib/utils/os-detector.js +74 -0
- package/install/lib/utils/yaml-utils.js +87 -0
- package/install/lib/yanstaller/backuper.js +108 -0
- package/install/lib/yanstaller/detector.js +141 -0
- package/install/lib/yanstaller/index.js +93 -0
- package/install/lib/yanstaller/installer.js +140 -0
- package/install/lib/yanstaller/interviewer.js +88 -0
- package/install/lib/yanstaller/recommender.js +98 -0
- package/install/lib/yanstaller/troubleshooter.js +89 -0
- package/install/lib/yanstaller/validator.js +198 -0
- package/install/lib/yanstaller/wizard.js +109 -0
- package/install/package-npm.json +55 -0
- package/install/package.json +63 -0
- package/install/src/byan-v2/context/copilot-context.js +79 -0
- package/install/src/byan-v2/context/session-state.js +98 -0
- package/install/src/byan-v2/dispatcher/complexity-scorer.js +232 -0
- package/install/src/byan-v2/dispatcher/local-executor.js +221 -0
- package/install/src/byan-v2/dispatcher/task-router.js +122 -0
- package/install/src/byan-v2/dispatcher/task-tool-interface-mock.js +134 -0
- package/install/src/byan-v2/dispatcher/task-tool-interface.js +123 -0
- package/install/src/byan-v2/generation/agent-profile-validator.js +113 -0
- package/install/src/byan-v2/generation/profile-template.js +113 -0
- package/install/src/byan-v2/generation/templates/default-agent.md +49 -0
- package/install/src/byan-v2/generation/templates/test-template.md +1 -0
- package/install/src/byan-v2/index.js +199 -0
- package/install/src/byan-v2/observability/error-tracker.js +105 -0
- package/install/src/byan-v2/observability/logger.js +154 -0
- package/install/src/byan-v2/observability/metrics-collector.js +194 -0
- package/install/src/byan-v2/orchestrator/analysis-state.js +268 -0
- package/install/src/byan-v2/orchestrator/generation-state.js +340 -0
- package/install/src/byan-v2/orchestrator/interview-state.js +271 -0
- package/install/src/byan-v2/orchestrator/state-machine.js +204 -0
- package/install/src/core/cache/cache.js +126 -0
- package/install/src/core/context/context.js +86 -0
- package/install/src/core/dispatcher/dispatcher.js +135 -0
- package/install/src/core/worker-pool/worker-pool.js +194 -0
- package/install/src/core/workflow/workflow-executor.js +220 -0
- package/install/src/index.js +139 -0
- package/install/src/observability/dashboard/dashboard.js +191 -0
- package/install/src/observability/logger/structured-logger.js +254 -0
- package/install/src/observability/metrics/metrics-collector.js +325 -0
- package/install/switch-to-v2.sh +126 -0
- package/install/test-chalk-fix.sh +210 -0
- package/install/test-installer-v2.sh +204 -0
- package/install/test-path-resolution.sh +200 -0
- package/package.json +53 -33
- package/src/byan-v2/context/copilot-context.js +79 -0
- package/src/byan-v2/context/session-state.js +98 -0
- package/src/byan-v2/data/mantras.json +852 -0
- package/src/byan-v2/dispatcher/complexity-scorer.js +232 -0
- package/src/byan-v2/dispatcher/five-whys-analyzer.js +310 -0
- package/src/byan-v2/dispatcher/local-executor.js +221 -0
- package/src/byan-v2/dispatcher/task-router.js +122 -0
- package/src/byan-v2/dispatcher/task-tool-interface-mock.js +134 -0
- package/src/byan-v2/dispatcher/task-tool-interface.js +123 -0
- package/src/byan-v2/generation/agent-profile-validator.js +113 -0
- package/src/byan-v2/generation/mantra-validator.js +416 -0
- package/src/byan-v2/generation/profile-template.js +113 -0
- package/src/byan-v2/generation/templates/default-agent.md +49 -0
- package/src/byan-v2/generation/templates/test-template.md +1 -0
- package/src/byan-v2/index.js +652 -0
- package/src/byan-v2/integration/voice-integration.js +295 -0
- package/src/byan-v2/observability/error-tracker.js +105 -0
- package/src/byan-v2/observability/logger.js +154 -0
- package/src/byan-v2/observability/metrics-collector.js +194 -0
- package/src/byan-v2/orchestrator/active-listener.js +541 -0
- package/src/byan-v2/orchestrator/analysis-state.js +268 -0
- package/src/byan-v2/orchestrator/generation-state.js +340 -0
- package/src/byan-v2/orchestrator/glossary-builder.js +431 -0
- package/src/byan-v2/orchestrator/interview-state.js +353 -0
- package/src/byan-v2/orchestrator/state-machine.js +253 -0
- package/src/core/cache/cache.js +126 -0
- package/src/core/context/context.js +86 -0
- package/src/core/dispatcher/dispatcher.js +135 -0
- package/src/core/worker-pool/worker-pool.js +194 -0
- package/src/core/workflow/workflow-executor.js +220 -0
- package/src/index.js +139 -0
- package/src/observability/dashboard/dashboard.js +191 -0
- package/src/observability/logger/structured-logger.js +254 -0
- package/src/observability/metrics/metrics-collector.js +325 -0
- package/templates/.github/agents/bmad-agent-test-dynamic.md +0 -21
- package/templates/.github/agents/franck.md +0 -379
- /package/{CHANGELOG.md → install/CHANGELOG.md} +0 -0
- /package/{bin → install/bin}/create-byan-agent-backup.js +0 -0
- /package/{bin → install/bin}/create-byan-agent-fixed.js +0 -0
- /package/{bin → install/bin}/create-byan-agent-v2.js +0 -0
- /package/{bin → install/bin}/create-byan-agent.js +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmad-master.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmb-agent-builder.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmb-module-builder.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmb-workflow-builder.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-analyst.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-architect.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-dev.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-pm.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-quick-flow-solo-dev.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-quinn.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-sm.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-tech-writer.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-bmm-ux-designer.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-byan-test.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-byan.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-carmack.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-cis-brainstorming-coach.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-cis-creative-problem-solver.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-cis-design-thinking-coach.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-cis-innovation-strategist.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-cis-presentation-master.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-cis-storyteller.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-marc.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-patnote.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-rachid.md +0 -0
- /package/{templates → install/templates}/.github/agents/bmad-agent-tea-tea.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/agent-builder.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/byan-test.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/byan.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/marc.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/module-builder.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/patnote.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/rachid.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/agents/workflow-builder.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/data/mantras.yaml +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/data/templates.yaml +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/delete-agent-workflow.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/edit-agent-workflow.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/interview-workflow.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/quick-create-workflow.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/templates/base-agent-template.md +0 -0
- /package/{templates → install/templates}/_bmad/bmb/workflows/byan/validate-agent-workflow.md +0 -0
- /package/{templates → install/templates}/_bmad/core/agents/carmack.md +0 -0
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# Résumé des Modifications - Package NPM v1.0.2
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-02-02
|
|
4
|
+
**Par:** RACHID (Expert NPM/NPX) + Yan
|
|
5
|
+
**Status:** ✅ Prêt pour publication
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 📦 Modifications Principales
|
|
10
|
+
|
|
11
|
+
### 1. Nouveaux Agents Ajoutés
|
|
12
|
+
|
|
13
|
+
#### RACHID - Expert NPM/NPX
|
|
14
|
+
- **Fichier:** `templates/_bmad/bmb/agents/rachid.md` (7.2 KB)
|
|
15
|
+
- **Stub:** `templates/.github/agents/bmad-agent-rachid.md` (1.8 KB)
|
|
16
|
+
- **Capacités:**
|
|
17
|
+
- Installation BYAN via npx
|
|
18
|
+
- Validation structure _bmad
|
|
19
|
+
- Gestion dépendances npm
|
|
20
|
+
- Publication npm registry
|
|
21
|
+
- Tests npx
|
|
22
|
+
- Audits sécurité
|
|
23
|
+
|
|
24
|
+
#### MARC - Expert GitHub Copilot CLI
|
|
25
|
+
- **Fichier:** `templates/_bmad/bmb/agents/marc.md` (10.8 KB)
|
|
26
|
+
- **Stub:** `templates/.github/agents/bmad-agent-marc.md` (1.9 KB)
|
|
27
|
+
- **Capacités:**
|
|
28
|
+
- Validation .github/agents/
|
|
29
|
+
- Test détection /agent
|
|
30
|
+
- Création stubs agents
|
|
31
|
+
- Configuration MCP servers
|
|
32
|
+
- Optimisation contexte
|
|
33
|
+
|
|
34
|
+
### 2. Structure Templates
|
|
35
|
+
|
|
36
|
+
**Nouveau dossier:** `install/templates/`
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
templates/
|
|
40
|
+
├── _bmad/
|
|
41
|
+
│ └── bmb/
|
|
42
|
+
│ ├── agents/ (6 agents)
|
|
43
|
+
│ │ ├── byan.md ✅ 12.8 KB
|
|
44
|
+
│ │ ├── rachid.md ✅ 7.2 KB (NOUVEAU)
|
|
45
|
+
│ │ ├── marc.md ✅ 10.8 KB (NOUVEAU)
|
|
46
|
+
│ │ ├── agent-builder.md ✅
|
|
47
|
+
│ │ ├── module-builder.md ✅
|
|
48
|
+
│ │ └── workflow-builder.md ✅
|
|
49
|
+
│ └── workflows/
|
|
50
|
+
│ └── byan/
|
|
51
|
+
│ ├── interview-workflow.md ✅
|
|
52
|
+
│ ├── quick-create-workflow.md ✅
|
|
53
|
+
│ ├── edit-agent-workflow.md ✅
|
|
54
|
+
│ ├── delete-agent-workflow.md ✅
|
|
55
|
+
│ ├── validate-agent-workflow.md ✅
|
|
56
|
+
│ ├── templates/
|
|
57
|
+
│ │ └── base-agent-template.md ✅
|
|
58
|
+
│ └── data/
|
|
59
|
+
│ ├── mantras.yaml ✅
|
|
60
|
+
│ └── templates.yaml ✅
|
|
61
|
+
└── .github/
|
|
62
|
+
└── agents/ (24 stubs au total)
|
|
63
|
+
├── bmad-agent-byan.md ✅ 13.2 KB
|
|
64
|
+
├── bmad-agent-rachid.md ✅ 1.8 KB (NOUVEAU)
|
|
65
|
+
├── bmad-agent-marc.md ✅ 1.9 KB (NOUVEAU)
|
|
66
|
+
└── ... (21 autres stubs)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**Total fichiers:** 37 fichiers
|
|
70
|
+
|
|
71
|
+
### 3. Script d'Installation Amélioré
|
|
72
|
+
|
|
73
|
+
**Fichier:** `bin/create-byan-agent.js` (mise à jour de 8.4 KB → 11.6 KB)
|
|
74
|
+
|
|
75
|
+
**Nouvelles fonctionnalités:**
|
|
76
|
+
- ✅ Fonction `getTemplateDir()` pour résolution chemin templates
|
|
77
|
+
- ✅ Copie complète depuis `templates/` vers projet
|
|
78
|
+
- ✅ Création automatique `.github/agents/`
|
|
79
|
+
- ✅ Vérification 10 checks (au lieu de 3)
|
|
80
|
+
- ✅ Messages post-installation détaillés pour les 3 agents
|
|
81
|
+
|
|
82
|
+
**Vérifications ajoutées:**
|
|
83
|
+
1. Agents directory
|
|
84
|
+
2. BYAN agent
|
|
85
|
+
3. RACHID agent (nouveau)
|
|
86
|
+
4. MARC agent (nouveau)
|
|
87
|
+
5. Workflows
|
|
88
|
+
6. Config
|
|
89
|
+
7. GitHub agents dir (nouveau)
|
|
90
|
+
8. BYAN stub (nouveau)
|
|
91
|
+
9. RACHID stub (nouveau)
|
|
92
|
+
10. MARC stub (nouveau)
|
|
93
|
+
|
|
94
|
+
### 4. Package.json
|
|
95
|
+
|
|
96
|
+
**Changements:**
|
|
97
|
+
```diff
|
|
98
|
+
- "version": "1.0.1"
|
|
99
|
+
+ "version": "1.0.2"
|
|
100
|
+
|
|
101
|
+
- "description": "NPX installer for BYAN - Builder of YAN agent creator"
|
|
102
|
+
+ "description": "NPX installer for BYAN - Builder of YAN agent creator with RACHID and MARC"
|
|
103
|
+
|
|
104
|
+
"keywords": [
|
|
105
|
+
"byan",
|
|
106
|
+
"agent",
|
|
107
|
+
"creator",
|
|
108
|
+
...
|
|
109
|
+
+ "rachid",
|
|
110
|
+
+ "marc",
|
|
111
|
+
+ "npm",
|
|
112
|
+
+ "deployment"
|
|
113
|
+
]
|
|
114
|
+
|
|
115
|
+
"files": [
|
|
116
|
+
"bin/",
|
|
117
|
+
+ "templates/",
|
|
118
|
+
"README.md",
|
|
119
|
+
+ "CHANGELOG.md",
|
|
120
|
+
"LICENSE"
|
|
121
|
+
]
|
|
122
|
+
|
|
123
|
+
+ "scripts": {
|
|
124
|
+
+ "start": "node bin/create-byan-agent.js",
|
|
125
|
+
+ "test": "node bin/create-byan-agent.js"
|
|
126
|
+
+ }
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### 5. Documentation
|
|
130
|
+
|
|
131
|
+
**Fichiers mis à jour:**
|
|
132
|
+
- ✅ `README.md` - Ajout RACHID et MARC
|
|
133
|
+
- ✅ `CHANGELOG.md` - Nouveau fichier avec historique complet
|
|
134
|
+
- ✅ `PUBLISH-GUIDE.md` - Guide de publication npm
|
|
135
|
+
|
|
136
|
+
**Sections ajoutées dans README:**
|
|
137
|
+
- Section "Three Specialized Agents"
|
|
138
|
+
- Instructions activation pour les 3 agents
|
|
139
|
+
- Menus RACHID et MARC
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## 📊 Statistiques
|
|
144
|
+
|
|
145
|
+
| Métrique | Avant (v1.0.1) | Après (v1.0.2) | Diff |
|
|
146
|
+
|----------|----------------|----------------|------|
|
|
147
|
+
| Agents | 1 (BYAN) | 3 (BYAN, RACHID, MARC) | +2 |
|
|
148
|
+
| Fichiers templates | 0 | 37 | +37 |
|
|
149
|
+
| Taille package | ~10 KB | ~200 KB | +190 KB |
|
|
150
|
+
| Checks validation | 3 | 10 | +7 |
|
|
151
|
+
| Mots-clés npm | 9 | 13 | +4 |
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## ✅ Tests Effectués
|
|
156
|
+
|
|
157
|
+
- [x] `npm pack --dry-run` - Package valide
|
|
158
|
+
- [x] `node bin/create-byan-agent.js --version` - Version 1.0.2
|
|
159
|
+
- [x] Vérification structure templates/ - 37 fichiers
|
|
160
|
+
- [x] Vérification agents: byan.md, rachid.md, marc.md présents
|
|
161
|
+
- [x] Vérification workflows complets
|
|
162
|
+
- [x] Vérification stubs .github/agents/
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## 🚀 Prêt pour Publication
|
|
167
|
+
|
|
168
|
+
### Commandes recommandées:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
# 1. Audit de sécurité
|
|
172
|
+
cd /home/yan/conception/install
|
|
173
|
+
npm audit
|
|
174
|
+
|
|
175
|
+
# 2. Test local
|
|
176
|
+
npm pack
|
|
177
|
+
mkdir -p /tmp/test-byan-v1.0.2
|
|
178
|
+
cd /tmp/test-byan-v1.0.2
|
|
179
|
+
npx /home/yan/conception/install/create-byan-agent-1.0.2.tgz
|
|
180
|
+
|
|
181
|
+
# 3. Commit Git
|
|
182
|
+
cd /home/yan/conception
|
|
183
|
+
git add install/
|
|
184
|
+
git commit -m "chore: release create-byan-agent v1.0.2"
|
|
185
|
+
git tag -a v1.0.2 -m "Release v1.0.2"
|
|
186
|
+
|
|
187
|
+
# 4. Publication NPM
|
|
188
|
+
cd install/
|
|
189
|
+
npm publish
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## 📝 Notes
|
|
195
|
+
|
|
196
|
+
- Package compatible Node.js >=18.0.0
|
|
197
|
+
- Dépendances: chalk, commander, inquirer, fs-extra, js-yaml, ora
|
|
198
|
+
- License: MIT
|
|
199
|
+
- Aucune vulnérabilité de sécurité connue
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
**Créé par:** RACHID
|
|
204
|
+
**Validé par:** Yan
|
|
205
|
+
**Date:** 2026-02-02 16:50 UTC
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detection Flow Integration Tests
|
|
3
|
+
*
|
|
4
|
+
* End-to-end integration tests for YANSTALLER Phase 1 Detection.
|
|
5
|
+
* These tests run on real environment (not fully mocked).
|
|
6
|
+
*
|
|
7
|
+
* Tests verify:
|
|
8
|
+
* - Full detection flow returns valid structure
|
|
9
|
+
* - Detection handles missing platforms gracefully
|
|
10
|
+
* - Detection performance is acceptable (< 5s with timeouts)
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const detector = require('../../lib/yanstaller/detector');
|
|
14
|
+
const osDetector = require('../../lib/utils/os-detector');
|
|
15
|
+
const nodeDetector = require('../../lib/utils/node-detector');
|
|
16
|
+
const gitDetector = require('../../lib/utils/git-detector');
|
|
17
|
+
|
|
18
|
+
describe('Detection Flow Integration', () => {
|
|
19
|
+
describe('Full detection', () => {
|
|
20
|
+
it('should return complete detection structure with real environment', async () => {
|
|
21
|
+
const result = await detector.detect();
|
|
22
|
+
|
|
23
|
+
// Validate structure
|
|
24
|
+
expect(result).toHaveProperty('os');
|
|
25
|
+
expect(result).toHaveProperty('osVersion');
|
|
26
|
+
expect(result).toHaveProperty('nodeVersion');
|
|
27
|
+
expect(result).toHaveProperty('hasGit');
|
|
28
|
+
expect(result).toHaveProperty('gitVersion');
|
|
29
|
+
expect(result).toHaveProperty('platforms');
|
|
30
|
+
|
|
31
|
+
// Validate OS detection
|
|
32
|
+
expect(result.os).toBe(osDetector.detect().name);
|
|
33
|
+
expect(typeof result.osVersion).toBe('string');
|
|
34
|
+
expect(result.osVersion.length).toBeGreaterThan(0);
|
|
35
|
+
|
|
36
|
+
// Validate Node detection
|
|
37
|
+
expect(typeof result.nodeVersion).toBe('string');
|
|
38
|
+
expect(result.nodeVersion).toMatch(/^\d+\.\d+\.\d+$/);
|
|
39
|
+
|
|
40
|
+
// Validate Git detection
|
|
41
|
+
expect(typeof result.hasGit).toBe('boolean');
|
|
42
|
+
if (result.hasGit) {
|
|
43
|
+
expect(typeof result.gitVersion).toBe('string');
|
|
44
|
+
expect(result.gitVersion.length).toBeGreaterThan(0);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Validate platforms (array of 4)
|
|
48
|
+
expect(Array.isArray(result.platforms)).toBe(true);
|
|
49
|
+
expect(result.platforms).toHaveLength(4);
|
|
50
|
+
|
|
51
|
+
// Each platform has required structure
|
|
52
|
+
result.platforms.forEach(platform => {
|
|
53
|
+
expect(platform).toHaveProperty('name');
|
|
54
|
+
expect(platform).toHaveProperty('detected');
|
|
55
|
+
expect(typeof platform.detected).toBe('boolean');
|
|
56
|
+
|
|
57
|
+
if (platform.detected) {
|
|
58
|
+
expect(platform).toHaveProperty('path');
|
|
59
|
+
expect(typeof platform.path).toBe('string');
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('should detect platforms based on current directory structure', async () => {
|
|
65
|
+
const result = await detector.detect();
|
|
66
|
+
|
|
67
|
+
// Count detected platforms
|
|
68
|
+
const detectedCount = result.platforms.filter(p => p.detected).length;
|
|
69
|
+
|
|
70
|
+
// Platform detection depends on CWD and environment
|
|
71
|
+
// At minimum, structure should be valid
|
|
72
|
+
expect(detectedCount).toBeGreaterThanOrEqual(0);
|
|
73
|
+
expect(detectedCount).toBeLessThanOrEqual(4);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
describe('Performance', () => {
|
|
78
|
+
it('should complete detection in under 5 seconds (with timeout protection)', async () => {
|
|
79
|
+
const startTime = Date.now();
|
|
80
|
+
|
|
81
|
+
await detector.detect();
|
|
82
|
+
|
|
83
|
+
const duration = Date.now() - startTime;
|
|
84
|
+
|
|
85
|
+
// With 10s timeout per platform, worst case is ~10s
|
|
86
|
+
// Normal case should be < 5s
|
|
87
|
+
expect(duration).toBeLessThan(5000);
|
|
88
|
+
}, 6000); // Test timeout 6s (allows 5s + overhead)
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
describe('Node version validation', () => {
|
|
92
|
+
it('should validate current Node version meets requirement', () => {
|
|
93
|
+
const currentVersion = nodeDetector.detect();
|
|
94
|
+
const requirement = '18.0.0';
|
|
95
|
+
|
|
96
|
+
const isValid = detector.isNodeVersionValid(currentVersion, requirement);
|
|
97
|
+
|
|
98
|
+
// Current environment runs Node >= 18
|
|
99
|
+
expect(isValid).toBe(true);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('should reject old Node versions', () => {
|
|
103
|
+
const isValid = detector.isNodeVersionValid('16.0.0', '18.0.0');
|
|
104
|
+
|
|
105
|
+
expect(isValid).toBe(false);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
describe('Platform detection details', () => {
|
|
110
|
+
it('should return valid structure for copilot-cli detection', async () => {
|
|
111
|
+
const platformInfo = await detector.detectPlatform('copilot-cli');
|
|
112
|
+
|
|
113
|
+
expect(platformInfo.name).toBe('copilot-cli');
|
|
114
|
+
expect(typeof platformInfo.detected).toBe('boolean');
|
|
115
|
+
|
|
116
|
+
// Path present only if detected
|
|
117
|
+
if (platformInfo.detected) {
|
|
118
|
+
expect(platformInfo.path).toBe('.github/agents');
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('should detect vscode platform (delegates to copilot-cli)', async () => {
|
|
123
|
+
const platformInfo = await detector.detectPlatform('vscode');
|
|
124
|
+
|
|
125
|
+
expect(platformInfo.name).toBe('vscode');
|
|
126
|
+
// VSCode uses same path as copilot-cli
|
|
127
|
+
expect(typeof platformInfo.detected).toBe('boolean');
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('should handle unknown platform gracefully', async () => {
|
|
131
|
+
await expect(
|
|
132
|
+
detector.detectPlatform('unknown-platform')
|
|
133
|
+
).rejects.toThrow('Unknown platform: unknown-platform');
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
describe('Resilience', () => {
|
|
138
|
+
it('should handle all platforms gracefully even if none detected', async () => {
|
|
139
|
+
// This test validates structure even if detection returns false
|
|
140
|
+
const result = await detector.detect();
|
|
141
|
+
|
|
142
|
+
// All 4 platforms should be checked
|
|
143
|
+
const platformNames = result.platforms.map(p => p.name).sort();
|
|
144
|
+
expect(platformNames).toEqual(['claude', 'codex', 'copilot-cli', 'vscode']);
|
|
145
|
+
|
|
146
|
+
// Each platform has valid structure
|
|
147
|
+
result.platforms.forEach(platform => {
|
|
148
|
+
expect(platform).toHaveProperty('name');
|
|
149
|
+
expect(platform).toHaveProperty('detected');
|
|
150
|
+
expect(typeof platform.detected).toBe('boolean');
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
});
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code Platform Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests for install/lib/platforms/claude-code.js
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const claudeCode = require('../../lib/platforms/claude-code');
|
|
8
|
+
const fileUtils = require('../../lib/utils/file-utils');
|
|
9
|
+
const os = require('os');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
|
|
12
|
+
// Mock dependencies
|
|
13
|
+
jest.mock('../../lib/utils/file-utils');
|
|
14
|
+
jest.mock('os');
|
|
15
|
+
|
|
16
|
+
describe('Claude Code Platform', () => {
|
|
17
|
+
const mockHomedir = '/home/testuser';
|
|
18
|
+
|
|
19
|
+
// Helper to mock platform
|
|
20
|
+
function mockPlatform(platformName) {
|
|
21
|
+
os.platform.mockReturnValue(platformName);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
beforeEach(() => {
|
|
25
|
+
os.homedir.mockReturnValue(mockHomedir);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
afterEach(() => {
|
|
29
|
+
jest.clearAllMocks();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
describe('detect() - macOS', () => {
|
|
33
|
+
it('should check correct path on macOS and return true if exists', async () => {
|
|
34
|
+
os.platform.mockReturnValue('darwin');
|
|
35
|
+
fileUtils.exists.mockResolvedValue(true);
|
|
36
|
+
|
|
37
|
+
const result = await claudeCode.detect();
|
|
38
|
+
|
|
39
|
+
expect(result).toBe(true);
|
|
40
|
+
expect(fileUtils.exists).toHaveBeenCalledWith(
|
|
41
|
+
path.join(mockHomedir, 'Library/Application Support/Claude/claude_desktop_config.json')
|
|
42
|
+
);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should return false if config does not exist on macOS', async () => {
|
|
46
|
+
os.platform.mockReturnValue('darwin');
|
|
47
|
+
fileUtils.exists.mockResolvedValue(false);
|
|
48
|
+
|
|
49
|
+
const result = await claudeCode.detect();
|
|
50
|
+
|
|
51
|
+
expect(result).toBe(false);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
describe('detect() - Windows', () => {
|
|
56
|
+
it('should check correct path on Windows and return true if exists', async () => {
|
|
57
|
+
os.platform.mockReturnValue('win32');
|
|
58
|
+
fileUtils.exists.mockResolvedValue(true);
|
|
59
|
+
|
|
60
|
+
const result = await claudeCode.detect();
|
|
61
|
+
|
|
62
|
+
expect(result).toBe(true);
|
|
63
|
+
expect(fileUtils.exists).toHaveBeenCalledWith(
|
|
64
|
+
path.join(mockHomedir, 'AppData/Roaming/Claude/claude_desktop_config.json')
|
|
65
|
+
);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('should return false if config does not exist on Windows', async () => {
|
|
69
|
+
os.platform.mockReturnValue('win32');
|
|
70
|
+
fileUtils.exists.mockResolvedValue(false);
|
|
71
|
+
|
|
72
|
+
const result = await claudeCode.detect();
|
|
73
|
+
|
|
74
|
+
expect(result).toBe(false);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
describe('detect() - Linux', () => {
|
|
79
|
+
it('should check correct path on Linux and return true if exists', async () => {
|
|
80
|
+
os.platform.mockReturnValue('linux');
|
|
81
|
+
fileUtils.exists.mockResolvedValue(true);
|
|
82
|
+
|
|
83
|
+
const result = await claudeCode.detect();
|
|
84
|
+
|
|
85
|
+
expect(result).toBe(true);
|
|
86
|
+
expect(fileUtils.exists).toHaveBeenCalledWith(
|
|
87
|
+
path.join(mockHomedir, '.config/Claude/claude_desktop_config.json')
|
|
88
|
+
);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('should return false if config does not exist on Linux', async () => {
|
|
92
|
+
os.platform.mockReturnValue('linux');
|
|
93
|
+
fileUtils.exists.mockResolvedValue(false);
|
|
94
|
+
|
|
95
|
+
const result = await claudeCode.detect();
|
|
96
|
+
|
|
97
|
+
expect(result).toBe(false);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
describe('detect() - Unknown OS', () => {
|
|
102
|
+
it('should return false for unsupported platform', async () => {
|
|
103
|
+
os.platform.mockReturnValue('freebsd');
|
|
104
|
+
|
|
105
|
+
const result = await claudeCode.detect();
|
|
106
|
+
|
|
107
|
+
expect(result).toBe(false);
|
|
108
|
+
expect(fileUtils.exists).not.toHaveBeenCalled();
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
describe('getPath()', () => {
|
|
113
|
+
it('should return correct path for macOS', () => {
|
|
114
|
+
os.platform.mockReturnValue('darwin');
|
|
115
|
+
|
|
116
|
+
const result = claudeCode.getPath();
|
|
117
|
+
|
|
118
|
+
expect(result).toBe(
|
|
119
|
+
path.join(mockHomedir, 'Library/Application Support/Claude/claude_desktop_config.json')
|
|
120
|
+
);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('should return correct path for Windows', () => {
|
|
124
|
+
os.platform.mockReturnValue('win32');
|
|
125
|
+
|
|
126
|
+
const result = claudeCode.getPath();
|
|
127
|
+
|
|
128
|
+
expect(result).toBe(
|
|
129
|
+
path.join(mockHomedir, 'AppData/Roaming/Claude/claude_desktop_config.json')
|
|
130
|
+
);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('should return correct path for Linux', () => {
|
|
134
|
+
os.platform.mockReturnValue('linux');
|
|
135
|
+
|
|
136
|
+
const result = claudeCode.getPath();
|
|
137
|
+
|
|
138
|
+
expect(result).toBe(
|
|
139
|
+
path.join(mockHomedir, '.config/Claude/claude_desktop_config.json')
|
|
140
|
+
);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('should return "unknown" for unsupported platform', () => {
|
|
144
|
+
os.platform.mockReturnValue('freebsd');
|
|
145
|
+
|
|
146
|
+
const result = claudeCode.getPath();
|
|
147
|
+
|
|
148
|
+
expect(result).toBe('unknown');
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
describe('name property', () => {
|
|
153
|
+
it('should have correct platform name', () => {
|
|
154
|
+
expect(claudeCode.name).toBe('Claude Code');
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
describe('install()', () => {
|
|
159
|
+
it('should return success for supported platforms', async () => {
|
|
160
|
+
mockPlatform('darwin');
|
|
161
|
+
|
|
162
|
+
const result = await claudeCode.install('/project', ['agent1', 'agent2'], {});
|
|
163
|
+
|
|
164
|
+
expect(result).toEqual({ success: true, installed: 2 });
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('should throw error for unsupported platform', async () => {
|
|
168
|
+
mockPlatform('freebsd');
|
|
169
|
+
|
|
170
|
+
await expect(
|
|
171
|
+
claudeCode.install('/project', ['agent1'], {})
|
|
172
|
+
).rejects.toThrow('Unsupported platform: freebsd');
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
});
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex Platform Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests for install/lib/platforms/codex.js
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const codex = require('../../lib/platforms/codex');
|
|
8
|
+
const fileUtils = require('../../lib/utils/file-utils');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
|
|
11
|
+
// Mock fileUtils
|
|
12
|
+
jest.mock('../../lib/utils/file-utils');
|
|
13
|
+
|
|
14
|
+
describe('Codex Platform', () => {
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
jest.clearAllMocks();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
describe('detect() - Directory exists', () => {
|
|
20
|
+
it('should return true when .codex/prompts/ directory exists', async () => {
|
|
21
|
+
fileUtils.exists.mockResolvedValue(true);
|
|
22
|
+
|
|
23
|
+
const result = await codex.detect();
|
|
24
|
+
|
|
25
|
+
expect(result).toBe(true);
|
|
26
|
+
expect(fileUtils.exists).toHaveBeenCalledWith('.codex/prompts');
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
describe('detect() - Directory missing', () => {
|
|
31
|
+
it('should return false when .codex/prompts/ directory does not exist', async () => {
|
|
32
|
+
fileUtils.exists.mockResolvedValue(false);
|
|
33
|
+
|
|
34
|
+
const result = await codex.detect();
|
|
35
|
+
|
|
36
|
+
expect(result).toBe(false);
|
|
37
|
+
expect(fileUtils.exists).toHaveBeenCalledWith('.codex/prompts');
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
describe('getPath()', () => {
|
|
42
|
+
it('should return .codex/prompts directory path', () => {
|
|
43
|
+
expect(codex.getPath()).toBe('.codex/prompts');
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe('name property', () => {
|
|
48
|
+
it('should have correct platform name', () => {
|
|
49
|
+
expect(codex.name).toBe('Codex');
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
describe('install()', () => {
|
|
54
|
+
const mockFileUtils = require('../../lib/utils/file-utils');
|
|
55
|
+
|
|
56
|
+
beforeEach(() => {
|
|
57
|
+
jest.clearAllMocks();
|
|
58
|
+
mockFileUtils.ensureDir.mockResolvedValue();
|
|
59
|
+
mockFileUtils.writeFile.mockResolvedValue();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('should create .codex/prompts directory and install agents', async () => {
|
|
63
|
+
const result = await codex.install('/project', ['agent1', 'agent2'], {});
|
|
64
|
+
|
|
65
|
+
expect(mockFileUtils.ensureDir).toHaveBeenCalledWith(
|
|
66
|
+
path.join('/project', '.codex', 'prompts')
|
|
67
|
+
);
|
|
68
|
+
expect(mockFileUtils.writeFile).toHaveBeenCalledTimes(2);
|
|
69
|
+
expect(result).toEqual({ success: true, installed: 2 });
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('should handle empty agent list', async () => {
|
|
73
|
+
const result = await codex.install('/project', [], {});
|
|
74
|
+
|
|
75
|
+
expect(mockFileUtils.ensureDir).toHaveBeenCalled();
|
|
76
|
+
expect(mockFileUtils.writeFile).not.toHaveBeenCalled();
|
|
77
|
+
expect(result).toEqual({ success: true, installed: 0 });
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
});
|