exaai-agent 2.0.9__py3-none-any.whl → 2.2.0__py3-none-any.whl
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.
- {exaai_agent-2.0.9.dist-info → exaai_agent-2.2.0.dist-info}/METADATA +72 -42
- {exaai_agent-2.0.9.dist-info → exaai_agent-2.2.0.dist-info}/RECORD +34 -22
- {exaai_agent-2.0.9.dist-info → exaai_agent-2.2.0.dist-info}/WHEEL +1 -1
- exaaiagnt/dashboard/server.py +99 -0
- exaaiagnt/dashboard/templates/index.html +232 -0
- exaaiagnt/interface/cli.py +62 -30
- exaaiagnt/interface/main.py +11 -1
- exaaiagnt/interface/tui.py +12 -8
- exaaiagnt/llm/llm.py +43 -8
- exaaiagnt/llm/llm_traffic_controller.py +5 -3
- exaaiagnt/prompts/README.md +3 -1
- exaaiagnt/prompts/auto_loader.py +31 -0
- exaaiagnt/prompts/cloud/azure_cloud_security.jinja +126 -0
- exaaiagnt/prompts/cloud/gcp_cloud_security.jinja +158 -0
- exaaiagnt/prompts/cloud/kubernetes_security.jinja +97 -0
- exaaiagnt/prompts/vulnerabilities/prompt_injection.jinja +276 -0
- exaaiagnt/runtime/tool_manager.py +12 -3
- exaaiagnt/telemetry/tracer.py +17 -1
- exaaiagnt/tools/__init__.py +24 -0
- exaaiagnt/tools/executor.py +16 -4
- exaaiagnt/tools/k8s_scanner/__init__.py +29 -0
- exaaiagnt/tools/k8s_scanner/k8s_actions.py +319 -0
- exaaiagnt/tools/k8s_scanner/k8s_actions_schema.xml +36 -0
- exaaiagnt/tools/prompt_injection/__init__.py +26 -0
- exaaiagnt/tools/prompt_injection/prompt_injection_actions.py +712 -0
- exaaiagnt/tools/prompt_injection/prompt_injection_actions_schema.xml +28 -0
- exaaiagnt/tools/python/python_instance.py +16 -1
- exaaiagnt/tools/reporting/reporting_actions.py +34 -5
- exaaiagnt/tools/response_analyzer.py +5 -3
- exaaiagnt/tools/smart_fuzzer.py +5 -3
- exaaiagnt/tools/vuln_validator.py +5 -3
- exaaiagnt/tools/web_search/web_search_actions.py +4 -2
- {exaai_agent-2.0.9.dist-info → exaai_agent-2.2.0.dist-info}/entry_points.txt +0 -0
- {exaai_agent-2.0.9.dist-info → exaai_agent-2.2.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: exaai-agent
|
|
3
|
-
Version: 2.0
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: ExaAi - Advanced AI Security Agent for Comprehensive Penetration Testing
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
License-File: LICENSE
|
|
@@ -53,57 +53,60 @@ Description-Content-Type: text/markdown
|
|
|
53
53
|
[](https://pypi.org/project/exaai-agent/)
|
|
54
54
|
[](https://pypi.org/project/exaai-agent/)
|
|
55
55
|
[](LICENSE)
|
|
56
|
-
[]()
|
|
57
57
|
|
|
58
58
|
</div>
|
|
59
59
|
|
|
60
60
|
<br>
|
|
61
61
|
|
|
62
62
|
> [!TIP]
|
|
63
|
-
> **🚀 v2.1.
|
|
63
|
+
> **🚀 v2.1.2 Released!** Now supports **AI Agent Integration (OpenClaw)**, Kubernetes Security, Azure/GCP modules, and Prompt Injection detection.
|
|
64
|
+
>
|
|
65
|
+
> 🤖 **Connect Your Agent:** You can now control ExaAiAgent via any AI agent (OpenClaw, etc).
|
|
66
|
+
> Just send this command to your agent:
|
|
67
|
+
> ```
|
|
68
|
+
> Read https://raw.githubusercontent.com/hleliofficiel/ExaAiAgent/main/SKILL.md and follow the instructions to join ExaAiAgent
|
|
69
|
+
> ```
|
|
64
70
|
|
|
65
71
|
---
|
|
66
72
|
|
|
67
|
-
## 🔥 What's New in v2.1.
|
|
73
|
+
## 🔥 What's New in v2.1.2
|
|
68
74
|
|
|
69
|
-
###
|
|
75
|
+
### 🤖 AI Agent Integration (OpenClaw)
|
|
70
76
|
|
|
71
|
-
|
|
77
|
+
Seamlessly integrate ExaAiAgent with your AI workforce:
|
|
72
78
|
|
|
73
|
-
- **
|
|
74
|
-
- Auto-
|
|
75
|
-
-
|
|
76
|
-
- WAF bypass techniques included
|
|
79
|
+
- **Agent Control**: Control scans via OpenClaw or any agent framework
|
|
80
|
+
- **Auto-Discovery**: Agents can read `SKILL.md` to self-onboard
|
|
81
|
+
- **Output Optimization**: Tools now output cleaner data (no ANSI codes) for LLM consumption
|
|
77
82
|
|
|
78
|
-
###
|
|
83
|
+
### ⚓ Kubernetes & Cloud Security (Updated)
|
|
79
84
|
|
|
80
|
-
|
|
85
|
+
Expanded coverage for cloud-native infrastructure:
|
|
81
86
|
|
|
82
|
-
- **
|
|
83
|
-
- **Azure**: Blob
|
|
84
|
-
- **GCP**: Cloud Storage, Service Account
|
|
85
|
-
- **
|
|
87
|
+
- **Kubernetes**: Deep RBAC auditing, Pod Security Standards (PSS), Network Policy checks
|
|
88
|
+
- **Azure**: Blob Storage, Entra ID (Azure AD), Key Vault auditing
|
|
89
|
+
- **GCP**: Cloud Storage, IAM, Service Account key leaks
|
|
90
|
+
- **Prompt Injection**: Dedicated scanner for AI/LLM applications
|
|
86
91
|
|
|
87
|
-
###
|
|
92
|
+
### 🛡️ Smart Security Tools
|
|
88
93
|
|
|
89
94
|
| Tool | Capability |
|
|
90
95
|
|------|------------|
|
|
91
|
-
| **Smart Fuzzer** |
|
|
96
|
+
| **Smart Fuzzer** | Thread-safe, context-aware fuzzing with rate limiting |
|
|
92
97
|
| **Response Analyzer** | SQL errors, stack traces, sensitive data detection |
|
|
93
|
-
| **Vuln Validator** | PoC generation
|
|
94
|
-
| **WAF Bypass** | Multi-layer bypass
|
|
98
|
+
| **Vuln Validator** | PoC generation with false positive reduction |
|
|
99
|
+
| **WAF Bypass** | Multi-layer bypass for Cloudflare, Akamai, AWS WAF |
|
|
95
100
|
|
|
96
|
-
### ⚡ CLI
|
|
101
|
+
### ⚡ CLI & Stability
|
|
97
102
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
# Version check
|
|
103
|
-
exaai --version
|
|
103
|
+
- **Thread-Safety**: Fixed race conditions in async scans
|
|
104
|
+
- **Resource Management**: Auto-shutdown and cleanup of background processes
|
|
105
|
+
- **Installation**: Robust `install.sh` for Linux/macOS (bash/zsh/fish)
|
|
104
106
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
+
```bash
|
|
108
|
+
# New install script
|
|
109
|
+
curl -sSL https://raw.githubusercontent.com/hleliofficiel/ExaAiAgent/main/install.sh | bash
|
|
107
110
|
```
|
|
108
111
|
|
|
109
112
|
---
|
|
@@ -146,6 +149,10 @@ ExaAiAgent is an elite AI-powered cybersecurity agent that acts like a real pene
|
|
|
146
149
|
|
|
147
150
|
```bash
|
|
148
151
|
# Install ExaAiAgent
|
|
152
|
+
|
|
153
|
+
# Method 1: Automated Script (Recommended)
|
|
154
|
+
pip install exaai-agent
|
|
155
|
+
# Method 2: pipx
|
|
149
156
|
pipx install exaai-agent
|
|
150
157
|
|
|
151
158
|
# Configure your AI provider (choose one)
|
|
@@ -287,7 +294,7 @@ jobs:
|
|
|
287
294
|
- uses: actions/checkout@v4
|
|
288
295
|
|
|
289
296
|
- name: Install ExaAiAgent
|
|
290
|
-
run:
|
|
297
|
+
run: curl -sSL https://raw.githubusercontent.com/hleliofficiel/ExaAiAgent/main/install.sh | bash
|
|
291
298
|
|
|
292
299
|
- name: Run ExaAiAgent
|
|
293
300
|
env:
|
|
@@ -339,26 +346,49 @@ export PERPLEXITY_API_KEY="key" # For search capabilities
|
|
|
339
346
|
| `oauth_oidc` | OAuth2/OIDC flaws |
|
|
340
347
|
| `waf_bypass` | WAF bypass techniques |
|
|
341
348
|
| `subdomain_takeover` | Subdomain takeover |
|
|
349
|
+
| `prompt_injection` | AI/LLM prompt injection attacks |
|
|
350
|
+
| `kubernetes_security` | **NEW!** K8s RBAC & Pod Security auditing |
|
|
342
351
|
|
|
343
352
|
---
|
|
344
353
|
|
|
345
354
|
## 🆕 Changelog
|
|
346
355
|
|
|
347
|
-
### v2.
|
|
356
|
+
### v2.1.2 (Latest)
|
|
357
|
+
- **AI Agent Integration**: OpenClaw/Agent compatibility
|
|
358
|
+
- **Stability Fixes**: ToolManager thread-safety, Resource cleanup
|
|
359
|
+
- **DevEx**: New `install.sh` script, improved logging
|
|
360
|
+
|
|
361
|
+
### v2.1.0
|
|
362
|
+
- **New Modules**: K8s, Azure, GCP, Prompt Injection
|
|
363
|
+
- **React2Shell**: CVE-2025-55182 detection
|
|
364
|
+
- **Auto-Discovery**: Improved target detection
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
## 🛠️ Troubleshooting
|
|
348
369
|
|
|
349
|
-
|
|
350
|
-
- ⚡ **Token Optimization** - Lightweight mode & task scaling
|
|
351
|
-
- 🛡️ **5 New Security Modules** - GraphQL, WebSocket, OAuth, WAF, Subdomain
|
|
352
|
-
- 🎨 **New UI/Branding** - Fresh ExaAi logo with Cyan/Purple theme
|
|
353
|
-
- 📊 **Improved Performance** - Reduced unnecessary LLM calls
|
|
370
|
+
### 🔧 Troubleshooting
|
|
354
371
|
|
|
355
|
-
|
|
372
|
+
#### Problem: "LLM Connection Failed" or Model Not Found
|
|
373
|
+
Modern models (like `gemini-3-pro-preview`) require the latest version of `litellm` to be recognized correctly.
|
|
356
374
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
-
|
|
360
|
-
|
|
361
|
-
|
|
375
|
+
**Solution: Update LiteLLM**
|
|
376
|
+
```bash
|
|
377
|
+
pip install -U litellm
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
**Linux/Debian Users (Externally Managed Environment):**
|
|
381
|
+
If you encounter permission errors or "externally-managed-environment", you may need to use a virtual environment (`venv`) or force a user install:
|
|
382
|
+
|
|
383
|
+
```bash
|
|
384
|
+
# Option 1: Virtual Environment (Recommended for Servers)
|
|
385
|
+
python3 -m venv venv
|
|
386
|
+
source venv/bin/activate
|
|
387
|
+
pip install exaai-agent
|
|
388
|
+
|
|
389
|
+
# Option 2: Force User Install
|
|
390
|
+
pip install -U litellm --user --break-system-packages
|
|
391
|
+
```
|
|
362
392
|
|
|
363
393
|
---
|
|
364
394
|
|
|
@@ -8,10 +8,12 @@ exaaiagnt/agents/base_agent.py,sha256=WzVJwjBM_gUo-P92zLHKq7C6wclDsVfAAO-bavLx5C
|
|
|
8
8
|
exaaiagnt/agents/scan_modes.py,sha256=q2sSuTRCh_hOdVfikhHhOrEWl1GRCG9Uh6S6rALhLv0,8580
|
|
9
9
|
exaaiagnt/agents/shared_memory.py,sha256=4Ps_kcUHIRVhpumlaF5ZGXmpoeAFi9JrJgEBK33qB84,10774
|
|
10
10
|
exaaiagnt/agents/state.py,sha256=Tzjdegq3L4IS26XPlK9GQDcwqf6X-KKvih9_4LcXPYw,5881
|
|
11
|
+
exaaiagnt/dashboard/server.py,sha256=jmx6UwBm-Lpso5izf-W0pclqrTDoyBeF89B9l11eemY,3332
|
|
12
|
+
exaaiagnt/dashboard/templates/index.html,sha256=d5_Uwl2bNTm8Ynb_jlOoXftlrZ7F1KptzZBdxyDK3F0,11751
|
|
11
13
|
exaaiagnt/interface/__init__.py,sha256=ww23sFOQhICEIrIo0MtwWv2qHW5qUprvPj8QVjv3SM0,44
|
|
12
14
|
exaaiagnt/interface/assets/tui_styles.tcss,sha256=iwhx72f5bIiSg72168ifyR_Q0TKfL3Bf0lU6cyJw1Bg,12114
|
|
13
|
-
exaaiagnt/interface/cli.py,sha256=
|
|
14
|
-
exaaiagnt/interface/main.py,sha256=
|
|
15
|
+
exaaiagnt/interface/cli.py,sha256=vTkeNELONfXwzQ_XgPhX3UcHVSbOBL_E6USnkRZtM74,9855
|
|
16
|
+
exaaiagnt/interface/main.py,sha256=PO62c4P26qT9v2nLWkfQSC_SWjaCncaxdZUT42U9Lu0,19483
|
|
15
17
|
exaaiagnt/interface/tool_components/__init__.py,sha256=Dz5ci3VMzvhlPOwQ2x9Nd11cmFzx1OP7sdlpZPMTT4k,935
|
|
16
18
|
exaaiagnt/interface/tool_components/agents_graph_renderer.py,sha256=eVFRqmJ-TxyxZ-hssLTweDAio4UvsZZgxo2dKky0N1U,4399
|
|
17
19
|
exaaiagnt/interface/tool_components/base_renderer.py,sha256=P0zYeRnbkr2NYoE8KDQmj1TzrAGX6r7qLMb4Sw7AoTI,1905
|
|
@@ -28,22 +30,25 @@ exaaiagnt/interface/tool_components/terminal_renderer.py,sha256=-ORL2vBH5XImUZrI
|
|
|
28
30
|
exaaiagnt/interface/tool_components/thinking_renderer.py,sha256=-MQLkKCgOJksrustULFf2jhAjJrP5bbfS2BQ6zgNKCc,927
|
|
29
31
|
exaaiagnt/interface/tool_components/user_message_renderer.py,sha256=6gHJ1hG-pwcTsxLM7JuYZuaDu8cZ2MeOuUDF3LGy-4I,1432
|
|
30
32
|
exaaiagnt/interface/tool_components/web_search_renderer.py,sha256=JnJa22ACIcRksfxxdenesUo8Th9cHSxo-fej9YcuYHs,911
|
|
31
|
-
exaaiagnt/interface/tui.py,sha256=
|
|
33
|
+
exaaiagnt/interface/tui.py,sha256=bMuIJvrauCStAJkjvRWzDueLDraKnrHWtC5ZjyuDxOc,49970
|
|
32
34
|
exaaiagnt/interface/utils.py,sha256=xp6eDOC8C0c3cjt791S_jBDs1B-xp_ydIb74QnMLEt8,20219
|
|
33
35
|
exaaiagnt/llm/__init__.py,sha256=hUVixjSSIUtwIP2I5D_9e6Kdxhhunnajgxx_2DEYNww,1095
|
|
34
36
|
exaaiagnt/llm/config.py,sha256=HQ0skwQxtHwiDLDWBCU1Fp4UoQ8tbrTNQw9s7JGVaiY,3303
|
|
35
37
|
exaaiagnt/llm/fallback.py,sha256=oPS0PGRxEHnyyBgS4yP9zdwSf4JFJh4dYZ3g8OFwWEE,11413
|
|
36
|
-
exaaiagnt/llm/llm.py,sha256=
|
|
37
|
-
exaaiagnt/llm/llm_traffic_controller.py,sha256=
|
|
38
|
+
exaaiagnt/llm/llm.py,sha256=pMMRaHCnpD29iJR3ZTotqiONJ5JNI_Bc4Aem1ThZJl8,19858
|
|
39
|
+
exaaiagnt/llm/llm_traffic_controller.py,sha256=DIgJvjrT0MIOStb8g2wTAMoDXp9YLEBlFD5Bwt862K8,12304
|
|
38
40
|
exaaiagnt/llm/memory_compressor.py,sha256=_At7e5QlDv2vrUDUJMEwm4CjNJ2uGYQsOBhiHiQvVr8,7054
|
|
39
41
|
exaaiagnt/llm/output_processor.py,sha256=JC3TtzYj9DJhJRuKzz_VV3WIwAyYhUdZeY1N9c4SzVw,13568
|
|
40
42
|
exaaiagnt/llm/request_queue.py,sha256=2H-jEcI1krY8U8oMoULu-1y6kEV84enI36QLUkTLKm0,9198
|
|
41
43
|
exaaiagnt/llm/utils.py,sha256=0Z0r6qo9IfUSOJt5FJsq3X-veXrA8A09frc2VIy-aS4,2540
|
|
42
|
-
exaaiagnt/prompts/README.md,sha256=
|
|
44
|
+
exaaiagnt/prompts/README.md,sha256=PPeH0Up6_Ygk6zfYchcLVVZ-OqU5PhWIUwYx6KbhFaY,3975
|
|
43
45
|
exaaiagnt/prompts/__init__.py,sha256=nUs1powNe_6sWmM5_KkAIxZj97t5IiMMgNrL39WwUjg,5042
|
|
44
|
-
exaaiagnt/prompts/auto_loader.py,sha256=
|
|
46
|
+
exaaiagnt/prompts/auto_loader.py,sha256=vVXBDLk8O08x3LglREvAReB2GqJqZKIsnhcwsQlKm4w,12994
|
|
45
47
|
exaaiagnt/prompts/cloud/.gitkeep,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
46
48
|
exaaiagnt/prompts/cloud/aws_cloud_security.jinja,sha256=ObimikftsoqGzxhrvI6pQLVRQ4MmkJpjwexORS7P7uo,6768
|
|
49
|
+
exaaiagnt/prompts/cloud/azure_cloud_security.jinja,sha256=jKlQpWvPy6grYtU6S44cP1uKw5sLbCj6QmdUv9tu_PI,5225
|
|
50
|
+
exaaiagnt/prompts/cloud/gcp_cloud_security.jinja,sha256=n5GMgRufa0PBV8WbB6RfmmBAUeJZqEK_67b87MgjF7Y,6656
|
|
51
|
+
exaaiagnt/prompts/cloud/kubernetes_security.jinja,sha256=qmXHxMVg3wcj5aFzi176djJUhSp756obtk2Ff8PWGjo,4068
|
|
47
52
|
exaaiagnt/prompts/coordination/root_agent.jinja,sha256=05VUZKnBX_7-FjEYilEq_OJG4u01_56bf4mzGNbFtJc,1996
|
|
48
53
|
exaaiagnt/prompts/custom/.gitkeep,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
49
54
|
exaaiagnt/prompts/frameworks/fastapi.jinja,sha256=zXa08RDG9tVQu6MZetKCcOUPuDDKJJF1anTei7_2TZg,10200
|
|
@@ -74,6 +79,7 @@ exaaiagnt/prompts/vulnerabilities/open_redirect.jinja,sha256=Mbit385OO7fTSGRb0xF
|
|
|
74
79
|
exaaiagnt/prompts/vulnerabilities/path_traversal_lfi_rfi.jinja,sha256=5Zfr424yM2LyFxt9A6q18RhbIjdq1MB6mpjWbG_FA7o,7916
|
|
75
80
|
exaaiagnt/prompts/vulnerabilities/post_exploitation.jinja,sha256=YgGCIQu1FmrLq-KN930Pb-VqGWQV9BTbPIkcEFzkzac,8396
|
|
76
81
|
exaaiagnt/prompts/vulnerabilities/privilege_escalation.jinja,sha256=XY0atQ4nEkGsmPiNoLtc0QwVTLV8r3w0ZvH4snmCgHE,6796
|
|
82
|
+
exaaiagnt/prompts/vulnerabilities/prompt_injection.jinja,sha256=7AsziV8IFMeQT1sUjFKppd76vlVfNSsiM9W523wew-E,9387
|
|
77
83
|
exaaiagnt/prompts/vulnerabilities/prototype_pollution.jinja,sha256=g-I6ouqaZpxqoTa4MyGHaUKxwlM-gFrPo_F1T8r_ASI,6486
|
|
78
84
|
exaaiagnt/prompts/vulnerabilities/race_conditions.jinja,sha256=ZHxdZc7v7yvhmUWJK3P3kIzOz3oaYRb2OJEzG1momcg,8372
|
|
79
85
|
exaaiagnt/prompts/vulnerabilities/rce.jinja,sha256=tgmocWH3Y9FJ3fBeR9DTR7ViBcuH5salGis8vywJ2h8,8425
|
|
@@ -90,11 +96,11 @@ exaaiagnt/prompts/vulnerabilities/xxe.jinja,sha256=yyWl5i74YiFZIhQknMPWXLKL0C5gw
|
|
|
90
96
|
exaaiagnt/runtime/__init__.py,sha256=MnuwXAMjvj2kQKJCOyzW-qQSpiipGzmESVWz436lqkQ,760
|
|
91
97
|
exaaiagnt/runtime/docker_runtime.py,sha256=lb4cipUbCkwPw3_BxKyICFoIW8Su2zFs_sFW-r59Nfk,16185
|
|
92
98
|
exaaiagnt/runtime/runtime.py,sha256=PRYByipRG9OhtIphIruGBSe4k-glVnYAXH68mikqt78,730
|
|
93
|
-
exaaiagnt/runtime/tool_manager.py,sha256=
|
|
99
|
+
exaaiagnt/runtime/tool_manager.py,sha256=3PSUxTmGsFptNlKkZDnzXyyBA_AfbKvqhMPyRi6_fMU,14770
|
|
94
100
|
exaaiagnt/runtime/tool_server.py,sha256=e23TJYL5w32gMqLS9UJ0xw3XZ4lM38ETBvHVHKk3APU,6835
|
|
95
101
|
exaaiagnt/telemetry/__init__.py,sha256=8QLHMvrVNLlGKezWTf3mTSmTOLIvDS5xVciry1KVS1Y,130
|
|
96
|
-
exaaiagnt/telemetry/tracer.py,sha256=
|
|
97
|
-
exaaiagnt/tools/__init__.py,sha256=
|
|
102
|
+
exaaiagnt/telemetry/tracer.py,sha256=W7jWmsy41LZG_rvRCFRxa6Pxt6tAx8i5O3rW2dM6QUA,13299
|
|
103
|
+
exaaiagnt/tools/__init__.py,sha256=1Z4EECFThur9Bn_EkqVHJYx9Z3pM1cdh6qXc3rTcyPA,4000
|
|
98
104
|
exaaiagnt/tools/agents_graph/__init__.py,sha256=FLJ2kGxXICY2pRKrC0sgIc3w3KhZo7VID7hbwYcgBfM,278
|
|
99
105
|
exaaiagnt/tools/agents_graph/agents_graph_actions.py,sha256=ujBj3R3MpOmIVsN4T3nekVhreu60xA2EEg9rYXCdz2c,21103
|
|
100
106
|
exaaiagnt/tools/agents_graph/agents_graph_actions_schema.xml,sha256=fczqDpNw2m58p2O_G0amBZso--EjEGZuK829lB-cXdE,12617
|
|
@@ -104,16 +110,22 @@ exaaiagnt/tools/browser/browser_actions.py,sha256=6p3drOznDLPVnqSo3CnJjq4qXXSvCh
|
|
|
104
110
|
exaaiagnt/tools/browser/browser_actions_schema.xml,sha256=zZQD8sZWsNnxxnlY3QYDrfKHFu0x6i1vtfSOlIGyiho,9573
|
|
105
111
|
exaaiagnt/tools/browser/browser_instance.py,sha256=vgb-dJP20SLaBOhFExn-uwfjdISBrHJpG7ewfiKQkYU,18605
|
|
106
112
|
exaaiagnt/tools/browser/tab_manager.py,sha256=SMkDFOgEr3ADK2rP5Ko2uK-A24-8p0VsbjoxEj5eU-Y,13011
|
|
107
|
-
exaaiagnt/tools/executor.py,sha256
|
|
113
|
+
exaaiagnt/tools/executor.py,sha256=nglkwrW_Tt0ZAkn9CQUheoOv6Ac5ZaKoRmwCGWY0uIU,11465
|
|
108
114
|
exaaiagnt/tools/file_edit/__init__.py,sha256=8f6VlEoGP627hGtcdLkr63vdrTmdb8uyPIqB0qVgZd8,141
|
|
109
115
|
exaaiagnt/tools/file_edit/file_edit_actions.py,sha256=w-rEB9MphijtXJUyypttQ4DLU4y9rwHd7Zpl21LTTis,3955
|
|
110
116
|
exaaiagnt/tools/file_edit/file_edit_actions_schema.xml,sha256=tt0_QgSjOtTEy8ordsXUcEiVTePiybgn4aisZJ_qnbc,5477
|
|
111
117
|
exaaiagnt/tools/finish/__init__.py,sha256=QIMaHYusly8YaFR3zjYsy_CFawwgtTZvOU7gsEumFrw,68
|
|
112
118
|
exaaiagnt/tools/finish/finish_actions.py,sha256=ZLyOuYMjdTPHN9_6sQxyHwp3-BVSusk5dM2WHUn3WMI,5714
|
|
113
119
|
exaaiagnt/tools/finish/finish_actions_schema.xml,sha256=CS6Vq3ByyNxv2spRWS4oJcmUzWQRB7jvUAOS8aiWd8o,2294
|
|
120
|
+
exaaiagnt/tools/k8s_scanner/__init__.py,sha256=MIo_Hl4p7Zzea9KSR_wVnxnlyyrB9eS8g3DlZxwSsHk,557
|
|
121
|
+
exaaiagnt/tools/k8s_scanner/k8s_actions.py,sha256=DdwnXm0Z86guNsAtuxsNhLeexIFk1y_Xza_GvACd2zM,13477
|
|
122
|
+
exaaiagnt/tools/k8s_scanner/k8s_actions_schema.xml,sha256=s-Qnq8FX6zjT6qIRHG81dq9zSToj6BbnntLGQ-vWzhM,1272
|
|
114
123
|
exaaiagnt/tools/notes/__init__.py,sha256=DUpkZUWN21tb9AXCWfJLrKrgLz9YEBVU8KQy1J6cyxU,189
|
|
115
124
|
exaaiagnt/tools/notes/notes_actions.py,sha256=8ewd1kCxZO_ujKP2oXuU03r9p8EZEYgoO7i_6GWw_VA,5775
|
|
116
125
|
exaaiagnt/tools/notes/notes_actions_schema.xml,sha256=nzirWDyzbPRxaG3jdSjmSCjfY-ggDy1kH7oxAuj-osw,6264
|
|
126
|
+
exaaiagnt/tools/prompt_injection/__init__.py,sha256=YjzfqLYKdOuEeV8WgE_b9swnP2uhYtOlPbeRplKOTzc,645
|
|
127
|
+
exaaiagnt/tools/prompt_injection/prompt_injection_actions.py,sha256=yNJv7ESHBMvzFiNZGI8Jc8m0GwG73Z5yIngYEmZTOic,27903
|
|
128
|
+
exaaiagnt/tools/prompt_injection/prompt_injection_actions_schema.xml,sha256=wZHYpaS35tOEuzY8j1-4JkkLgDWvFhJwm7MzlRGpfyg,1381
|
|
117
129
|
exaaiagnt/tools/proxy/__init__.py,sha256=K3BFmT6QWw9heB7l7DnmI-Yj-DOI3BAow6g0GLWsA0c,329
|
|
118
130
|
exaaiagnt/tools/proxy/proxy_actions.py,sha256=HyfI6iUVkRSnzLR_xNRKWhr4roDEAatGyYTq4wij2Js,2549
|
|
119
131
|
exaaiagnt/tools/proxy/proxy_actions_schema.xml,sha256=d87SUKD2J16KQCCFpI5w2y-Ax1NgwOuGO3crr1bFPDw,11567
|
|
@@ -121,14 +133,14 @@ exaaiagnt/tools/proxy/proxy_manager.py,sha256=rmy8c_7jcYl9WeeA3O2lcZBnN7hESpTYxo
|
|
|
121
133
|
exaaiagnt/tools/python/__init__.py,sha256=l5mFWKbtis61S8lOQY-gFn-vIlc13lu1K-pqqRywOCk,72
|
|
122
134
|
exaaiagnt/tools/python/python_actions.py,sha256=ggLFFLW7cQamY1fvgUxzz9beOy_deY1zdouK_K8iF50,1436
|
|
123
135
|
exaaiagnt/tools/python/python_actions_schema.xml,sha256=XcIUjz5uEoI7J3VFcby0O-0ovm9r9cIoADfpqDGJXlU,7122
|
|
124
|
-
exaaiagnt/tools/python/python_instance.py,sha256=
|
|
136
|
+
exaaiagnt/tools/python/python_instance.py,sha256=pXF8MFVjxNeIUt6h_f2Oe5gjFEYJ-NM5Lqc6A3PUi40,6246
|
|
125
137
|
exaaiagnt/tools/python/python_manager.py,sha256=C_k8C8uQ6ESpAgzhbf3km9jeFyI52SGd2m36mD1ErhM,4235
|
|
126
138
|
exaaiagnt/tools/registry.py,sha256=iBRwtiWLQr3fo1vSAOehWbIlr6cqnNPLB1dluXtsf8s,6029
|
|
127
139
|
exaaiagnt/tools/reporting/__init__.py,sha256=_cYxb3OP0vZtCwO_ExLBjhAn1ECaG-SH1Z4wfGDyT1Y,110
|
|
128
|
-
exaaiagnt/tools/reporting/reporting_actions.py,sha256=
|
|
140
|
+
exaaiagnt/tools/reporting/reporting_actions.py,sha256=CYAXz5ee_eN-zFxBdhJ-QsmtCECulnf9m44y2SrX4kk,3107
|
|
129
141
|
exaaiagnt/tools/reporting/reporting_actions_schema.xml,sha256=y_g0iuyBuCh79fvA0ri8fOPlXY7uUd-P-mdzXLUyIJg,1629
|
|
130
|
-
exaaiagnt/tools/response_analyzer.py,sha256=
|
|
131
|
-
exaaiagnt/tools/smart_fuzzer.py,sha256=
|
|
142
|
+
exaaiagnt/tools/response_analyzer.py,sha256=0B8LZ3pvBImH40t8QqCtLdxwc28Chq-2C8I23zi-XJM,10647
|
|
143
|
+
exaaiagnt/tools/smart_fuzzer.py,sha256=cN9TgJcLz3MzDuBIP8EVtEdoJL67LcrFBc2zo9j53cE,12367
|
|
132
144
|
exaaiagnt/tools/terminal/__init__.py,sha256=xvflcrbLQ31o_K3cWFsIhTm7gxY5JF0nVnhOIadwFV0,80
|
|
133
145
|
exaaiagnt/tools/terminal/terminal_actions.py,sha256=5z3OTF0YwZL0n_CVsx1yLmbSx7oUQg-xD0Wv8IXsIlw,892
|
|
134
146
|
exaaiagnt/tools/terminal/terminal_actions_schema.xml,sha256=L7dzjvKNZpJA0qDGp1gCBuwXiY4mtjOq7T2tNDmUPA4,7257
|
|
@@ -138,13 +150,13 @@ exaaiagnt/tools/thinking/__init__.py,sha256=-v4fG4fyFkqsTSWspDtCT6IRlyRM8zeUwEM-
|
|
|
138
150
|
exaaiagnt/tools/thinking/thinking_actions.py,sha256=Ynw1gBN4Z8iXGll0v9kObhkjQzc8-dEcHTWKeyFutAw,568
|
|
139
151
|
exaaiagnt/tools/thinking/thinking_actions_schema.xml,sha256=otD4dOhQx4uyudLnjA_HIP6EmUS5NvKG4l3CVFrg8go,2756
|
|
140
152
|
exaaiagnt/tools/tool_prompts.py,sha256=eQL7B8H8mo6d6mvtN_X9rmSfjwgz9Cuzfg7C7WH6TnU,5751
|
|
141
|
-
exaaiagnt/tools/vuln_validator.py,sha256=
|
|
153
|
+
exaaiagnt/tools/vuln_validator.py,sha256=jViG2-3pVBwI3VXe5JsgCFsDBNk9nmT_s2vEe7cZjmA,14025
|
|
142
154
|
exaaiagnt/tools/waf_bypass.py,sha256=71oPWnDHjn2EHi6I1SluZCKfqfXkA5j61oIkL5kNoSw,12047
|
|
143
155
|
exaaiagnt/tools/web_search/__init__.py,sha256=m5PCHXqeNVraLRLNIbh54Z2N4Y_75d-ftqwyq3dbCd0,70
|
|
144
|
-
exaaiagnt/tools/web_search/web_search_actions.py,sha256=
|
|
156
|
+
exaaiagnt/tools/web_search/web_search_actions.py,sha256=k9zjzdqTVsNdh0pFtntIfwO77_ThQIedXSaUhJxPs2U,3295
|
|
145
157
|
exaaiagnt/tools/web_search/web_search_actions_schema.xml,sha256=Ihc3Gv4LaPI_MzBbwZOt3y4pwg9xmtl8KfPNvFihEP4,4805
|
|
146
|
-
exaai_agent-2.0.
|
|
147
|
-
exaai_agent-2.0.
|
|
148
|
-
exaai_agent-2.0.
|
|
149
|
-
exaai_agent-2.0.
|
|
150
|
-
exaai_agent-2.0.
|
|
158
|
+
exaai_agent-2.2.0.dist-info/METADATA,sha256=92DfPaFHPXBZkhl09w4pWJ0CE_mKFs4mIOh3TMd3bZ8,13421
|
|
159
|
+
exaai_agent-2.2.0.dist-info/WHEEL,sha256=kJCRJT_g0adfAJzTx2GUMmS80rTJIVHRCfG0DQgLq3o,88
|
|
160
|
+
exaai_agent-2.2.0.dist-info/entry_points.txt,sha256=iLSTRDSjN8Zyc2Wo6WXmr4MtyEWkdqtZ1j_Hx73MiUs,137
|
|
161
|
+
exaai_agent-2.2.0.dist-info/licenses/LICENSE,sha256=RV6IGl0sWdfbbtJmjPr1w_qwGyGt2jv02PXsAzN_kNs,11460
|
|
162
|
+
exaai_agent-2.2.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
|
|
2
|
+
from fastapi.staticfiles import StaticFiles
|
|
3
|
+
from fastapi.responses import HTMLResponse
|
|
4
|
+
import uvicorn
|
|
5
|
+
import json
|
|
6
|
+
import asyncio
|
|
7
|
+
import logging
|
|
8
|
+
from typing import List, Dict, Any
|
|
9
|
+
import os
|
|
10
|
+
|
|
11
|
+
from exaaiagnt.telemetry.tracer import get_global_tracer
|
|
12
|
+
|
|
13
|
+
app = FastAPI(title="ExaAi Live Dashboard")
|
|
14
|
+
|
|
15
|
+
# Serve static files
|
|
16
|
+
static_dir = os.path.join(os.path.dirname(__file__), "static")
|
|
17
|
+
app.mount("/static", StaticFiles(directory=static_dir), name="static")
|
|
18
|
+
|
|
19
|
+
class ConnectionManager:
|
|
20
|
+
def __init__(self):
|
|
21
|
+
self.active_connections: List[WebSocket] = []
|
|
22
|
+
|
|
23
|
+
async def connect(self, websocket: WebSocket):
|
|
24
|
+
await websocket.accept()
|
|
25
|
+
self.active_connections.append(websocket)
|
|
26
|
+
|
|
27
|
+
def disconnect(self, websocket: WebSocket):
|
|
28
|
+
self.active_connections.remove(websocket)
|
|
29
|
+
|
|
30
|
+
async def broadcast(self, message: str):
|
|
31
|
+
for connection in self.active_connections:
|
|
32
|
+
try:
|
|
33
|
+
await connection.send_text(message)
|
|
34
|
+
except Exception:
|
|
35
|
+
pass
|
|
36
|
+
|
|
37
|
+
manager = ConnectionManager()
|
|
38
|
+
|
|
39
|
+
@app.get("/")
|
|
40
|
+
async def get_dashboard():
|
|
41
|
+
html_path = os.path.join(os.path.dirname(__file__), "templates", "index.html")
|
|
42
|
+
with open(html_path, "r") as f:
|
|
43
|
+
return HTMLResponse(content=f.read())
|
|
44
|
+
|
|
45
|
+
@app.get("/api/stats")
|
|
46
|
+
async def get_stats():
|
|
47
|
+
tracer = get_global_tracer()
|
|
48
|
+
if not tracer:
|
|
49
|
+
return {"status": "Waiting for agent..."}
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
"agents_count": len(tracer.agents),
|
|
53
|
+
"vulnerabilities": len(tracer.vulnerability_reports),
|
|
54
|
+
"tool_calls": len(tracer.tool_executions),
|
|
55
|
+
"start_time": tracer.start_time,
|
|
56
|
+
"run_name": tracer.run_name
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@app.get("/api/vulnerabilities")
|
|
60
|
+
async def get_vulns():
|
|
61
|
+
tracer = get_global_tracer()
|
|
62
|
+
if not tracer:
|
|
63
|
+
return []
|
|
64
|
+
return tracer.vulnerability_reports
|
|
65
|
+
|
|
66
|
+
@app.websocket("/ws")
|
|
67
|
+
async def websocket_endpoint(websocket: WebSocket):
|
|
68
|
+
await manager.connect(websocket)
|
|
69
|
+
try:
|
|
70
|
+
while True:
|
|
71
|
+
# Send updates every second
|
|
72
|
+
tracer = get_global_tracer()
|
|
73
|
+
if tracer:
|
|
74
|
+
data = {
|
|
75
|
+
"agents": tracer.agents,
|
|
76
|
+
"stats": {
|
|
77
|
+
"active": sum(1 for a in tracer.agents.values() if a.get("status") == "running"),
|
|
78
|
+
"completed": sum(1 for a in tracer.agents.values() if a.get("status") == "completed"),
|
|
79
|
+
"failed": sum(1 for a in tracer.agents.values() if a.get("status") == "failed"),
|
|
80
|
+
},
|
|
81
|
+
"recent_logs": tracer.chat_messages[-10:] if tracer.chat_messages else []
|
|
82
|
+
}
|
|
83
|
+
await websocket.send_json(data)
|
|
84
|
+
await asyncio.sleep(1)
|
|
85
|
+
except WebSocketDisconnect:
|
|
86
|
+
manager.disconnect(websocket)
|
|
87
|
+
except Exception as e:
|
|
88
|
+
logging.error(f"WebSocket error: {e}")
|
|
89
|
+
manager.disconnect(websocket)
|
|
90
|
+
|
|
91
|
+
def start_dashboard(host="0.0.0.0", port=8000):
|
|
92
|
+
"""Start the dashboard server in a background thread or process."""
|
|
93
|
+
config = uvicorn.Config(app, host=host, port=port, log_level="error")
|
|
94
|
+
server = uvicorn.Server(config)
|
|
95
|
+
# We'll run this in a thread from the main agent
|
|
96
|
+
import threading
|
|
97
|
+
t = threading.Thread(target=server.run, daemon=True)
|
|
98
|
+
t.start()
|
|
99
|
+
return t
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>ExaAi Mission Control</title>
|
|
7
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
8
|
+
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
9
|
+
<style>
|
|
10
|
+
body { background-color: #0f172a; color: #e2e8f0; font-family: 'Courier New', Courier, monospace; }
|
|
11
|
+
.neon-text { text-shadow: 0 0 5px #3b82f6, 0 0 10px #3b82f6; }
|
|
12
|
+
.neon-border { box-shadow: 0 0 5px #3b82f6; border-color: #3b82f6; }
|
|
13
|
+
.agent-card { transition: all 0.3s ease; }
|
|
14
|
+
.agent-card:hover { transform: translateY(-2px); box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); }
|
|
15
|
+
.vuln-critical { border-left: 4px solid #ef4444; background: rgba(239, 68, 68, 0.1); }
|
|
16
|
+
.vuln-high { border-left: 4px solid #f97316; background: rgba(249, 115, 22, 0.1); }
|
|
17
|
+
.vuln-medium { border-left: 4px solid #eab308; background: rgba(234, 179, 8, 0.1); }
|
|
18
|
+
::-webkit-scrollbar { width: 8px; }
|
|
19
|
+
::-webkit-scrollbar-track { background: #1e293b; }
|
|
20
|
+
::-webkit-scrollbar-thumb { background: #475569; border-radius: 4px; }
|
|
21
|
+
::-webkit-scrollbar-thumb:hover { background: #64748b; }
|
|
22
|
+
</style>
|
|
23
|
+
</head>
|
|
24
|
+
<body class="h-screen flex flex-col overflow-hidden">
|
|
25
|
+
<!-- Header -->
|
|
26
|
+
<header class="bg-slate-900 border-b border-slate-700 p-4 flex justify-between items-center shadow-lg z-10">
|
|
27
|
+
<div class="flex items-center gap-3">
|
|
28
|
+
<div class="w-3 h-3 rounded-full bg-green-500 animate-pulse"></div>
|
|
29
|
+
<h1 class="text-2xl font-bold tracking-wider text-blue-400 neon-text">EXAAI <span class="text-white">MISSION CONTROL</span></h1>
|
|
30
|
+
</div>
|
|
31
|
+
<div class="flex gap-6 text-sm">
|
|
32
|
+
<div class="flex flex-col items-end">
|
|
33
|
+
<span class="text-slate-400">STATUS</span>
|
|
34
|
+
<span class="text-green-400 font-bold">ONLINE</span>
|
|
35
|
+
</div>
|
|
36
|
+
<div class="flex flex-col items-end">
|
|
37
|
+
<span class="text-slate-400">AGENTS</span>
|
|
38
|
+
<span id="total-agents" class="text-blue-400 font-bold">0</span>
|
|
39
|
+
</div>
|
|
40
|
+
<div class="flex flex-col items-end">
|
|
41
|
+
<span class="text-slate-400">VULNERABILITIES</span>
|
|
42
|
+
<span id="total-vulns" class="text-red-500 font-bold neon-text">0</span>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
</header>
|
|
46
|
+
|
|
47
|
+
<!-- Main Content -->
|
|
48
|
+
<main class="flex-1 flex overflow-hidden">
|
|
49
|
+
<!-- Sidebar: Agent Tree -->
|
|
50
|
+
<aside class="w-1/4 bg-slate-900 border-r border-slate-700 flex flex-col">
|
|
51
|
+
<div class="p-3 border-b border-slate-700 bg-slate-800">
|
|
52
|
+
<h2 class="font-bold text-slate-300 flex items-center gap-2">
|
|
53
|
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"></path></svg>
|
|
54
|
+
Active Operations
|
|
55
|
+
</h2>
|
|
56
|
+
</div>
|
|
57
|
+
<div id="agent-list" class="flex-1 overflow-y-auto p-3 space-y-2">
|
|
58
|
+
<!-- Agents injected here -->
|
|
59
|
+
</div>
|
|
60
|
+
</aside>
|
|
61
|
+
|
|
62
|
+
<!-- Center: Live Feed & Stats -->
|
|
63
|
+
<section class="flex-1 flex flex-col bg-slate-900/50 relative">
|
|
64
|
+
<!-- Matrix Rain Background Effect (Optional/Subtle) -->
|
|
65
|
+
<div class="absolute inset-0 pointer-events-none opacity-5 bg-[url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0IiBoZWlnaHQ9IjQiPgo8cmVjdCB3aWR0aD0iNCIgaGVpZ2h0PSI0IiBmaWxsPSIjMWUyOTNiIi8+CjxyZWN0IHdpZHRoPSIxIiBoZWlnaHQ9IjEiIGZpbGw9IiMzMzQxNTUiLz4KPC9zdmc+')]"></div>
|
|
66
|
+
|
|
67
|
+
<div class="h-1/2 border-b border-slate-700 flex">
|
|
68
|
+
<!-- Live Terminal Log -->
|
|
69
|
+
<div class="w-2/3 border-r border-slate-700 flex flex-col">
|
|
70
|
+
<div class="p-2 bg-slate-800 border-b border-slate-700 flex justify-between">
|
|
71
|
+
<span class="text-xs font-mono text-slate-400">>_ SYSTEM LOGS</span>
|
|
72
|
+
<span class="text-xs text-green-500">● LIVE</span>
|
|
73
|
+
</div>
|
|
74
|
+
<div id="console-logs" class="flex-1 overflow-y-auto p-4 font-mono text-xs text-slate-300 space-y-1 bg-black/40">
|
|
75
|
+
<!-- Logs injected here -->
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
<!-- Quick Stats Chart -->
|
|
80
|
+
<div class="w-1/3 p-4 bg-slate-800/30 flex flex-col items-center justify-center">
|
|
81
|
+
<canvas id="statusChart"></canvas>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
<!-- Vulnerabilities Panel -->
|
|
86
|
+
<div class="h-1/2 flex flex-col bg-slate-900">
|
|
87
|
+
<div class="p-3 border-b border-slate-700 bg-slate-800 flex justify-between items-center">
|
|
88
|
+
<h2 class="font-bold text-red-400 flex items-center gap-2">
|
|
89
|
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path></svg>
|
|
90
|
+
Detected Vulnerabilities
|
|
91
|
+
</h2>
|
|
92
|
+
<span class="text-xs text-slate-500">Auto-refreshing...</span>
|
|
93
|
+
</div>
|
|
94
|
+
<div id="vuln-list" class="flex-1 overflow-y-auto p-4 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
95
|
+
<!-- Vulns injected here -->
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
</section>
|
|
99
|
+
</main>
|
|
100
|
+
|
|
101
|
+
<script>
|
|
102
|
+
const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
103
|
+
const socket = new WebSocket(`${wsProtocol}//${window.location.host}/ws`);
|
|
104
|
+
|
|
105
|
+
// Chart setup
|
|
106
|
+
const ctx = document.getElementById('statusChart').getContext('2d');
|
|
107
|
+
const statusChart = new Chart(ctx, {
|
|
108
|
+
type: 'doughnut',
|
|
109
|
+
data: {
|
|
110
|
+
labels: ['Active', 'Completed', 'Failed'],
|
|
111
|
+
datasets: [{
|
|
112
|
+
data: [0, 0, 0],
|
|
113
|
+
backgroundColor: ['#3b82f6', '#22c55e', '#ef4444'],
|
|
114
|
+
borderWidth: 0
|
|
115
|
+
}]
|
|
116
|
+
},
|
|
117
|
+
options: {
|
|
118
|
+
responsive: true,
|
|
119
|
+
plugins: {
|
|
120
|
+
legend: { position: 'bottom', labels: { color: '#94a3b8' } }
|
|
121
|
+
},
|
|
122
|
+
cutout: '70%'
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
socket.onmessage = function(event) {
|
|
127
|
+
const data = JSON.parse(event.data);
|
|
128
|
+
updateDashboard(data);
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
function updateDashboard(data) {
|
|
132
|
+
// Update Headers
|
|
133
|
+
document.getElementById('total-agents').textContent = Object.keys(data.agents).length;
|
|
134
|
+
|
|
135
|
+
// Update Agent List
|
|
136
|
+
const agentList = document.getElementById('agent-list');
|
|
137
|
+
agentList.innerHTML = '';
|
|
138
|
+
|
|
139
|
+
Object.values(data.agents).forEach(agent => {
|
|
140
|
+
const div = document.createElement('div');
|
|
141
|
+
div.className = `agent-card p-3 rounded bg-slate-800 border border-slate-700 ${agent.status === 'running' ? 'border-l-4 border-l-blue-500' : ''}`;
|
|
142
|
+
div.innerHTML = `
|
|
143
|
+
<div class="flex justify-between items-start mb-1">
|
|
144
|
+
<span class="font-bold text-xs text-slate-200 truncate" title="${agent.name}">${agent.name}</span>
|
|
145
|
+
<span class="text-[10px] px-1.5 py-0.5 rounded ${getStatusColor(agent.status)}">${agent.status}</span>
|
|
146
|
+
</div>
|
|
147
|
+
<div class="text-[10px] text-slate-500 truncate">${agent.id.substring(0, 8)}...</div>
|
|
148
|
+
<div class="text-[11px] text-slate-400 mt-1 line-clamp-2">${agent.task || 'No task description'}</div>
|
|
149
|
+
`;
|
|
150
|
+
agentList.appendChild(div);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
// Update Logs
|
|
154
|
+
const logContainer = document.getElementById('console-logs');
|
|
155
|
+
logContainer.innerHTML = '';
|
|
156
|
+
data.recent_logs.forEach(log => {
|
|
157
|
+
const div = document.createElement('div');
|
|
158
|
+
const time = new Date(log.timestamp * 1000).toLocaleTimeString();
|
|
159
|
+
const color = log.role === 'assistant' ? 'text-blue-400' : 'text-slate-400';
|
|
160
|
+
div.innerHTML = `<span class="text-slate-600">[${time}]</span> <span class="${color}">${log.role.toUpperCase()}:</span> <span class="text-slate-300">${escapeHtml(log.content.substring(0, 150))}...</span>`;
|
|
161
|
+
logContainer.appendChild(div);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// Update Chart
|
|
165
|
+
statusChart.data.datasets[0].data = [
|
|
166
|
+
data.stats.active,
|
|
167
|
+
data.stats.completed,
|
|
168
|
+
data.stats.failed
|
|
169
|
+
];
|
|
170
|
+
statusChart.update();
|
|
171
|
+
|
|
172
|
+
// Update Vulns (Fetching separately or from WS if included)
|
|
173
|
+
fetchVulns();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
async function fetchVulns() {
|
|
177
|
+
try {
|
|
178
|
+
const response = await fetch('/api/vulnerabilities');
|
|
179
|
+
const vulns = await response.json();
|
|
180
|
+
document.getElementById('total-vulns').textContent = vulns.length;
|
|
181
|
+
|
|
182
|
+
const container = document.getElementById('vuln-list');
|
|
183
|
+
container.innerHTML = '';
|
|
184
|
+
|
|
185
|
+
if (vulns.length === 0) {
|
|
186
|
+
container.innerHTML = '<div class="col-span-full text-center text-slate-500 py-10">No vulnerabilities detected... yet.</div>';
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
vulns.forEach(v => {
|
|
191
|
+
const div = document.createElement('div');
|
|
192
|
+
const severityClass = `vuln-${v.severity.toLowerCase()}`;
|
|
193
|
+
div.className = `p-4 rounded bg-slate-800 border border-slate-700 ${severityClass}`;
|
|
194
|
+
div.innerHTML = `
|
|
195
|
+
<div class="flex justify-between items-center mb-2">
|
|
196
|
+
<h3 class="font-bold text-sm text-white">${v.title}</h3>
|
|
197
|
+
<span class="text-[10px] font-bold uppercase tracking-wider px-2 py-1 bg-black/30 rounded text-white">${v.severity}</span>
|
|
198
|
+
</div>
|
|
199
|
+
<p class="text-xs text-slate-400 line-clamp-3 mb-2">${v.content}</p>
|
|
200
|
+
<div class="text-[10px] text-slate-500">ID: ${v.report_id}</div>
|
|
201
|
+
`;
|
|
202
|
+
container.appendChild(div);
|
|
203
|
+
});
|
|
204
|
+
} catch (e) {
|
|
205
|
+
console.error("Failed to fetch vulns", e);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function getStatusColor(status) {
|
|
210
|
+
switch(status) {
|
|
211
|
+
case 'running': return 'bg-blue-900 text-blue-300';
|
|
212
|
+
case 'completed': return 'bg-green-900 text-green-300';
|
|
213
|
+
case 'failed': return 'bg-red-900 text-red-300';
|
|
214
|
+
default: return 'bg-slate-700 text-slate-300';
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function escapeHtml(text) {
|
|
219
|
+
if (!text) return "";
|
|
220
|
+
return text
|
|
221
|
+
.replace(/&/g, "&")
|
|
222
|
+
.replace(/</g, "<")
|
|
223
|
+
.replace(/>/g, ">")
|
|
224
|
+
.replace(/"/g, """)
|
|
225
|
+
.replace(/'/g, "'");
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Initial load
|
|
229
|
+
fetchVulns();
|
|
230
|
+
</script>
|
|
231
|
+
</body>
|
|
232
|
+
</html>
|