chrome-cdp-cli 1.9.0 → 2.0.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.
package/README.md CHANGED
@@ -2,6 +2,19 @@
2
2
 
3
3
  A command-line tool for browser automation via Chrome DevTools Protocol (CDP). Designed for developers who need reliable, scriptable browser control with both dedicated commands and flexible JavaScript execution.
4
4
 
5
+ ## 🚀 Enhanced CLI Features
6
+
7
+ **New in v2.0:** The CLI now includes a comprehensive refactored parameter system with:
8
+
9
+ - 🔧 **Advanced Configuration Management**: YAML/JSON config files with profiles and precedence handling
10
+ - ⚙️ **Enhanced Argument Parser**: Consistent option handling with validation and schema support
11
+ - 📚 **Comprehensive Help System**: Contextual help, advanced topics, and detailed examples
12
+ - 🎯 **Standardized Output**: JSON/text formats with quiet/verbose modes and custom templates
13
+ - 🔗 **Command Aliasing**: Built-in and custom aliases for efficient workflows
14
+ - 🧩 **Plugin Architecture**: Extensible system for custom commands and functionality
15
+ - 🖥️ **Interactive Mode**: Command prompt with tab completion and session management
16
+ - ⚡ **Performance Optimizations**: Configuration caching and connection reuse
17
+
5
18
  ## 🤔 Why This Tool Exists
6
19
 
7
20
  **The honest story:** I started using `chrome-devtools-mcp` like everyone else. It worked great... until it didn't. One day it just stopped working - Cursor showed 26 tools available, everything looked normal, but every single tool call threw errors. Classic black box problem: you can't debug what you can't see inside.
@@ -882,27 +895,103 @@ For detailed documentation, see the [Form Filling Guide](docs/FORM_FILLING.md).
882
895
 
883
896
  ## Configuration
884
897
 
885
- ### Configuration File
898
+ The CLI supports comprehensive configuration management with multiple sources and precedence handling.
899
+
900
+ ### Quick Configuration
901
+
902
+ Create a `.chrome-cdp-cli.yaml` file in your project root or home directory:
903
+
904
+ ```yaml
905
+ # Basic configuration
906
+ host: localhost
907
+ port: 9222
908
+ timeout: 30000
909
+ outputFormat: text
910
+ verbose: false
911
+
912
+ # Profiles for different environments
913
+ profiles:
914
+ development:
915
+ debug: true
916
+ verbose: true
917
+ production:
918
+ quiet: true
919
+ outputFormat: json
920
+
921
+ # Command aliases
922
+ aliases:
923
+ ss: screenshot
924
+ js: eval
925
+ health: eval "document.readyState === 'complete'"
926
+
927
+ # Command-specific defaults
928
+ commands:
929
+ screenshot:
930
+ defaults:
931
+ format: png
932
+ quality: 90
933
+ ```
886
934
 
887
- Create a `.chrome-cdp-cli.json` file in your project root or home directory:
935
+ ### Environment Variables
888
936
 
889
- ```json
890
- {
891
- "host": "localhost",
892
- "port": 9222,
893
- "timeout": 30000,
894
- "outputFormat": "text",
895
- "verbose": false,
896
- "quiet": false
897
- }
937
+ ```bash
938
+ export CHROME_CDP_CLI_HOST=localhost
939
+ export CHROME_CDP_CLI_PORT=9222
940
+ export CHROME_CDP_CLI_TIMEOUT=30000
941
+ export CHROME_CDP_CLI_VERBOSE=true
942
+ export CHROME_CDP_CLI_PROFILE=development
898
943
  ```
899
944
 
900
- ### Environment Variables
945
+ ### Configuration Precedence
946
+
947
+ Configuration values are resolved in order (highest to lowest priority):
948
+ 1. **Command-line arguments** (highest)
949
+ 2. **Environment variables**
950
+ 3. **Configuration files** (profile-specific, then default)
951
+ 4. **Default values** (lowest)
952
+
953
+ ### Advanced Configuration
954
+
955
+ For comprehensive configuration options, see the [Configuration Guide](docs/CONFIGURATION.md).
956
+
957
+ ## Enhanced Help System
958
+
959
+ The CLI includes a comprehensive help system with contextual assistance:
960
+
961
+ ```bash
962
+ # General help with categorized commands
963
+ chrome-cdp-cli help
964
+
965
+ # Command-specific help with examples
966
+ chrome-cdp-cli help eval
967
+ chrome-cdp-cli help screenshot
968
+
969
+ # Advanced help topics
970
+ chrome-cdp-cli help topic configuration
971
+ chrome-cdp-cli help topic selectors
972
+ chrome-cdp-cli help topic automation
973
+ chrome-cdp-cli help topic debugging
974
+
975
+ # Contextual help (shown automatically on errors)
976
+ chrome-cdp-cli click "#nonexistent" # Shows selector help
977
+ ```
978
+
979
+ ## Plugin System
980
+
981
+ Extend the CLI with custom commands and functionality:
982
+
983
+ ```bash
984
+ # Install plugins
985
+ npm install -g chrome-cdp-cli-plugin-form-automation
986
+
987
+ # Load plugins from directory
988
+ chrome-cdp-cli --plugin-dir ./plugins custom-command
989
+
990
+ # List available plugins
991
+ chrome-cdp-cli --show-plugins
992
+ ```
901
993
 
902
- - `CHROME_CLI_HOST`: Default Chrome host
903
- - `CHROME_CLI_PORT`: Default DevTools port
904
- - `CHROME_CLI_TIMEOUT`: Default command timeout
905
- - `CHROME_CLI_FORMAT`: Default output format
994
+ For plugin development, see the [Plugin Development Guide](docs/PLUGIN_DEVELOPMENT.md).
906
995
 
907
996
  ## Development
908
997
 
@@ -0,0 +1,506 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ArgumentParser = void 0;
4
+ const HelpSystem_1 = require("./HelpSystem");
5
+ class ArgumentParser {
6
+ constructor() {
7
+ this.commands = new Map();
8
+ this.aliases = new Map();
9
+ this.helpSystem = new HelpSystem_1.HelpSystem(undefined, this);
10
+ }
11
+ parseArguments(argv) {
12
+ try {
13
+ if (!Array.isArray(argv)) {
14
+ return this.createParseResult('help', {}, [], true);
15
+ }
16
+ const sliceStart = Math.max(0, Math.min(2, argv.length));
17
+ const args = argv.slice(sliceStart);
18
+ if (args.length === 0) {
19
+ return this.createParseResult('help', {}, [], true);
20
+ }
21
+ if (args.includes('--help')) {
22
+ return this.createParseResult('help', {}, [], true);
23
+ }
24
+ if (args.includes('--version') || args.includes('-V')) {
25
+ return this.createParseResult('version', {}, [], true);
26
+ }
27
+ let globalOptions;
28
+ let commandName;
29
+ let commandArgs;
30
+ try {
31
+ const parseResult = this.parseGlobalAndCommand(args);
32
+ globalOptions = parseResult.globalOptions;
33
+ commandName = parseResult.commandName;
34
+ commandArgs = parseResult.commandArgs;
35
+ }
36
+ catch (parseError) {
37
+ if (args.some(arg => arg === '--help' || arg === 'help')) {
38
+ return this.createParseResult('help', {}, [], true);
39
+ }
40
+ throw parseError;
41
+ }
42
+ const resolvedCommand = this.resolveCommandName(commandName);
43
+ if (resolvedCommand === 'help') {
44
+ return this.createParseResult(resolvedCommand, globalOptions, [], true, commandArgs);
45
+ }
46
+ const commandDef = this.commands.get(resolvedCommand);
47
+ if (!commandDef) {
48
+ return this.createParseResult(resolvedCommand, globalOptions, [`Unknown command: ${commandName}. Use 'help' to see available commands.`], false);
49
+ }
50
+ const parseResult = this.parseCommandArguments(commandDef, commandArgs);
51
+ const allOptions = { ...globalOptions, ...parseResult.options };
52
+ return this.createParseResult(resolvedCommand, allOptions, parseResult.errors, parseResult.errors.length === 0, parseResult.arguments);
53
+ }
54
+ catch (error) {
55
+ const errorMessage = error instanceof Error ? error.message : String(error);
56
+ if (process.env.DEBUG) {
57
+ console.error('Parse error details:', error);
58
+ if (error instanceof Error && error.stack) {
59
+ console.error('Stack trace:', error.stack);
60
+ }
61
+ }
62
+ if (errorMessage.includes('Invalid count value')) {
63
+ return this.createParseResult('help', {}, [`Parse error: Invalid argument format. Please check your command syntax.`], false);
64
+ }
65
+ return this.createParseResult('help', {}, [`Parse error: ${errorMessage}`], false);
66
+ }
67
+ }
68
+ registerCommand(command) {
69
+ const validation = this.validateCommandDefinition(command);
70
+ if (!validation.valid) {
71
+ throw new Error(`Invalid command definition: ${validation.errors.join(', ')}`);
72
+ }
73
+ this.commands.set(command.name, command);
74
+ for (const alias of command.aliases) {
75
+ if (this.aliases.has(alias)) {
76
+ throw new Error(`Alias '${alias}' is already registered for command '${this.aliases.get(alias)}'`);
77
+ }
78
+ this.aliases.set(alias, command.name);
79
+ }
80
+ }
81
+ generateHelp(command) {
82
+ if (command) {
83
+ if (command.startsWith('topic ')) {
84
+ const topicName = command.substring(6);
85
+ return this.helpSystem.generateTopicHelp(topicName);
86
+ }
87
+ return this.helpSystem.generateCommandHelp(command);
88
+ }
89
+ return this.helpSystem.generateGeneralHelp();
90
+ }
91
+ validateArguments(command, args) {
92
+ const commandDef = this.commands.get(command);
93
+ if (!commandDef) {
94
+ return {
95
+ valid: false,
96
+ errors: [`Unknown command: ${command}`],
97
+ warnings: []
98
+ };
99
+ }
100
+ const errors = [];
101
+ const warnings = [];
102
+ for (const option of commandDef.options) {
103
+ if (option.required && !(option.name in args.options)) {
104
+ errors.push(`Required option --${option.name} is missing`);
105
+ }
106
+ }
107
+ const requiredArgs = commandDef.arguments.filter(arg => arg.required);
108
+ if (args.arguments.length < requiredArgs.length) {
109
+ const providedCount = Math.max(0, Math.min(args.arguments.length, requiredArgs.length));
110
+ const missingCount = Math.max(0, requiredArgs.length - providedCount);
111
+ if (missingCount > 0) {
112
+ const startIndex = Math.max(0, providedCount);
113
+ const endIndex = Math.min(requiredArgs.length, startIndex + missingCount);
114
+ if (startIndex < endIndex && startIndex >= 0 && endIndex <= requiredArgs.length) {
115
+ const missingArgs = requiredArgs.slice(startIndex, endIndex).map(arg => arg.name);
116
+ if (missingArgs.length > 0) {
117
+ errors.push(`Missing required arguments: ${missingArgs.join(', ')}`);
118
+ }
119
+ }
120
+ }
121
+ }
122
+ for (const [optionName, value] of Object.entries(args.options)) {
123
+ const optionDef = commandDef.options.find(opt => opt.name === optionName);
124
+ if (optionDef) {
125
+ const optionValidation = this.validateOptionValue(optionDef, value);
126
+ if (!optionValidation.valid) {
127
+ errors.push(...optionValidation.errors);
128
+ }
129
+ warnings.push(...optionValidation.warnings);
130
+ }
131
+ }
132
+ for (let i = 0; i < args.arguments.length; i++) {
133
+ const argDef = commandDef.arguments[i];
134
+ if (argDef) {
135
+ const argValidation = this.validateArgumentValue(argDef, args.arguments[i]);
136
+ if (!argValidation.valid) {
137
+ errors.push(...argValidation.errors);
138
+ }
139
+ warnings.push(...argValidation.warnings);
140
+ }
141
+ }
142
+ return {
143
+ valid: errors.length === 0,
144
+ errors,
145
+ warnings
146
+ };
147
+ }
148
+ parseGlobalAndCommand(args) {
149
+ if (args.includes('--help')) {
150
+ return { globalOptions: {}, commandName: 'help', commandArgs: [] };
151
+ }
152
+ const globalOptions = {};
153
+ let commandName = 'help';
154
+ let commandArgs = [];
155
+ let i = 0;
156
+ const globalOptionDefs = [
157
+ { name: 'host', short: 'h', type: 'string', description: 'Chrome host address', default: 'localhost' },
158
+ { name: 'port', short: 'p', type: 'number', description: 'DevTools port', default: 9222 },
159
+ { name: 'format', short: 'f', type: 'string', description: 'Output format', choices: ['json', 'text'], default: 'text' },
160
+ { name: 'verbose', short: 'v', type: 'boolean', description: 'Enable verbose logging', default: false },
161
+ { name: 'quiet', short: 'q', type: 'boolean', description: 'Enable quiet mode', default: false },
162
+ { name: 'timeout', short: 't', type: 'number', description: 'Command timeout in milliseconds', default: 30000 },
163
+ { name: 'debug', short: 'd', type: 'boolean', description: 'Enable debug logging', default: false },
164
+ { name: 'config', short: 'c', type: 'string', description: 'Configuration file path' }
165
+ ];
166
+ while (i < args.length) {
167
+ const arg = args[i];
168
+ if (arg.startsWith('--')) {
169
+ const { option, value, consumed } = this.parseLongOption(arg, args, i, globalOptionDefs);
170
+ if (option) {
171
+ globalOptions[option.name] = value;
172
+ const validConsumed = Math.max(1, Math.min(consumed, 2));
173
+ i += validConsumed;
174
+ }
175
+ else {
176
+ commandName = arg.substring(2);
177
+ const nextIndex = i + 1;
178
+ if (nextIndex >= 0 && nextIndex <= args.length) {
179
+ commandArgs = args.slice(nextIndex);
180
+ }
181
+ else {
182
+ commandArgs = [];
183
+ }
184
+ break;
185
+ }
186
+ }
187
+ else if (arg.startsWith('-') && arg.length > 1) {
188
+ const { option, value, consumed } = this.parseShortOption(arg, args, i, globalOptionDefs);
189
+ if (option) {
190
+ globalOptions[option.name] = value;
191
+ const validConsumed = Math.max(1, Math.min(consumed || 1, 2));
192
+ i += validConsumed;
193
+ }
194
+ else {
195
+ commandName = arg.substring(1);
196
+ const nextIndex = i + 1;
197
+ if (nextIndex >= 0 && nextIndex <= args.length) {
198
+ commandArgs = args.slice(nextIndex);
199
+ }
200
+ else {
201
+ commandArgs = [];
202
+ }
203
+ break;
204
+ }
205
+ }
206
+ else {
207
+ commandName = arg;
208
+ const nextIndex = i + 1;
209
+ if (nextIndex >= 0 && nextIndex <= args.length) {
210
+ commandArgs = args.slice(nextIndex);
211
+ }
212
+ else {
213
+ commandArgs = [];
214
+ }
215
+ break;
216
+ }
217
+ }
218
+ return { globalOptions, commandName, commandArgs };
219
+ }
220
+ parseLongOption(arg, args, index, optionDefs) {
221
+ let optionName = arg.substring(2);
222
+ let value;
223
+ let consumed = 1;
224
+ const equalIndex = optionName.indexOf('=');
225
+ if (equalIndex !== -1) {
226
+ value = optionName.substring(equalIndex + 1);
227
+ optionName = optionName.substring(0, equalIndex);
228
+ }
229
+ let isNegated = false;
230
+ if (optionName.startsWith('no-')) {
231
+ isNegated = true;
232
+ optionName = optionName.substring(3);
233
+ }
234
+ const optionDef = optionDefs.find(opt => opt.name === optionName);
235
+ if (!optionDef) {
236
+ return { option: null, value: null, consumed: 0 };
237
+ }
238
+ if (optionDef.type === 'boolean') {
239
+ value = !isNegated;
240
+ }
241
+ else if (value === undefined) {
242
+ if (index + 1 < args.length && !args[index + 1].startsWith('-')) {
243
+ value = args[index + 1];
244
+ consumed = 2;
245
+ }
246
+ else {
247
+ throw new Error(`Option --${optionName} requires a value`);
248
+ }
249
+ }
250
+ value = this.convertOptionValue(optionDef, value);
251
+ return { option: optionDef, value, consumed };
252
+ }
253
+ parseShortOption(arg, args, index, optionDefs) {
254
+ const shortName = arg.substring(1);
255
+ if (shortName.length > 1) {
256
+ return { option: null, value: null, consumed: 0 };
257
+ }
258
+ const optionDef = optionDefs.find(opt => opt.short === shortName);
259
+ if (!optionDef) {
260
+ return { option: null, value: null, consumed: 0 };
261
+ }
262
+ let value;
263
+ let consumed = 1;
264
+ if (optionDef.type === 'boolean') {
265
+ value = true;
266
+ }
267
+ else {
268
+ if (index + 1 < args.length && !args[index + 1].startsWith('-')) {
269
+ value = args[index + 1];
270
+ consumed = 2;
271
+ }
272
+ else {
273
+ throw new Error(`Option -${shortName} requires a value`);
274
+ }
275
+ }
276
+ try {
277
+ value = this.convertOptionValue(optionDef, value);
278
+ }
279
+ catch (error) {
280
+ throw new Error(`Invalid value for option -${shortName}: ${error instanceof Error ? error.message : String(error)}`);
281
+ }
282
+ if (consumed < 1 || consumed > 2) {
283
+ consumed = 1;
284
+ }
285
+ return { option: optionDef, value, consumed };
286
+ }
287
+ parseCommandArguments(commandDef, args) {
288
+ const options = {};
289
+ const arguments_ = [];
290
+ const errors = [];
291
+ let i = 0;
292
+ while (i < args.length) {
293
+ const arg = args[i];
294
+ if (arg.startsWith('--')) {
295
+ try {
296
+ const { option, value, consumed } = this.parseLongOption(arg, args, i, commandDef.options);
297
+ if (option) {
298
+ options[option.name] = value;
299
+ if (consumed > 0) {
300
+ i += consumed;
301
+ }
302
+ else {
303
+ i++;
304
+ }
305
+ }
306
+ else {
307
+ errors.push(`Unknown option: ${arg}`);
308
+ i++;
309
+ }
310
+ }
311
+ catch (error) {
312
+ errors.push(error instanceof Error ? error.message : String(error));
313
+ i++;
314
+ }
315
+ }
316
+ else if (arg.startsWith('-') && arg.length > 1) {
317
+ try {
318
+ const { option, value, consumed } = this.parseShortOption(arg, args, i, commandDef.options);
319
+ if (option) {
320
+ options[option.name] = value;
321
+ if (consumed > 0) {
322
+ i += consumed;
323
+ }
324
+ else {
325
+ i++;
326
+ }
327
+ }
328
+ else {
329
+ errors.push(`Unknown option: ${arg}`);
330
+ i++;
331
+ }
332
+ }
333
+ catch (error) {
334
+ errors.push(error instanceof Error ? error.message : String(error));
335
+ i++;
336
+ }
337
+ }
338
+ else {
339
+ arguments_.push(arg);
340
+ i++;
341
+ }
342
+ }
343
+ return { options, arguments: arguments_, errors };
344
+ }
345
+ convertOptionValue(optionDef, value) {
346
+ if (value === undefined || value === null) {
347
+ return optionDef.default;
348
+ }
349
+ const stringValue = String(value);
350
+ switch (optionDef.type) {
351
+ case 'number':
352
+ const numValue = Number(stringValue);
353
+ if (isNaN(numValue)) {
354
+ throw new Error(`Option --${optionDef.name} must be a number, got: ${stringValue}`);
355
+ }
356
+ return numValue;
357
+ case 'boolean':
358
+ if (typeof value === 'boolean') {
359
+ return value;
360
+ }
361
+ const lowerValue = stringValue.toLowerCase();
362
+ if (lowerValue === 'true' || lowerValue === '1' || lowerValue === 'yes') {
363
+ return true;
364
+ }
365
+ if (lowerValue === 'false' || lowerValue === '0' || lowerValue === 'no') {
366
+ return false;
367
+ }
368
+ throw new Error(`Option --${optionDef.name} must be a boolean, got: ${stringValue}`);
369
+ case 'array':
370
+ if (Array.isArray(value)) {
371
+ return value;
372
+ }
373
+ return stringValue.split(',').map(s => s.trim());
374
+ case 'string':
375
+ default:
376
+ return stringValue;
377
+ }
378
+ }
379
+ validateOptionValue(optionDef, value) {
380
+ const errors = [];
381
+ const warnings = [];
382
+ if (optionDef.choices && optionDef.choices.length > 0) {
383
+ if (!optionDef.choices.includes(String(value))) {
384
+ errors.push(`Option --${optionDef.name} must be one of: ${optionDef.choices.join(', ')}`);
385
+ }
386
+ }
387
+ if (optionDef.validator) {
388
+ const validationResult = optionDef.validator(value);
389
+ if (!validationResult.valid) {
390
+ errors.push(...validationResult.errors);
391
+ warnings.push(...validationResult.warnings);
392
+ }
393
+ }
394
+ return {
395
+ valid: errors.length === 0,
396
+ errors,
397
+ warnings
398
+ };
399
+ }
400
+ validateArgumentValue(argDef, value) {
401
+ const errors = [];
402
+ const warnings = [];
403
+ switch (argDef.type) {
404
+ case 'number':
405
+ if (isNaN(Number(value))) {
406
+ errors.push(`Argument ${argDef.name} must be a number, got: ${value}`);
407
+ }
408
+ break;
409
+ case 'file':
410
+ if (typeof value !== 'string' || value.trim().length === 0) {
411
+ errors.push(`Argument ${argDef.name} must be a valid file path`);
412
+ }
413
+ break;
414
+ case 'url':
415
+ try {
416
+ new URL(String(value));
417
+ }
418
+ catch {
419
+ errors.push(`Argument ${argDef.name} must be a valid URL`);
420
+ }
421
+ break;
422
+ }
423
+ if (argDef.validator) {
424
+ const validationResult = argDef.validator(value);
425
+ if (!validationResult.valid) {
426
+ errors.push(...validationResult.errors);
427
+ warnings.push(...validationResult.warnings);
428
+ }
429
+ }
430
+ return {
431
+ valid: errors.length === 0,
432
+ errors,
433
+ warnings
434
+ };
435
+ }
436
+ resolveCommandName(commandName) {
437
+ return this.aliases.get(commandName) || commandName;
438
+ }
439
+ validateCommandDefinition(command) {
440
+ const errors = [];
441
+ if (!command.name || typeof command.name !== 'string') {
442
+ errors.push('Command name is required and must be a string');
443
+ }
444
+ if (!command.description || typeof command.description !== 'string') {
445
+ errors.push('Command description is required and must be a string');
446
+ }
447
+ if (!Array.isArray(command.aliases)) {
448
+ errors.push('Command aliases must be an array');
449
+ }
450
+ if (!Array.isArray(command.options)) {
451
+ errors.push('Command options must be an array');
452
+ }
453
+ if (!Array.isArray(command.arguments)) {
454
+ errors.push('Command arguments must be an array');
455
+ }
456
+ for (const option of command.options) {
457
+ if (!option.name || typeof option.name !== 'string') {
458
+ errors.push(`Option name is required and must be a string`);
459
+ }
460
+ if (!['string', 'number', 'boolean', 'array'].includes(option.type)) {
461
+ errors.push(`Option ${option.name} has invalid type: ${option.type}`);
462
+ }
463
+ }
464
+ for (const arg of command.arguments) {
465
+ if (!arg.name || typeof arg.name !== 'string') {
466
+ errors.push(`Argument name is required and must be a string`);
467
+ }
468
+ if (!['string', 'number', 'file', 'url'].includes(arg.type)) {
469
+ errors.push(`Argument ${arg.name} has invalid type: ${arg.type}`);
470
+ }
471
+ }
472
+ return {
473
+ valid: errors.length === 0,
474
+ errors,
475
+ warnings: []
476
+ };
477
+ }
478
+ createParseResult(command, options, errors, success, arguments_ = []) {
479
+ return {
480
+ success,
481
+ command,
482
+ options,
483
+ arguments: arguments_,
484
+ errors,
485
+ warnings: []
486
+ };
487
+ }
488
+ getCommands() {
489
+ return Array.from(this.commands.values());
490
+ }
491
+ getCommand(name) {
492
+ const resolvedName = this.resolveCommandName(name);
493
+ return this.commands.get(resolvedName);
494
+ }
495
+ hasCommand(name) {
496
+ const resolvedName = this.resolveCommandName(name);
497
+ return this.commands.has(resolvedName);
498
+ }
499
+ generateContextualHelp(error, commandName) {
500
+ return this.helpSystem.generateContextualHelp(error, commandName);
501
+ }
502
+ getHelpSystem() {
503
+ return this.helpSystem;
504
+ }
505
+ }
506
+ exports.ArgumentParser = ArgumentParser;