ciscollm-cli 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +147 -78
- package/dist/cli/ui/ui.d.ts +1 -0
- package/dist/cli/ui/ui.js +19 -4
- package/dist/cli/ui/ui.js.map +1 -1
- package/dist/core/agent/AgentLoop.d.ts +6 -0
- package/dist/core/agent/AgentLoop.js +137 -15
- package/dist/core/agent/AgentLoop.js.map +1 -1
- package/dist/core/agent/CommandReferenceEngine.d.ts +2 -0
- package/dist/core/agent/CommandReferenceEngine.js +73 -4
- package/dist/core/agent/CommandReferenceEngine.js.map +1 -1
- package/dist/core/agent/HierarchicalAgentManager.d.ts +11 -0
- package/dist/core/agent/HierarchicalAgentManager.js +70 -0
- package/dist/core/agent/HierarchicalAgentManager.js.map +1 -0
- package/dist/core/agent/MultiAgentCoordinator.d.ts +5 -1
- package/dist/core/agent/MultiAgentCoordinator.js +55 -0
- package/dist/core/agent/MultiAgentCoordinator.js.map +1 -1
- package/dist/core/agent/PromptEngine.d.ts +1 -1
- package/dist/core/agent/PromptEngine.js +64 -48
- package/dist/core/agent/PromptEngine.js.map +1 -1
- package/dist/core/guardrails/AuditLogger.d.ts +15 -0
- package/dist/core/guardrails/AuditLogger.js +66 -0
- package/dist/core/guardrails/AuditLogger.js.map +1 -0
- package/dist/core/guardrails/CommandFirewall.js +24 -0
- package/dist/core/guardrails/CommandFirewall.js.map +1 -1
- package/dist/core/guardrails/PreExecutionValidator.d.ts +9 -0
- package/dist/core/guardrails/PreExecutionValidator.js +58 -0
- package/dist/core/guardrails/PreExecutionValidator.js.map +1 -0
- package/dist/core/rollback/StateDiff.d.ts +47 -0
- package/dist/core/rollback/StateDiff.js +121 -0
- package/dist/core/rollback/StateDiff.js.map +1 -0
- package/dist/core/rollback/TransactionManager.d.ts +2 -0
- package/dist/core/rollback/TransactionManager.js +113 -41
- package/dist/core/rollback/TransactionManager.js.map +1 -1
- package/dist/core/topology/TopologyDiscovery.d.ts +5 -0
- package/dist/core/topology/TopologyDiscovery.js +54 -0
- package/dist/core/topology/TopologyDiscovery.js.map +1 -0
- package/dist/index.js +95 -24
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/llm/LLMClient.js +52 -2
- package/dist/infrastructure/llm/LLMClient.js.map +1 -1
- package/dist/infrastructure/protocols/BaseSession.js +1 -1
- package/dist/infrastructure/protocols/BaseSession.js.map +1 -1
- package/dist/infrastructure/protocols/CmlSession.d.ts +11 -0
- package/dist/infrastructure/protocols/CmlSession.js +60 -0
- package/dist/infrastructure/protocols/CmlSession.js.map +1 -0
- package/dist/infrastructure/protocols/MockSession.d.ts +33 -0
- package/dist/infrastructure/protocols/MockSession.js +427 -33
- package/dist/infrastructure/protocols/MockSession.js.map +1 -1
- package/dist/infrastructure/protocols/NetconfSession.d.ts +9 -0
- package/dist/infrastructure/protocols/NetconfSession.js +65 -0
- package/dist/infrastructure/protocols/NetconfSession.js.map +1 -0
- package/dist/infrastructure/protocols/PlinkSerial.js +107 -23
- package/dist/infrastructure/protocols/PlinkSerial.js.map +1 -1
- package/dist/shared/types.d.ts +12 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,112 +1,181 @@
|
|
|
1
1
|
# ciscollm-cli
|
|
2
2
|
|
|
3
|
-
`ciscollm-cli` is a Cisco IOS automation agent CLI for configuration, troubleshooting, and simulation.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
`ciscollm-cli` is a premium, autonomous Cisco IOS automation agent CLI designed for network configuration, troubleshooting, and simulation. By leveraging LLM tool-calling capabilities, it allows engineers to manage local, remote, or simulated Cisco hardware safely and efficiently.
|
|
4
|
+
|
|
5
|
+
The CLI features an **Interactive Setup Wizard**, **Multi-Device Coordination**, **Safety Guardrails (Command Firewall)**, **Automatic Configuration Rollbacks**, **Mock Device Simulation**, and **Strict Command Reference Validation**.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 🚀 Key Features
|
|
10
|
+
|
|
11
|
+
### 1. ⚙️ Interactive Setup Wizard
|
|
12
|
+
If `ciscollm run` is executed without a `--goal` parameter, the CLI automatically launches a step-by-step interactive setup wizard (using `inquirer`). The wizard guides the user through:
|
|
13
|
+
* **LLM Provider Selection:** Local (Ollama / LM Studio) or Cloud (OpenRouter).
|
|
14
|
+
* **Local LLM Settings:** Service type (Ollama/LM Studio), API endpoint URL, and model name.
|
|
15
|
+
* **Cloud LLM Settings:** OpenRouter API Key, model name, and endpoint.
|
|
16
|
+
* **Connection Protocol:** Serial (with automated COM port scanning), SSH, Telnet, or Mock simulation.
|
|
17
|
+
* **Connection Details:** COM port and Baud rate (for serial), or Host target, Port, Username, and Password (for SSH/Telnet).
|
|
18
|
+
* **Configuration Goal:** Prompting for the network task the agent needs to achieve.
|
|
19
|
+
* **Configuration Summary:** Displays a summary of the setup and prompts for final confirmation before starting execution.
|
|
20
|
+
|
|
21
|
+
### 2. 🔀 Multi-Device & Multi-Agent Coordination
|
|
22
|
+
Manage configurations across multiple Cisco hardware devices simultaneously. The `--com` (for serial) and `--host` (for SSH/Telnet) flags accept comma-separated inputs (e.g. `--com COM3,COM4` or `--host 10.0.0.1,10.0.0.2`). The internal `MultiAgentCoordinator` manages all connections in parallel, tracks status, and handles clean disconnections upon exit.
|
|
23
|
+
|
|
24
|
+
### 3. 🛡️ Command Firewall & Safety Guardrails
|
|
25
|
+
To prevent accidental lockouts, service disruptions, or losing device access, the built-in `CommandFirewall` monitors all LLM-generated commands.
|
|
26
|
+
* **Blocked Operations:**
|
|
27
|
+
* Removing default static routes (`no ip route 0.0.0.0...`) which can break management access.
|
|
28
|
+
* Disabling AAA authentication (`no aaa new-model`) or zeroizing crypto keys (`crypto key zeroize`).
|
|
29
|
+
* Deleting access lists or access groups (`no access-list`, `no ip access-group`).
|
|
30
|
+
* Shutting down active protected interfaces (e.g. `GigabitEthernet0/0`, `GigabitEthernet0/1`, `GigabitEthernet1/0`, `Vlan1`).
|
|
31
|
+
* Removing configured IP addresses on protected interfaces (`no ip address`).
|
|
32
|
+
* **Human-in-the-Loop Validation:** High-risk commands trigger a warning prompt, requiring the operator to manually authorize the execution.
|
|
33
|
+
* **Non-Interactive Mode:** Running with `--non-interactive` (or setting environment variable `CISCOLLM_NON_INTERACTIVE=true`) automatically rejects all blocked/high-risk commands.
|
|
34
|
+
|
|
35
|
+
### 4. 🔄 Transaction Rollback & Inversion Manager
|
|
36
|
+
If a configuration step fails or the agent encounters command errors, the `TransactionManager` restores the device state:
|
|
37
|
+
* **Atomic Backup:** Before modifying config, the agent attempts to back up the current running-config to `flash:backup-agent.cfg`.
|
|
38
|
+
* **Atomic Configuration Replace:** Rollbacks prioritize replacing the configuration atomically using `configure replace flash:backup-agent.cfg force`.
|
|
39
|
+
* **Command Inversion Fallback:** If flash storage is unreachable, it builds an inverse command sequence in reverse order (e.g. `ip address ...` -> `no ip address`, `shutdown` -> `no shutdown`, `no shutdown` -> `shutdown`, `description ...` -> `no description`) and executes them sequentially in their respective submodes.
|
|
40
|
+
|
|
41
|
+
### 5. 📚 Strict Command Reference Validation
|
|
42
|
+
Enforces compliance against an official Cisco IOS Command Reference index:
|
|
43
|
+
* **Strict Validation Mode:** Enabled via `--strict-command-ref` (or setting `CISCOLLM_STRICT_COMMAND_REF=true`). The agent will block any command not listed in the command-reference index.
|
|
44
|
+
* **PDF Command Indexer:** The engine reads `cf_command_ref.pdf`, extracts structural commands, and caches them in `.cache/cf_command_ref.index.json` to speed up startup times.
|
|
45
|
+
* **Fuzzy Command Family Expansion:** Automatically expands shortened commands (e.g. `sh` -> `show`, `conf t` -> `configure terminal`, `int gig0/1` -> `interface GigabitEthernet0/1`) to check they match valid command families in the index.
|
|
46
|
+
* **Reference Telemetry:** Telemetry logs detail the warmup time, source (PDF, cache, or memory), and matched command count. Can be disabled with `--no-ref-telemetry`.
|
|
47
|
+
|
|
48
|
+
### 6. 🧪 Mock Device Simulation
|
|
49
|
+
Mock mode (`--protocol mock`) provides a stateful simulation of a Cisco IOS device, allowing offline development and testing. It features:
|
|
50
|
+
* **Stateful Database:** Maintains interfaces, VLANs, shell variables, shell functions, and static routing tables, saved locally under `.mock-state-<device>.json`.
|
|
51
|
+
* **Interactive CLI Simulator:** Simulates user and privileged EXEC modes, configuration modes, VLAN databases, DHCP pools, OSPF routers, and IP routing tables.
|
|
52
|
+
* **Output Filtering (Pipes):** Supports standard IOS output piping such as `| include`, `| grep`, `| exclude`, and `| begin`.
|
|
53
|
+
* **Network Testing:** Simulates latency and ICMP ping responses.
|
|
54
|
+
|
|
55
|
+
### 7. 🛡️ Pre-Execution Safety Validation (Dry-Run Check)
|
|
56
|
+
Before executing any state-mutating command, the agent runs a dry-run check against the known network topology:
|
|
57
|
+
* **Topology Awareness:** Analyzes active physical/logical links between core, distribution, and access segments.
|
|
58
|
+
* **Accidental Disruption Prevention:** Detects and intercepts commands that could accidentally shut down critical uplink ports or neighbor nodes, ensuring continuous uptime.
|
|
59
|
+
|
|
60
|
+
### 8. 📊 Live Configuration State Diff Engine
|
|
61
|
+
Maintains deep visibility of system modifications:
|
|
62
|
+
* **Before/After Snapshots:** Takes memory-efficient snapshots of device interfaces, IP addresses, subnets, routing tables, and active VLAN databases before and after executing any command.
|
|
63
|
+
* **Visual Colorized Diffs:** Automatically outputs a structured difference report highlighting additions in green, removals in red, and updates/modifications in yellow.
|
|
64
|
+
|
|
65
|
+
### 9. 🪵 Continuous Enterprise Audit Trails
|
|
66
|
+
Ensures accountability for automated activities:
|
|
67
|
+
* **Detailed Logs:** Generates structured records containing the timestamp, target device, active agent role, LLM reasoning thoughts, executed commands, and final output status.
|
|
68
|
+
* **Local Audit Store:** Persists all interactions locally to `audit.log` for easy integration with standard security information and event management (SIEM) systems.
|
|
69
|
+
|
|
70
|
+
### 10. 🔀 Hierarchical Network Swarms
|
|
71
|
+
Supports role-specific command delegation and intelligence:
|
|
72
|
+
* **Role Routing:** Multi-agent coordinator routes tasks to specialized personalities—**Core Agent**, **Distribution Agent**, and **Access Agent**—matching the logical tier of the configuration task.
|
|
73
|
+
* **RBAC Constraints:** Restricts operations according to the `--rbac-role` parameter. The `read_only` role safely blocks any modifying actions and logs violations to the audit log.
|
|
74
|
+
|
|
75
|
+
### 11. 🔌 NETCONF & CML Simulation Adapters
|
|
76
|
+
Extends sandbox capabilities beyond local mock devices:
|
|
77
|
+
* **Cisco Modeling Labs (CML):** Provides sessions to interact directly with digital twin network simulations.
|
|
78
|
+
* **NETCONF XML Sessions:** Supports programmatic configuration using structured XML RPC calls and YANG schemas.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## 📦 Installation
|
|
83
|
+
|
|
84
|
+
To install `ciscollm-cli` globally from npm:
|
|
8
85
|
|
|
9
86
|
```bash
|
|
10
87
|
npm install -g ciscollm-cli
|
|
11
88
|
```
|
|
12
89
|
|
|
13
|
-
|
|
90
|
+
Once installed, the global executable `ciscollm` becomes available.
|
|
14
91
|
|
|
15
|
-
|
|
92
|
+
---
|
|
16
93
|
|
|
17
|
-
|
|
94
|
+
## 🛠️ CLI Usage & Options
|
|
18
95
|
|
|
19
96
|
```bash
|
|
20
|
-
ciscollm run
|
|
97
|
+
ciscollm run [options]
|
|
21
98
|
```
|
|
22
99
|
|
|
23
|
-
|
|
24
|
-
|
|
100
|
+
### Options Table
|
|
101
|
+
|
|
102
|
+
| Option / Flag | Alias | Description | Default Value |
|
|
103
|
+
|---|---|---|---|
|
|
104
|
+
| `-g, --goal <intent>` | - | The goal of the configuration/troubleshooting task. If not specified, launches the Interactive Setup Wizard. | - |
|
|
105
|
+
| `--protocol <type>` | - | Connection protocol (`serial`, `ssh`, `telnet`, `mock`, `netconf`, `cml`). | `serial` |
|
|
106
|
+
| `--provider <type>` | - | LLM provider mode (`local`, `cloud`). | `local` |
|
|
107
|
+
| `--local-type <type>` | - | Local LLM server flavor (`ollama`, `lmstudio`). | `ollama` |
|
|
108
|
+
| `--model <name>` | - | Name of the LLM model to compile. | - |
|
|
109
|
+
| `--endpoint <url>` | - | The LLM API endpoint URL. | - |
|
|
110
|
+
| `--api-key <key>` | - | API key for the cloud provider (OpenRouter). | - |
|
|
111
|
+
| `-c, --com <ports>` | - | COM Port(s), comma-separated (e.g., `COM3` or `COM3,COM4`). | - |
|
|
112
|
+
| `-b, --baud <rate>` | - | Serial transmission baud rate. | `9600` |
|
|
113
|
+
| `--host <address>` | - | Target IP address or hostname (comma-separated for multi-device). | - |
|
|
114
|
+
| `--port <port>` | - | Target connection port. | - |
|
|
115
|
+
| `-u, --username <name>` | - | Device login username. | - |
|
|
116
|
+
| `-p, --password <pass>` | - | Device login password. | - |
|
|
117
|
+
| `--strict-command-ref` | - | Block commands not found in the `cf_command_ref.pdf` index. | `false` |
|
|
118
|
+
| `--no-ref-telemetry` | - | Disable command-reference warmup telemetry logs. | `false` |
|
|
119
|
+
| `--non-interactive` | - | Run without interactive prompts (auto-rejects dangerous commands). | `false` |
|
|
120
|
+
| `--rbac-role <role>` | - | Specify the Active Agent RBAC authorization role (`admin`, `read_only`). | `admin` |
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## 💡 Usage Examples
|
|
125
|
+
|
|
126
|
+
### 1. Launching the Interactive Setup Wizard
|
|
127
|
+
Start the interactive CLI configuration process:
|
|
25
128
|
```bash
|
|
26
|
-
ciscollm run
|
|
129
|
+
ciscollm run
|
|
27
130
|
```
|
|
28
131
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
The CLI takes a user goal, sends it to the selected LLM provider, and lets the agent choose Cisco IOS tool calls step by step.
|
|
32
|
-
|
|
33
|
-
It can:
|
|
34
|
-
- inspect and modify Cisco-style configuration
|
|
35
|
-
- validate commands with guardrails
|
|
36
|
-
- roll back failed configuration changes
|
|
37
|
-
- simulate interfaces, IP addresses, shell commands, and ping checks in mock mode
|
|
38
|
-
|
|
39
|
-
## Common Usage
|
|
40
|
-
|
|
41
|
-
Start a mock session for learning or testing:
|
|
42
|
-
|
|
132
|
+
### 2. Running a Quick Mock Simulation
|
|
43
133
|
```bash
|
|
44
|
-
ciscollm run --protocol mock --goal "Configure 192.168.
|
|
134
|
+
ciscollm run --protocol mock --goal "Configure GigabitEthernet0/1 with IP 192.168.2.1/24 and interface description 'LAN B'"
|
|
45
135
|
```
|
|
46
136
|
|
|
47
|
-
|
|
48
|
-
|
|
137
|
+
### 3. Local Model (Ollama)
|
|
49
138
|
```bash
|
|
50
|
-
ciscollm run --provider local --local-type
|
|
139
|
+
ciscollm run --provider local --local-type ollama --endpoint http://127.0.0.1:11434/v1 --model qwen3.5-4b --protocol mock --goal "Show IP routing table"
|
|
51
140
|
```
|
|
52
141
|
|
|
53
|
-
|
|
54
|
-
|
|
142
|
+
### 4. Cloud Inference via OpenRouter
|
|
55
143
|
```bash
|
|
56
|
-
ciscollm run --provider cloud --api-key
|
|
144
|
+
ciscollm run --provider cloud --api-key YOUR_OPENROUTER_API_KEY --protocol mock --goal "Verify interface states"
|
|
57
145
|
```
|
|
58
146
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
```bash
|
|
62
|
-
ciscollm run --strict-command-ref --protocol mock --goal "Review LAN design"
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
Disable startup telemetry if you want quieter output:
|
|
66
|
-
|
|
147
|
+
### 5. Enforcing Strict Validation Mode
|
|
67
148
|
```bash
|
|
68
|
-
ciscollm run --
|
|
149
|
+
ciscollm run --strict-command-ref --protocol mock --goal "Configure router ospf 1 and advertise network 192.168.1.0/24"
|
|
69
150
|
```
|
|
70
151
|
|
|
71
|
-
|
|
152
|
+
---
|
|
72
153
|
|
|
73
|
-
|
|
74
|
-
- `--provider <type>`: Selects the LLM provider. Supported values: `local`, `cloud`.
|
|
75
|
-
- `--local-type <type>`: Chooses the local LLM server flavor. Supported values: `ollama`, `lmstudio`.
|
|
76
|
-
- `--endpoint <url>`: Sets the LLM API endpoint.
|
|
77
|
-
- `--model <name>`: Sets the model name to use.
|
|
78
|
-
- `--strict-command-ref`: Blocks commands that are not found in the command-reference index.
|
|
79
|
-
- `--no-ref-telemetry`: Turns off command-reference startup telemetry.
|
|
80
|
-
- `--goal <intent>`: Describes the configuration or troubleshooting task.
|
|
154
|
+
## 💻 Development & Contribution
|
|
81
155
|
|
|
82
|
-
|
|
156
|
+
Follow these steps to set up the project locally for development:
|
|
83
157
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
## Mock Mode
|
|
92
|
-
|
|
93
|
-
Mock mode is designed for safe offline testing.
|
|
94
|
-
|
|
95
|
-
It simulates:
|
|
96
|
-
- device connection and prompt modes
|
|
97
|
-
- interface configuration
|
|
98
|
-
- ping behavior
|
|
99
|
-
- command parsing errors
|
|
100
|
-
- shell variable and function behavior
|
|
101
|
-
|
|
102
|
-
This is the recommended mode when you want to test agent behavior without hardware.
|
|
103
|
-
|
|
104
|
-
## Troubleshooting
|
|
158
|
+
### 1. Clone & Install Dependencies
|
|
159
|
+
```bash
|
|
160
|
+
git clone https://github.com/ThemeHackers/ciscollm-cli.git
|
|
161
|
+
cd ciscollm-cli
|
|
162
|
+
npm install
|
|
163
|
+
```
|
|
105
164
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
165
|
+
### 2. Build the Project
|
|
166
|
+
Compile the TypeScript code to target JavaScript inside `dist/`:
|
|
167
|
+
```bash
|
|
168
|
+
npm run build
|
|
169
|
+
```
|
|
109
170
|
|
|
110
|
-
|
|
171
|
+
### 3. Run Development Build
|
|
172
|
+
Run the CLI locally from source code:
|
|
173
|
+
```bash
|
|
174
|
+
npm start -- run --protocol mock --goal "Show running config"
|
|
175
|
+
```
|
|
111
176
|
|
|
112
|
-
|
|
177
|
+
### 4. Run Unit Tests
|
|
178
|
+
Validate features including the Command Firewall, Transaction Manager, and Error Analyzer:
|
|
179
|
+
```bash
|
|
180
|
+
npm run test
|
|
181
|
+
```
|
package/dist/cli/ui/ui.d.ts
CHANGED
package/dist/cli/ui/ui.js
CHANGED
|
@@ -8,12 +8,27 @@ exports.createSpinner = createSpinner;
|
|
|
8
8
|
const chalk_1 = __importDefault(require("chalk"));
|
|
9
9
|
const ora_1 = __importDefault(require("ora"));
|
|
10
10
|
exports.logger = {
|
|
11
|
-
info: (msg) => console.log(chalk_1.default.
|
|
12
|
-
success: (msg) => console.log(chalk_1.default.green('✔ ') + chalk_1.default.bold(msg)),
|
|
11
|
+
info: (msg) => console.log(chalk_1.default.cyan('ℹ ') + msg),
|
|
12
|
+
success: (msg) => console.log(chalk_1.default.green('✔ ') + chalk_1.default.bold.green(msg)),
|
|
13
13
|
warn: (msg) => console.warn(chalk_1.default.yellow('⚠ ') + chalk_1.default.yellow(msg)),
|
|
14
14
|
error: (msg) => console.error(chalk_1.default.red('✖ ') + chalk_1.default.red.bold(msg)),
|
|
15
|
-
critical: (msg) =>
|
|
16
|
-
|
|
15
|
+
critical: (msg) => {
|
|
16
|
+
console.error('\n' + chalk_1.default.bgRed.black.bold(' ⚡ CRITICAL ERROR ') + ' ' + chalk_1.default.red.bold(msg) + '\n');
|
|
17
|
+
},
|
|
18
|
+
heading: (msg) => {
|
|
19
|
+
const line = '━'.repeat(msg.length + 6);
|
|
20
|
+
console.log('\n' + chalk_1.default.magenta.bold(` ┏${line}┓`));
|
|
21
|
+
console.log(chalk_1.default.magenta.bold(` ┃ ${chalk_1.default.white.bold(msg)} ┃`));
|
|
22
|
+
console.log(chalk_1.default.magenta.bold(` ┗${line}┛`) + '\n');
|
|
23
|
+
},
|
|
24
|
+
reasoning: (msg) => {
|
|
25
|
+
const border = chalk_1.default.blue('│');
|
|
26
|
+
console.log('\n' + chalk_1.default.blue('┌─── 🤖 Agent Reasoning Thought Process ───────────────────────'));
|
|
27
|
+
msg.trim().split('\n').forEach(line => {
|
|
28
|
+
console.log(`${border} ${chalk_1.default.gray.italic(line)}`);
|
|
29
|
+
});
|
|
30
|
+
console.log(chalk_1.default.blue('└─────────────────────────────────────────────────────────────') + '\n');
|
|
31
|
+
}
|
|
17
32
|
};
|
|
18
33
|
function createSpinner(text) {
|
|
19
34
|
return (0, ora_1.default)({
|
package/dist/cli/ui/ui.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../../../src/cli/ui/ui.ts"],"names":[],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../../../src/cli/ui/ui.ts"],"names":[],"mappings":";;;;;;AA2BA,sCAMC;AAjCD,kDAA0B;AAC1B,8CAAsB;AAET,QAAA,MAAM,GAAG;IAClB,IAAI,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC;IAC1D,OAAO,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,eAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAChF,IAAI,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,eAAK,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,eAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC3E,KAAK,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,eAAK,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC5E,QAAQ,EAAE,CAAC,GAAW,EAAE,EAAE;QACtB,OAAO,CAAC,KAAK,CAAC,IAAI,GAAG,eAAK,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,GAAG,GAAG,GAAG,eAAK,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;IAC1G,CAAC;IACD,OAAO,EAAE,CAAC,GAAW,EAAE,EAAE;QACrB,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACxC,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,eAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC;QACtD,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,eAAK,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;QACpE,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;IAC1D,CAAC;IACD,SAAS,EAAE,CAAC,GAAW,EAAE,EAAE;QACvB,MAAM,MAAM,GAAG,eAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,eAAK,CAAC,IAAI,CAAC,iEAAiE,CAAC,CAAC,CAAC;QAClG,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;YAClC,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,KAAK,eAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACzD,CAAC,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,gEAAgE,CAAC,GAAG,IAAI,CAAC,CAAC;IACrG,CAAC;CACJ,CAAC;AAEF,SAAgB,aAAa,CAAC,IAAY;IACtC,OAAO,IAAA,aAAG,EAAC;QACP,IAAI;QACJ,KAAK,EAAE,MAAM;QACb,OAAO,EAAE,MAAM;KAClB,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -3,6 +3,7 @@ import { MultiAgentCoordinator } from './MultiAgentCoordinator';
|
|
|
3
3
|
type AgentLoopOptions = {
|
|
4
4
|
strictReferenceMode?: boolean;
|
|
5
5
|
referenceTelemetry?: boolean;
|
|
6
|
+
rbacRole?: string;
|
|
6
7
|
};
|
|
7
8
|
export declare class CiscoAgentLoop {
|
|
8
9
|
private llmClient;
|
|
@@ -15,17 +16,22 @@ export declare class CiscoAgentLoop {
|
|
|
15
16
|
private commandReferenceEngine;
|
|
16
17
|
private strictReferenceMode;
|
|
17
18
|
private referenceTelemetry;
|
|
19
|
+
private rbacRole;
|
|
18
20
|
private options;
|
|
19
21
|
private validationNudgeCount;
|
|
22
|
+
private lastTopologyDiscoveryAt;
|
|
23
|
+
private readonly topologyRefreshIntervalMs;
|
|
20
24
|
constructor(llmClient: LLMClient, coordinator: MultiAgentCoordinator, options?: AgentLoopOptions);
|
|
21
25
|
private applyOptions;
|
|
22
26
|
run(userGoal: string): Promise<void>;
|
|
27
|
+
private buildTopologyInfoString;
|
|
23
28
|
private triggerAutomaticValidationPing;
|
|
24
29
|
private resolveValidationDestination;
|
|
25
30
|
private buildStateInfoString;
|
|
26
31
|
private findLastMutatedDevice;
|
|
27
32
|
private resolveTargetDevice;
|
|
28
33
|
private handleExecuteCommandCall;
|
|
34
|
+
private captureDeviceSnapshot;
|
|
29
35
|
private handleEnableIosShellCall;
|
|
30
36
|
private handleDefineShellVariableCall;
|
|
31
37
|
private handleExecuteShellLoopCall;
|
|
@@ -13,6 +13,10 @@ const ToolDefinitions_1 = require("../../infrastructure/llm/ToolDefinitions");
|
|
|
13
13
|
const child_process_1 = require("child_process");
|
|
14
14
|
const ui_1 = require("../../cli/ui/ui");
|
|
15
15
|
const chalk_1 = __importDefault(require("chalk"));
|
|
16
|
+
const PreExecutionValidator_1 = require("../guardrails/PreExecutionValidator");
|
|
17
|
+
const AuditLogger_1 = require("../guardrails/AuditLogger");
|
|
18
|
+
const HierarchicalAgentManager_1 = require("./HierarchicalAgentManager");
|
|
19
|
+
const StateDiff_1 = require("../rollback/StateDiff");
|
|
16
20
|
class CiscoAgentLoop {
|
|
17
21
|
llmClient;
|
|
18
22
|
coordinator;
|
|
@@ -24,8 +28,11 @@ class CiscoAgentLoop {
|
|
|
24
28
|
commandReferenceEngine = CommandReferenceEngine_1.CommandReferenceEngine.getInstance();
|
|
25
29
|
strictReferenceMode = false;
|
|
26
30
|
referenceTelemetry = true;
|
|
31
|
+
rbacRole = 'admin';
|
|
27
32
|
options;
|
|
28
33
|
validationNudgeCount = 0;
|
|
34
|
+
lastTopologyDiscoveryAt = 0;
|
|
35
|
+
topologyRefreshIntervalMs = 15000;
|
|
29
36
|
constructor(llmClient, coordinator, options = {}) {
|
|
30
37
|
this.llmClient = llmClient;
|
|
31
38
|
this.coordinator = coordinator;
|
|
@@ -39,6 +46,9 @@ class CiscoAgentLoop {
|
|
|
39
46
|
if (typeof options.strictReferenceMode === 'boolean') {
|
|
40
47
|
this.commandReferenceEngine.setStrictMode(options.strictReferenceMode);
|
|
41
48
|
}
|
|
49
|
+
if (options.rbacRole) {
|
|
50
|
+
this.rbacRole = options.rbacRole.toLowerCase();
|
|
51
|
+
}
|
|
42
52
|
}
|
|
43
53
|
async run(userGoal) {
|
|
44
54
|
const backupSpinner = (0, ui_1.createSpinner)('Initializing device configuration backups to flash...').start();
|
|
@@ -72,9 +82,10 @@ class CiscoAgentLoop {
|
|
|
72
82
|
refSpinner.warn('Cisco command reference hints unavailable. Continuing with base policy.');
|
|
73
83
|
}
|
|
74
84
|
const stateInfo = this.buildStateInfoString();
|
|
85
|
+
const topologyInfo = await this.buildTopologyInfoString();
|
|
75
86
|
this.messages.push({
|
|
76
87
|
role: 'system',
|
|
77
|
-
content: PromptEngine_1.PromptEngine.getSystemPrompt(stateInfo, this.commandHints, this.strictReferenceMode)
|
|
88
|
+
content: PromptEngine_1.PromptEngine.getSystemPrompt(stateInfo, this.commandHints, this.strictReferenceMode, topologyInfo)
|
|
78
89
|
});
|
|
79
90
|
this.messages.push({ role: 'user', content: userGoal });
|
|
80
91
|
let dynamicLoopActive = true;
|
|
@@ -83,9 +94,10 @@ class CiscoAgentLoop {
|
|
|
83
94
|
while (dynamicLoopActive && executionDepth < MAX_STEPS) {
|
|
84
95
|
executionDepth++;
|
|
85
96
|
const updatedStateInfo = this.buildStateInfoString();
|
|
97
|
+
const updatedTopologyInfo = await this.buildTopologyInfoString();
|
|
86
98
|
this.messages[0] = {
|
|
87
99
|
role: 'system',
|
|
88
|
-
content: PromptEngine_1.PromptEngine.getSystemPrompt(updatedStateInfo, this.commandHints, this.strictReferenceMode)
|
|
100
|
+
content: PromptEngine_1.PromptEngine.getSystemPrompt(updatedStateInfo, this.commandHints, this.strictReferenceMode, updatedTopologyInfo)
|
|
89
101
|
};
|
|
90
102
|
let shellEnabled = false;
|
|
91
103
|
for (const session of this.coordinator.getSessions().values()) {
|
|
@@ -109,11 +121,7 @@ class CiscoAgentLoop {
|
|
|
109
121
|
modelSpinner.succeed(`[Step ${executionDepth}/${MAX_STEPS}] Thinking complete.`);
|
|
110
122
|
const thoughts = response.reasoning_content || response.content;
|
|
111
123
|
if (thoughts && thoughts.trim()) {
|
|
112
|
-
|
|
113
|
-
thoughts.trim().split('\n').forEach(line => {
|
|
114
|
-
console.log(chalk_1.default.dim(` | ${line}`));
|
|
115
|
-
});
|
|
116
|
-
console.log(chalk_1.default.gray(' ' + '─'.repeat(40)));
|
|
124
|
+
ui_1.logger.reasoning(thoughts);
|
|
117
125
|
}
|
|
118
126
|
}
|
|
119
127
|
catch (err) {
|
|
@@ -173,6 +181,21 @@ class CiscoAgentLoop {
|
|
|
173
181
|
ui_1.logger.warn('Maximum loop steps limit reached.');
|
|
174
182
|
}
|
|
175
183
|
}
|
|
184
|
+
async buildTopologyInfoString() {
|
|
185
|
+
const now = Date.now();
|
|
186
|
+
if (now - this.lastTopologyDiscoveryAt > this.topologyRefreshIntervalMs) {
|
|
187
|
+
await this.coordinator.discoverTopology();
|
|
188
|
+
this.lastTopologyDiscoveryAt = now;
|
|
189
|
+
}
|
|
190
|
+
const topology = this.coordinator.getTopology();
|
|
191
|
+
if (topology.links.length === 0) {
|
|
192
|
+
return `Discovered at: ${topology.discoveredAt}\nNodes: ${topology.nodes.join(', ') || '(none)'}\nLinks: none`;
|
|
193
|
+
}
|
|
194
|
+
const links = topology.links
|
|
195
|
+
.map(link => `- ${link.localDeviceId} [${link.localInterface}] <-> ${link.remoteDeviceId} [${link.remoteInterface}] via ${link.protocol.toUpperCase()}`)
|
|
196
|
+
.join('\n');
|
|
197
|
+
return `Discovered at: ${topology.discoveredAt}\nNodes: ${topology.nodes.join(', ')}\n${links}`;
|
|
198
|
+
}
|
|
176
199
|
async triggerAutomaticValidationPing(deviceId) {
|
|
177
200
|
const destination = await this.resolveValidationDestination(deviceId);
|
|
178
201
|
const fallbackCall = {
|
|
@@ -206,7 +229,6 @@ class CiscoAgentLoop {
|
|
|
206
229
|
}
|
|
207
230
|
}
|
|
208
231
|
catch {
|
|
209
|
-
// Fall through to safe default.
|
|
210
232
|
}
|
|
211
233
|
return '127.0.0.1';
|
|
212
234
|
}
|
|
@@ -257,6 +279,26 @@ class CiscoAgentLoop {
|
|
|
257
279
|
const targetCommand = args.command;
|
|
258
280
|
const requestedDevice = args.device;
|
|
259
281
|
const cleanCommand = targetCommand.trim();
|
|
282
|
+
const assignedRole = HierarchicalAgentManager_1.HierarchicalAgentManager.routeCommand(cleanCommand);
|
|
283
|
+
if (this.rbacRole === 'read_only') {
|
|
284
|
+
const lower = cleanCommand.toLowerCase();
|
|
285
|
+
const allowedReadOnlyPatterns = [/^show\s+/i, /^ping\s+/i, /^dir\s+/i, /^terminal\s+/i, /^exit$/i, /^end$/i];
|
|
286
|
+
const isAllowedReadOnly = allowedReadOnlyPatterns.some(p => p.test(lower));
|
|
287
|
+
if (!isAllowedReadOnly) {
|
|
288
|
+
ui_1.logger.warn(`[RBAC BLOCK] Read-Only role blocked command: "${cleanCommand}"`);
|
|
289
|
+
this.injectToolResponse(call.id, 'execute_ios_command', `CRITICAL ERROR: RBAC policy violation. Your current role is READ_ONLY and you are blocked from executing modifying command "${cleanCommand}".`);
|
|
290
|
+
AuditLogger_1.AuditLogger.log({
|
|
291
|
+
timestamp: new Date().toISOString(),
|
|
292
|
+
deviceId: requestedDevice || 'unknown',
|
|
293
|
+
role: this.rbacRole,
|
|
294
|
+
thought: this.messages[this.messages.length - 1]?.content || '',
|
|
295
|
+
command: cleanCommand,
|
|
296
|
+
status: 'BLOCKED',
|
|
297
|
+
reason: 'RBAC role is READ_ONLY'
|
|
298
|
+
});
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
260
302
|
const commandValidation = await this.commandReferenceEngine.validateCommand(cleanCommand);
|
|
261
303
|
if (this.strictReferenceMode && !commandValidation.allowed) {
|
|
262
304
|
const suggestions = commandValidation.suggestions.length
|
|
@@ -273,6 +315,26 @@ class CiscoAgentLoop {
|
|
|
273
315
|
this.injectToolResponse(call.id, 'execute_ios_command', `Error: ${err.message}`);
|
|
274
316
|
return;
|
|
275
317
|
}
|
|
318
|
+
const tx = this.transactions.get(targetDeviceId);
|
|
319
|
+
const currentInterface = tx ? tx.targetInterface : null;
|
|
320
|
+
const dryRunCheck = PreExecutionValidator_1.PreExecutionValidator.validateCommand(cleanCommand, targetDeviceId, this.coordinator.getTopology(), currentInterface);
|
|
321
|
+
if (dryRunCheck.warnLevel === 'CRITICAL' || !dryRunCheck.safe) {
|
|
322
|
+
ui_1.logger.warn(`[PRE-EXECUTION WARNING] Critical risk detected: ${dryRunCheck.reason}`);
|
|
323
|
+
const allowed = await this.firewall.verifyWithHuman(cleanCommand, dryRunCheck.reason || 'High risk context');
|
|
324
|
+
if (!allowed) {
|
|
325
|
+
this.injectToolResponse(call.id, 'execute_ios_command', `CRITICAL ERROR: Pre-execution validation blocked this command. Reason: ${dryRunCheck.reason}`);
|
|
326
|
+
AuditLogger_1.AuditLogger.log({
|
|
327
|
+
timestamp: new Date().toISOString(),
|
|
328
|
+
deviceId: targetDeviceId,
|
|
329
|
+
role: this.rbacRole,
|
|
330
|
+
thought: this.messages[this.messages.length - 1]?.content || '',
|
|
331
|
+
command: cleanCommand,
|
|
332
|
+
status: 'BLOCKED',
|
|
333
|
+
reason: dryRunCheck.reason
|
|
334
|
+
});
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
276
338
|
const lastCmdInfo = this.lastCommandPerDevice[targetDeviceId];
|
|
277
339
|
if (lastCmdInfo && lastCmdInfo.command === cleanCommand) {
|
|
278
340
|
lastCmdInfo.count++;
|
|
@@ -285,8 +347,6 @@ class CiscoAgentLoop {
|
|
|
285
347
|
this.injectToolResponse(call.id, 'execute_ios_command', `CRITICAL ERROR: Loop check block. You have run "${cleanCommand}" multiple times with errors. Re-verify your settings before retrying.`);
|
|
286
348
|
return;
|
|
287
349
|
}
|
|
288
|
-
const tx = this.transactions.get(targetDeviceId);
|
|
289
|
-
const currentInterface = tx ? tx.targetInterface : null;
|
|
290
350
|
const firewallResult = this.firewall.checkCommand(cleanCommand, currentInterface);
|
|
291
351
|
if (firewallResult.dangerous) {
|
|
292
352
|
const allowed = await this.firewall.verifyWithHuman(cleanCommand, firewallResult.reason || 'High-risk token');
|
|
@@ -298,10 +358,10 @@ class CiscoAgentLoop {
|
|
|
298
358
|
if (tx) {
|
|
299
359
|
tx.trackMutation(cleanCommand);
|
|
300
360
|
}
|
|
301
|
-
const
|
|
361
|
+
const snapshotA = await this.captureDeviceSnapshot(targetDeviceId);
|
|
362
|
+
const cmdSpinner = (0, ui_1.createSpinner)(`[${targetDeviceId}] [Agent: ${assignedRole}] Executing command: "${cleanCommand}"...`).start();
|
|
302
363
|
try {
|
|
303
364
|
const session = this.coordinator.getSession(targetDeviceId);
|
|
304
|
-
// Normalize context for read-only inspection commands to avoid mode-related failures.
|
|
305
365
|
const state = session.getState();
|
|
306
366
|
if (/^show\s+/i.test(cleanCommand) && (state.currentMode === 'GLOBAL_CONFIG' || state.currentMode === 'INTERFACE_CONFIG')) {
|
|
307
367
|
await session.execute('end');
|
|
@@ -317,11 +377,38 @@ class CiscoAgentLoop {
|
|
|
317
377
|
rollbackLogs = await tx.executeRollback(session);
|
|
318
378
|
}
|
|
319
379
|
rbSpinner.succeed(`[${targetDeviceId}] Rollback execution complete.`);
|
|
380
|
+
AuditLogger_1.AuditLogger.log({
|
|
381
|
+
timestamp: new Date().toISOString(),
|
|
382
|
+
deviceId: targetDeviceId,
|
|
383
|
+
role: this.rbacRole,
|
|
384
|
+
thought: this.messages[this.messages.length - 2]?.content || '',
|
|
385
|
+
command: cleanCommand,
|
|
386
|
+
status: 'ROLLBACK',
|
|
387
|
+
reason: `Rollback triggered by error ${verification.errorType}. Reverted state successfully.`
|
|
388
|
+
});
|
|
320
389
|
this.injectToolResponse(call.id, 'execute_ios_command', `IOS Error [${verification.errorType}]:\n${processedOutput}\n\nAutomated configuration rollback executed:\n${rollbackLogs}`);
|
|
321
390
|
}
|
|
322
391
|
else {
|
|
323
392
|
cmdSpinner.succeed(`[${targetDeviceId}] Command completed: "${cleanCommand}"`);
|
|
324
|
-
this.
|
|
393
|
+
const snapshotB = await this.captureDeviceSnapshot(targetDeviceId);
|
|
394
|
+
let diffSummary = '';
|
|
395
|
+
if (snapshotA && snapshotB) {
|
|
396
|
+
const diffResult = StateDiff_1.StateDiff.diff(snapshotA, snapshotB);
|
|
397
|
+
diffSummary = StateDiff_1.StateDiff.renderDiff(diffResult);
|
|
398
|
+
if (diffSummary && diffSummary !== 'No configuration differences detected.') {
|
|
399
|
+
ui_1.logger.info(`[State Diff for ${targetDeviceId}]:\n${diffSummary}`);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
AuditLogger_1.AuditLogger.log({
|
|
403
|
+
timestamp: new Date().toISOString(),
|
|
404
|
+
deviceId: targetDeviceId,
|
|
405
|
+
role: this.rbacRole,
|
|
406
|
+
thought: this.messages[this.messages.length - 2]?.content || '',
|
|
407
|
+
command: cleanCommand,
|
|
408
|
+
status: 'SUCCESS',
|
|
409
|
+
outputSnippet: `${processedOutput}${diffSummary ? `\nState Changes:\n${diffSummary}` : ''}`
|
|
410
|
+
});
|
|
411
|
+
this.injectToolResponse(call.id, 'execute_ios_command', processedOutput + (diffSummary ? `\n\n[State Diff Configured]:\n${diffSummary}` : ''));
|
|
325
412
|
}
|
|
326
413
|
}
|
|
327
414
|
catch (error) {
|
|
@@ -329,6 +416,41 @@ class CiscoAgentLoop {
|
|
|
329
416
|
this.injectToolResponse(call.id, 'execute_ios_command', `Hardware Session Fault: ${error.message}`);
|
|
330
417
|
}
|
|
331
418
|
}
|
|
419
|
+
async captureDeviceSnapshot(deviceId) {
|
|
420
|
+
const session = this.coordinator.getSession(deviceId);
|
|
421
|
+
if (!session)
|
|
422
|
+
return null;
|
|
423
|
+
if (typeof session.interfaces !== 'undefined') {
|
|
424
|
+
const mock = session;
|
|
425
|
+
const interfaceList = [];
|
|
426
|
+
for (const [name, conf] of mock.interfaces.entries()) {
|
|
427
|
+
interfaceList.push({
|
|
428
|
+
name,
|
|
429
|
+
ip: conf.ip,
|
|
430
|
+
subnet: conf.subnet,
|
|
431
|
+
adminShutdown: conf.adminShutdown,
|
|
432
|
+
lineProtocolUp: conf.lineProtocolUp,
|
|
433
|
+
description: conf.description
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
return {
|
|
437
|
+
deviceId,
|
|
438
|
+
timestamp: new Date().toISOString(),
|
|
439
|
+
sessionState: session.getState(),
|
|
440
|
+
interfaces: interfaceList,
|
|
441
|
+
routes: [...mock.routes],
|
|
442
|
+
vlans: Array.from(mock.vlans)
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
return {
|
|
446
|
+
deviceId,
|
|
447
|
+
timestamp: new Date().toISOString(),
|
|
448
|
+
sessionState: session.getState(),
|
|
449
|
+
interfaces: [],
|
|
450
|
+
routes: [],
|
|
451
|
+
vlans: []
|
|
452
|
+
};
|
|
453
|
+
}
|
|
332
454
|
async handleEnableIosShellCall(call) {
|
|
333
455
|
let args;
|
|
334
456
|
try {
|
|
@@ -523,8 +645,8 @@ class CiscoAgentLoop {
|
|
|
523
645
|
async pingFromHost(destination) {
|
|
524
646
|
return new Promise((resolve) => {
|
|
525
647
|
const isWindows = process.platform === 'win32';
|
|
526
|
-
const
|
|
527
|
-
(0, child_process_1.
|
|
648
|
+
const pingArgs = isWindows ? ['-n', '4', destination] : ['-c', '4', destination];
|
|
649
|
+
(0, child_process_1.execFile)('ping', pingArgs, (error, stdout, stderr) => {
|
|
528
650
|
if (error) {
|
|
529
651
|
resolve(`PING FAILED:\n${stdout || stderr || error.message}`);
|
|
530
652
|
return;
|