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,93 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BOOT_BANNER = void 0;
4
+ exports.BOOT_BANNER = `
5
+ Initializing Hardware ...
6
+
7
+ System integrity status: 00000610
8
+ Rom image verified correctly
9
+
10
+
11
+ System Bootstrap, Version 15.4(3r)S5, RELEASE SOFTWARE
12
+ Copyright (c) 1994-2015 by cisco Systems, Inc.
13
+
14
+ Current image running: Boot ROM0
15
+
16
+ Last reset cause: LocalSoft
17
+ Cisco ISR4321/K9 platform with 4194304 Kbytes of main memory
18
+
19
+
20
+
21
+ no valid BOOT image found
22
+ Final autoboot attempt from default boot device...
23
+ File size is 0x1d0580a0
24
+ Located isr4300-universalk9.03.16.05.S.155-3.S5-ext.SPA.bin
25
+ Image size 486899872 inode num 12, bks cnt 102567 blk size 8*512
26
+ ##########################################################################################################################
27
+ Boot image size = 486899872 (0x1d0580a0) bytes
28
+
29
+ Package header rev 1 structure detected
30
+ Calculating SHA-1 hash...done
31
+ validate_package: SHA-1 hash:
32
+ calculated 83acd4f8:dc03c892:f243621c:06872286:6c9f0cf5
33
+ expected 83acd4f8:dc03c892:f243621c:06872286:6c9f0cf5
34
+
35
+ RSA Signed RELEASE Image Signature Verification Successful.
36
+ Package Load Test Latency : 6390 msec
37
+ Image validated
38
+ %IOSXEBOOT-4-BOOT_SRC: (rp/0): mounting /boot/super.iso to /tmp/sw/isos
39
+
40
+ Restricted Rights Legend
41
+ Use, duplication, or disclosure by the Government is
42
+ subject to restrictions as set forth in subparagraph
43
+ (c) of the Commercial Computer Software - Restricted
44
+ Rights clause at FAR sec. 52.227-19 and subparagraph
45
+ (c) (1) (ii) of the Rights in Technical Data and Computer
46
+ Software clause at DFARS sec. 252.227-7013.
47
+ cisco Systems, Inc.
48
+ 170 West Tasman Drive
49
+ San Jose, California 95134-1706
50
+
51
+ Cisco IOS Software, ISR Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 15.5(3)S5, RELEASE SOFTWARE (fc2)
52
+ Technical Support: http://www.cisco.com/techsupport
53
+ Copyright (c) 1986-2017 by Cisco Systems, Inc.
54
+ Compiled Thu 19-Jan-17 11:24 by mcpre
55
+
56
+
57
+
58
+ Cisco IOS - XE software, Copyright(c) 2005 - 2017 by cisco Systems, Inc.
59
+ All rights reserved.Certain components of Cisco IOS - XE software are
60
+ licensed under the GNU General Public License("GPL") Version 2.0.The
61
+ software code licensed under GPL Version 2.0 is free software that comes
62
+ with ABSOLUTELY NO WARRANTY.You can redistribute and / or modify such
63
+ GPL code under the terms of GPL Version 2.0.For more details, see the
64
+ documentation or "License Notice" file accompanying the IOS - XE software,
65
+ or the applicable URL provided on the flyer accompanying the IOS - XE
66
+ software.
67
+
68
+
69
+
70
+ This product contains cryptographic features and is subject to United
71
+ States and local country laws governing import, export, transfer and
72
+ use. Delivery of Cisco cryptographic products does not imply
73
+ third-party authority to import, export, distribute or use encryption.
74
+ Importers, exporters, distributors and users are responsible for
75
+ compliance with U.S. and local country laws. By using this product you
76
+ agree to comply with applicable laws and regulations. If you are unable
77
+ to comply with U.S. and local laws, return this product immediately.
78
+
79
+ A summary of U.S. laws governing Cisco cryptographic products may be found at:
80
+ http://www.cisco.com/wwl/export/crypto/tool/stqrg.html
81
+
82
+ If you require further assistance please contact us by sending email to
83
+ export@cisco.com.
84
+
85
+ cisco ISR4321/K9 (1RU) processor with 1687137K/6147K bytes of memory.
86
+ Processor board ID FLM2041W2HD
87
+ 2 Gigabit Ethernet interfaces
88
+ 32768K bytes of non-volatile configuration memory.
89
+ 4194304K bytes of physical memory.
90
+ 3223551K bytes of flash memory at bootflash:.
91
+
92
+ `;
93
+ //# sourceMappingURL=bootBanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootBanner.js","sourceRoot":"","sources":["../../src/shared/bootBanner.ts"],"names":[],"mappings":";;;AAAa,QAAA,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwF1B,CAAC"}
@@ -14,7 +14,7 @@ exports.IOS_ERROR_PATTERNS = [
14
14
  { type: 'CommandRejected', regex: /% Command rejected/i },
15
15
  { type: 'AccessDenied', regex: /% Permission denied/i }
16
16
  ];
17
- exports.PROMPT_REGEX = /(?:^|[\r\n])\s*([A-Za-z0-9_\-@\.:\(\)/\\\[]+(?:>|#|\$|\]))\s*$/;
17
+ exports.PROMPT_REGEX = /(?:^|[\r\n])\s*([A-Za-z0-9_\-@\.:\(\)/\\\[]+\s*(?:>|#|\$|\]))\s*$/;
18
18
  exports.MORE_REGEX = /(?:--\s*More\s*--|---\s*\(more\)\s*---|---- More ----|Press any key to continue|Press SPACE to continue)/i;
19
19
  exports.DEFAULT_PROTECTED_INTERFACES = [
20
20
  'GigabitEthernet0/0',
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/shared/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,kBAAkB,GAAG;IAC9B,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,aAAa;IACpD,aAAa,EAAE,iBAAiB,EAAE,oBAAoB;CACzD,CAAC;AAEW,QAAA,kBAAkB,GAAG;IAC9B,EAAE,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,sBAAsB,EAAE;IAC3D,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE,uBAAuB,EAAE;IAC7D,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,8BAA8B,EAAE;IAC/D,EAAE,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE,yBAAyB,EAAE;IAC5D,EAAE,IAAI,EAAE,uBAAuB,EAAE,KAAK,EAAE,4BAA4B,EAAE;IACtE,EAAE,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,qBAAqB,EAAE;IACzD,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,sBAAsB,EAAE;CAC1D,CAAC;AAGW,QAAA,YAAY,GAAG,gEAAgE,CAAC;AAGhF,QAAA,UAAU,GAAG,2GAA2G,CAAC;AAIzH,QAAA,4BAA4B,GAAG;IACxC,oBAAoB;IACpB,oBAAoB;IACpB,oBAAoB;IACpB,OAAO;CACV,CAAC"}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/shared/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,kBAAkB,GAAG;IAC9B,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,aAAa;IACpD,aAAa,EAAE,iBAAiB,EAAE,oBAAoB;CACzD,CAAC;AAEW,QAAA,kBAAkB,GAAG;IAC9B,EAAE,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,sBAAsB,EAAE;IAC3D,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE,uBAAuB,EAAE;IAC7D,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,8BAA8B,EAAE;IAC/D,EAAE,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE,yBAAyB,EAAE;IAC5D,EAAE,IAAI,EAAE,uBAAuB,EAAE,KAAK,EAAE,4BAA4B,EAAE;IACtE,EAAE,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,qBAAqB,EAAE;IACzD,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,sBAAsB,EAAE;CAC1D,CAAC;AAGW,QAAA,YAAY,GAAG,mEAAmE,CAAC;AAGnF,QAAA,UAAU,GAAG,2GAA2G,CAAC;AAIzH,QAAA,4BAA4B,GAAG;IACxC,oBAAoB;IACpB,oBAAoB;IACpB,oBAAoB;IACpB,OAAO;CACV,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ciscollm-cli",
3
- "version": "1.3.3",
3
+ "version": "1.3.5",
4
4
  "description": "Cisco IOS automation agent CLI with mock simulation, guardrails, and LLM tool-calling support.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -1 +0,0 @@
1
- export declare function dashboardAction(options: any): void;
@@ -1,16 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.dashboardAction = dashboardAction;
7
- const chalk_1 = __importDefault(require("chalk"));
8
- const MultiAgentCoordinator_1 = require("../../core/agent/MultiAgentCoordinator");
9
- const dashboard_1 = require("../../server/dashboard");
10
- function dashboardAction(options) {
11
- const port = parseInt(options.port, 10);
12
- const coordinator = new MultiAgentCoordinator_1.MultiAgentCoordinator();
13
- (0, dashboard_1.startDashboardServer)(coordinator, port);
14
- console.log(chalk_1.default.yellow('Standalone mode: Visualizing historical records and active topology when connected.'));
15
- }
16
- //# sourceMappingURL=dashboardCommand.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"dashboardCommand.js","sourceRoot":"","sources":["../../../src/cli/commands/dashboardCommand.ts"],"names":[],"mappings":";;;;;AAIA,0CAKC;AATD,kDAA0B;AAC1B,kFAA+E;AAC/E,sDAA8D;AAE9D,SAAgB,eAAe,CAAC,OAAY;IACxC,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACxC,MAAM,WAAW,GAAG,IAAI,6CAAqB,EAAE,CAAC;IAChD,IAAA,gCAAoB,EAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IACxC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,MAAM,CAAC,qFAAqF,CAAC,CAAC,CAAC;AACrH,CAAC"}
@@ -1 +0,0 @@
1
- export declare function shellAction(): void;
@@ -1,44 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.shellAction = shellAction;
7
- const readline_1 = __importDefault(require("readline"));
8
- const chalk_1 = __importDefault(require("chalk"));
9
- const shell_simulator_1 = require("../../server/shell-simulator");
10
- function shellAction() {
11
- const simulator = new shell_simulator_1.ShellSimulator();
12
- console.clear();
13
- console.log(chalk_1.default.bold.yellow('============================================================'));
14
- console.log(chalk_1.default.bold.yellow(' Cisco IOS Interactive Mock Shell Simulator (v1.1.0)'));
15
- console.log(chalk_1.default.bold.yellow('============================================================'));
16
- const welcomeBanner = `\r\nCisco IOS Software, C2960 Software (C2960-LANBASEK9-M), Version 15.0(2)SE4, RELEASE SOFTWARE (fc1)\r\nTechnical Support: http://www.cisco.com/techsupport\r\nCopyright (c) 1986-2013 by Cisco Systems, Inc.\r\nCompiled Wed 26-Jun-13 02:49 by prod_rel_team\r\n\r\n`;
17
- console.log(welcomeBanner);
18
- const rl = readline_1.default.createInterface({ input: process.stdin, output: process.stdout });
19
- const promptUser = () => {
20
- rl.question(simulator.getPrompt(), (line) => {
21
- const cmd = line.trim();
22
- if (cmd.toLowerCase() === 'exit' && simulator.mode === 'USER_EXEC') {
23
- console.log('Connection closed by foreign host.');
24
- rl.close();
25
- return;
26
- }
27
- try {
28
- const output = simulator.execute(cmd);
29
- if (output) {
30
- console.log(output);
31
- }
32
- }
33
- catch (err) {
34
- console.log(`% Error: ${err.message}`);
35
- }
36
- promptUser();
37
- });
38
- };
39
- promptUser();
40
- rl.on('close', () => {
41
- process.exit(0);
42
- });
43
- }
44
- //# sourceMappingURL=shellCommand.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"shellCommand.js","sourceRoot":"","sources":["../../../src/cli/commands/shellCommand.ts"],"names":[],"mappings":";;;;;AAIA,kCAsCC;AA1CD,wDAAgC;AAChC,kDAA0B;AAC1B,kEAA8D;AAE9D,SAAgB,WAAW;IACvB,MAAM,SAAS,GAAG,IAAI,gCAAc,EAAE,CAAC;IAEvC,OAAO,CAAC,KAAK,EAAE,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,MAAM,CAAC,8DAA8D,CAAC,CAAC,CAAC;IAC/F,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,MAAM,CAAC,wDAAwD,CAAC,CAAC,CAAC;IACzF,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,MAAM,CAAC,8DAA8D,CAAC,CAAC,CAAC;IAC/F,MAAM,aAAa,GAAG,0QAA0Q,CAAC;IACjS,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAE3B,MAAM,EAAE,GAAG,kBAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAEtF,MAAM,UAAU,GAAG,GAAG,EAAE;QACpB,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,CAAC,IAAY,EAAE,EAAE;YAChD,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YACxB,IAAI,GAAG,CAAC,WAAW,EAAE,KAAK,MAAM,IAAI,SAAS,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;gBACjE,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;gBAClD,EAAE,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO;YACX,CAAC;YAED,IAAI,CAAC;gBACD,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBACtC,IAAI,MAAM,EAAE,CAAC;oBACT,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBACxB,CAAC;YACL,CAAC;YAAC,OAAO,GAAQ,EAAE,CAAC;gBAChB,OAAO,CAAC,GAAG,CAAC,YAAY,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YAC3C,CAAC;YACD,UAAU,EAAE,CAAC;QACjB,CAAC,CAAC,CAAC;IACP,CAAC,CAAC;IAEF,UAAU,EAAE,CAAC;IAEb,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;QAChB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -1,26 +0,0 @@
1
- import { BaseSession } from './BaseSession';
2
- export declare class CmlSession extends BaseSession {
3
- private apiUrl;
4
- private username?;
5
- private password?;
6
- private token;
7
- private activeLabId;
8
- private ownedLab;
9
- private activeNode;
10
- private sshClient;
11
- private sshStream;
12
- constructor(apiUrl: string, username?: string | undefined, password?: string | undefined);
13
- private request;
14
- connect(): Promise<void>;
15
- private provisionNode;
16
- private waitForNodeBoot;
17
- private findBestRunningNode;
18
- private openSsh;
19
- execute(command: string, timeoutMs?: number): Promise<string>;
20
- private execViaSsh;
21
- private getCmlStatus;
22
- private listLabs;
23
- private switchNode;
24
- private getTopology;
25
- disconnect(): Promise<void>;
26
- }
@@ -1,448 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.CmlSession = void 0;
40
- const BaseSession_1 = require("./BaseSession");
41
- const chalk_1 = __importDefault(require("chalk"));
42
- const https = __importStar(require("https"));
43
- const net = __importStar(require("net"));
44
- const PREFERRED_NODE_DEFS = ['iosv', 'iol-xe', 'csr1000v', 'cat8000v', 'iosxrv9000'];
45
- const NODE_BOOT_TIMEOUT_MS = 5 * 60 * 1000;
46
- const NODE_BOOT_POLL_MS = 8000;
47
- class CmlSession extends BaseSession_1.BaseSession {
48
- apiUrl;
49
- username;
50
- password;
51
- token = null;
52
- activeLabId = null;
53
- ownedLab = false;
54
- activeNode = null;
55
- sshClient = null;
56
- sshStream = null;
57
- constructor(apiUrl, username, password) {
58
- super();
59
- this.apiUrl = apiUrl;
60
- this.username = username;
61
- this.password = password;
62
- this.state = {
63
- currentMode: 'PRIVILEGED_EXEC',
64
- hostname: 'cml-sandbox',
65
- prompt: 'cml-sandbox#'
66
- };
67
- }
68
- async request(method, path, body) {
69
- const base = this.apiUrl.replace(/\/$/, '');
70
- const url = new URL(`${base}/api/v0${path}`);
71
- return new Promise((resolve, reject) => {
72
- const payload = body ? JSON.stringify(body) : undefined;
73
- const headers = {
74
- 'Content-Type': 'application/json',
75
- 'Accept': 'application/json'
76
- };
77
- if (this.token)
78
- headers['Authorization'] = `Bearer ${this.token}`;
79
- if (payload)
80
- headers['Content-Length'] = Buffer.byteLength(payload).toString();
81
- const opts = {
82
- hostname: url.hostname,
83
- port: Number(url.port) || 443,
84
- path: url.pathname + url.search,
85
- method,
86
- headers,
87
- rejectUnauthorized: true
88
- };
89
- const req = https.request(opts, (res) => {
90
- let data = '';
91
- res.on('data', (c) => (data += c));
92
- res.on('end', () => {
93
- if (res.statusCode && res.statusCode >= 400) {
94
- return reject(new Error(`CML API Error ${res.statusCode} on ${method} ${path}: ${data}`));
95
- }
96
- try {
97
- resolve(data ? JSON.parse(data) : {});
98
- }
99
- catch {
100
- resolve(data);
101
- }
102
- });
103
- });
104
- req.on('error', (e) => reject(e));
105
- if (payload)
106
- req.write(payload);
107
- req.end();
108
- });
109
- }
110
- async connect() {
111
- const base = this.apiUrl.replace(/\/$/, '');
112
- console.log(chalk_1.default.cyan(`❯ Connecting to Cisco Modeling Labs at ${chalk_1.default.bold(base)}...`));
113
- const raw = await this.request('POST', '/authenticate', {
114
- username: this.username || 'admin',
115
- password: this.password || ''
116
- });
117
- this.token = typeof raw === 'string' ? raw : raw.token || String(raw);
118
- console.log(chalk_1.default.green(`[+] Authenticated as ${chalk_1.default.bold(this.username || 'admin')}`));
119
- console.log(chalk_1.default.cyan(`❯ Scanning CML for running labs and nodes...`));
120
- const labIds = await this.request('GET', '/labs');
121
- const runningNode = await this.findBestRunningNode(labIds || []);
122
- if (runningNode) {
123
- this.activeNode = runningNode;
124
- this.activeLabId = runningNode.labId;
125
- this.ownedLab = false;
126
- this.state.hostname = runningNode.label;
127
- this.state.prompt = `${runningNode.label}#`;
128
- console.log(chalk_1.default.green(`[+] Found running node: ${chalk_1.default.bold(runningNode.label)} ` +
129
- `[${runningNode.nodeDefinition}] in lab "${runningNode.labTitle}"`));
130
- if (runningNode.mgmtIp) {
131
- try {
132
- await this.openSsh(runningNode.mgmtIp, runningNode.mgmtPort || 22);
133
- console.log(chalk_1.default.green(`[+] SSH reachable at ${runningNode.label} (${runningNode.mgmtIp})`));
134
- }
135
- catch {
136
- this.sshStream = null;
137
- }
138
- }
139
- }
140
- else {
141
- const node = await this.provisionNode();
142
- this.activeNode = node;
143
- }
144
- }
145
- async provisionNode() {
146
- console.log(chalk_1.default.cyan(`❯ No running nodes found — provisioning a new Cisco node on CML...`));
147
- const availDefs = await this.request('GET', '/simplified_node_definitions').catch(() => []);
148
- const defIds = (availDefs || []).map((d) => d.id);
149
- const chosenDef = PREFERRED_NODE_DEFS.find(d => defIds.includes(d)) || defIds[0];
150
- if (!chosenDef) {
151
- throw new Error('No node definitions available on this CML server.');
152
- }
153
- console.log(chalk_1.default.cyan(`❯ Creating sandbox lab with node type: ${chalk_1.default.bold(chosenDef)}...`));
154
- const labRes = await this.request('POST', '/labs', {
155
- title: `ciscollm-${chosenDef}-${Date.now()}`,
156
- description: 'Auto-provisioned by ciscollm-cli.'
157
- });
158
- this.activeLabId = labRes.id;
159
- this.ownedLab = true;
160
- const nodeRes = await this.request('POST', `/labs/${this.activeLabId}/nodes`, {
161
- label: `${chosenDef}-0`,
162
- node_definition: chosenDef,
163
- x: 0,
164
- y: 0
165
- });
166
- const nodeId = nodeRes.id;
167
- console.log(chalk_1.default.cyan(`❯ Starting lab ${this.activeLabId}...`));
168
- await this.request('PUT', `/labs/${this.activeLabId}/start`);
169
- const node = await this.waitForNodeBoot(this.activeLabId, nodeId, chosenDef);
170
- console.log(chalk_1.default.green(`[+] Node ${chalk_1.default.bold(node.label)} is ${chalk_1.default.bold(node.state)} and ready.`));
171
- return node;
172
- }
173
- async waitForNodeBoot(labId, nodeId, defId) {
174
- const deadline = Date.now() + NODE_BOOT_TIMEOUT_MS;
175
- let dots = 0;
176
- process.stdout.write(chalk_1.default.cyan(`❯ Waiting for node to boot`));
177
- while (Date.now() < deadline) {
178
- const node = await this.request('GET', `/labs/${labId}/nodes/${nodeId}`);
179
- const state = node.state || '';
180
- if (state === 'BOOTED') {
181
- process.stdout.write(`\n`);
182
- const lab = await this.request('GET', `/labs/${labId}`);
183
- const cmlNode = {
184
- id: nodeId,
185
- label: node.label || defId,
186
- state,
187
- nodeDefinition: defId,
188
- labId,
189
- labTitle: lab.title || labId
190
- };
191
- this.state.hostname = cmlNode.label;
192
- this.state.prompt = `${cmlNode.label}#`;
193
- return cmlNode;
194
- }
195
- dots++;
196
- process.stdout.write(chalk_1.default.dim('.'));
197
- await new Promise(r => setTimeout(r, NODE_BOOT_POLL_MS));
198
- }
199
- process.stdout.write(`\n`);
200
- throw new Error(`Node did not reach BOOTED state within ${NODE_BOOT_TIMEOUT_MS / 60000} minutes.`);
201
- }
202
- async findBestRunningNode(labIds) {
203
- const candidates = [];
204
- for (const labId of labIds) {
205
- try {
206
- const lab = await this.request('GET', `/labs/${labId}`);
207
- if (!lab || lab.state === 'STOPPED')
208
- continue;
209
- const nodeIds = await this.request('GET', `/labs/${labId}/nodes`);
210
- if (!nodeIds || nodeIds.length === 0)
211
- continue;
212
- for (const nodeId of nodeIds) {
213
- try {
214
- const node = await this.request('GET', `/labs/${labId}/nodes/${nodeId}`);
215
- if (!node || node.state === 'STOPPED' || node.state === 'DEFINED_ON_CORE') {
216
- continue;
217
- }
218
- const candidate = {
219
- id: nodeId,
220
- label: node.label || nodeId,
221
- state: node.state || 'UNKNOWN',
222
- nodeDefinition: node.node_definition || 'unknown',
223
- labId,
224
- labTitle: lab.title || labId
225
- };
226
- try {
227
- const l3 = await this.request('GET', `/labs/${labId}/nodes/${nodeId}/layer3_addresses`);
228
- if (l3 && typeof l3 === 'object') {
229
- const addresses = Object.values(l3);
230
- for (const iface of addresses) {
231
- if (iface?.ip4 && iface.ip4.length > 0) {
232
- const ip = iface.ip4[0].split('/')[0];
233
- candidate.mgmtIp = ip;
234
- break;
235
- }
236
- }
237
- }
238
- }
239
- catch { }
240
- candidates.push(candidate);
241
- }
242
- catch { }
243
- }
244
- }
245
- catch { }
246
- }
247
- if (candidates.length === 0)
248
- return null;
249
- const sorted = candidates.sort((a, b) => {
250
- const stateScore = (s) => s === 'BOOTED' ? 3 : s === 'STARTED' ? 2 : s === 'DEFINED_ON_CORE' ? 1 : 0;
251
- const sd = stateScore(b.state) - stateScore(a.state);
252
- if (sd !== 0)
253
- return sd;
254
- return (b.mgmtIp ? 1 : 0) - (a.mgmtIp ? 1 : 0);
255
- });
256
- return sorted[0];
257
- }
258
- openSsh(host, port) {
259
- return new Promise((resolve, reject) => {
260
- const socket = new net.Socket();
261
- const timeout = setTimeout(() => {
262
- socket.destroy();
263
- reject(new Error(`TCP connection to ${host}:${port} timed out`));
264
- }, 4000);
265
- socket.connect(port, host, () => {
266
- clearTimeout(timeout);
267
- socket.destroy();
268
- resolve();
269
- });
270
- socket.on('error', (e) => {
271
- clearTimeout(timeout);
272
- reject(e);
273
- });
274
- });
275
- }
276
- async execute(command, timeoutMs = 8000) {
277
- const lower = command.toLowerCase().trim();
278
- if (lower === 'cml-status' || lower === 'cml status') {
279
- return this.getCmlStatus();
280
- }
281
- if (lower === 'cml-labs' || lower === 'cml labs') {
282
- return this.listLabs();
283
- }
284
- if (lower.startsWith('cml-node ') || lower.startsWith('cml node ')) {
285
- const nodeLabel = command.split(' ').slice(1).join(' ');
286
- return this.switchNode(nodeLabel);
287
- }
288
- if (lower === 'cml-topology' || lower === 'cml topology') {
289
- return this.getTopology();
290
- }
291
- const prompt = this.state.prompt || `${this.state.hostname}#`;
292
- console.log(`${chalk_1.default.blue('❯')} ${chalk_1.default.bold.yellow(prompt)} ${chalk_1.default.white(command)}`);
293
- if (this.activeNode?.mgmtIp && this.sshStream === null) {
294
- try {
295
- const output = await this.execViaSsh(this.activeNode.mgmtIp, this.activeNode.mgmtPort || 22, command, timeoutMs);
296
- if (output)
297
- return output;
298
- }
299
- catch (e) {
300
- console.log(chalk_1.default.dim(` [SSH fallback: ${e.message}]`));
301
- }
302
- }
303
- if (this.activeLabId && this.activeNode) {
304
- try {
305
- const log = await this.request('GET', `/labs/${this.activeLabId}/nodes/${this.activeNode.id}/consoles/0/log`);
306
- const lines = (log || '').trim().split('\n');
307
- return lines.slice(-30).join('\n') || '';
308
- }
309
- catch {
310
- return '';
311
- }
312
- }
313
- return '';
314
- }
315
- execViaSsh(host, port, command, timeoutMs) {
316
- return new Promise((resolve, reject) => {
317
- const { spawn } = require('child_process');
318
- const args = [
319
- '-o', 'StrictHostKeyChecking=no',
320
- '-o', 'UserKnownHostsFile=/dev/null',
321
- '-o', `ConnectTimeout=${Math.ceil(timeoutMs / 1000)}`,
322
- '-p', String(port),
323
- `${this.username || 'admin'}@${host}`,
324
- command
325
- ];
326
- const proc = spawn('ssh', args, { env: process.env });
327
- let out = '';
328
- let err = '';
329
- proc.stdout.on('data', (d) => { out += d.toString(); });
330
- proc.stderr.on('data', (d) => { err += d.toString(); });
331
- const timer = setTimeout(() => {
332
- proc.kill();
333
- resolve(out || '');
334
- }, timeoutMs);
335
- proc.on('close', () => {
336
- clearTimeout(timer);
337
- if (out)
338
- resolve(out);
339
- else if (err && !err.includes('Warning:'))
340
- reject(new Error(err.trim()));
341
- else
342
- resolve('');
343
- });
344
- });
345
- }
346
- async getCmlStatus() {
347
- if (!this.activeLabId) {
348
- return JSON.stringify({ status: 'not_connected', mode: 'config-only' });
349
- }
350
- try {
351
- const lab = await this.request('GET', `/labs/${this.activeLabId}`);
352
- const stats = await this.request('GET', `/labs/${this.activeLabId}/simulation_stats`).catch(() => null);
353
- return JSON.stringify({
354
- status: lab.state,
355
- lab_id: this.activeLabId,
356
- title: lab.title,
357
- node: this.activeNode
358
- ? { id: this.activeNode.id, label: this.activeNode.label, state: this.activeNode.state }
359
- : null,
360
- stats
361
- }, null, 2);
362
- }
363
- catch (e) {
364
- return JSON.stringify({ error: e.message });
365
- }
366
- }
367
- async listLabs() {
368
- try {
369
- const labIds = await this.request('GET', '/labs');
370
- const details = await Promise.all((labIds || []).map(async (id) => {
371
- try {
372
- const lab = await this.request('GET', `/labs/${id}`);
373
- const nodes = await this.request('GET', `/labs/${id}/nodes`);
374
- return { id, title: lab.title, state: lab.state, nodeCount: (nodes || []).length };
375
- }
376
- catch {
377
- return { id, error: 'fetch_failed' };
378
- }
379
- }));
380
- return JSON.stringify(details, null, 2);
381
- }
382
- catch (e) {
383
- return JSON.stringify({ error: e.message });
384
- }
385
- }
386
- async switchNode(label) {
387
- if (!this.activeLabId)
388
- return JSON.stringify({ error: 'no_lab_connected' });
389
- try {
390
- const result = await this.request('GET', `/labs/${this.activeLabId}/find/node/label/${encodeURIComponent(label)}`);
391
- if (result && result.node_id) {
392
- const node = await this.request('GET', `/labs/${this.activeLabId}/nodes/${result.node_id}`);
393
- this.activeNode = {
394
- id: result.node_id,
395
- label: node.label,
396
- state: node.state,
397
- nodeDefinition: node.node_definition,
398
- labId: this.activeLabId,
399
- labTitle: ''
400
- };
401
- this.state.hostname = node.label;
402
- this.state.prompt = `${node.label}#`;
403
- return JSON.stringify({ switched_to: node.label, node_id: result.node_id });
404
- }
405
- return JSON.stringify({ error: `Node "${label}" not found` });
406
- }
407
- catch (e) {
408
- return JSON.stringify({ error: e.message });
409
- }
410
- }
411
- async getTopology() {
412
- if (!this.activeLabId)
413
- return JSON.stringify({ error: 'no_lab_connected' });
414
- try {
415
- const topology = await this.request('GET', `/labs/${this.activeLabId}/topology`);
416
- return JSON.stringify(topology, null, 2);
417
- }
418
- catch (e) {
419
- return JSON.stringify({ error: e.message });
420
- }
421
- }
422
- async disconnect() {
423
- if (this.activeLabId && this.ownedLab) {
424
- try {
425
- console.log(chalk_1.default.cyan(`❯ Deleting sandbox lab ${this.activeLabId}...`));
426
- await this.request('DELETE', `/labs/${this.activeLabId}`);
427
- console.log(chalk_1.default.green(`[+] Sandbox lab deleted cleanly.`));
428
- }
429
- catch (e) {
430
- console.warn(chalk_1.default.yellow(`[!] Could not delete lab: ${e.message}`));
431
- }
432
- }
433
- else if (this.activeLabId && !this.ownedLab) {
434
- console.log(chalk_1.default.dim(` Leaving external lab ${this.activeLabId} intact (not owned by this session).`));
435
- }
436
- this.activeLabId = null;
437
- if (this.token) {
438
- try {
439
- await this.request('DELETE', '/logout');
440
- console.log(chalk_1.default.green(`[+] Logged out from CML successfully.`));
441
- }
442
- catch { }
443
- this.token = null;
444
- }
445
- }
446
- }
447
- exports.CmlSession = CmlSession;
448
- //# sourceMappingURL=CmlSession.js.map