create-byan-agent 1.1.2 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/CHANGELOG.md +250 -177
  2. package/LICENSE +21 -21
  3. package/README.md +1245 -421
  4. package/bin/create-byan-agent-backup.js +220 -220
  5. package/bin/create-byan-agent-fixed.js +301 -301
  6. package/bin/create-byan-agent.js +322 -301
  7. package/lib/errors.js +61 -0
  8. package/lib/exit-codes.js +54 -0
  9. package/lib/platforms/claude-code.js +113 -0
  10. package/lib/platforms/codex.js +92 -0
  11. package/lib/platforms/copilot-cli.js +123 -0
  12. package/lib/platforms/index.js +14 -0
  13. package/lib/platforms/vscode.js +51 -0
  14. package/lib/utils/config-loader.js +79 -0
  15. package/lib/utils/file-utils.js +104 -0
  16. package/lib/utils/git-detector.js +35 -0
  17. package/lib/utils/logger.js +64 -0
  18. package/lib/utils/node-detector.js +58 -0
  19. package/lib/utils/os-detector.js +74 -0
  20. package/lib/utils/yaml-utils.js +87 -0
  21. package/lib/yanstaller/backuper.js +308 -0
  22. package/lib/yanstaller/detector.js +141 -0
  23. package/lib/yanstaller/index.js +93 -0
  24. package/lib/yanstaller/installer.js +225 -0
  25. package/lib/yanstaller/interviewer.js +250 -0
  26. package/lib/yanstaller/recommender.js +298 -0
  27. package/lib/yanstaller/troubleshooter.js +498 -0
  28. package/lib/yanstaller/validator.js +578 -0
  29. package/lib/yanstaller/wizard.js +211 -0
  30. package/package.json +61 -55
  31. package/templates/.github/agents/bmad-agent-bmad-master.md +15 -15
  32. package/templates/.github/agents/bmad-agent-bmb-agent-builder.md +15 -15
  33. package/templates/.github/agents/bmad-agent-bmb-module-builder.md +15 -15
  34. package/templates/.github/agents/bmad-agent-bmb-workflow-builder.md +15 -15
  35. package/templates/.github/agents/bmad-agent-bmm-analyst.md +15 -15
  36. package/templates/.github/agents/bmad-agent-bmm-architect.md +15 -15
  37. package/templates/.github/agents/bmad-agent-bmm-dev.md +15 -15
  38. package/templates/.github/agents/bmad-agent-bmm-pm.md +15 -15
  39. package/templates/.github/agents/bmad-agent-bmm-quick-flow-solo-dev.md +15 -15
  40. package/templates/.github/agents/bmad-agent-bmm-quinn.md +15 -15
  41. package/templates/.github/agents/bmad-agent-bmm-sm.md +15 -15
  42. package/templates/.github/agents/bmad-agent-bmm-tech-writer.md +15 -15
  43. package/templates/.github/agents/bmad-agent-bmm-ux-designer.md +15 -15
  44. package/templates/.github/agents/bmad-agent-byan-test.md +32 -0
  45. package/templates/.github/agents/bmad-agent-byan.md +224 -224
  46. package/templates/.github/agents/bmad-agent-carmack.md +18 -0
  47. package/templates/.github/agents/bmad-agent-cis-brainstorming-coach.md +15 -15
  48. package/templates/.github/agents/bmad-agent-cis-creative-problem-solver.md +15 -15
  49. package/templates/.github/agents/bmad-agent-cis-design-thinking-coach.md +15 -15
  50. package/templates/.github/agents/bmad-agent-cis-innovation-strategist.md +15 -15
  51. package/templates/.github/agents/bmad-agent-cis-presentation-master.md +15 -15
  52. package/templates/.github/agents/bmad-agent-cis-storyteller.md +15 -15
  53. package/templates/.github/agents/bmad-agent-marc.md +48 -48
  54. package/templates/.github/agents/bmad-agent-patnote.md +48 -0
  55. package/templates/.github/agents/bmad-agent-rachid.md +47 -47
  56. package/templates/.github/agents/bmad-agent-tea-tea.md +15 -15
  57. package/templates/.github/agents/bmad-agent-test-dynamic.md +21 -0
  58. package/templates/.github/agents/expert-merise-agile.md +1 -0
  59. package/templates/.github/agents/franck.md +379 -0
  60. package/templates/_bmad/bmb/agents/agent-builder.md +59 -59
  61. package/templates/_bmad/bmb/agents/byan-test.md +116 -116
  62. package/templates/_bmad/bmb/agents/byan.md +215 -215
  63. package/templates/_bmad/bmb/agents/marc.md +303 -303
  64. package/templates/_bmad/bmb/agents/module-builder.md +60 -60
  65. package/templates/_bmad/bmb/agents/patnote.md +495 -495
  66. package/templates/_bmad/bmb/agents/rachid.md +184 -184
  67. package/templates/_bmad/bmb/agents/workflow-builder.md +61 -61
  68. package/templates/_bmad/bmb/workflows/byan/data/mantras.yaml +272 -272
  69. package/templates/_bmad/bmb/workflows/byan/data/templates.yaml +59 -59
  70. package/templates/_bmad/bmb/workflows/byan/delete-agent-workflow.md +657 -657
  71. package/templates/_bmad/bmb/workflows/byan/edit-agent-workflow.md +688 -688
  72. package/templates/_bmad/bmb/workflows/byan/interview-workflow.md +753 -753
  73. package/templates/_bmad/bmb/workflows/byan/quick-create-workflow.md +450 -450
  74. package/templates/_bmad/bmb/workflows/byan/templates/base-agent-template.md +79 -79
  75. package/templates/_bmad/bmb/workflows/byan/validate-agent-workflow.md +676 -676
  76. package/templates/_bmad/core/agents/carmack.md +238 -238
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Git Detector Utility
3
+ *
4
+ * Detects if Git is installed.
5
+ *
6
+ * @module utils/git-detector
7
+ */
8
+
9
+ const { execSync } = require('child_process');
10
+
11
+ /**
12
+ * Detect if Git is installed
13
+ *
14
+ * @returns {Promise<{installed: boolean, version: string | null}>}
15
+ */
16
+ async function detect() {
17
+ try {
18
+ const version = execSync('git --version', { encoding: 'utf8' }).trim();
19
+ const versionMatch = version.match(/git version ([\d.]+)/);
20
+
21
+ return {
22
+ installed: true,
23
+ version: versionMatch ? versionMatch[1] : null
24
+ };
25
+ } catch {
26
+ return {
27
+ installed: false,
28
+ version: null
29
+ };
30
+ }
31
+ }
32
+
33
+ module.exports = {
34
+ detect
35
+ };
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Logger Utility
3
+ *
4
+ * Wrapper around chalk and console for colored logging.
5
+ *
6
+ * @module utils/logger
7
+ */
8
+
9
+ const chalk = require('chalk');
10
+
11
+ /**
12
+ * Log info message
13
+ *
14
+ * @param {string} message - Message to log
15
+ */
16
+ function info(message) {
17
+ console.log(chalk.blue('ℹ'), message);
18
+ }
19
+
20
+ /**
21
+ * Log success message
22
+ *
23
+ * @param {string} message - Message to log
24
+ */
25
+ function success(message) {
26
+ console.log(chalk.green('✓'), message);
27
+ }
28
+
29
+ /**
30
+ * Log warning message
31
+ *
32
+ * @param {string} message - Message to log
33
+ */
34
+ function warn(message) {
35
+ console.log(chalk.yellow('⚠'), message);
36
+ }
37
+
38
+ /**
39
+ * Log error message
40
+ *
41
+ * @param {string} message - Message to log
42
+ */
43
+ function error(message) {
44
+ console.error(chalk.red('✖'), message);
45
+ }
46
+
47
+ /**
48
+ * Log debug message (only if DEBUG env var set)
49
+ *
50
+ * @param {string} message - Message to log
51
+ */
52
+ function debug(message) {
53
+ if (process.env.DEBUG) {
54
+ console.log(chalk.gray('[DEBUG]'), message);
55
+ }
56
+ }
57
+
58
+ module.exports = {
59
+ info,
60
+ success,
61
+ warn,
62
+ error,
63
+ debug
64
+ };
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Node.js Detector Utility
3
+ *
4
+ * Detects Node.js version.
5
+ *
6
+ * @module utils/node-detector
7
+ */
8
+
9
+ /**
10
+ * Detect Node.js version
11
+ *
12
+ * @returns {string} - Version string (e.g., '18.19.0')
13
+ */
14
+ function detect() {
15
+ return process.version.slice(1); // Remove 'v' prefix
16
+ }
17
+
18
+ /**
19
+ * Compare two semver versions
20
+ *
21
+ * Strips version suffixes (-beta, -rc1, etc.) before comparison.
22
+ *
23
+ * @param {string} version1 - First version
24
+ * @param {string} version2 - Second version
25
+ * @returns {number} - -1 if v1 < v2, 0 if equal, 1 if v1 > v2
26
+ */
27
+ function compareVersions(version1, version2) {
28
+ // Strip suffixes: '18.0.0-beta' → '18.0.0'
29
+ const cleanV1 = version1.replace(/-.*$/, '');
30
+ const cleanV2 = version2.replace(/-.*$/, '');
31
+
32
+ const v1Parts = cleanV1.split('.').map(Number);
33
+ const v2Parts = cleanV2.split('.').map(Number);
34
+
35
+ for (let i = 0; i < 3; i++) {
36
+ if (v1Parts[i] > v2Parts[i]) return 1;
37
+ if (v1Parts[i] < v2Parts[i]) return -1;
38
+ }
39
+
40
+ return 0;
41
+ }
42
+
43
+ /**
44
+ * Check if Node version meets minimum requirement
45
+ *
46
+ * @param {string} currentVersion - Current Node version
47
+ * @param {string} requiredVersion - Required Node version
48
+ * @returns {boolean}
49
+ */
50
+ function meetsRequirement(currentVersion, requiredVersion) {
51
+ return compareVersions(currentVersion, requiredVersion) >= 0;
52
+ }
53
+
54
+ module.exports = {
55
+ detect,
56
+ compareVersions,
57
+ meetsRequirement
58
+ };
@@ -0,0 +1,74 @@
1
+ /**
2
+ * OS Detector Utility
3
+ *
4
+ * Detects operating system and version.
5
+ *
6
+ * @module utils/os-detector
7
+ */
8
+
9
+ const os = require('os');
10
+
11
+ /**
12
+ * Detect operating system
13
+ *
14
+ * @returns {{name: string, version: string, platform: string}}
15
+ */
16
+ function detect() {
17
+ const platform = os.platform();
18
+ const release = os.release();
19
+
20
+ let name;
21
+ switch (platform) {
22
+ case 'win32':
23
+ name = 'windows';
24
+ break;
25
+ case 'darwin':
26
+ name = 'macos';
27
+ break;
28
+ case 'linux':
29
+ name = 'linux';
30
+ break;
31
+ default:
32
+ name = 'unknown';
33
+ }
34
+
35
+ return {
36
+ name,
37
+ version: release,
38
+ platform
39
+ };
40
+ }
41
+
42
+ /**
43
+ * Check if running on Windows
44
+ *
45
+ * @returns {boolean}
46
+ */
47
+ function isWindows() {
48
+ return os.platform() === 'win32';
49
+ }
50
+
51
+ /**
52
+ * Check if running on macOS
53
+ *
54
+ * @returns {boolean}
55
+ */
56
+ function isMacOS() {
57
+ return os.platform() === 'darwin';
58
+ }
59
+
60
+ /**
61
+ * Check if running on Linux
62
+ *
63
+ * @returns {boolean}
64
+ */
65
+ function isLinux() {
66
+ return os.platform() === 'linux';
67
+ }
68
+
69
+ module.exports = {
70
+ detect,
71
+ isWindows,
72
+ isMacOS,
73
+ isLinux
74
+ };
@@ -0,0 +1,87 @@
1
+ /**
2
+ * YAML Utilities
3
+ *
4
+ * Wrapper around js-yaml for YAML parsing/dumping.
5
+ *
6
+ * @module utils/yaml-utils
7
+ */
8
+
9
+ const yaml = require('js-yaml');
10
+ const fileUtils = require('./file-utils');
11
+
12
+ /**
13
+ * Parse YAML string
14
+ *
15
+ * @param {string} yamlString - YAML string
16
+ * @returns {Object}
17
+ */
18
+ function parse(yamlString) {
19
+ return yaml.load(yamlString);
20
+ }
21
+
22
+ /**
23
+ * Dump object to YAML string
24
+ *
25
+ * @param {Object} obj - Object to dump
26
+ * @returns {string}
27
+ */
28
+ function dump(obj) {
29
+ return yaml.dump(obj, {
30
+ indent: 2,
31
+ lineWidth: -1
32
+ });
33
+ }
34
+
35
+ /**
36
+ * Read YAML file
37
+ *
38
+ * @param {string} filePath - YAML file path
39
+ * @returns {Promise<Object>}
40
+ */
41
+ async function readYAML(filePath) {
42
+ const content = await fileUtils.readFile(filePath);
43
+ return parse(content);
44
+ }
45
+
46
+ /**
47
+ * Write YAML file
48
+ *
49
+ * @param {string} filePath - YAML file path
50
+ * @param {Object} data - Data to write
51
+ * @returns {Promise<void>}
52
+ */
53
+ async function writeYAML(filePath, data) {
54
+ const yamlString = dump(data);
55
+ await fileUtils.writeFile(filePath, yamlString);
56
+ }
57
+
58
+ /**
59
+ * Extract YAML frontmatter from markdown
60
+ *
61
+ * @param {string} markdownContent - Markdown content
62
+ * @returns {{frontmatter: Object | null, content: string}}
63
+ */
64
+ function extractFrontmatter(markdownContent) {
65
+ const frontmatterRegex = /^---\n([\s\S]+?)\n---\n([\s\S]*)$/;
66
+ const match = markdownContent.match(frontmatterRegex);
67
+
68
+ if (!match) {
69
+ return {
70
+ frontmatter: null,
71
+ content: markdownContent
72
+ };
73
+ }
74
+
75
+ return {
76
+ frontmatter: parse(match[1]),
77
+ content: match[2]
78
+ };
79
+ }
80
+
81
+ module.exports = {
82
+ parse,
83
+ dump,
84
+ readYAML,
85
+ writeYAML,
86
+ extractFrontmatter
87
+ };
@@ -0,0 +1,308 @@
1
+ /**
2
+ * BACKUPER Module
3
+ *
4
+ * Backs up and restores _bmad/ directory.
5
+ *
6
+ * Phase 6: 24h development
7
+ *
8
+ * @module yanstaller/backuper
9
+ */
10
+
11
+ const path = require('path');
12
+ const fs = require('fs-extra');
13
+ const fileUtils = require('../utils/file-utils');
14
+ const logger = require('../utils/logger');
15
+
16
+ /**
17
+ * @typedef {Object} BackupResult
18
+ * @property {boolean} success
19
+ * @property {string} backupPath - Path to backup directory
20
+ * @property {number} filesBackedUp
21
+ * @property {number} size - Backup size in bytes
22
+ * @property {number} duration - Backup duration in ms
23
+ */
24
+
25
+ /**
26
+ * @typedef {Object} BackupInfo
27
+ * @property {string} path - Backup directory path
28
+ * @property {number} timestamp - Creation timestamp
29
+ * @property {Date} created - Creation date
30
+ * @property {number} size - Size in bytes
31
+ * @property {number} files - Number of files
32
+ */
33
+
34
+ /**
35
+ * Backup _bmad/ directory
36
+ *
37
+ * @param {string} bmadPath - Path to _bmad/ directory
38
+ * @param {Object} options - Backup options
39
+ * @returns {Promise<BackupResult>}
40
+ */
41
+ async function backup(bmadPath, options = {}) {
42
+ const startTime = Date.now();
43
+ const timestamp = Date.now();
44
+ const backupPath = `${bmadPath}.backup-${timestamp}`;
45
+
46
+ try {
47
+ logger.info(`Creating backup: ${backupPath}`);
48
+
49
+ // Check if source exists
50
+ if (!await fileUtils.exists(bmadPath)) {
51
+ throw new BackupError(`Source path does not exist: ${bmadPath}`);
52
+ }
53
+
54
+ // Copy entire _bmad/ to backup path
55
+ await fileUtils.copy(bmadPath, backupPath);
56
+
57
+ // Count files and calculate size
58
+ const { files, size } = await getDirectoryStats(backupPath);
59
+
60
+ // Create metadata file
61
+ const metadata = {
62
+ timestamp,
63
+ created: new Date(timestamp).toISOString(),
64
+ source: bmadPath,
65
+ files,
66
+ size,
67
+ version: '1.2.0'
68
+ };
69
+
70
+ await fileUtils.writeFile(
71
+ path.join(backupPath, '.backup-metadata.json'),
72
+ JSON.stringify(metadata, null, 2)
73
+ );
74
+
75
+ const duration = Date.now() - startTime;
76
+
77
+ logger.info(`✓ Backup created: ${files} files, ${formatSize(size)}, ${duration}ms`);
78
+
79
+ return {
80
+ success: true,
81
+ backupPath,
82
+ filesBackedUp: files,
83
+ size,
84
+ duration
85
+ };
86
+ } catch (error) {
87
+ throw new BackupError(`Failed to backup ${bmadPath}`, { cause: error });
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Restore from backup
93
+ *
94
+ * @param {string} backupPath - Path to backup directory
95
+ * @param {string} targetPath - Target restoration path
96
+ * @param {Object} options - Restore options
97
+ * @returns {Promise<void>}
98
+ */
99
+ async function restore(backupPath, targetPath, options = {}) {
100
+ try {
101
+ logger.info(`Restoring from backup: ${backupPath}`);
102
+
103
+ // Verify backup exists
104
+ if (!await fileUtils.exists(backupPath)) {
105
+ throw new BackupError(`Backup not found: ${backupPath}`);
106
+ }
107
+
108
+ // Verify backup metadata
109
+ const metadataPath = path.join(backupPath, '.backup-metadata.json');
110
+ if (await fileUtils.exists(metadataPath)) {
111
+ const metadata = await fileUtils.readJSON(metadataPath);
112
+ logger.info(`Backup created: ${metadata.created}, ${metadata.files} files`);
113
+ }
114
+
115
+ // Create backup of current state before restoring (if exists)
116
+ if (await fileUtils.exists(targetPath) && !options.skipCurrentBackup) {
117
+ logger.info('Creating backup of current state before restore...');
118
+ await backup(targetPath);
119
+ }
120
+
121
+ // Remove current installation
122
+ if (await fileUtils.exists(targetPath)) {
123
+ await fileUtils.remove(targetPath);
124
+ }
125
+
126
+ // Copy backup to target
127
+ await fileUtils.copy(backupPath, targetPath);
128
+
129
+ // Remove metadata file from restored directory
130
+ const restoredMetadata = path.join(targetPath, '.backup-metadata.json');
131
+ if (await fileUtils.exists(restoredMetadata)) {
132
+ await fileUtils.remove(restoredMetadata);
133
+ }
134
+
135
+ logger.info('✓ Restore completed successfully');
136
+ } catch (error) {
137
+ throw new BackupError(`Failed to restore from ${backupPath}`, { cause: error });
138
+ }
139
+ }
140
+
141
+ /**
142
+ * List available backups
143
+ *
144
+ * @param {string} projectRoot - Project root directory
145
+ * @returns {Promise<BackupInfo[]>} - Array of backup info objects
146
+ */
147
+ async function listBackups(projectRoot) {
148
+ try {
149
+ const backups = [];
150
+ const bmadPath = path.join(projectRoot, '_bmad');
151
+ const parentDir = path.dirname(bmadPath);
152
+
153
+ // Find all _bmad.backup-* directories
154
+ const items = await fileUtils.readDir(parentDir);
155
+
156
+ for (const item of items) {
157
+ if (item.startsWith('_bmad.backup-')) {
158
+ const backupPath = path.join(parentDir, item);
159
+ const timestamp = parseInt(item.replace('_bmad.backup-', ''));
160
+
161
+ // Read metadata if available
162
+ const metadataPath = path.join(backupPath, '.backup-metadata.json');
163
+ let metadata = { files: 0, size: 0 };
164
+
165
+ if (await fileUtils.exists(metadataPath)) {
166
+ metadata = await fileUtils.readJSON(metadataPath);
167
+ } else {
168
+ // Calculate if no metadata
169
+ const stats = await getDirectoryStats(backupPath);
170
+ metadata.files = stats.files;
171
+ metadata.size = stats.size;
172
+ }
173
+
174
+ backups.push({
175
+ path: backupPath,
176
+ timestamp,
177
+ created: new Date(timestamp),
178
+ size: metadata.size,
179
+ files: metadata.files
180
+ });
181
+ }
182
+ }
183
+
184
+ // Sort by timestamp (newest first)
185
+ backups.sort((a, b) => b.timestamp - a.timestamp);
186
+
187
+ return backups;
188
+ } catch (error) {
189
+ if (error.code === 'ENOENT') {
190
+ return []; // No backups found
191
+ }
192
+ throw error;
193
+ }
194
+ }
195
+
196
+ /**
197
+ * Clean old backups (keep last N)
198
+ *
199
+ * @param {string} projectRoot - Project root directory
200
+ * @param {number} keep - Number of backups to keep
201
+ * @returns {Promise<number>} - Number of backups deleted
202
+ */
203
+ async function cleanOldBackups(projectRoot, keep = 3) {
204
+ try {
205
+ const backups = await listBackups(projectRoot);
206
+
207
+ if (backups.length <= keep) {
208
+ return 0; // Nothing to delete
209
+ }
210
+
211
+ // Delete oldest backups
212
+ const toDelete = backups.slice(keep);
213
+ let deleted = 0;
214
+
215
+ for (const backup of toDelete) {
216
+ try {
217
+ await fileUtils.remove(backup.path);
218
+ logger.info(`✓ Deleted old backup: ${path.basename(backup.path)}`);
219
+ deleted++;
220
+ } catch (error) {
221
+ logger.warn(`Failed to delete backup ${backup.path}: ${error.message}`);
222
+ }
223
+ }
224
+
225
+ return deleted;
226
+ } catch (error) {
227
+ throw new BackupError(`Failed to clean old backups: ${error.message}`);
228
+ }
229
+ }
230
+
231
+ /**
232
+ * Get backup size
233
+ *
234
+ * @param {string} backupPath - Path to backup directory
235
+ * @returns {Promise<number>} - Size in bytes
236
+ */
237
+ async function getBackupSize(backupPath) {
238
+ const stats = await getDirectoryStats(backupPath);
239
+ return stats.size;
240
+ }
241
+
242
+ /**
243
+ * Get directory statistics (files count and total size)
244
+ *
245
+ * @param {string} dirPath - Directory path
246
+ * @returns {Promise<{files: number, size: number}>}
247
+ */
248
+ async function getDirectoryStats(dirPath) {
249
+ let files = 0;
250
+ let size = 0;
251
+
252
+ async function traverse(currentPath) {
253
+ const items = await fileUtils.readDir(currentPath);
254
+
255
+ for (const item of items) {
256
+ const itemPath = path.join(currentPath, item);
257
+ const stats = await fs.stat(itemPath);
258
+
259
+ if (stats.isDirectory()) {
260
+ await traverse(itemPath);
261
+ } else {
262
+ files++;
263
+ size += stats.size;
264
+ }
265
+ }
266
+ }
267
+
268
+ await traverse(dirPath);
269
+
270
+ return { files, size };
271
+ }
272
+
273
+ /**
274
+ * Format size in human-readable format
275
+ *
276
+ * @param {number} bytes - Size in bytes
277
+ * @returns {string}
278
+ */
279
+ function formatSize(bytes) {
280
+ const units = ['B', 'KB', 'MB', 'GB'];
281
+ let size = bytes;
282
+ let unitIndex = 0;
283
+
284
+ while (size >= 1024 && unitIndex < units.length - 1) {
285
+ size /= 1024;
286
+ unitIndex++;
287
+ }
288
+
289
+ return `${size.toFixed(2)} ${units[unitIndex]}`;
290
+ }
291
+
292
+ class BackupError extends Error {
293
+ constructor(message, options) {
294
+ super(message, options);
295
+ this.name = 'BackupError';
296
+ }
297
+ }
298
+
299
+ module.exports = {
300
+ backup,
301
+ restore,
302
+ listBackups,
303
+ cleanOldBackups,
304
+ getBackupSize,
305
+ getDirectoryStats,
306
+ formatSize,
307
+ BackupError
308
+ };