ciscollm-cli 1.3.3 → 1.3.5

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 (110) hide show
  1. package/README.md +19 -25
  2. package/dist/cli/commands/daemonCommand.d.ts +4 -0
  3. package/dist/cli/commands/daemonCommand.js +68 -0
  4. package/dist/cli/commands/daemonCommand.js.map +1 -0
  5. package/dist/cli/commands/monitorCommand.js +17 -1
  6. package/dist/cli/commands/monitorCommand.js.map +1 -1
  7. package/dist/cli/commands/runCommand.d.ts +1 -3
  8. package/dist/cli/commands/runCommand.js +177 -470
  9. package/dist/cli/commands/runCommand.js.map +1 -1
  10. package/dist/cli/ui/interactiveWizard.d.ts +1 -0
  11. package/dist/cli/ui/interactiveWizard.js +429 -0
  12. package/dist/cli/ui/interactiveWizard.js.map +1 -0
  13. package/dist/cli/ui/ui.js +0 -5
  14. package/dist/cli/ui/ui.js.map +1 -1
  15. package/dist/core/agent/AgentLoop.d.ts +15 -3
  16. package/dist/core/agent/AgentLoop.js +196 -67
  17. package/dist/core/agent/AgentLoop.js.map +1 -1
  18. package/dist/core/agent/AutoRemediationEngine.d.ts +14 -0
  19. package/dist/core/agent/AutoRemediationEngine.js +75 -0
  20. package/dist/core/agent/AutoRemediationEngine.js.map +1 -0
  21. package/dist/core/agent/DigitalTwin.d.ts +10 -0
  22. package/dist/core/agent/DigitalTwin.js +41 -0
  23. package/dist/core/agent/DigitalTwin.js.map +1 -0
  24. package/dist/core/agent/IntentTranslator.d.ts +8 -0
  25. package/dist/core/agent/IntentTranslator.js +63 -0
  26. package/dist/core/agent/IntentTranslator.js.map +1 -0
  27. package/dist/core/agent/MemoryManager.d.ts +14 -0
  28. package/dist/core/agent/MemoryManager.js +89 -0
  29. package/dist/core/agent/MemoryManager.js.map +1 -0
  30. package/dist/core/agent/MultiAgentCoordinator.js +0 -2
  31. package/dist/core/agent/MultiAgentCoordinator.js.map +1 -1
  32. package/dist/core/agent/NetworkPlanner.d.ts +9 -0
  33. package/dist/core/agent/NetworkPlanner.js +111 -0
  34. package/dist/core/agent/NetworkPlanner.js.map +1 -0
  35. package/dist/core/agent/PromptEngine.d.ts +1 -1
  36. package/dist/core/agent/PromptEngine.js +23 -13
  37. package/dist/core/agent/PromptEngine.js.map +1 -1
  38. package/dist/core/guardrails/NetworkAudit.js +1 -1
  39. package/dist/core/guardrails/NetworkAudit.js.map +1 -1
  40. package/dist/core/plugins/PluginManager.d.ts +17 -0
  41. package/dist/core/plugins/PluginManager.js +108 -0
  42. package/dist/core/plugins/PluginManager.js.map +1 -0
  43. package/dist/core/rollback/TransactionManager.js +0 -5
  44. package/dist/core/rollback/TransactionManager.js.map +1 -1
  45. package/dist/index.js +36 -61
  46. package/dist/index.js.map +1 -1
  47. package/dist/infrastructure/llm/LLMClient.d.ts +1 -0
  48. package/dist/infrastructure/llm/LLMClient.js +33 -9
  49. package/dist/infrastructure/llm/LLMClient.js.map +1 -1
  50. package/dist/infrastructure/protocols/SshSession.d.ts +1 -0
  51. package/dist/infrastructure/protocols/SshSession.js +5 -4
  52. package/dist/infrastructure/protocols/SshSession.js.map +1 -1
  53. package/dist/infrastructure/protocols/TelnetSession.d.ts +1 -0
  54. package/dist/infrastructure/protocols/TelnetSession.js +5 -1
  55. package/dist/infrastructure/protocols/TelnetSession.js.map +1 -1
  56. package/dist/server/devices/ASADevice.d.ts +17 -0
  57. package/dist/server/devices/ASADevice.js +160 -0
  58. package/dist/server/devices/ASADevice.js.map +1 -0
  59. package/dist/server/devices/BaseDevice.d.ts +11 -0
  60. package/dist/server/devices/BaseDevice.js +19 -0
  61. package/dist/server/devices/BaseDevice.js.map +1 -0
  62. package/dist/server/devices/IOSDevice.d.ts +100 -0
  63. package/dist/server/devices/IOSDevice.js +1561 -0
  64. package/dist/server/devices/IOSDevice.js.map +1 -0
  65. package/dist/server/devices/LinuxServerDevice.d.ts +8 -0
  66. package/dist/server/devices/LinuxServerDevice.js +71 -0
  67. package/dist/server/devices/LinuxServerDevice.js.map +1 -0
  68. package/dist/server/devices/PCDevice.d.ts +20 -0
  69. package/dist/server/devices/PCDevice.js +86 -0
  70. package/dist/server/devices/PCDevice.js.map +1 -0
  71. package/dist/server/devices/RouterDevice.d.ts +4 -0
  72. package/dist/server/devices/RouterDevice.js +11 -0
  73. package/dist/server/devices/RouterDevice.js.map +1 -0
  74. package/dist/server/devices/SwitchDevice.d.ts +4 -0
  75. package/dist/server/devices/SwitchDevice.js +11 -0
  76. package/dist/server/devices/SwitchDevice.js.map +1 -0
  77. package/dist/server/devices/WLCDevice.d.ts +15 -0
  78. package/dist/server/devices/WLCDevice.js +88 -0
  79. package/dist/server/devices/WLCDevice.js.map +1 -0
  80. package/dist/server/index.js +47 -22
  81. package/dist/server/index.js.map +1 -1
  82. package/dist/server/shell-simulator.js +1 -2
  83. package/dist/server/shell-simulator.js.map +1 -1
  84. package/dist/server/ssh.d.ts +2 -1
  85. package/dist/server/ssh.js +22 -9
  86. package/dist/server/ssh.js.map +1 -1
  87. package/dist/server/telnet.d.ts +3 -2
  88. package/dist/server/telnet.js +10 -42
  89. package/dist/server/telnet.js.map +1 -1
  90. package/dist/shared/bootBanner.d.ts +1 -0
  91. package/dist/shared/bootBanner.js +93 -0
  92. package/dist/shared/bootBanner.js.map +1 -0
  93. package/dist/shared/constants.js +1 -1
  94. package/dist/shared/constants.js.map +1 -1
  95. package/package.json +1 -1
  96. package/dist/cli/commands/dashboardCommand.d.ts +0 -1
  97. package/dist/cli/commands/dashboardCommand.js +0 -16
  98. package/dist/cli/commands/dashboardCommand.js.map +0 -1
  99. package/dist/cli/commands/shellCommand.d.ts +0 -1
  100. package/dist/cli/commands/shellCommand.js +0 -44
  101. package/dist/cli/commands/shellCommand.js.map +0 -1
  102. package/dist/infrastructure/protocols/CmlSession.d.ts +0 -26
  103. package/dist/infrastructure/protocols/CmlSession.js +0 -448
  104. package/dist/infrastructure/protocols/CmlSession.js.map +0 -1
  105. package/dist/infrastructure/protocols/NetconfSession.d.ts +0 -74
  106. package/dist/infrastructure/protocols/NetconfSession.js +0 -553
  107. package/dist/infrastructure/protocols/NetconfSession.js.map +0 -1
  108. package/dist/server/dashboard.d.ts +0 -3
  109. package/dist/server/dashboard.js +0 -1149
  110. package/dist/server/dashboard.js.map +0 -1
@@ -0,0 +1,1561 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.IOSDevice = void 0;
4
+ const BaseDevice_1 = require("./BaseDevice");
5
+ class IOSDevice extends BaseDevice_1.BaseDevice {
6
+ mode = 'USER_EXEC';
7
+ activeInterface = null;
8
+ interfaces = new Map([
9
+ ['GigabitEthernet0/0', {
10
+ name: 'GigabitEthernet0/0',
11
+ ip: '192.168.1.254',
12
+ subnet: '255.255.255.0',
13
+ adminShutdown: false,
14
+ lineProtocolUp: true,
15
+ description: 'Management Uplink'
16
+ }],
17
+ ['GigabitEthernet0/1', {
18
+ name: 'GigabitEthernet0/1',
19
+ ip: null,
20
+ subnet: null,
21
+ adminShutdown: true,
22
+ lineProtocolUp: false,
23
+ description: null
24
+ }],
25
+ ['GigabitEthernet0/2', {
26
+ name: 'GigabitEthernet0/2',
27
+ ip: null,
28
+ subnet: null,
29
+ adminShutdown: true,
30
+ lineProtocolUp: false,
31
+ description: null
32
+ }]
33
+ ]);
34
+ vlans = new Set([1]);
35
+ vlanNames = new Map([[1, 'default']]);
36
+ activeVlan = null;
37
+ routes = [
38
+ {
39
+ network: '192.168.1.0',
40
+ mask: '255.255.255.0',
41
+ nextHop: null,
42
+ outgoingInterface: 'GigabitEthernet0/0',
43
+ connected: true
44
+ }
45
+ ];
46
+ shellEnabled = false;
47
+ shellVariables = {};
48
+ shellFunctions = {};
49
+ ospfEnabled = false;
50
+ ospfProcessId = null;
51
+ ospfNetworks = [];
52
+ ripEnabled = false;
53
+ ripVersion = 2;
54
+ ripAutoSummary = false;
55
+ bgpEnabled = false;
56
+ bgpAsn = null;
57
+ eigrpEnabled = false;
58
+ eigrpAsn = null;
59
+ vtpMode = 'server';
60
+ vtpDomain = null;
61
+ vtpPassword = null;
62
+ hsrpGroups = new Map();
63
+ vrrpGroups = new Map();
64
+ ntpServers = [];
65
+ snmpCommunities = [];
66
+ natInsideInterfaces = new Set();
67
+ natOutsideInterfaces = new Set();
68
+ natRules = [];
69
+ acls = new Map();
70
+ ipRoutingEnabled = true;
71
+ featuresEnabled = new Set();
72
+ vpcDomainId = null;
73
+ vpcPeerKeepalive = null;
74
+ vnSegments = new Map();
75
+ vrfs = new Map();
76
+ activeVrf = null;
77
+ flashFiles = new Set(['c2960-lanbasek9-mz.150-2.SE4.bin']);
78
+ pendingCopyDest = null;
79
+ backupState = null;
80
+ saveBackupState() {
81
+ const interfacesCopy = new Map();
82
+ for (const [name, val] of this.interfaces.entries()) {
83
+ interfacesCopy.set(name, { ...val });
84
+ }
85
+ const routesCopy = this.routes.map(r => ({ ...r }));
86
+ const vlansCopy = new Set(this.vlans);
87
+ const vlanNamesCopy = new Map(this.vlanNames);
88
+ this.backupState = {
89
+ hostname: this.hostname,
90
+ interfaces: interfacesCopy,
91
+ routes: routesCopy,
92
+ vlans: vlansCopy,
93
+ vlanNames: vlanNamesCopy
94
+ };
95
+ }
96
+ restoreBackupState() {
97
+ if (!this.backupState)
98
+ return;
99
+ this.hostname = this.backupState.hostname;
100
+ this.interfaces = this.backupState.interfaces;
101
+ this.routes = this.backupState.routes;
102
+ this.vlans = this.backupState.vlans;
103
+ this.vlanNames = this.backupState.vlanNames;
104
+ }
105
+ constructor(initialHostname, type = 'ios') {
106
+ super(initialHostname || 'Switch1', type);
107
+ if (initialHostname) {
108
+ this.hostname = initialHostname;
109
+ }
110
+ }
111
+ getPrompt() {
112
+ switch (this.mode) {
113
+ case 'USER_EXEC':
114
+ return `${this.hostname}> `;
115
+ case 'PRIVILEGED_EXEC':
116
+ return `${this.hostname}# `;
117
+ case 'GLOBAL_CONFIG':
118
+ return `${this.hostname}(config)# `;
119
+ case 'INTERFACE_CONFIG':
120
+ return `${this.hostname}(config-if)# `;
121
+ case 'OSPF_CONFIG':
122
+ case 'RIP_CONFIG':
123
+ case 'BGP_CONFIG':
124
+ case 'EIGRP_CONFIG':
125
+ return `${this.hostname}(config-router)# `;
126
+ case 'DHCP_CONFIG':
127
+ return `${this.hostname}(config-dhcp)# `;
128
+ case 'ACL_CONFIG':
129
+ return `${this.hostname}(config-ext-nacl)# `;
130
+ case 'VLAN_CONFIG':
131
+ return `${this.hostname}(config-vlan)# `;
132
+ case 'VPC_CONFIG':
133
+ return `${this.hostname}(config-vpc-domain)# `;
134
+ case 'VRF_CONFIG':
135
+ return `${this.hostname}(config-vrf)# `;
136
+ case 'VRF_AF_CONFIG':
137
+ return `${this.hostname}(config-vrf-af-ipv4)# `;
138
+ default:
139
+ return `${this.hostname}# `;
140
+ }
141
+ }
142
+ processCommand(line) {
143
+ if (line.trim().endsWith('?')) {
144
+ return this.getContextHelp(line);
145
+ }
146
+ const normalizedLine = this.normalizeCommandString(line);
147
+ const trimmed = normalizedLine.trim();
148
+ if (this.pendingCopyDest) {
149
+ const dest = trimmed || this.pendingCopyDest;
150
+ this.flashFiles.add(dest);
151
+ this.saveBackupState();
152
+ this.pendingCopyDest = null;
153
+ return `1542 bytes copied in 0.456 secs (3381 bytes/sec)\n[OK]`;
154
+ }
155
+ if (!trimmed)
156
+ return '';
157
+ if (this.shellEnabled) {
158
+ const varMatch = trimmed.match(/^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/);
159
+ if (varMatch) {
160
+ const [, name, val] = varMatch;
161
+ this.shellVariables[name] = val;
162
+ return '';
163
+ }
164
+ const funcMatch = trimmed.match(/^([A-Za-z_][A-Za-z0-9_]*)\(\)\s*{(.*)}$/);
165
+ if (funcMatch) {
166
+ const [, name, body] = funcMatch;
167
+ this.shellFunctions[name] = body.trim();
168
+ return '';
169
+ }
170
+ }
171
+ let commandToExecute = trimmed;
172
+ const tempArgs = commandToExecute.split(/\s+/);
173
+ const tempCmd = tempArgs[0].toLowerCase();
174
+ const isConfigMode = this.mode !== 'USER_EXEC' && this.mode !== 'PRIVILEGED_EXEC';
175
+ if (tempCmd === 'do' && isConfigMode) {
176
+ const doMatch = commandToExecute.match(/^do\s+(.+)$/i);
177
+ if (doMatch) {
178
+ commandToExecute = doMatch[1];
179
+ }
180
+ }
181
+ const args = commandToExecute.split(/\s+/);
182
+ const cmd = args[0].toLowerCase();
183
+ const isShow = cmd === 'show' || cmd === 'sh' || (cmd === 'do' && (args[1]?.toLowerCase() === 'show' || args[1]?.toLowerCase() === 'sh'));
184
+ if (cmd === '?' || cmd === 'help') {
185
+ if (cmd === 'help') {
186
+ return `Help may be requested at any point in a command by entering
187
+ a question mark '?'. If nothing matches, the help list will
188
+ show the available options.`;
189
+ }
190
+ if (this.mode === 'USER_EXEC') {
191
+ return `Exec commands:
192
+ disable Turn off privileged commands
193
+ enable Turn on privileged commands
194
+ exit Exit from the EXEC
195
+ ping Send echo messages
196
+ show Show running system information`;
197
+ }
198
+ else if (this.mode === 'PRIVILEGED_EXEC') {
199
+ return `Exec commands:
200
+ clear Reset functions
201
+ configure Enter configuration mode
202
+ copy Copy from one file to another
203
+ dir List files on a filesystem
204
+ disable Turn off privileged commands
205
+ enable Turn on privileged commands
206
+ exit Exit from the EXEC
207
+ ping Send echo messages
208
+ show Show running system information
209
+ write Write running configuration to memory or terminal`;
210
+ }
211
+ else if (this.mode === 'GLOBAL_CONFIG') {
212
+ return `Configure commands:
213
+ do To run EXEC commands in config mode
214
+ end Exit from configure mode
215
+ exit Exit from configure mode
216
+ hostname Set system's network name
217
+ interface Select an interface to configure
218
+ ip Global IP configuration subcommands
219
+ no Negate a command or set defaults
220
+ router Enable a routing process
221
+ vlan Vlan configuration commands`;
222
+ }
223
+ else if (this.mode === 'INTERFACE_CONFIG') {
224
+ return `Interface configuration commands:
225
+ description Detailed description of this interface
226
+ exit Exit from interface configuration mode
227
+ ip IP interface configuration subcommands
228
+ no Negate a command or set defaults
229
+ shutdown Shutdown this interface`;
230
+ }
231
+ else {
232
+ return `Commands:
233
+ exit Exit current mode
234
+ end Exit to privileged EXEC mode`;
235
+ }
236
+ }
237
+ if (cmd === 'clear') {
238
+ if (this.mode === 'USER_EXEC') {
239
+ return `% Command rejected: Place in Privileged EXEC mode first.`;
240
+ }
241
+ return `% Incomplete command.`;
242
+ }
243
+ if (cmd === 'exit') {
244
+ if (this.mode === 'INTERFACE_CONFIG' || this.mode === 'OSPF_CONFIG' || this.mode === 'RIP_CONFIG' || this.mode === 'BGP_CONFIG' || this.mode === 'EIGRP_CONFIG' || this.mode === 'DHCP_CONFIG' || this.mode === 'ACL_CONFIG' || this.mode === 'VLAN_CONFIG' || this.mode === 'VPC_CONFIG' || this.mode === 'VRF_CONFIG') {
245
+ this.mode = 'GLOBAL_CONFIG';
246
+ this.activeInterface = null;
247
+ this.activeVlan = null;
248
+ this.activeVrf = null;
249
+ return '';
250
+ }
251
+ else if (this.mode === 'VRF_AF_CONFIG') {
252
+ this.mode = 'VRF_CONFIG';
253
+ return '';
254
+ }
255
+ else if (this.mode === 'GLOBAL_CONFIG') {
256
+ this.mode = 'PRIVILEGED_EXEC';
257
+ return '';
258
+ }
259
+ else if (this.mode === 'PRIVILEGED_EXEC') {
260
+ this.mode = 'USER_EXEC';
261
+ return '';
262
+ }
263
+ else {
264
+ return 'exit';
265
+ }
266
+ }
267
+ if (cmd === 'end') {
268
+ if (this.mode !== 'USER_EXEC' && this.mode !== 'PRIVILEGED_EXEC') {
269
+ this.mode = 'PRIVILEGED_EXEC';
270
+ this.activeInterface = null;
271
+ this.activeVlan = null;
272
+ this.activeVrf = null;
273
+ return '';
274
+ }
275
+ }
276
+ if (cmd === 'enable') {
277
+ if (this.mode === 'USER_EXEC') {
278
+ this.mode = 'PRIVILEGED_EXEC';
279
+ return '';
280
+ }
281
+ return '';
282
+ }
283
+ if (cmd === 'disable') {
284
+ if (this.mode !== 'USER_EXEC') {
285
+ this.mode = 'USER_EXEC';
286
+ return '';
287
+ }
288
+ return '';
289
+ }
290
+ if (trimmed.toLowerCase() === 'configure terminal' || trimmed.toLowerCase() === 'conf t') {
291
+ if (this.mode === 'PRIVILEGED_EXEC') {
292
+ this.mode = 'GLOBAL_CONFIG';
293
+ return 'Enter configuration commands, one per line. End with CNTL/Z.\n';
294
+ }
295
+ else {
296
+ return `% Command rejected: Place in Privileged EXEC mode first.`;
297
+ }
298
+ }
299
+ if (cmd === 'terminal' && args[1] === 'length' && args[2] === '0') {
300
+ return '';
301
+ }
302
+ if (cmd === 'screen-length' && args[1] === '0' && args[2] === 'temporary') {
303
+ return '';
304
+ }
305
+ if (cmd === 'set' && args[1] === 'cli' && args[2] === 'screen-length' && args[3] === '0') {
306
+ return '';
307
+ }
308
+ if (cmd === 'terminal' && args[1] === 'shell') {
309
+ this.shellEnabled = true;
310
+ return '';
311
+ }
312
+ if (cmd === 'shell' && args[1] === 'processing' && args[2] === 'full') {
313
+ this.shellEnabled = true;
314
+ return '';
315
+ }
316
+ const isGeneralCommand = isShow || cmd === 'ping' || cmd === 'write' || cmd === 'wr' || cmd === 'copy' || cmd === 'dir' || cmd === 'test';
317
+ if (this.mode === 'GLOBAL_CONFIG' && !isGeneralCommand) {
318
+ if (cmd === 'feature' && args[1]) {
319
+ const featureName = args.slice(1).join(' ').toLowerCase();
320
+ this.featuresEnabled.add(featureName);
321
+ return '';
322
+ }
323
+ if (cmd === 'no' && args[1] === 'feature' && args[2]) {
324
+ const featureName = args.slice(2).join(' ').toLowerCase();
325
+ this.featuresEnabled.delete(featureName);
326
+ return '';
327
+ }
328
+ if (cmd === 'vpc' && args[1] === 'domain' && args[2]) {
329
+ const domainId = parseInt(args[2], 10);
330
+ if (!isNaN(domainId)) {
331
+ this.vpcDomainId = domainId;
332
+ this.mode = 'VPC_CONFIG';
333
+ return '';
334
+ }
335
+ }
336
+ if (cmd === 'vrf' && args[1] === 'context' && args[2]) {
337
+ const vrfName = args[2];
338
+ this.activeVrf = vrfName;
339
+ if (!this.vrfs.has(vrfName)) {
340
+ this.vrfs.set(vrfName, { routeTargets: [] });
341
+ }
342
+ this.mode = 'VRF_CONFIG';
343
+ return '';
344
+ }
345
+ if (cmd === 'hostname' && args[1]) {
346
+ this.hostname = args[1];
347
+ return '';
348
+ }
349
+ if (cmd === 'interface' && args[1]) {
350
+ const ifaceName = this.normalizeInterfaceName(args[1]);
351
+ this.mode = 'INTERFACE_CONFIG';
352
+ this.activeInterface = ifaceName;
353
+ if (!this.interfaces.has(ifaceName)) {
354
+ this.interfaces.set(ifaceName, {
355
+ name: ifaceName,
356
+ ip: null,
357
+ subnet: null,
358
+ adminShutdown: false,
359
+ lineProtocolUp: true,
360
+ description: null
361
+ });
362
+ }
363
+ return '';
364
+ }
365
+ if (cmd === 'vlan' && args[1]) {
366
+ const vlanId = parseInt(args[1], 10);
367
+ if (!isNaN(vlanId)) {
368
+ this.vlans.add(vlanId);
369
+ this.activeVlan = vlanId;
370
+ this.mode = 'VLAN_CONFIG';
371
+ return '';
372
+ }
373
+ }
374
+ if (cmd === 'no' && args[1] === 'vlan' && args[2]) {
375
+ const vlanId = parseInt(args[2], 10);
376
+ if (!isNaN(vlanId)) {
377
+ this.vlans.delete(vlanId);
378
+ this.vlanNames.delete(vlanId);
379
+ return '';
380
+ }
381
+ }
382
+ if (cmd === 'ip' && args[1] === 'route' && args[2] && args[3]) {
383
+ const network = args[2];
384
+ const mask = args[3];
385
+ const next = args[4] || null;
386
+ this.routes.push({
387
+ network,
388
+ mask,
389
+ nextHop: next && !next.startsWith('Gig') && !next.startsWith('Loop') ? next : null,
390
+ outgoingInterface: next && (next.startsWith('Gig') || next.startsWith('Loop')) ? next : null,
391
+ connected: false
392
+ });
393
+ return '';
394
+ }
395
+ if (cmd === 'no' && args[1] === 'ip' && args[2] === 'route' && args[3] && args[4]) {
396
+ const network = args[3];
397
+ const mask = args[4];
398
+ this.routes = this.routes.filter(r => !(r.network === network && r.mask === mask));
399
+ return '';
400
+ }
401
+ if (cmd === 'ip' && args[1] === 'routing') {
402
+ this.ipRoutingEnabled = true;
403
+ return '';
404
+ }
405
+ if (cmd === 'no' && args[1] === 'ip' && args[2] === 'routing') {
406
+ this.ipRoutingEnabled = false;
407
+ return '';
408
+ }
409
+ if (cmd === 'router' && args[1] === 'ospf') {
410
+ this.mode = 'OSPF_CONFIG';
411
+ this.ospfProcessId = args[2] || null;
412
+ this.ospfEnabled = true;
413
+ return '';
414
+ }
415
+ if (cmd === 'no' && args[1] === 'router' && args[2] === 'ospf') {
416
+ this.ospfEnabled = false;
417
+ this.ospfProcessId = null;
418
+ return '';
419
+ }
420
+ if (cmd === 'router' && args[1] === 'rip') {
421
+ this.mode = 'RIP_CONFIG';
422
+ this.ripEnabled = true;
423
+ return '';
424
+ }
425
+ if (cmd === 'no' && args[1] === 'router' && args[2] === 'rip') {
426
+ this.ripEnabled = false;
427
+ return '';
428
+ }
429
+ if (cmd === 'router' && args[1] === 'bgp') {
430
+ this.mode = 'BGP_CONFIG';
431
+ this.bgpAsn = args[2] || null;
432
+ this.bgpEnabled = true;
433
+ return '';
434
+ }
435
+ if (cmd === 'no' && args[1] === 'router' && args[2] === 'bgp') {
436
+ this.bgpEnabled = false;
437
+ this.bgpAsn = null;
438
+ return '';
439
+ }
440
+ if (cmd === 'spanning-tree' && args[1]) {
441
+ return '';
442
+ }
443
+ if (cmd === 'router' && args[1] === 'eigrp') {
444
+ this.mode = 'EIGRP_CONFIG';
445
+ this.eigrpAsn = args[2] || null;
446
+ this.eigrpEnabled = true;
447
+ return '';
448
+ }
449
+ if (cmd === 'no' && args[1] === 'router' && args[2] === 'eigrp') {
450
+ this.eigrpEnabled = false;
451
+ this.eigrpAsn = null;
452
+ return '';
453
+ }
454
+ if (cmd === 'vtp' && args[1]) {
455
+ if (args[1] === 'mode' && args[2]) {
456
+ this.vtpMode = args[2].toLowerCase();
457
+ }
458
+ else if (args[1] === 'domain' && args[2]) {
459
+ this.vtpDomain = args[2];
460
+ }
461
+ else if (args[1] === 'password' && args[2]) {
462
+ this.vtpPassword = args[2];
463
+ }
464
+ return '';
465
+ }
466
+ if (cmd === 'ntp' && args[1] === 'server' && args[2]) {
467
+ if (!this.ntpServers.includes(args[2])) {
468
+ this.ntpServers.push(args[2]);
469
+ }
470
+ return '';
471
+ }
472
+ if (cmd === 'snmp-server' && args[1] === 'community' && args[2]) {
473
+ if (!this.snmpCommunities.includes(args[2])) {
474
+ this.snmpCommunities.push(args[2]);
475
+ }
476
+ return '';
477
+ }
478
+ if (cmd === 'ip' && args[1] === 'nat' && args[2] === 'inside' && args[3] === 'source') {
479
+ this.natRules.push(args.slice(2).join(' '));
480
+ return '';
481
+ }
482
+ if (cmd === 'access-list' && args[1] && args[2]) {
483
+ const aclId = args[1];
484
+ const rule = args.slice(2).join(' ');
485
+ if (!this.acls.has(aclId)) {
486
+ this.acls.set(aclId, []);
487
+ }
488
+ this.acls.get(aclId).push(rule);
489
+ return '';
490
+ }
491
+ if (cmd === 'ip' && args[1] === 'access-list' && (args[2] === 'standard' || args[2] === 'extended') && args[3]) {
492
+ this.mode = 'ACL_CONFIG';
493
+ return '';
494
+ }
495
+ if (cmd === 'ip' && args[1] === 'dhcp' && args[2] === 'pool' && args[3]) {
496
+ this.mode = 'DHCP_CONFIG';
497
+ return '';
498
+ }
499
+ if (cmd === 'ip' && args[1] === 'dhcp' && args[2] === 'excluded-address') {
500
+ return '';
501
+ }
502
+ if (cmd === 'ip' && args[1] === 'access-list') {
503
+ this.mode = 'ACL_CONFIG';
504
+ return '';
505
+ }
506
+ if (cmd === 'access-list') {
507
+ return '';
508
+ }
509
+ return `% Invalid input detected at '^' marker.`;
510
+ }
511
+ if (this.mode === 'VLAN_CONFIG' && this.activeVlan !== null && !isGeneralCommand) {
512
+ if (cmd === 'name' && args[1]) {
513
+ this.vlanNames.set(this.activeVlan, args.slice(1).join(' '));
514
+ return '';
515
+ }
516
+ if (cmd === 'no' && args[1] === 'name') {
517
+ this.vlanNames.set(this.activeVlan, `VLAN${this.activeVlan.toString().padStart(4, '0')}`);
518
+ return '';
519
+ }
520
+ if (cmd === 'vn-segment' && args[1]) {
521
+ const vni = parseInt(args[1], 10);
522
+ if (!isNaN(vni)) {
523
+ this.vnSegments.set(this.activeVlan, vni);
524
+ return '';
525
+ }
526
+ }
527
+ return `% Invalid input detected at '^' marker.`;
528
+ }
529
+ if (this.mode === 'INTERFACE_CONFIG' && this.activeInterface && !isGeneralCommand) {
530
+ const iface = this.interfaces.get(this.activeInterface);
531
+ if (cmd === 'vpc' && args[1]) {
532
+ const vpcId = parseInt(args[1], 10);
533
+ if (!isNaN(vpcId)) {
534
+ iface.vpcMemberId = vpcId;
535
+ return '';
536
+ }
537
+ }
538
+ if (cmd === 'source-interface' && args[1]) {
539
+ iface.sourceInterface = args[1];
540
+ return '';
541
+ }
542
+ if (cmd === 'member' && args[1] === 'vni' && args[2]) {
543
+ const vni = parseInt(args[2], 10);
544
+ if (!isNaN(vni)) {
545
+ if (!iface.memberVnis) {
546
+ iface.memberVnis = new Map();
547
+ }
548
+ const mcastGroup = args[3] === 'mcast-group' ? args[4] : undefined;
549
+ const associateVrf = args.includes('associate-vrf');
550
+ iface.memberVnis.set(vni, { mcastGroup, associateVrf });
551
+ return '';
552
+ }
553
+ }
554
+ if (cmd === 'shutdown') {
555
+ iface.adminShutdown = true;
556
+ iface.lineProtocolUp = false;
557
+ return '';
558
+ }
559
+ if (cmd === 'no' && args[1] === 'shutdown') {
560
+ iface.adminShutdown = false;
561
+ iface.lineProtocolUp = true;
562
+ return '';
563
+ }
564
+ if (cmd === 'ip' && args[1] === 'address' && args[2] && args[3]) {
565
+ iface.ip = args[2];
566
+ iface.subnet = args[3];
567
+ const network = this.calculateNetwork(args[2], args[3]);
568
+ this.routes = this.routes.filter(r => !(r.outgoingInterface === this.activeInterface && r.connected));
569
+ this.routes.push({
570
+ network,
571
+ mask: args[3],
572
+ nextHop: null,
573
+ outgoingInterface: this.activeInterface,
574
+ connected: true
575
+ });
576
+ return '';
577
+ }
578
+ if (cmd === 'no' && args[1] === 'ip' && args[2] === 'address') {
579
+ iface.ip = null;
580
+ iface.subnet = null;
581
+ this.routes = this.routes.filter(r => !(r.outgoingInterface === this.activeInterface && r.connected));
582
+ return '';
583
+ }
584
+ if (cmd === 'description') {
585
+ iface.description = args.slice(1).join(' ');
586
+ return '';
587
+ }
588
+ if (cmd === 'no' && args[1] === 'description') {
589
+ iface.description = null;
590
+ return '';
591
+ }
592
+ if (cmd === 'switchport') {
593
+ if (args[1] === 'mode' && args[2] === 'access') {
594
+ iface.switchportMode = 'access';
595
+ iface.isSwitchport = true;
596
+ return '';
597
+ }
598
+ if (args[1] === 'access' && args[2] === 'vlan' && args[3]) {
599
+ const vlanId = parseInt(args[3], 10);
600
+ if (!isNaN(vlanId)) {
601
+ iface.vlan = vlanId;
602
+ iface.isSwitchport = true;
603
+ let output = '';
604
+ if (!this.vlans.has(vlanId)) {
605
+ this.vlans.add(vlanId);
606
+ this.vlanNames.set(vlanId, `VLAN${vlanId.toString().padStart(4, '0')}`);
607
+ output = `%% Access VLAN ${vlanId} does not exist. Creating vlan ${vlanId}\n`;
608
+ }
609
+ return output;
610
+ }
611
+ }
612
+ if (!args[1]) {
613
+ iface.isSwitchport = true;
614
+ return '';
615
+ }
616
+ }
617
+ if (cmd === 'no' && args[1] === 'switchport') {
618
+ iface.isSwitchport = false;
619
+ iface.vlan = undefined;
620
+ iface.switchportMode = undefined;
621
+ return '';
622
+ }
623
+ if (cmd === 'ip' && args[1] === 'access-group') {
624
+ return '';
625
+ }
626
+ if (cmd === 'ip' && args[1] === 'ospf') {
627
+ return '';
628
+ }
629
+ if (cmd === 'switchport' && args[1] === 'mode' && args[2] === 'trunk') {
630
+ iface.switchportMode = 'trunk';
631
+ iface.isSwitchport = true;
632
+ return '';
633
+ }
634
+ if (cmd === 'switchport' && args[1] === 'trunk' && args[2] === 'allowed' && args[3] === 'vlan') {
635
+ return '';
636
+ }
637
+ if (cmd === 'channel-group' && args[1] && args[2] === 'mode' && args[3]) {
638
+ return '';
639
+ }
640
+ if (cmd === 'standby' && args[1]) {
641
+ const group = args[1];
642
+ if (!this.hsrpGroups.has(group)) {
643
+ this.hsrpGroups.set(group, { virtualIp: '', priority: 100, preempt: false });
644
+ }
645
+ const hsrp = this.hsrpGroups.get(group);
646
+ if (args[2] === 'ip' && args[3]) {
647
+ hsrp.virtualIp = args[3];
648
+ }
649
+ else if (args[2] === 'priority' && args[3]) {
650
+ hsrp.priority = parseInt(args[3], 10);
651
+ }
652
+ else if (args[2] === 'preempt') {
653
+ hsrp.preempt = true;
654
+ }
655
+ return '';
656
+ }
657
+ if (cmd === 'vrrp' && args[1]) {
658
+ const group = args[1];
659
+ if (!this.vrrpGroups.has(group)) {
660
+ this.vrrpGroups.set(group, { virtualIp: '', priority: 100 });
661
+ }
662
+ const vrrp = this.vrrpGroups.get(group);
663
+ if (args[2] === 'ip' && args[3]) {
664
+ vrrp.virtualIp = args[3];
665
+ }
666
+ else if (args[2] === 'priority' && args[3]) {
667
+ vrrp.priority = parseInt(args[3], 10);
668
+ }
669
+ return '';
670
+ }
671
+ if (cmd === 'ip' && args[1] === 'nat' && (args[2] === 'inside' || args[2] === 'outside')) {
672
+ iface.natType = args[2];
673
+ if (args[2] === 'inside') {
674
+ this.natInsideInterfaces.add(this.activeInterface);
675
+ }
676
+ else {
677
+ this.natOutsideInterfaces.add(this.activeInterface);
678
+ }
679
+ return '';
680
+ }
681
+ return `% Invalid input detected at '^' marker.`;
682
+ }
683
+ if (this.mode === 'OSPF_CONFIG' && !isGeneralCommand) {
684
+ if (cmd === 'network' && args[1] && args[2] && args[3] === 'area' && args[4]) {
685
+ const network = args[1];
686
+ const wildcard = args[2];
687
+ const area = args[4];
688
+ this.ospfNetworks.push({ network, wildcard, area });
689
+ return '';
690
+ }
691
+ if (cmd === 'network' || cmd === 'router-id') {
692
+ return '';
693
+ }
694
+ if (cmd === 'passive-interface' || (cmd === 'no' && args[1] === 'passive-interface')) {
695
+ return '';
696
+ }
697
+ return `% Invalid input detected at '^' marker.`;
698
+ }
699
+ if (this.mode === 'RIP_CONFIG' && !isGeneralCommand) {
700
+ if (cmd === 'version' && (args[1] === '1' || args[1] === '2')) {
701
+ this.ripVersion = parseInt(args[1], 10);
702
+ return '';
703
+ }
704
+ if (cmd === 'no' && args[1] === 'auto-summary') {
705
+ this.ripAutoSummary = false;
706
+ return '';
707
+ }
708
+ if (cmd === 'auto-summary') {
709
+ this.ripAutoSummary = true;
710
+ return '';
711
+ }
712
+ if (cmd === 'network' && args[1]) {
713
+ return '';
714
+ }
715
+ if (cmd === 'passive-interface' || (cmd === 'no' && args[1] === 'passive-interface')) {
716
+ return '';
717
+ }
718
+ return `% Invalid input detected at '^' marker.`;
719
+ }
720
+ if (this.mode === 'BGP_CONFIG' && !isGeneralCommand) {
721
+ if (cmd === 'neighbor' && args[1]) {
722
+ return '';
723
+ }
724
+ if (cmd === 'no' && args[1] === 'neighbor' && args[2]) {
725
+ return '';
726
+ }
727
+ if (cmd === 'network' && args[1]) {
728
+ return '';
729
+ }
730
+ if (cmd === 'no' && args[1] === 'auto-summary') {
731
+ return '';
732
+ }
733
+ if (cmd === 'auto-summary') {
734
+ return '';
735
+ }
736
+ if (cmd === 'address-family' && args[1] === 'l2vpn' && args[2] === 'evpn') {
737
+ return '';
738
+ }
739
+ if (cmd === 'send-community') {
740
+ return '';
741
+ }
742
+ return `% Invalid input detected at '^' marker.`;
743
+ }
744
+ if (this.mode === 'VPC_CONFIG' && !isGeneralCommand) {
745
+ if (cmd === 'peer-keepalive' && args[1] === 'destination') {
746
+ this.vpcPeerKeepalive = commandToExecute;
747
+ return '';
748
+ }
749
+ if (cmd === 'system-priority' || cmd === 'role' || cmd === 'peer-gateway' || cmd === 'peer-switch') {
750
+ return '';
751
+ }
752
+ return `% Invalid input detected at '^' marker.`;
753
+ }
754
+ if (this.mode === 'VRF_CONFIG' && this.activeVrf && !isGeneralCommand) {
755
+ const vrf = this.vrfs.get(this.activeVrf);
756
+ if (cmd === 'vni' && args[1]) {
757
+ vrf.vni = parseInt(args[1], 10);
758
+ return '';
759
+ }
760
+ if (cmd === 'rd' && args[1]) {
761
+ vrf.rd = args.slice(1).join(' ');
762
+ return '';
763
+ }
764
+ if (cmd === 'address-family' && args[1] === 'ipv4' && args[2] === 'unicast') {
765
+ this.mode = 'VRF_AF_CONFIG';
766
+ return '';
767
+ }
768
+ return `% Invalid input detected at '^' marker.`;
769
+ }
770
+ if (this.mode === 'VRF_AF_CONFIG' && this.activeVrf && !isGeneralCommand) {
771
+ const vrf = this.vrfs.get(this.activeVrf);
772
+ if (cmd === 'route-target' && args[1] === 'both' && args[2]) {
773
+ vrf.routeTargets.push(args.slice(1).join(' '));
774
+ return '';
775
+ }
776
+ return `% Invalid input detected at '^' marker.`;
777
+ }
778
+ if (this.mode === 'EIGRP_CONFIG' && !isGeneralCommand) {
779
+ if (cmd === 'network' && args[1]) {
780
+ return '';
781
+ }
782
+ if (cmd === 'no' && args[1] === 'auto-summary') {
783
+ return '';
784
+ }
785
+ if (cmd === 'auto-summary') {
786
+ return '';
787
+ }
788
+ if (cmd === 'passive-interface' || (cmd === 'no' && args[1] === 'passive-interface')) {
789
+ return '';
790
+ }
791
+ return `% Invalid input detected at '^' marker.`;
792
+ }
793
+ if (this.mode === 'DHCP_CONFIG' && !isGeneralCommand) {
794
+ if (cmd === 'network' || cmd === 'default-router' || cmd === 'dns-server') {
795
+ return '';
796
+ }
797
+ return `% Invalid input detected at '^' marker.`;
798
+ }
799
+ if (this.mode === 'ACL_CONFIG' && !isGeneralCommand) {
800
+ if (cmd === 'permit' || cmd === 'deny') {
801
+ return '';
802
+ }
803
+ return `% Invalid input detected at '^' marker.`;
804
+ }
805
+ if (isShow) {
806
+ const showArgs = cmd === 'do' ? args.slice(2) : args.slice(1);
807
+ const showCmd = showArgs[0]?.toLowerCase();
808
+ if (showCmd === 'vpc') {
809
+ const domainId = this.vpcDomainId || 10;
810
+ const peerStatus = this.vpcPeerKeepalive ? 'peer adjacency formed ok' : 'peer link not configured';
811
+ const keepaliveStatus = this.vpcPeerKeepalive ? 'peer is alive' : 'peer keep-alive not configured';
812
+ return `Legend:
813
+ (*) - local vPC is down, dynamic backup loop preventer
814
+
815
+ vPC domain id : ${domainId}
816
+ Peer status : ${peerStatus}
817
+ vPC keep-alive status : ${keepaliveStatus}
818
+ Configuration-consistency status : success
819
+ Per-vlan consistency status : success
820
+ Type-2 consistency status : success
821
+ vPC role : primary
822
+ Number of vPCs configured : ${Array.from(this.interfaces.values()).filter(i => i.vpcMemberId !== undefined).length}
823
+ Peer Gateway : Enabled
824
+ `;
825
+ }
826
+ if (showCmd === 'nve' && showArgs[1] === 'interface') {
827
+ const nveIface = Array.from(this.interfaces.values()).find(i => i.name.toLowerCase().startsWith('nve'));
828
+ if (!nveIface) {
829
+ return '% NVE interface is not configured';
830
+ }
831
+ const sourceInt = nveIface.sourceInterface || 'Loopback0';
832
+ return `Interface: ${nveIface.name}, State: Up, Encapsulation: VXLAN
833
+ Source-Interface: ${sourceInt} (10.0.0.1)
834
+ `;
835
+ }
836
+ if (showCmd === 'nve' && showArgs[1] === 'vni') {
837
+ const nveIface = Array.from(this.interfaces.values()).find(i => i.name.toLowerCase().startsWith('nve'));
838
+ if (!nveIface || !nveIface.memberVnis) {
839
+ return `Interface VNI Multicast-group State Mode vPC Dev\n` +
840
+ `--------- -------- ----------------- ----- ---- -------\n`;
841
+ }
842
+ let out = `Interface VNI Multicast-group State Mode vPC Dev\n` +
843
+ `--------- -------- ----------------- ----- ---- -------\n`;
844
+ for (const [vni, details] of nveIface.memberVnis.entries()) {
845
+ const mcast = details.mcastGroup || 'n/a';
846
+ out += `${nveIface.name.padEnd(9)} ${vni.toString().padEnd(8)} ${mcast.padEnd(17)} Up CP n/a\n`;
847
+ }
848
+ return out;
849
+ }
850
+ if (showCmd === 'bgp' && showArgs[1] === 'l2vpn' && showArgs[2] === 'evpn' && showArgs[3] === 'summary') {
851
+ const bgpAs = this.bgpAsn || '65000';
852
+ return `BGP summary information for VRF default, address family L2VPN EVPN
853
+ BGP router identifier 10.0.0.1, local AS number ${bgpAs}
854
+ Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
855
+ 10.0.0.2 4 ${bgpAs} 120 125 47 0 0 01:24:55 2
856
+ `;
857
+ }
858
+ if (showCmd === 'version' || showCmd === 'ver') {
859
+ return `Cisco IOS Software, C2960 Software (C2960-LANBASEK9-M), Version 15.0(2)SE4, RELEASE SOFTWARE (fc1)
860
+ Technical Support: http://www.cisco.com/techsupport
861
+ Copyright (c) 1986-2013 by Cisco Systems, Inc.
862
+ Compiled Wed 26-Jun-13 02:49 by prod_rel_team
863
+
864
+ ROM: Bootstrap program is 12.2(44)SE Version
865
+ BOOTLDR: C2960 Boot Loader (C2960-HBOOT-M) Version 12.2(44)SE, RELEASE SOFTWARE (fc1)
866
+
867
+ Switch1 uptime is 2 hours, 15 minutes
868
+ System returned to ROM by power-on
869
+ System image file is "flash:/c2960-lanbasek9-mz.150-2.SE4.bin"
870
+
871
+ This product contains cryptographic features and is subject to Y...
872
+ `;
873
+ }
874
+ if (showCmd === 'ip' && showArgs[1]?.startsWith('int') && showArgs[2]?.startsWith('br')) {
875
+ let out = 'Interface IP-Address OK? Method Status Protocol\n';
876
+ for (const [name, status] of this.interfaces.entries()) {
877
+ const ip = status.ip || 'unassigned';
878
+ const method = status.ip ? 'manual' : 'unset';
879
+ const adminStatus = status.adminShutdown ? 'administratively down' : 'up';
880
+ const protocolStatus = status.lineProtocolUp ? 'up' : 'down';
881
+ out += `${name.padEnd(26)} ${ip.padEnd(15)} YES ${method.padEnd(6)} ${adminStatus.padEnd(21)} ${protocolStatus}\n`;
882
+ }
883
+ return out;
884
+ }
885
+ if (showCmd?.startsWith('run')) {
886
+ let out = `Building configuration...\n\nCurrent configuration : 1542 bytes\n!\nversion 15.0\n!\nhostname ${this.hostname}\n!\n`;
887
+ for (const [name, status] of this.interfaces.entries()) {
888
+ out += `interface ${name}\n`;
889
+ if (status.description) {
890
+ out += ` description ${status.description}\n`;
891
+ }
892
+ if (status.isSwitchport) {
893
+ out += ` switchport\n`;
894
+ if (status.switchportMode) {
895
+ out += ` switchport mode ${status.switchportMode}\n`;
896
+ }
897
+ if (status.vlan) {
898
+ out += ` switchport access vlan ${status.vlan}\n`;
899
+ }
900
+ }
901
+ if (status.ip) {
902
+ out += ` ip address ${status.ip} ${status.subnet}\n`;
903
+ }
904
+ if (status.adminShutdown) {
905
+ out += ` shutdown\n`;
906
+ }
907
+ out += `!\n`;
908
+ }
909
+ for (const r of this.routes) {
910
+ if (!r.connected) {
911
+ out += `ip route ${r.network} ${r.mask} ${r.nextHop || r.outgoingInterface}\n`;
912
+ }
913
+ }
914
+ if (this.ospfEnabled) {
915
+ out += `router ospf ${this.ospfProcessId || '10'}\n`;
916
+ for (const net of this.ospfNetworks) {
917
+ out += ` network ${net.network} ${net.wildcard} area ${net.area}\n`;
918
+ }
919
+ }
920
+ out += `!\nend\n`;
921
+ return out;
922
+ }
923
+ if (showCmd === 'ip' && showArgs[1] === 'protocols') {
924
+ let out = '';
925
+ if (this.ospfEnabled) {
926
+ out += `Routing Protocol is "ospf ${this.ospfProcessId || '10'}"\n` +
927
+ ` Outgoing update filter list for all interfaces is not set\n` +
928
+ ` Incoming update filter list for all interfaces is not set\n` +
929
+ ` Router ID 192.168.1.254\n` +
930
+ ` Number of areas in this router is 1. 1 normal 0 stub 0 nssa\n` +
931
+ ` Routing for Networks:\n`;
932
+ if (this.ospfNetworks.length > 0) {
933
+ for (const net of this.ospfNetworks) {
934
+ out += ` ${net.network}/${this.getPrefixLength(this.wildcardToSubnet(net.wildcard))} area ${net.area}\n`;
935
+ }
936
+ }
937
+ else {
938
+ out += ` 192.168.1.0/24 area 0\n`;
939
+ }
940
+ out += ` Routing Information Sources:\n` +
941
+ ` Gateway Distance Last Update\n` +
942
+ ` Distance: (default is 110)\n\n`;
943
+ }
944
+ if (this.ripEnabled) {
945
+ out += `Routing Protocol is "rip"\n` +
946
+ ` Sending updates every 30 seconds, next due in 15 seconds\n` +
947
+ ` Invalid 180 seconds, hold down 180, flushed 240\n` +
948
+ ` Outgoing update filter list for all interfaces is not set\n` +
949
+ ` Incoming update filter list for all interfaces is not set\n` +
950
+ ` Redistributing: rip\n` +
951
+ ` Default version control: send version ${this.ripVersion}, receive version ${this.ripVersion}\n` +
952
+ ` Interface Send Recv Triggered RIP Key-chain\n`;
953
+ for (const name of this.interfaces.keys()) {
954
+ out += ` ${name.padEnd(21)} ${this.ripVersion} ${this.ripVersion}\n`;
955
+ }
956
+ out += ` Automatic network summarization is ${this.ripAutoSummary ? 'in effect' : 'not in effect'}\n` +
957
+ ` Maximum path: 4\n` +
958
+ ` Routing for Networks:\n` +
959
+ ` 192.168.1.0\n` +
960
+ ` Routing Information Sources:\n` +
961
+ ` Gateway Distance Last Update\n` +
962
+ ` Distance: (default is 120)\n\n`;
963
+ }
964
+ if (this.bgpEnabled) {
965
+ out += `Routing Protocol is "bgp ${this.bgpAsn || '65000'}"\n` +
966
+ ` Outgoing update filter list for all interfaces is not set\n` +
967
+ ` Incoming update filter list for all interfaces is not set\n` +
968
+ ` IGP synchronization is disabled\n` +
969
+ ` Automatic route summarization is disabled\n` +
970
+ ` Routing Information Sources:\n` +
971
+ ` Gateway Distance Last Update\n` +
972
+ ` Distance: external 20 internal 200 local 200\n\n`;
973
+ }
974
+ if (this.eigrpEnabled) {
975
+ out += `Routing Protocol is "eigrp ${this.eigrpAsn || '100'}"\n` +
976
+ ` Outgoing update filter list for all interfaces is not set\n` +
977
+ ` Incoming update filter list for all interfaces is not set\n` +
978
+ ` Default networks being advertised:\n` +
979
+ ` 192.168.1.0\n` +
980
+ ` EIGRP-IPv4 Protocol for AS(${this.eigrpAsn || '100'})\n` +
981
+ ` Metric weight K1=1, K2=0, K3=1, K4=0, K5=0\n` +
982
+ ` NSF-aware route hold timer is 240s\n` +
983
+ ` Router-ID: 192.168.1.254\n` +
984
+ ` Topology Kisspoint limit: 100\n` +
985
+ ` Routing Information Sources:\n` +
986
+ ` Gateway Distance Last Update\n` +
987
+ ` Distance: internal 90 external 170\n\n`;
988
+ }
989
+ if (!out) {
990
+ out = '*** No routing protocols configured ***\n';
991
+ }
992
+ return out;
993
+ }
994
+ if (showCmd === 'ip' && showArgs[1]?.startsWith('ro')) {
995
+ if (!this.ipRoutingEnabled) {
996
+ return '% IP routing table is not enabled';
997
+ }
998
+ let out = `Codes: L - local, C - connected, S - static, R - RIP, M - mobile, B - BGP\n\n`;
999
+ out += `Gateway of last resort is not set\n\n`;
1000
+ for (const r of this.routes) {
1001
+ if (r.connected && r.outgoingInterface) {
1002
+ const iface = this.interfaces.get(r.outgoingInterface);
1003
+ if (iface && iface.adminShutdown) {
1004
+ continue;
1005
+ }
1006
+ }
1007
+ const code = r.connected ? 'C' : 'S';
1008
+ const target = r.nextHop ? `via ${r.nextHop}` : `directly connected, ${r.outgoingInterface || 'Null0'}`;
1009
+ out += `${code} ${r.network}/${this.getPrefixLength(r.mask)} is ${target}\n`;
1010
+ }
1011
+ return out;
1012
+ }
1013
+ if (showCmd === 'ip' && showArgs[1] === 'ospf' && showArgs[2]?.startsWith('ne')) {
1014
+ if (!this.ospfEnabled) {
1015
+ return '% OSPF is not enabled';
1016
+ }
1017
+ return `Neighbor ID Pri State Dead Time Address Interface\n` +
1018
+ `2.2.2.2 1 FULL/DR 00:00:35 192.168.1.2 GigabitEthernet0/0\n`;
1019
+ }
1020
+ if (showCmd === 'ip' && showArgs[1] === 'ospf' && showArgs[2]?.startsWith('in')) {
1021
+ if (!this.ospfEnabled) {
1022
+ return '% OSPF is not enabled';
1023
+ }
1024
+ return `GigabitEthernet0/0 is up, line protocol is up \n` +
1025
+ ` Internet Address 192.168.1.254/24, Area 0 \n` +
1026
+ ` Process ID ${this.ospfProcessId || '10'}, Router ID 192.168.1.254, Network Type BROADCAST, Cost: 1\n`;
1027
+ }
1028
+ if (showCmd === 'ip' && showArgs[1] === 'ospf' && !showArgs[2]) {
1029
+ if (!this.ospfEnabled) {
1030
+ return '% OSPF is not enabled';
1031
+ }
1032
+ return ` Routing Process "ospf ${this.ospfProcessId || '10'}" with ID 192.168.1.254\n` +
1033
+ ` Supports only single TOS(TOS0) routes\n` +
1034
+ ` Supports opaque LSA\n`;
1035
+ }
1036
+ if (showCmd?.startsWith('vl') && (showArgs[1]?.startsWith('br') || !showArgs[1])) {
1037
+ let out = 'VLAN Name Status Ports\n';
1038
+ out += '---- -------------------------------- --------- -------------------------------\n';
1039
+ for (const vid of this.vlans) {
1040
+ const name = this.vlanNames.get(vid) || `VLAN${vid.toString().padStart(4, '0')}`;
1041
+ const ports = Array.from(this.interfaces.values())
1042
+ .filter(iface => iface.vlan === vid)
1043
+ .map(iface => this.shortenInterfaceName(iface.name))
1044
+ .join(', ');
1045
+ out += `${vid.toString().padEnd(4)} ${name.padEnd(32)} active ${ports}\n`;
1046
+ }
1047
+ return out;
1048
+ }
1049
+ if (showCmd === 'cdp' && showArgs[1]?.startsWith('ne')) {
1050
+ return `Capability Codes: R - Router, T - Trans Bridge, B - Source Route Bridge
1051
+ S - Switch, H - Host, I - IGMP, r - Repeater, P - Phone
1052
+
1053
+ Device ID Local Intrfce Holdtme Capability Platform Port ID
1054
+ Switch2 Gig 0/1 125 S I WS-C2960- Gig 0/1
1055
+ `;
1056
+ }
1057
+ if (showCmd === 'vtp' && showArgs[1] === 'status') {
1058
+ return `VTP Version capability : 1 to 3\n` +
1059
+ `VTP version running : 1\n` +
1060
+ `VTP Operating Mode : ${this.vtpMode}\n` +
1061
+ `VTP Domain Name : ${this.vtpDomain || ''}\n` +
1062
+ `VTP Pruning Mode : Disabled\n` +
1063
+ `VTP V2 Mode : Disabled\n` +
1064
+ `VTP Traps Generation : Disabled\n` +
1065
+ `MD5 digest : 0x94 0xC2 0x6E 0x93 0xA3 0xE2 0xD4 0xFA \n` +
1066
+ `Configuration last modified by 0.0.0.0 at 0-0-00 00:00:00\n`;
1067
+ }
1068
+ if (showCmd === 'standby' && (showArgs[1] === 'brief' || !showArgs[1])) {
1069
+ let out = ' Preempt State Active Standby Virtual IP\n';
1070
+ for (const [group, hsrp] of this.hsrpGroups.entries()) {
1071
+ out += `Gi0/1 ${group.padEnd(6)} ${hsrp.priority.toString().padEnd(4)} ${hsrp.preempt ? 'P' : ' '} Active local unknown ${hsrp.virtualIp}\n`;
1072
+ }
1073
+ if (this.hsrpGroups.size === 0) {
1074
+ out = '*** No HSRP standby groups configured ***\n';
1075
+ }
1076
+ return out;
1077
+ }
1078
+ if (showCmd === 'vrrp' && (showArgs[1] === 'brief' || !showArgs[1])) {
1079
+ let out = 'Interface Grp Fip Pri Time Own Pre State Master addr Group addr\n';
1080
+ for (const [group, vrrp] of this.vrrpGroups.entries()) {
1081
+ out += `Gi0/1 ${group.padEnd(4)} 1 ${vrrp.priority.toString().padEnd(3)} 3.609 N Y Master local ${vrrp.virtualIp}\n`;
1082
+ }
1083
+ if (this.vrrpGroups.size === 0) {
1084
+ out = '*** No VRRP groups configured ***\n';
1085
+ }
1086
+ return out;
1087
+ }
1088
+ if (showCmd === 'ip' && showArgs[1] === 'nat' && showArgs[2] === 'translations') {
1089
+ let out = 'Pro Inside global Inside local Outside local Outside global\n';
1090
+ for (const rule of this.natRules) {
1091
+ out += `tcp 192.0.2.1:80 192.168.1.10:80 --- ---\n`;
1092
+ }
1093
+ if (this.natRules.length === 0) {
1094
+ out = '*** No NAT translations active ***\n';
1095
+ }
1096
+ return out;
1097
+ }
1098
+ if (showCmd === 'access-lists') {
1099
+ let out = '';
1100
+ for (const [aclId, rules] of this.acls.entries()) {
1101
+ out += `Standard IP access list ${aclId}\n`;
1102
+ rules.forEach((rule, idx) => {
1103
+ out += ` ${(idx + 1) * 10} ${rule}\n`;
1104
+ });
1105
+ }
1106
+ if (this.acls.size === 0) {
1107
+ out = '*** No access lists configured ***\n';
1108
+ }
1109
+ return out;
1110
+ }
1111
+ if (showCmd === 'ntp' && (showArgs[1] === 'status' || showArgs[1] === 'associations')) {
1112
+ if (this.ntpServers.length === 0) {
1113
+ return 'NTP is not enabled.\n';
1114
+ }
1115
+ let out = 'Clock is synchronized, stratum 2, reference is ' + this.ntpServers[0] + '\n';
1116
+ out += 'nominal freq is 250.0000 Hz, actual freq is 250.0000 Hz, precision is 2**24\n';
1117
+ return out;
1118
+ }
1119
+ if (showCmd === 'lldp' && showArgs[1]?.startsWith('ne')) {
1120
+ return `Device ID Local Intf Hold-time Capability Port ID
1121
+ Switch2 Gi0/1 120 S Gi0/1
1122
+ Total entries displayed: 1
1123
+ `;
1124
+ }
1125
+ if (showCmd === 'interfaces' && showArgs[1] === 'status') {
1126
+ return `Port Name Status Vlan Duplex Speed Type
1127
+ Gi0/0 Management Uplink connected routed a-full a-1000 10/100/1000BaseTX
1128
+ Gi0/1 disabled 1 auto auto 10/100/1000BaseTX
1129
+ Gi0/2 disabled 1 auto auto 10/100/1000BaseTX
1130
+ `;
1131
+ }
1132
+ return `% Unrecognized show command: show ${showArgs.join(' ')}`;
1133
+ }
1134
+ if (cmd === 'write' || cmd === 'wr') {
1135
+ return `Building configuration...\n[OK]`;
1136
+ }
1137
+ if (cmd === 'copy' && args[1]?.startsWith('run') && args[2]?.startsWith('sta')) {
1138
+ return `Destination filename [startup-config]? \nBuilding configuration...\n[OK]`;
1139
+ }
1140
+ if (cmd === 'copy' && args[1]?.startsWith('run') && args[2]?.startsWith('flash:')) {
1141
+ const destFile = args[2].replace(/^flash:/i, '');
1142
+ this.pendingCopyDest = destFile || 'backup-agent.cfg';
1143
+ return `Destination filename [${this.pendingCopyDest}]? `;
1144
+ }
1145
+ if (cmd === 'dir' && args[1] === 'flash:') {
1146
+ let out = `Directory of flash:/\n\n`;
1147
+ let index = 1;
1148
+ let totalBytesUsed = 0;
1149
+ out += ` ${index++} -rw- 4414921 Mar 01 1993 00:02:18 +00:00 c2960-lanbasek9-mz.150-2.SE4.bin\n`;
1150
+ totalBytesUsed += 4414921;
1151
+ if (this.flashFiles.has('backup-agent.cfg')) {
1152
+ out += ` ${index++} -rw- 1542 May 31 2026 12:24:17 +00:00 backup-agent.cfg\n`;
1153
+ totalBytesUsed += 1542;
1154
+ }
1155
+ const totalBytes = 32514048;
1156
+ const freeBytes = totalBytes - totalBytesUsed;
1157
+ out += `\n${totalBytes} bytes total (${freeBytes} bytes free)\n`;
1158
+ return out;
1159
+ }
1160
+ if (cmd === 'configure' && args[1] === 'replace' && args[2]?.startsWith('flash:')) {
1161
+ const file = args[2].replace(/^flash:/i, '');
1162
+ if (!this.flashFiles.has(file)) {
1163
+ return `% Error opening flash:${file} (No such file or directory)`;
1164
+ }
1165
+ this.restoreBackupState();
1166
+ return `Total number of passes: 1\nRollback Done\n`;
1167
+ }
1168
+ if (cmd === 'ping' && args[1]) {
1169
+ const ip = args[1];
1170
+ return `Sending 5, 100-byte ICMP Echos to ${ip}, timeout is 2 seconds:
1171
+ !!!!!
1172
+ Success rate is 100 percent (5/5), round-trip min/avg/max = 1/1/4 ms
1173
+ `;
1174
+ }
1175
+ if (cmd === 'test' && args[1] === 'trigger-syslog') {
1176
+ const msgText = args.slice(2).join(' ');
1177
+ BaseDevice_1.simulatorEvents.emit('syslog', msgText);
1178
+ return `[Simulator Test] Triggered syslog: ${msgText}`;
1179
+ }
1180
+ return `% Unrecognized command: ${trimmed}`;
1181
+ }
1182
+ normalizeCommandString(line) {
1183
+ const trimmed = line.trim();
1184
+ if (!trimmed)
1185
+ return '';
1186
+ if (trimmed.toLowerCase().startsWith('do ')) {
1187
+ const rest = trimmed.substring(3);
1188
+ return 'do ' + this.normalizeCommandString(rest);
1189
+ }
1190
+ const parts = trimmed.split(/\s+/);
1191
+ if (parts.length === 0 || !parts[0])
1192
+ return trimmed;
1193
+ let cmd = parts[0].toLowerCase();
1194
+ if (cmd === 'conf' || cmd === 'config' || cmd === 'configure') {
1195
+ parts[0] = 'configure';
1196
+ if (parts[1] && (parts[1].toLowerCase() === 't' || parts[1].toLowerCase() === 'term' || parts[1].toLowerCase() === 'terminal')) {
1197
+ parts[1] = 'terminal';
1198
+ }
1199
+ }
1200
+ else if (cmd === 'int' || cmd === 'inter' || cmd === 'interface') {
1201
+ parts[0] = 'interface';
1202
+ if (parts[1]) {
1203
+ parts[1] = this.normalizeInterfaceName(parts[1]);
1204
+ }
1205
+ }
1206
+ else if (cmd === 'sh' || cmd === 'sho' || cmd === 'show') {
1207
+ parts[0] = 'show';
1208
+ }
1209
+ else if (cmd === 'en' || cmd === 'ena' || cmd === 'enab' || cmd === 'enable') {
1210
+ parts[0] = 'enable';
1211
+ }
1212
+ else if (cmd === 'di' || cmd === 'dis' || cmd === 'disa' || cmd === 'disable') {
1213
+ parts[0] = 'disable';
1214
+ }
1215
+ else if (cmd === 'ex' || cmd === 'exi' || cmd === 'exit') {
1216
+ parts[0] = 'exit';
1217
+ }
1218
+ else if (cmd === 'end') {
1219
+ parts[0] = 'end';
1220
+ }
1221
+ else if (cmd === 'wr' || cmd === 'wri' || cmd === 'write') {
1222
+ parts[0] = 'write';
1223
+ }
1224
+ else if (cmd === 'p' || cmd === 'pi' || cmd === 'pin' || cmd === 'ping') {
1225
+ parts[0] = 'ping';
1226
+ }
1227
+ else if (cmd === 'net' || cmd === 'network') {
1228
+ parts[0] = 'network';
1229
+ }
1230
+ else if (cmd === 'sw' || cmd === 'swit' || cmd === 'switch' || cmd === 'switchport') {
1231
+ parts[0] = 'switchport';
1232
+ }
1233
+ else if (cmd === 'no') {
1234
+ if (parts.length > 1) {
1235
+ const normalizedSub = this.normalizeCommandString(parts.slice(1).join(' '));
1236
+ return 'no ' + normalizedSub;
1237
+ }
1238
+ return trimmed;
1239
+ }
1240
+ cmd = parts[0].toLowerCase();
1241
+ if (cmd === 'show') {
1242
+ if (parts[1]) {
1243
+ const sub = parts[1].toLowerCase();
1244
+ if (sub === 'ru' || sub === 'run' || sub === 'runn' || sub === 'running' || sub === 'running-config') {
1245
+ parts[1] = 'running-config';
1246
+ }
1247
+ else if (sub === 'vl' || sub === 'vla' || sub === 'vlan') {
1248
+ parts[1] = 'vlan';
1249
+ }
1250
+ else if (sub === 'ip') {
1251
+ if (parts[2]) {
1252
+ const sub2 = parts[2].toLowerCase();
1253
+ if (sub2 === 'ro' || sub2 === 'rou' || sub2 === 'rout' || sub2 === 'route') {
1254
+ parts[2] = 'route';
1255
+ }
1256
+ else if (sub2 === 'int' || sub2 === 'inter' || sub2 === 'interface') {
1257
+ parts[2] = 'interface';
1258
+ if (parts[3] && (parts[3].toLowerCase() === 'br' || parts[3].toLowerCase() === 'brief')) {
1259
+ parts[3] = 'brief';
1260
+ }
1261
+ }
1262
+ else if (sub2 === 'ospf') {
1263
+ if (parts[3]) {
1264
+ const sub3 = parts[3].toLowerCase();
1265
+ if (sub3 === 'ne' || sub3 === 'nei' || sub3 === 'neig' || sub3 === 'neigh' || sub3 === 'neighbor') {
1266
+ parts[3] = 'neighbor';
1267
+ }
1268
+ else if (sub3 === 'in' || sub3 === 'int' || sub3 === 'interface') {
1269
+ parts[3] = 'interface';
1270
+ }
1271
+ }
1272
+ }
1273
+ }
1274
+ }
1275
+ }
1276
+ }
1277
+ else if (cmd === 'ip') {
1278
+ if (parts[1]) {
1279
+ const sub = parts[1].toLowerCase();
1280
+ if (sub === 'add' || sub === 'addr' || sub === 'address') {
1281
+ parts[1] = 'address';
1282
+ }
1283
+ else if (sub === 'ro' || sub === 'rou' || sub === 'rout' || sub === 'route') {
1284
+ parts[1] = 'route';
1285
+ }
1286
+ else if (sub === 'routing') {
1287
+ parts[1] = 'routing';
1288
+ }
1289
+ }
1290
+ }
1291
+ else if (cmd === 'router') {
1292
+ if (parts[1]) {
1293
+ const sub = parts[1].toLowerCase();
1294
+ if (sub === 'os' || sub === 'osp' || sub === 'ospf') {
1295
+ parts[1] = 'ospf';
1296
+ }
1297
+ else if (sub === 'ri' || sub === 'rip') {
1298
+ parts[1] = 'rip';
1299
+ }
1300
+ }
1301
+ }
1302
+ else if (cmd === 'shutdown' || cmd === 'shut') {
1303
+ parts[0] = 'shutdown';
1304
+ }
1305
+ else if (cmd === 'description' || cmd === 'desc') {
1306
+ parts[0] = 'description';
1307
+ }
1308
+ else if (cmd === 'switchport') {
1309
+ if (parts[1]) {
1310
+ const sub1 = parts[1].toLowerCase();
1311
+ if (sub1 === 'mo' || sub1 === 'mod' || sub1 === 'mode') {
1312
+ parts[1] = 'mode';
1313
+ if (parts[2]) {
1314
+ const sub2 = parts[2].toLowerCase();
1315
+ if (sub2 === 'ac' || sub2 === 'acc' || sub2 === 'access') {
1316
+ parts[2] = 'access';
1317
+ }
1318
+ else if (sub2 === 'tr' || sub2 === 'tru' || sub2 === 'trun' || sub2 === 'trunk') {
1319
+ parts[2] = 'trunk';
1320
+ }
1321
+ }
1322
+ }
1323
+ else if (sub1 === 'ac' || sub1 === 'acc' || sub1 === 'access') {
1324
+ parts[1] = 'access';
1325
+ if (parts[2]) {
1326
+ const sub2 = parts[2].toLowerCase();
1327
+ if (sub2 === 'vl' || sub2 === 'vla' || sub2 === 'vlan') {
1328
+ parts[2] = 'vlan';
1329
+ }
1330
+ }
1331
+ }
1332
+ else if (sub1 === 'tr' || sub1 === 'tru' || sub1 === 'trun' || sub1 === 'trunk') {
1333
+ parts[1] = 'trunk';
1334
+ if (parts[2]) {
1335
+ const sub2 = parts[2].toLowerCase();
1336
+ if (sub2 === 'al' || sub2 === 'all' || sub2 === 'allow' || sub2 === 'allowed') {
1337
+ parts[2] = 'allowed';
1338
+ if (parts[3] && (parts[3].toLowerCase() === 'vl' || parts[3].toLowerCase() === 'vla' || parts[3].toLowerCase() === 'vlan')) {
1339
+ parts[3] = 'vlan';
1340
+ }
1341
+ }
1342
+ }
1343
+ }
1344
+ }
1345
+ }
1346
+ return parts.join(' ');
1347
+ }
1348
+ normalizeInterfaceName(name) {
1349
+ const lower = name.toLowerCase();
1350
+ if (lower.startsWith('gigabitethernet')) {
1351
+ return 'GigabitEthernet' + name.substring(15);
1352
+ }
1353
+ if (lower.startsWith('gig')) {
1354
+ return 'GigabitEthernet' + name.substring(3);
1355
+ }
1356
+ if (lower.startsWith('gi')) {
1357
+ return 'GigabitEthernet' + name.substring(2);
1358
+ }
1359
+ if (lower.startsWith('loopback')) {
1360
+ return 'Loopback' + name.substring(8);
1361
+ }
1362
+ if (lower.startsWith('lo')) {
1363
+ return 'Loopback' + name.substring(2);
1364
+ }
1365
+ if (lower.startsWith('fastethernet')) {
1366
+ return 'FastEthernet' + name.substring(12);
1367
+ }
1368
+ if (lower.startsWith('fa')) {
1369
+ return 'FastEthernet' + name.substring(2);
1370
+ }
1371
+ if (lower.startsWith('tengigabitethernet')) {
1372
+ return 'TenGigabitEthernet' + name.substring(18);
1373
+ }
1374
+ if (lower.startsWith('ten-gigabitethernet')) {
1375
+ return 'TenGigabitEthernet' + name.substring(19);
1376
+ }
1377
+ if (lower.startsWith('te')) {
1378
+ return 'TenGigabitEthernet' + name.substring(2);
1379
+ }
1380
+ if (lower.startsWith('vlan')) {
1381
+ return 'Vlan' + name.substring(4);
1382
+ }
1383
+ if (lower.startsWith('vl')) {
1384
+ return 'Vlan' + name.substring(2);
1385
+ }
1386
+ if (lower.startsWith('ethernet')) {
1387
+ return 'Ethernet' + name.substring(8);
1388
+ }
1389
+ if (lower.startsWith('eth')) {
1390
+ return 'Ethernet' + name.substring(3);
1391
+ }
1392
+ if (lower.startsWith('port-channel')) {
1393
+ return 'Port-channel' + name.substring(12);
1394
+ }
1395
+ if (lower.startsWith('po')) {
1396
+ return 'Port-channel' + name.substring(2);
1397
+ }
1398
+ if (lower.startsWith('nve')) {
1399
+ return 'Nve' + name.substring(3);
1400
+ }
1401
+ return name;
1402
+ }
1403
+ shortenInterfaceName(name) {
1404
+ return name
1405
+ .replace('GigabitEthernet', 'Gi')
1406
+ .replace('FastEthernet', 'Fa')
1407
+ .replace('TenGigabitEthernet', 'Te')
1408
+ .replace('Loopback', 'Lo')
1409
+ .replace('Ethernet', 'Eth')
1410
+ .replace('Port-channel', 'Po');
1411
+ }
1412
+ getPrefixLength(mask) {
1413
+ const parts = mask.split('.').map(Number);
1414
+ let len = 0;
1415
+ for (const p of parts) {
1416
+ let b = p;
1417
+ while (b > 0) {
1418
+ if (b & 1)
1419
+ len++;
1420
+ b = b >> 1;
1421
+ }
1422
+ }
1423
+ return len;
1424
+ }
1425
+ calculateNetwork(ip, mask) {
1426
+ const ipParts = ip.split('.').map(Number);
1427
+ const maskParts = mask.split('.').map(Number);
1428
+ const netParts = ipParts.map((p, i) => p & maskParts[i]);
1429
+ return netParts.join('.');
1430
+ }
1431
+ wildcardToSubnet(wildcard) {
1432
+ return wildcard.split('.').map(p => (255 - parseInt(p, 10)).toString()).join('.');
1433
+ }
1434
+ getContextHelp(line) {
1435
+ const trimmed = line.trim();
1436
+ const endsWithSpaceHelp = line.endsWith(' ?') || line.endsWith(' ?');
1437
+ const searchPrefix = trimmed.substring(0, trimmed.length - 1).trim();
1438
+ const normalizedPrefix = this.normalizeCommandString(searchPrefix);
1439
+ const parts = normalizedPrefix.split(/\s+/).filter(Boolean);
1440
+ if (parts.length === 0) {
1441
+ return this.getModeCommandsHelp();
1442
+ }
1443
+ if (!endsWithSpaceHelp) {
1444
+ const lastWord = parts[parts.length - 1].toLowerCase();
1445
+ const precedingPrefix = parts.slice(0, -1).join(' ');
1446
+ return this.getWordCompletionHelp(precedingPrefix, lastWord);
1447
+ }
1448
+ const cmd = parts[0].toLowerCase();
1449
+ if (cmd === 'show') {
1450
+ if (parts.length === 1) {
1451
+ return ` running-config Current operating configuration
1452
+ ip IP information
1453
+ vlan VLAN status
1454
+ version System hardware and software status
1455
+ cdp Discovery Protocol neighbors`;
1456
+ }
1457
+ if (parts[1]?.toLowerCase() === 'ip') {
1458
+ if (parts.length === 2) {
1459
+ return ` interface IP interface status and configuration
1460
+ route IP routing table
1461
+ protocols Active IP routing protocols`;
1462
+ }
1463
+ if (parts[2]?.toLowerCase() === 'interface') {
1464
+ return ` brief Brief summary of IP status and configuration`;
1465
+ }
1466
+ }
1467
+ }
1468
+ else if (cmd === 'ip') {
1469
+ if (parts.length === 1) {
1470
+ return ` address Configure interface IP address
1471
+ route Configure static IP route
1472
+ routing Enable IP routing`;
1473
+ }
1474
+ }
1475
+ else if (cmd === 'interface') {
1476
+ if (parts.length === 1) {
1477
+ return ` GigabitEthernet GigabitEthernet IEEE 802.3z
1478
+ FastEthernet FastEthernet IEEE 802.3
1479
+ Loopback Loopback interface
1480
+ Vlan Vlan interface`;
1481
+ }
1482
+ }
1483
+ else if (cmd === 'switchport') {
1484
+ if (parts.length === 1) {
1485
+ return ` mode Set trunking mode of the interface
1486
+ access Set access mode characteristics`;
1487
+ }
1488
+ if (parts[1]?.toLowerCase() === 'mode') {
1489
+ return ` access Set port to Access mode
1490
+ trunk Set port to Trunking mode`;
1491
+ }
1492
+ if (parts[1]?.toLowerCase() === 'access') {
1493
+ return ` vlan Set access VLAN`;
1494
+ }
1495
+ }
1496
+ else if (cmd === 'no') {
1497
+ if (parts.length === 1) {
1498
+ return ` shutdown Enable the interface
1499
+ ip Remove IP configuration
1500
+ description Remove interface description`;
1501
+ }
1502
+ }
1503
+ return `% No help available for command: "${normalizedPrefix} ?"`;
1504
+ }
1505
+ getModeCommandsHelp() {
1506
+ switch (this.mode) {
1507
+ case 'USER_EXEC':
1508
+ return ` enable Turn on privileged commands
1509
+ show Show running system information
1510
+ ping Send echo messages`;
1511
+ case 'PRIVILEGED_EXEC':
1512
+ return ` configure Enter configuration mode
1513
+ show Show running system information
1514
+ write Write running configuration to memory
1515
+ copy Copy configuration files
1516
+ ping Send echo messages
1517
+ disable Turn off privileged commands`;
1518
+ case 'GLOBAL_CONFIG':
1519
+ return ` hostname Set system network name
1520
+ interface Configure an interface
1521
+ ip Global IP configuration commands
1522
+ router Enable routing protocol
1523
+ vlan Configure VLAN parameters
1524
+ end Exit configuration mode
1525
+ exit Exit configuration mode`;
1526
+ case 'INTERFACE_CONFIG':
1527
+ return ` ip Interface IP configuration commands
1528
+ shutdown Shutdown the selected interface
1529
+ description Set interface description
1530
+ switchport Set interface switchport parameters
1531
+ exit Exit interface configuration mode`;
1532
+ default:
1533
+ return ` exit Exit current configuration mode
1534
+ end Exit to privileged exec mode`;
1535
+ }
1536
+ }
1537
+ getWordCompletionHelp(precedingPrefix, lastWord) {
1538
+ const allCommands = this.getModeCommandsList();
1539
+ const matches = allCommands.filter(c => c.startsWith(lastWord));
1540
+ if (matches.length > 0) {
1541
+ return matches.map(m => ` ${m}`).join('\n');
1542
+ }
1543
+ return `% No command matches prefix: "${lastWord}"`;
1544
+ }
1545
+ getModeCommandsList() {
1546
+ switch (this.mode) {
1547
+ case 'USER_EXEC':
1548
+ return ['enable', 'show', 'ping', 'exit'];
1549
+ case 'PRIVILEGED_EXEC':
1550
+ return ['configure', 'show', 'write', 'copy', 'ping', 'disable', 'exit'];
1551
+ case 'GLOBAL_CONFIG':
1552
+ return ['hostname', 'interface', 'ip', 'router', 'vlan', 'end', 'exit'];
1553
+ case 'INTERFACE_CONFIG':
1554
+ return ['ip', 'shutdown', 'description', 'switchport', 'exit', 'end'];
1555
+ default:
1556
+ return ['exit', 'end'];
1557
+ }
1558
+ }
1559
+ }
1560
+ exports.IOSDevice = IOSDevice;
1561
+ //# sourceMappingURL=IOSDevice.js.map