devops-copilot 0.1.0__tar.gz → 0.1.1__tar.gz
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.
- devops_copilot-0.1.1/PKG-INFO +139 -0
- devops_copilot-0.1.1/README.md +113 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/cli/main.py +41 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/chat/agent.py +93 -13
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/chat/router.py +77 -4
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/knowledge/service.py +52 -1
- devops_copilot-0.1.1/devops_copilot.egg-info/PKG-INFO +139 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/pyproject.toml +1 -1
- devops_copilot-0.1.0/PKG-INFO +0 -81
- devops_copilot-0.1.0/README.md +0 -55
- devops_copilot-0.1.0/devops_copilot.egg-info/PKG-INFO +0 -81
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/__init__.py +0 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/cli/__init__.py +0 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/cli/config.py +0 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/core/config.py +0 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/core/database/__init__.py +0 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/core/security.py +0 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/main.py +0 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/__init__.py +0 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/auth/__init__.py +0 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/auth/router.py +0 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/auth/schema.py +0 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/auth/service.py +0 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/chat/__init__.py +0 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/chat/models.py +0 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/chat/schema.py +0 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/guardrails/__init__.py +0 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/guardrails/schema.py +0 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/guardrails/service.py +0 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/knowledge/__init__.py +0 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/servers/__init__.py +0 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/servers/models.py +0 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/servers/router.py +0 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/servers/schema.py +0 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/servers/service.py +0 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/devops_copilot.egg-info/SOURCES.txt +0 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/devops_copilot.egg-info/dependency_links.txt +0 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/devops_copilot.egg-info/entry_points.txt +0 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/devops_copilot.egg-info/requires.txt +0 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/devops_copilot.egg-info/top_level.txt +0 -0
- {devops_copilot-0.1.0 → devops_copilot-0.1.1}/setup.cfg +0 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: devops-copilot
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: An AI-driven DevOps Copilot and CLI Client for managing bare-metal servers securely
|
|
5
|
+
Author: irzix
|
|
6
|
+
Requires-Python: >=3.12
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: typer>=0.12.0
|
|
9
|
+
Requires-Dist: httpx>=0.27.0
|
|
10
|
+
Requires-Dist: websockets>=12.0
|
|
11
|
+
Provides-Extra: server
|
|
12
|
+
Requires-Dist: fastapi>=0.111.0; extra == "server"
|
|
13
|
+
Requires-Dist: uvicorn>=0.30.0; extra == "server"
|
|
14
|
+
Requires-Dist: sqlmodel>=0.0.22; extra == "server"
|
|
15
|
+
Requires-Dist: pyjwt>=2.8.0; extra == "server"
|
|
16
|
+
Requires-Dist: aiosqlite>=0.20.0; extra == "server"
|
|
17
|
+
Requires-Dist: cryptography>=42.0.0; extra == "server"
|
|
18
|
+
Requires-Dist: langchain>=0.2.0; extra == "server"
|
|
19
|
+
Requires-Dist: chromadb>=0.5.0; extra == "server"
|
|
20
|
+
Requires-Dist: pydantic-settings>=2.2.0; extra == "server"
|
|
21
|
+
Requires-Dist: bcrypt>=4.1.0; extra == "server"
|
|
22
|
+
Requires-Dist: python-multipart>=0.0.9; extra == "server"
|
|
23
|
+
Requires-Dist: greenlet>=3.0.0; extra == "server"
|
|
24
|
+
Requires-Dist: langchain-openai>=0.1.0; extra == "server"
|
|
25
|
+
Requires-Dist: asyncssh>=2.14.0; extra == "server"
|
|
26
|
+
|
|
27
|
+
# DevOps Copilot 🚀
|
|
28
|
+
|
|
29
|
+
**An autonomous, self-learning AI DevOps Assistant & CLI Client that manages bare-metal servers with Experiential Memory (`ExpeL`), Semantic Guardrails, and Real-Time SSH Tunneling.**
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 💡 About The Project
|
|
34
|
+
|
|
35
|
+
Managing infrastructure via traditional CLI tools or basic AI wrappers often leads to dangerous mistakes, repetitive debugging dead-ends, and fragmented server logs. **DevOps Copilot** redefines server management by bringing **Closed-Loop Experiential Learning (ExpeL)** directly to your terminal.
|
|
36
|
+
|
|
37
|
+
Unlike standard AI chat wrappers that forget previous troubleshooting sessions, `DevOps Copilot` builds a permanent, structured **ChromaDB Vector Knowledge Base** of your infrastructure:
|
|
38
|
+
|
|
39
|
+
- **🧠 Zero-Click Experiential Learning (ExpeL & Reflexion):** Every time an incident or bug is diagnosed and resolved, the agent distills the entire session into a structured Postmortem (`Problem`, `Real Cause`, `What didn't work`, `What worked`). Before tackling new errors, relevant past lessons are **automatically retrieved and injected** into the agent's context—ensuring it *never repeats a dead end*.
|
|
40
|
+
- **🛡️ Semantic Security Guardrails:** Local vector search intercepts and blocks catastrophic shell commands (e.g., `rm -rf /`, `mkfs`) before they ever touch your servers.
|
|
41
|
+
- **🧑💻 Human-in-the-Loop (HITL) Approvals:** State-modifying actions dynamically prompt for explicit admin confirmation (`[y/N]`) inside the terminal with clean prompt synchronization.
|
|
42
|
+
- **⚡ Real-Time Async Execution Tunnel:** Streams LLM reasoning, SSH `stdout`, and `stderr` line-by-line via resilient WebSockets with automatic reconnection and exponential backoff.
|
|
43
|
+
- **🔒 Zero-Trust Credential Encryption:** Passwords and SSH private keys are encrypted at rest using AES-256 (`Fernet`).
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 🏛️ System Architecture & ExpeL Loop
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
+-----------------------------------------------------------------------------------+
|
|
51
|
+
| DevOps Copilot CLI |
|
|
52
|
+
| (Typer Async Client + Real-Time WebSocket Tunnel + [y/N] Terminal Approval) |
|
|
53
|
+
+-----------------------------------------------------------------------------------+
|
|
54
|
+
| ^
|
|
55
|
+
REST Auth/CRUD | | WebSocket Stream (stdout/stderr)
|
|
56
|
+
v |
|
|
57
|
+
+-----------------------------------------------------------------------------------+
|
|
58
|
+
| FastAPI Backend Server |
|
|
59
|
+
| |
|
|
60
|
+
| +------------------------+ +-----------------------+ +--------------------+ |
|
|
61
|
+
| | Auth Module | | Servers Module | | Guardrails Module | |
|
|
62
|
+
| | (JWT & AES Fernet) | | (AsyncSSH Execution) | | (Vector Blacklist) | |
|
|
63
|
+
| +------------------------+ +-----------------------+ +--------------------+ |
|
|
64
|
+
| |
|
|
65
|
+
| +-----------------------------------------------------------------------------+ |
|
|
66
|
+
| | Chat & Agent Module | |
|
|
67
|
+
| | LangChain StateGraph + Zero-Click ExpeL Injection + OpenRouter LLM | |
|
|
68
|
+
| +-----------------------------------------------------------------------------+ |
|
|
69
|
+
| | |
|
|
70
|
+
| v |
|
|
71
|
+
| +-----------------------------------------------------------------------------+ |
|
|
72
|
+
| | Knowledge Base (ChromaDB) | |
|
|
73
|
+
| | [command_history] [server_logs] [server_configs] [lessons_learned] | |
|
|
74
|
+
| +-----------------------------------------------------------------------------+ |
|
|
75
|
+
+-----------------------------------------------------------------------------------+
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### The Closed-Loop Experiential Learning (`ExpeL`) Flow:
|
|
79
|
+
1. **Observe & Act:** Agent connects via `AsyncSSH`, runs non-destructive diagnostics or approved actions, and indexes outputs into `command_history` and `server_logs`.
|
|
80
|
+
2. **Judge & Extract:** When an incident is resolved, running `devops-copilot lesson <session_id>` triggers an automated LLM extraction (`Problem`, `Real Cause`, `What didn't work`, `What worked`) stored in `lessons_learned`.
|
|
81
|
+
3. **Zero-Click Injection (Future Decision):** On any future chat turn or command error, the `inject_experiential_memory` middleware queries `lessons_learned` and injects proven solutions directly into the prompt context.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Key Features
|
|
86
|
+
- **Experiential Learning (ExpeL / Reflexion Postmortems):** Distills complex debugging sessions into structured `Lessons Learned` cards indexed into ChromaDB with zero-click context injection.
|
|
87
|
+
- **Lean RAG Knowledge Base:** Automatically chunks and indexes executed SSH command outputs, logs, and server configs into separate **ChromaDB** collections.
|
|
88
|
+
- **Semantic Guardrails:** Uses local vector search to intercept and block dangerous terminal commands.
|
|
89
|
+
- **Human-in-the-Loop (HITL):** Enforces admin approval (`[y/N]`) inside the terminal for any state-modifying actions.
|
|
90
|
+
- **CLI Connection Resilience:** Automatically reconnects to the WebSocket server using exponential backoff if the network drops or the server restarts.
|
|
91
|
+
- **Real-Time Streaming:** Streams LLM thoughts and active SSH `stdout`/`stderr` line-by-line using WebSockets with 30s execution timeouts.
|
|
92
|
+
- **Encrypted Credentials:** Securely encrypts passwords and SSH private keys using Fernet (AES-256).
|
|
93
|
+
- **Server & Session CRUD:** Full REST API support for updating/deleting server connections and deleting chat sessions.
|
|
94
|
+
- **Flexible AI Models:** Powered by **OpenRouter** (supports Llama 3, Gemini, GPT, etc.).
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## 📦 Quick Start (Backend Server)
|
|
99
|
+
|
|
100
|
+
### 1. Configure Settings
|
|
101
|
+
Copy the env file and populate keys:
|
|
102
|
+
```bash
|
|
103
|
+
cp .env.example .env
|
|
104
|
+
```
|
|
105
|
+
Make sure to add your `OPENROUTER_API_KEY` and a custom base64 `ENCRYPTION_KEY` in `.env`.
|
|
106
|
+
|
|
107
|
+
### 2. Run with Docker Compose
|
|
108
|
+
```bash
|
|
109
|
+
docker compose up -d --build
|
|
110
|
+
```
|
|
111
|
+
The server will boot on port `8000`. Database tables and security blacklist vectors are automatically seeded on startup.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## 💻 Quick Start (CLI Client)
|
|
116
|
+
|
|
117
|
+
### 1. Install Globally
|
|
118
|
+
Install the package in editable mode from your local repository root:
|
|
119
|
+
```bash
|
|
120
|
+
uv pip install -e .
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### 2. Authenticate
|
|
124
|
+
Configure the server URL and log in to get your JWT access token:
|
|
125
|
+
```bash
|
|
126
|
+
devops-copilot login
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### 3. Interactive Chat & Auto-Postmortems
|
|
130
|
+
Start the real-time DevOps chat session:
|
|
131
|
+
```bash
|
|
132
|
+
devops-copilot chat
|
|
133
|
+
```
|
|
134
|
+
*Ask the agent to check stats or run actions. Approve state-modifying commands directly in the prompt.*
|
|
135
|
+
|
|
136
|
+
Extract and index a structured Experiential Lesson Learned from any completed troubleshooting session:
|
|
137
|
+
```bash
|
|
138
|
+
devops-copilot lesson <session_id>
|
|
139
|
+
```
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# DevOps Copilot 🚀
|
|
2
|
+
|
|
3
|
+
**An autonomous, self-learning AI DevOps Assistant & CLI Client that manages bare-metal servers with Experiential Memory (`ExpeL`), Semantic Guardrails, and Real-Time SSH Tunneling.**
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 💡 About The Project
|
|
8
|
+
|
|
9
|
+
Managing infrastructure via traditional CLI tools or basic AI wrappers often leads to dangerous mistakes, repetitive debugging dead-ends, and fragmented server logs. **DevOps Copilot** redefines server management by bringing **Closed-Loop Experiential Learning (ExpeL)** directly to your terminal.
|
|
10
|
+
|
|
11
|
+
Unlike standard AI chat wrappers that forget previous troubleshooting sessions, `DevOps Copilot` builds a permanent, structured **ChromaDB Vector Knowledge Base** of your infrastructure:
|
|
12
|
+
|
|
13
|
+
- **🧠 Zero-Click Experiential Learning (ExpeL & Reflexion):** Every time an incident or bug is diagnosed and resolved, the agent distills the entire session into a structured Postmortem (`Problem`, `Real Cause`, `What didn't work`, `What worked`). Before tackling new errors, relevant past lessons are **automatically retrieved and injected** into the agent's context—ensuring it *never repeats a dead end*.
|
|
14
|
+
- **🛡️ Semantic Security Guardrails:** Local vector search intercepts and blocks catastrophic shell commands (e.g., `rm -rf /`, `mkfs`) before they ever touch your servers.
|
|
15
|
+
- **🧑💻 Human-in-the-Loop (HITL) Approvals:** State-modifying actions dynamically prompt for explicit admin confirmation (`[y/N]`) inside the terminal with clean prompt synchronization.
|
|
16
|
+
- **⚡ Real-Time Async Execution Tunnel:** Streams LLM reasoning, SSH `stdout`, and `stderr` line-by-line via resilient WebSockets with automatic reconnection and exponential backoff.
|
|
17
|
+
- **🔒 Zero-Trust Credential Encryption:** Passwords and SSH private keys are encrypted at rest using AES-256 (`Fernet`).
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 🏛️ System Architecture & ExpeL Loop
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
+-----------------------------------------------------------------------------------+
|
|
25
|
+
| DevOps Copilot CLI |
|
|
26
|
+
| (Typer Async Client + Real-Time WebSocket Tunnel + [y/N] Terminal Approval) |
|
|
27
|
+
+-----------------------------------------------------------------------------------+
|
|
28
|
+
| ^
|
|
29
|
+
REST Auth/CRUD | | WebSocket Stream (stdout/stderr)
|
|
30
|
+
v |
|
|
31
|
+
+-----------------------------------------------------------------------------------+
|
|
32
|
+
| FastAPI Backend Server |
|
|
33
|
+
| |
|
|
34
|
+
| +------------------------+ +-----------------------+ +--------------------+ |
|
|
35
|
+
| | Auth Module | | Servers Module | | Guardrails Module | |
|
|
36
|
+
| | (JWT & AES Fernet) | | (AsyncSSH Execution) | | (Vector Blacklist) | |
|
|
37
|
+
| +------------------------+ +-----------------------+ +--------------------+ |
|
|
38
|
+
| |
|
|
39
|
+
| +-----------------------------------------------------------------------------+ |
|
|
40
|
+
| | Chat & Agent Module | |
|
|
41
|
+
| | LangChain StateGraph + Zero-Click ExpeL Injection + OpenRouter LLM | |
|
|
42
|
+
| +-----------------------------------------------------------------------------+ |
|
|
43
|
+
| | |
|
|
44
|
+
| v |
|
|
45
|
+
| +-----------------------------------------------------------------------------+ |
|
|
46
|
+
| | Knowledge Base (ChromaDB) | |
|
|
47
|
+
| | [command_history] [server_logs] [server_configs] [lessons_learned] | |
|
|
48
|
+
| +-----------------------------------------------------------------------------+ |
|
|
49
|
+
+-----------------------------------------------------------------------------------+
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### The Closed-Loop Experiential Learning (`ExpeL`) Flow:
|
|
53
|
+
1. **Observe & Act:** Agent connects via `AsyncSSH`, runs non-destructive diagnostics or approved actions, and indexes outputs into `command_history` and `server_logs`.
|
|
54
|
+
2. **Judge & Extract:** When an incident is resolved, running `devops-copilot lesson <session_id>` triggers an automated LLM extraction (`Problem`, `Real Cause`, `What didn't work`, `What worked`) stored in `lessons_learned`.
|
|
55
|
+
3. **Zero-Click Injection (Future Decision):** On any future chat turn or command error, the `inject_experiential_memory` middleware queries `lessons_learned` and injects proven solutions directly into the prompt context.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Key Features
|
|
60
|
+
- **Experiential Learning (ExpeL / Reflexion Postmortems):** Distills complex debugging sessions into structured `Lessons Learned` cards indexed into ChromaDB with zero-click context injection.
|
|
61
|
+
- **Lean RAG Knowledge Base:** Automatically chunks and indexes executed SSH command outputs, logs, and server configs into separate **ChromaDB** collections.
|
|
62
|
+
- **Semantic Guardrails:** Uses local vector search to intercept and block dangerous terminal commands.
|
|
63
|
+
- **Human-in-the-Loop (HITL):** Enforces admin approval (`[y/N]`) inside the terminal for any state-modifying actions.
|
|
64
|
+
- **CLI Connection Resilience:** Automatically reconnects to the WebSocket server using exponential backoff if the network drops or the server restarts.
|
|
65
|
+
- **Real-Time Streaming:** Streams LLM thoughts and active SSH `stdout`/`stderr` line-by-line using WebSockets with 30s execution timeouts.
|
|
66
|
+
- **Encrypted Credentials:** Securely encrypts passwords and SSH private keys using Fernet (AES-256).
|
|
67
|
+
- **Server & Session CRUD:** Full REST API support for updating/deleting server connections and deleting chat sessions.
|
|
68
|
+
- **Flexible AI Models:** Powered by **OpenRouter** (supports Llama 3, Gemini, GPT, etc.).
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## 📦 Quick Start (Backend Server)
|
|
73
|
+
|
|
74
|
+
### 1. Configure Settings
|
|
75
|
+
Copy the env file and populate keys:
|
|
76
|
+
```bash
|
|
77
|
+
cp .env.example .env
|
|
78
|
+
```
|
|
79
|
+
Make sure to add your `OPENROUTER_API_KEY` and a custom base64 `ENCRYPTION_KEY` in `.env`.
|
|
80
|
+
|
|
81
|
+
### 2. Run with Docker Compose
|
|
82
|
+
```bash
|
|
83
|
+
docker compose up -d --build
|
|
84
|
+
```
|
|
85
|
+
The server will boot on port `8000`. Database tables and security blacklist vectors are automatically seeded on startup.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## 💻 Quick Start (CLI Client)
|
|
90
|
+
|
|
91
|
+
### 1. Install Globally
|
|
92
|
+
Install the package in editable mode from your local repository root:
|
|
93
|
+
```bash
|
|
94
|
+
uv pip install -e .
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### 2. Authenticate
|
|
98
|
+
Configure the server URL and log in to get your JWT access token:
|
|
99
|
+
```bash
|
|
100
|
+
devops-copilot login
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### 3. Interactive Chat & Auto-Postmortems
|
|
104
|
+
Start the real-time DevOps chat session:
|
|
105
|
+
```bash
|
|
106
|
+
devops-copilot chat
|
|
107
|
+
```
|
|
108
|
+
*Ask the agent to check stats or run actions. Approve state-modifying commands directly in the prompt.*
|
|
109
|
+
|
|
110
|
+
Extract and index a structured Experiential Lesson Learned from any completed troubleshooting session:
|
|
111
|
+
```bash
|
|
112
|
+
devops-copilot lesson <session_id>
|
|
113
|
+
```
|
|
@@ -247,5 +247,46 @@ def chat():
|
|
|
247
247
|
# 3. Enter the async WebSocket execution loop
|
|
248
248
|
asyncio.run(run_chat_loop(server_url, token, session_id))
|
|
249
249
|
|
|
250
|
+
|
|
251
|
+
@app.command("lesson")
|
|
252
|
+
def lesson(
|
|
253
|
+
session_id: int = typer.Argument(..., help="The Chat Session ID to analyze and extract postmortem from")
|
|
254
|
+
):
|
|
255
|
+
"""
|
|
256
|
+
Extract a structured Experiential Lesson Learned (ExpeL Postmortem) from a past debugging session
|
|
257
|
+
and index it into the permanent vector database.
|
|
258
|
+
"""
|
|
259
|
+
config = load_config()
|
|
260
|
+
if not config:
|
|
261
|
+
typer.secho("Error: No configuration found. Please run 'devops-copilot login' first.", fg=typer.colors.RED, err=True)
|
|
262
|
+
raise typer.Exit(code=1)
|
|
263
|
+
|
|
264
|
+
server_url = config["server_url"]
|
|
265
|
+
token = config["token"]
|
|
266
|
+
headers = {"Authorization": f"Bearer {token}"}
|
|
267
|
+
|
|
268
|
+
typer.echo(f"Analyzing session #{session_id} and extracting Experiential Lesson Learned...")
|
|
269
|
+
try:
|
|
270
|
+
response = httpx.post(f"{server_url}/api/v1/chat/sessions/{session_id}/postmortem", headers=headers, timeout=60.0)
|
|
271
|
+
if response.status_code == 404:
|
|
272
|
+
typer.secho(f"Session #{session_id} not found or no access.", fg=typer.colors.RED, err=True)
|
|
273
|
+
raise typer.Exit(code=1)
|
|
274
|
+
response.raise_for_status()
|
|
275
|
+
res_data = response.json()
|
|
276
|
+
lesson_data = res_data.get("lesson_learned", {})
|
|
277
|
+
typer.secho("\n✨ [Experiential Lesson Learned Recorded successfully!]", fg=typer.colors.GREEN, bold=True)
|
|
278
|
+
typer.echo(f" • Server: {lesson_data.get('server_name', 'N/A')}")
|
|
279
|
+
typer.echo(f" • Problem: {lesson_data.get('problem', 'N/A')}")
|
|
280
|
+
typer.echo(f" • Real Cause: {lesson_data.get('real_cause', 'N/A')}")
|
|
281
|
+
typer.echo(f" • What didn't work: {lesson_data.get('what_didnt_work', 'N/A')}")
|
|
282
|
+
typer.echo(f" • What worked: {lesson_data.get('what_worked', 'N/A')}")
|
|
283
|
+
typer.echo(f" • Time to Resolve: {lesson_data.get('time_to_resolve', 'N/A')}\n")
|
|
284
|
+
except typer.Exit:
|
|
285
|
+
raise
|
|
286
|
+
except Exception as e:
|
|
287
|
+
typer.secho(f"Error generating lesson learned: {str(e)}", fg=typer.colors.RED, err=True)
|
|
288
|
+
raise typer.Exit(code=1)
|
|
289
|
+
|
|
290
|
+
|
|
250
291
|
if __name__ == "__main__":
|
|
251
292
|
app()
|
|
@@ -18,6 +18,15 @@ from app.core.security import decrypt_data
|
|
|
18
18
|
from app.modules.servers.models import Server
|
|
19
19
|
from app.modules.servers.service import servers_service
|
|
20
20
|
from app.modules.chat.models import AgentAction
|
|
21
|
+
from app.modules.guardrails.service import is_command_safe
|
|
22
|
+
from app.modules.knowledge.service import (
|
|
23
|
+
index_command_output,
|
|
24
|
+
search as knowledge_search,
|
|
25
|
+
index_log,
|
|
26
|
+
index_config,
|
|
27
|
+
index_lesson_learned,
|
|
28
|
+
search_lessons_learned as service_search_lessons,
|
|
29
|
+
)
|
|
21
30
|
|
|
22
31
|
# Context variables to track active execution details across async threads
|
|
23
32
|
active_websocket = contextvars.ContextVar("active_websocket")
|
|
@@ -123,7 +132,6 @@ async def execute_ssh_command(server_id: int | str, command: str) -> str:
|
|
|
123
132
|
"""
|
|
124
133
|
try:
|
|
125
134
|
# 1. Run semantic safety guardrail
|
|
126
|
-
from app.modules.guardrails.service import is_command_safe
|
|
127
135
|
is_safe, warning, similarity = is_command_safe(command)
|
|
128
136
|
if not is_safe:
|
|
129
137
|
return f"Execution Blocked by Guardrail: {warning} (similarity index: {similarity:.2f})"
|
|
@@ -249,7 +257,6 @@ async def execute_ssh_command(server_id: int | str, command: str) -> str:
|
|
|
249
257
|
|
|
250
258
|
# Auto-index execution output into RAG knowledge base
|
|
251
259
|
try:
|
|
252
|
-
from app.modules.knowledge.service import index_command_output
|
|
253
260
|
index_command_output(server.name, command, stdout_str, stderr_str, exit_code)
|
|
254
261
|
except Exception:
|
|
255
262
|
pass # Non-critical: don't break execution if indexing fails
|
|
@@ -273,8 +280,7 @@ async def search_knowledge(query: str, sources: list[str] | None = None) -> str:
|
|
|
273
280
|
Use this tool to recall past command outputs, server logs, or config file contents.
|
|
274
281
|
"""
|
|
275
282
|
try:
|
|
276
|
-
|
|
277
|
-
return search(query, collection_names=sources, n_results=3)
|
|
283
|
+
return knowledge_search(query, collection_names=sources, n_results=3)
|
|
278
284
|
except Exception as e:
|
|
279
285
|
return f"Knowledge search error: {str(e)}"
|
|
280
286
|
|
|
@@ -328,7 +334,6 @@ async def fetch_server_logs(server_id: int | str, log_source: str = "journalctl
|
|
|
328
334
|
|
|
329
335
|
# Auto-index fetched logs
|
|
330
336
|
try:
|
|
331
|
-
from app.modules.knowledge.service import index_log
|
|
332
337
|
index_log(server.name, log_source, stdout)
|
|
333
338
|
except Exception:
|
|
334
339
|
pass
|
|
@@ -397,7 +402,6 @@ async def fetch_server_config(server_id: int | str, file_path: str) -> str:
|
|
|
397
402
|
|
|
398
403
|
# Auto-index the config file
|
|
399
404
|
try:
|
|
400
|
-
from app.modules.knowledge.service import index_config
|
|
401
405
|
index_config(server.name, file_path, stdout)
|
|
402
406
|
except Exception:
|
|
403
407
|
pass
|
|
@@ -407,6 +411,56 @@ async def fetch_server_config(server_id: int | str, file_path: str) -> str:
|
|
|
407
411
|
return f"Error fetching config: {str(e)}"
|
|
408
412
|
|
|
409
413
|
|
|
414
|
+
@tool
|
|
415
|
+
async def record_lesson_learned(
|
|
416
|
+
server_id: int | str,
|
|
417
|
+
problem: str,
|
|
418
|
+
real_cause: str,
|
|
419
|
+
what_didnt_work: str,
|
|
420
|
+
what_worked: str,
|
|
421
|
+
time_to_resolve: str
|
|
422
|
+
) -> str:
|
|
423
|
+
"""
|
|
424
|
+
Record a structured lesson learned (postmortem) after successfully resolving an incident or bug on a server.
|
|
425
|
+
This populates the knowledge base (ExpeL/Reflexion) to resolve similar issues instantly next time.
|
|
426
|
+
"""
|
|
427
|
+
try:
|
|
428
|
+
owner_id = active_owner_id.get()
|
|
429
|
+
async with async_session_maker() as session:
|
|
430
|
+
try:
|
|
431
|
+
is_id = isinstance(server_id, int) or (isinstance(server_id, str) and server_id.isdigit())
|
|
432
|
+
if is_id:
|
|
433
|
+
server = await servers_service.get_server_by_id(session, int(server_id) if isinstance(server_id, str) else server_id, owner_id)
|
|
434
|
+
else:
|
|
435
|
+
server = await servers_service.get_server_by_name(session, str(server_id), owner_id)
|
|
436
|
+
except Exception:
|
|
437
|
+
return f"Error: Server '{server_id}' not found."
|
|
438
|
+
|
|
439
|
+
index_lesson_learned(
|
|
440
|
+
server_name=server.name,
|
|
441
|
+
problem=problem,
|
|
442
|
+
real_cause=real_cause,
|
|
443
|
+
what_didnt_work=what_didnt_work,
|
|
444
|
+
what_worked=what_worked,
|
|
445
|
+
time_to_resolve=time_to_resolve
|
|
446
|
+
)
|
|
447
|
+
return f"Lesson Learned recorded for {server.name}: Problem '{problem}' resolved via '{what_worked}'."
|
|
448
|
+
except Exception as e:
|
|
449
|
+
return f"Error recording lesson learned: {str(e)}"
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
@tool
|
|
453
|
+
async def search_lessons_learned(query: str) -> str:
|
|
454
|
+
"""
|
|
455
|
+
Semantic search across structured past lessons learned (postmortems).
|
|
456
|
+
Always call this before troubleshooting an incident or error to see what worked and what didn't work previously.
|
|
457
|
+
"""
|
|
458
|
+
try:
|
|
459
|
+
return service_search_lessons(query)
|
|
460
|
+
except Exception as e:
|
|
461
|
+
return f"Error searching lessons learned: {str(e)}"
|
|
462
|
+
|
|
463
|
+
|
|
410
464
|
# Define list of tools available to the Agent
|
|
411
465
|
tools = [
|
|
412
466
|
list_available_servers,
|
|
@@ -414,23 +468,28 @@ tools = [
|
|
|
414
468
|
search_knowledge,
|
|
415
469
|
fetch_server_logs,
|
|
416
470
|
fetch_server_config,
|
|
471
|
+
record_lesson_learned,
|
|
472
|
+
search_lessons_learned,
|
|
417
473
|
]
|
|
418
474
|
|
|
419
475
|
# Setup agent prompt template
|
|
420
476
|
system_prompt = """You are a highly capable DevOps AI Assistant managing servers via SSH.
|
|
421
|
-
You have tools to list servers, execute commands, fetch logs/configs, and search
|
|
477
|
+
You have tools to list servers, execute commands, fetch logs/configs, search past knowledge, and record/search structured lessons learned.
|
|
422
478
|
|
|
423
479
|
IMPORTANT INSTRUCTIONS:
|
|
424
480
|
1. Always call `list_available_servers` first if you do not know the server_id.
|
|
425
|
-
2.
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
481
|
+
2. EXPERIENTIAL LEARNING PROTOCOL (ExpeL / Reflexion):
|
|
482
|
+
- Before debugging or troubleshooting ANY server error or incident: ALWAYS call `search_lessons_learned` first to check if a similar issue occurred before. Pay close attention to "What didn't work" to avoid dead ends.
|
|
483
|
+
- After successfully resolving a server issue, bug, or incident: ALWAYS call `record_lesson_learned` with the structured breakdown (Problem, Real Cause, What didn't work, What worked, Time to Resolve).
|
|
484
|
+
3. Use `search_knowledge` to recall general past command outputs, logs, or configs before re-running commands.
|
|
485
|
+
4. Use `fetch_server_logs` to pull and index server logs (journalctl, syslog, etc.).
|
|
486
|
+
5. Use `fetch_server_config` to read and index config files (nginx, systemd, etc.).
|
|
487
|
+
6. Any command you execute will be checked by a semantic guardrail.
|
|
488
|
+
7. If a tool returns 'PAUSED: REQUIRES_APPROVAL: <action_id>', you MUST:
|
|
430
489
|
- STOP all execution immediately. Do not attempt to call any other tools.
|
|
431
490
|
- Reply to the user explaining that the command requires their approval.
|
|
432
491
|
- Explicitly mention the Action ID: '<action_id>'.
|
|
433
|
-
|
|
492
|
+
8. Be concise and report the final outputs clearly.
|
|
434
493
|
"""
|
|
435
494
|
|
|
436
495
|
def create_agent_executor(callbacks=None):
|
|
@@ -441,3 +500,24 @@ def create_agent_executor(callbacks=None):
|
|
|
441
500
|
tools=tools,
|
|
442
501
|
system_prompt=system_prompt
|
|
443
502
|
)
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
def inject_experiential_memory(prompt: str) -> str:
|
|
506
|
+
"""
|
|
507
|
+
Zero-Click ExpeL Auto-Retrieval:
|
|
508
|
+
Automatically searches past structured lessons learned and injects them directly into the prompt context.
|
|
509
|
+
Ensures the 'Retrieve Next Time -> Future Decision' loop is 100% systemic and guaranteed.
|
|
510
|
+
"""
|
|
511
|
+
try:
|
|
512
|
+
retrieved_lessons = service_search_lessons(prompt, n_results=2)
|
|
513
|
+
if "No matching lessons" not in retrieved_lessons and "No lessons learned recorded" not in retrieved_lessons:
|
|
514
|
+
return (
|
|
515
|
+
f"{prompt}\n\n"
|
|
516
|
+
f"[⚡ AUTO-RETRIEVED EXPERIENTIAL MEMORY (ExpeL) ⚡]\n"
|
|
517
|
+
f"Relevant past troubleshooting postmortems automatically retrieved for your current task:\n"
|
|
518
|
+
f"{retrieved_lessons}\n"
|
|
519
|
+
f"CRITICAL INSTRUCTION: Review 'What didn't work' and 'What worked' above. Do NOT repeat dead ends.\n"
|
|
520
|
+
)
|
|
521
|
+
return prompt
|
|
522
|
+
except Exception:
|
|
523
|
+
return prompt
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import jwt
|
|
2
|
+
import json
|
|
2
3
|
from fastapi import APIRouter, Depends, HTTPException, status, WebSocket, WebSocketDisconnect, Query
|
|
3
4
|
from typing import List
|
|
4
5
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
5
6
|
from sqlmodel import select
|
|
6
|
-
from langchain_core.messages import HumanMessage, AIMessage
|
|
7
|
+
from langchain_core.messages import HumanMessage, AIMessage, SystemMessage
|
|
7
8
|
|
|
8
9
|
from app.core.config import settings
|
|
9
10
|
from app.core.database import get_session, async_session_maker
|
|
@@ -20,6 +21,8 @@ from app.modules.chat.schema import (
|
|
|
20
21
|
)
|
|
21
22
|
from app.modules.chat.agent import (
|
|
22
23
|
create_agent_executor,
|
|
24
|
+
get_llm,
|
|
25
|
+
inject_experiential_memory,
|
|
23
26
|
StreamingCallbackHandler,
|
|
24
27
|
active_websocket,
|
|
25
28
|
active_session_id,
|
|
@@ -27,6 +30,7 @@ from app.modules.chat.agent import (
|
|
|
27
30
|
decrypt_data,
|
|
28
31
|
asyncssh
|
|
29
32
|
)
|
|
33
|
+
from app.modules.knowledge.service import index_lesson_learned, index_command_output
|
|
30
34
|
|
|
31
35
|
router = APIRouter()
|
|
32
36
|
|
|
@@ -105,6 +109,70 @@ async def delete_session(
|
|
|
105
109
|
await session.commit()
|
|
106
110
|
return {"status": "success", "message": f"Chat session {session_id} deleted successfully"}
|
|
107
111
|
|
|
112
|
+
@router.post("/sessions/{session_id}/postmortem")
|
|
113
|
+
async def generate_postmortem(
|
|
114
|
+
session_id: int,
|
|
115
|
+
current_user: User = Depends(get_current_user),
|
|
116
|
+
session: AsyncSession = Depends(get_session)
|
|
117
|
+
):
|
|
118
|
+
"""
|
|
119
|
+
Generate an automatic Post-Incident Lesson Learned (Postmortem) from the session history
|
|
120
|
+
using Experiential Learning (ExpeL) protocol, and index it into ChromaDB.
|
|
121
|
+
"""
|
|
122
|
+
sess_statement = select(ChatSession).where(ChatSession.id == session_id, ChatSession.user_id == current_user.id)
|
|
123
|
+
sess_result = await session.exec(sess_statement)
|
|
124
|
+
if not sess_result.first():
|
|
125
|
+
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Chat session not found")
|
|
126
|
+
|
|
127
|
+
msg_statement = select(ChatMessage).where(ChatMessage.session_id == session_id).order_by(ChatMessage.created_at.asc())
|
|
128
|
+
msg_result = await session.exec(msg_statement)
|
|
129
|
+
messages = msg_result.all()
|
|
130
|
+
if not messages:
|
|
131
|
+
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="No messages found in this session to analyze.")
|
|
132
|
+
|
|
133
|
+
transcript = "\n".join([f"[{m.role.upper()}]: {m.content}" for m in messages])
|
|
134
|
+
llm = get_llm()
|
|
135
|
+
prompt = """You are an Expert DevOps Incident Analyzer performing an Experiential Learning (ExpeL / Reflexion) postmortem.
|
|
136
|
+
Analyze the following troubleshooting conversation transcript between an admin and an AI agent.
|
|
137
|
+
Extract the core troubleshooting lesson into the exact JSON schema below. Output ONLY valid JSON:
|
|
138
|
+
{
|
|
139
|
+
"server_name": "The name or IP of the server where the incident occurred (or 'unknown' if not clear)",
|
|
140
|
+
"problem": "A concise 2-5 word description of the problem (e.g. OOMKilled, Nginx 502 Bad Gateway)",
|
|
141
|
+
"real_cause": "The actual root cause discovered during troubleshooting",
|
|
142
|
+
"what_didnt_work": "Summary of commands or approaches that failed or didn't fix the issue",
|
|
143
|
+
"what_worked": "The exact resolution or deployment that fixed the issue",
|
|
144
|
+
"time_to_resolve": "Estimated time taken to resolve (e.g. 15 min, 3 steps)"
|
|
145
|
+
}"""
|
|
146
|
+
|
|
147
|
+
try:
|
|
148
|
+
response = await llm.ainvoke([SystemMessage(content=prompt), HumanMessage(content=f"TRANSCRIPT:\n{transcript[:15000]}")])
|
|
149
|
+
content_text = response.content
|
|
150
|
+
if isinstance(content_text, list):
|
|
151
|
+
content_text = " ".join([str(c) for c in content_text])
|
|
152
|
+
|
|
153
|
+
# Clean markdown code block if present
|
|
154
|
+
clean_json = content_text.strip()
|
|
155
|
+
if clean_json.startswith("```json"):
|
|
156
|
+
clean_json = clean_json[7:]
|
|
157
|
+
if clean_json.startswith("```"):
|
|
158
|
+
clean_json = clean_json[3:]
|
|
159
|
+
if clean_json.endswith("```"):
|
|
160
|
+
clean_json = clean_json[:-3]
|
|
161
|
+
clean_json = clean_json.strip()
|
|
162
|
+
|
|
163
|
+
data = json.loads(clean_json)
|
|
164
|
+
index_lesson_learned(
|
|
165
|
+
server_name=data.get("server_name", "unknown"),
|
|
166
|
+
problem=data.get("problem", "Unknown Issue"),
|
|
167
|
+
real_cause=data.get("real_cause", "N/A"),
|
|
168
|
+
what_didnt_work=data.get("what_didnt_work", "N/A"),
|
|
169
|
+
what_worked=data.get("what_worked", "N/A"),
|
|
170
|
+
time_to_resolve=data.get("time_to_resolve", "N/A")
|
|
171
|
+
)
|
|
172
|
+
return {"status": "success", "lesson_learned": data}
|
|
173
|
+
except Exception as e:
|
|
174
|
+
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to extract postmortem: {str(e)}")
|
|
175
|
+
|
|
108
176
|
# --- WebSocket Real-Time Chat & Execution Tunnel ---
|
|
109
177
|
|
|
110
178
|
@router.websocket("/ws")
|
|
@@ -188,9 +256,12 @@ async def websocket_endpoint(
|
|
|
188
256
|
callback = StreamingCallbackHandler(websocket)
|
|
189
257
|
agent_executor = create_agent_executor(callbacks=[callback])
|
|
190
258
|
|
|
259
|
+
# Auto-inject Experiential Learning memory into context if matches exist
|
|
260
|
+
enriched_content = inject_experiential_memory(content)
|
|
261
|
+
|
|
191
262
|
# Invoke agent compiled StateGraph using messages schema
|
|
192
263
|
inputs = {
|
|
193
|
-
"messages": chat_history + [HumanMessage(content=
|
|
264
|
+
"messages": chat_history + [HumanMessage(content=enriched_content)]
|
|
194
265
|
}
|
|
195
266
|
agent_response = await agent_executor.ainvoke(inputs)
|
|
196
267
|
|
|
@@ -306,7 +377,6 @@ async def websocket_endpoint(
|
|
|
306
377
|
|
|
307
378
|
# Auto-index approved command output into RAG knowledge base
|
|
308
379
|
try:
|
|
309
|
-
from app.modules.knowledge.service import index_command_output
|
|
310
380
|
index_command_output(server.name, action.command, stdout_str, stderr_str, exit_code)
|
|
311
381
|
except Exception:
|
|
312
382
|
pass
|
|
@@ -330,9 +400,12 @@ async def websocket_endpoint(
|
|
|
330
400
|
f"Please analyze these outputs and provide your final response to the user."
|
|
331
401
|
)
|
|
332
402
|
|
|
403
|
+
# Auto-inject Experiential Learning memory into resume prompt
|
|
404
|
+
enriched_resume = inject_experiential_memory(resume_prompt)
|
|
405
|
+
|
|
333
406
|
# Invoke the agent graph with the resume message
|
|
334
407
|
agent_response = await agent_executor.ainvoke({
|
|
335
|
-
"messages": [HumanMessage(content=
|
|
408
|
+
"messages": [HumanMessage(content=enriched_resume)]
|
|
336
409
|
})
|
|
337
410
|
|
|
338
411
|
ai_text = agent_response["messages"][-1].content
|
|
@@ -5,10 +5,11 @@ from typing import List, Optional
|
|
|
5
5
|
# Shared ChromaDB persistent client (same data volume as guardrails)
|
|
6
6
|
client = chromadb.PersistentClient(path="data/chroma_db")
|
|
7
7
|
|
|
8
|
-
# ---
|
|
8
|
+
# --- 4 Separate Collections ---
|
|
9
9
|
command_history = client.get_or_create_collection(name="command_history")
|
|
10
10
|
server_logs = client.get_or_create_collection(name="server_logs")
|
|
11
11
|
server_configs = client.get_or_create_collection(name="server_configs")
|
|
12
|
+
lessons_learned = client.get_or_create_collection(name="lessons_learned")
|
|
12
13
|
|
|
13
14
|
CHUNK_SIZE = 500
|
|
14
15
|
CHUNK_OVERLAP = 50
|
|
@@ -84,11 +85,61 @@ def index_config(server_name: str, file_path: str, content: str):
|
|
|
84
85
|
)
|
|
85
86
|
|
|
86
87
|
|
|
88
|
+
def index_lesson_learned(
|
|
89
|
+
server_name: str,
|
|
90
|
+
problem: str,
|
|
91
|
+
real_cause: str,
|
|
92
|
+
what_didnt_work: str,
|
|
93
|
+
what_worked: str,
|
|
94
|
+
time_to_resolve: str
|
|
95
|
+
):
|
|
96
|
+
"""Index a structured post-incident postmortem (Experiential Learning / ExpeL) into lessons_learned."""
|
|
97
|
+
doc = (
|
|
98
|
+
f"Problem: {problem}\n"
|
|
99
|
+
f"Real Cause: {real_cause}\n"
|
|
100
|
+
f"What didn't work: {what_didnt_work}\n"
|
|
101
|
+
f"What worked: {what_worked}\n"
|
|
102
|
+
f"Time to Resolve: {time_to_resolve}"
|
|
103
|
+
)
|
|
104
|
+
metadata = {
|
|
105
|
+
"server_name": server_name,
|
|
106
|
+
"problem": problem,
|
|
107
|
+
"real_cause": real_cause,
|
|
108
|
+
"what_worked": what_worked,
|
|
109
|
+
"time_to_resolve": time_to_resolve,
|
|
110
|
+
"source": "lessons_learned",
|
|
111
|
+
}
|
|
112
|
+
lessons_learned.add(
|
|
113
|
+
ids=[f"lsn_{uuid.uuid4().hex[:12]}"],
|
|
114
|
+
documents=[doc],
|
|
115
|
+
metadatas=[metadata],
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def search_lessons_learned(query: str, n_results: int = 3) -> str:
|
|
120
|
+
"""Semantic search specifically across structured past lessons learned."""
|
|
121
|
+
if lessons_learned.count() == 0:
|
|
122
|
+
return "No lessons learned recorded yet in the vector database."
|
|
123
|
+
|
|
124
|
+
results = lessons_learned.query(query_texts=[query], n_results=min(n_results, lessons_learned.count()))
|
|
125
|
+
if not results or not results["documents"] or not results["documents"][0]:
|
|
126
|
+
return "No matching lessons learned found."
|
|
127
|
+
|
|
128
|
+
cards = []
|
|
129
|
+
for doc, meta in zip(results["documents"][0], results["metadatas"][0]):
|
|
130
|
+
cards.append(
|
|
131
|
+
f"[Lesson Learned - Server: {meta.get('server_name', '?')}]\n"
|
|
132
|
+
f"{doc}"
|
|
133
|
+
)
|
|
134
|
+
return "\n\n---\n\n".join(cards)
|
|
135
|
+
|
|
136
|
+
|
|
87
137
|
# Map collection name -> collection object
|
|
88
138
|
_COLLECTIONS = {
|
|
89
139
|
"command_history": command_history,
|
|
90
140
|
"server_logs": server_logs,
|
|
91
141
|
"server_configs": server_configs,
|
|
142
|
+
"lessons_learned": lessons_learned,
|
|
92
143
|
}
|
|
93
144
|
|
|
94
145
|
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: devops-copilot
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: An AI-driven DevOps Copilot and CLI Client for managing bare-metal servers securely
|
|
5
|
+
Author: irzix
|
|
6
|
+
Requires-Python: >=3.12
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: typer>=0.12.0
|
|
9
|
+
Requires-Dist: httpx>=0.27.0
|
|
10
|
+
Requires-Dist: websockets>=12.0
|
|
11
|
+
Provides-Extra: server
|
|
12
|
+
Requires-Dist: fastapi>=0.111.0; extra == "server"
|
|
13
|
+
Requires-Dist: uvicorn>=0.30.0; extra == "server"
|
|
14
|
+
Requires-Dist: sqlmodel>=0.0.22; extra == "server"
|
|
15
|
+
Requires-Dist: pyjwt>=2.8.0; extra == "server"
|
|
16
|
+
Requires-Dist: aiosqlite>=0.20.0; extra == "server"
|
|
17
|
+
Requires-Dist: cryptography>=42.0.0; extra == "server"
|
|
18
|
+
Requires-Dist: langchain>=0.2.0; extra == "server"
|
|
19
|
+
Requires-Dist: chromadb>=0.5.0; extra == "server"
|
|
20
|
+
Requires-Dist: pydantic-settings>=2.2.0; extra == "server"
|
|
21
|
+
Requires-Dist: bcrypt>=4.1.0; extra == "server"
|
|
22
|
+
Requires-Dist: python-multipart>=0.0.9; extra == "server"
|
|
23
|
+
Requires-Dist: greenlet>=3.0.0; extra == "server"
|
|
24
|
+
Requires-Dist: langchain-openai>=0.1.0; extra == "server"
|
|
25
|
+
Requires-Dist: asyncssh>=2.14.0; extra == "server"
|
|
26
|
+
|
|
27
|
+
# DevOps Copilot 🚀
|
|
28
|
+
|
|
29
|
+
**An autonomous, self-learning AI DevOps Assistant & CLI Client that manages bare-metal servers with Experiential Memory (`ExpeL`), Semantic Guardrails, and Real-Time SSH Tunneling.**
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 💡 About The Project
|
|
34
|
+
|
|
35
|
+
Managing infrastructure via traditional CLI tools or basic AI wrappers often leads to dangerous mistakes, repetitive debugging dead-ends, and fragmented server logs. **DevOps Copilot** redefines server management by bringing **Closed-Loop Experiential Learning (ExpeL)** directly to your terminal.
|
|
36
|
+
|
|
37
|
+
Unlike standard AI chat wrappers that forget previous troubleshooting sessions, `DevOps Copilot` builds a permanent, structured **ChromaDB Vector Knowledge Base** of your infrastructure:
|
|
38
|
+
|
|
39
|
+
- **🧠 Zero-Click Experiential Learning (ExpeL & Reflexion):** Every time an incident or bug is diagnosed and resolved, the agent distills the entire session into a structured Postmortem (`Problem`, `Real Cause`, `What didn't work`, `What worked`). Before tackling new errors, relevant past lessons are **automatically retrieved and injected** into the agent's context—ensuring it *never repeats a dead end*.
|
|
40
|
+
- **🛡️ Semantic Security Guardrails:** Local vector search intercepts and blocks catastrophic shell commands (e.g., `rm -rf /`, `mkfs`) before they ever touch your servers.
|
|
41
|
+
- **🧑💻 Human-in-the-Loop (HITL) Approvals:** State-modifying actions dynamically prompt for explicit admin confirmation (`[y/N]`) inside the terminal with clean prompt synchronization.
|
|
42
|
+
- **⚡ Real-Time Async Execution Tunnel:** Streams LLM reasoning, SSH `stdout`, and `stderr` line-by-line via resilient WebSockets with automatic reconnection and exponential backoff.
|
|
43
|
+
- **🔒 Zero-Trust Credential Encryption:** Passwords and SSH private keys are encrypted at rest using AES-256 (`Fernet`).
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 🏛️ System Architecture & ExpeL Loop
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
+-----------------------------------------------------------------------------------+
|
|
51
|
+
| DevOps Copilot CLI |
|
|
52
|
+
| (Typer Async Client + Real-Time WebSocket Tunnel + [y/N] Terminal Approval) |
|
|
53
|
+
+-----------------------------------------------------------------------------------+
|
|
54
|
+
| ^
|
|
55
|
+
REST Auth/CRUD | | WebSocket Stream (stdout/stderr)
|
|
56
|
+
v |
|
|
57
|
+
+-----------------------------------------------------------------------------------+
|
|
58
|
+
| FastAPI Backend Server |
|
|
59
|
+
| |
|
|
60
|
+
| +------------------------+ +-----------------------+ +--------------------+ |
|
|
61
|
+
| | Auth Module | | Servers Module | | Guardrails Module | |
|
|
62
|
+
| | (JWT & AES Fernet) | | (AsyncSSH Execution) | | (Vector Blacklist) | |
|
|
63
|
+
| +------------------------+ +-----------------------+ +--------------------+ |
|
|
64
|
+
| |
|
|
65
|
+
| +-----------------------------------------------------------------------------+ |
|
|
66
|
+
| | Chat & Agent Module | |
|
|
67
|
+
| | LangChain StateGraph + Zero-Click ExpeL Injection + OpenRouter LLM | |
|
|
68
|
+
| +-----------------------------------------------------------------------------+ |
|
|
69
|
+
| | |
|
|
70
|
+
| v |
|
|
71
|
+
| +-----------------------------------------------------------------------------+ |
|
|
72
|
+
| | Knowledge Base (ChromaDB) | |
|
|
73
|
+
| | [command_history] [server_logs] [server_configs] [lessons_learned] | |
|
|
74
|
+
| +-----------------------------------------------------------------------------+ |
|
|
75
|
+
+-----------------------------------------------------------------------------------+
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### The Closed-Loop Experiential Learning (`ExpeL`) Flow:
|
|
79
|
+
1. **Observe & Act:** Agent connects via `AsyncSSH`, runs non-destructive diagnostics or approved actions, and indexes outputs into `command_history` and `server_logs`.
|
|
80
|
+
2. **Judge & Extract:** When an incident is resolved, running `devops-copilot lesson <session_id>` triggers an automated LLM extraction (`Problem`, `Real Cause`, `What didn't work`, `What worked`) stored in `lessons_learned`.
|
|
81
|
+
3. **Zero-Click Injection (Future Decision):** On any future chat turn or command error, the `inject_experiential_memory` middleware queries `lessons_learned` and injects proven solutions directly into the prompt context.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Key Features
|
|
86
|
+
- **Experiential Learning (ExpeL / Reflexion Postmortems):** Distills complex debugging sessions into structured `Lessons Learned` cards indexed into ChromaDB with zero-click context injection.
|
|
87
|
+
- **Lean RAG Knowledge Base:** Automatically chunks and indexes executed SSH command outputs, logs, and server configs into separate **ChromaDB** collections.
|
|
88
|
+
- **Semantic Guardrails:** Uses local vector search to intercept and block dangerous terminal commands.
|
|
89
|
+
- **Human-in-the-Loop (HITL):** Enforces admin approval (`[y/N]`) inside the terminal for any state-modifying actions.
|
|
90
|
+
- **CLI Connection Resilience:** Automatically reconnects to the WebSocket server using exponential backoff if the network drops or the server restarts.
|
|
91
|
+
- **Real-Time Streaming:** Streams LLM thoughts and active SSH `stdout`/`stderr` line-by-line using WebSockets with 30s execution timeouts.
|
|
92
|
+
- **Encrypted Credentials:** Securely encrypts passwords and SSH private keys using Fernet (AES-256).
|
|
93
|
+
- **Server & Session CRUD:** Full REST API support for updating/deleting server connections and deleting chat sessions.
|
|
94
|
+
- **Flexible AI Models:** Powered by **OpenRouter** (supports Llama 3, Gemini, GPT, etc.).
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## 📦 Quick Start (Backend Server)
|
|
99
|
+
|
|
100
|
+
### 1. Configure Settings
|
|
101
|
+
Copy the env file and populate keys:
|
|
102
|
+
```bash
|
|
103
|
+
cp .env.example .env
|
|
104
|
+
```
|
|
105
|
+
Make sure to add your `OPENROUTER_API_KEY` and a custom base64 `ENCRYPTION_KEY` in `.env`.
|
|
106
|
+
|
|
107
|
+
### 2. Run with Docker Compose
|
|
108
|
+
```bash
|
|
109
|
+
docker compose up -d --build
|
|
110
|
+
```
|
|
111
|
+
The server will boot on port `8000`. Database tables and security blacklist vectors are automatically seeded on startup.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## 💻 Quick Start (CLI Client)
|
|
116
|
+
|
|
117
|
+
### 1. Install Globally
|
|
118
|
+
Install the package in editable mode from your local repository root:
|
|
119
|
+
```bash
|
|
120
|
+
uv pip install -e .
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### 2. Authenticate
|
|
124
|
+
Configure the server URL and log in to get your JWT access token:
|
|
125
|
+
```bash
|
|
126
|
+
devops-copilot login
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### 3. Interactive Chat & Auto-Postmortems
|
|
130
|
+
Start the real-time DevOps chat session:
|
|
131
|
+
```bash
|
|
132
|
+
devops-copilot chat
|
|
133
|
+
```
|
|
134
|
+
*Ask the agent to check stats or run actions. Approve state-modifying commands directly in the prompt.*
|
|
135
|
+
|
|
136
|
+
Extract and index a structured Experiential Lesson Learned from any completed troubleshooting session:
|
|
137
|
+
```bash
|
|
138
|
+
devops-copilot lesson <session_id>
|
|
139
|
+
```
|
devops_copilot-0.1.0/PKG-INFO
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: devops-copilot
|
|
3
|
-
Version: 0.1.0
|
|
4
|
-
Summary: An AI-driven DevOps Copilot and CLI Client for managing bare-metal servers securely
|
|
5
|
-
Author: irzix
|
|
6
|
-
Requires-Python: >=3.12
|
|
7
|
-
Description-Content-Type: text/markdown
|
|
8
|
-
Requires-Dist: typer>=0.12.0
|
|
9
|
-
Requires-Dist: httpx>=0.27.0
|
|
10
|
-
Requires-Dist: websockets>=12.0
|
|
11
|
-
Provides-Extra: server
|
|
12
|
-
Requires-Dist: fastapi>=0.111.0; extra == "server"
|
|
13
|
-
Requires-Dist: uvicorn>=0.30.0; extra == "server"
|
|
14
|
-
Requires-Dist: sqlmodel>=0.0.22; extra == "server"
|
|
15
|
-
Requires-Dist: pyjwt>=2.8.0; extra == "server"
|
|
16
|
-
Requires-Dist: aiosqlite>=0.20.0; extra == "server"
|
|
17
|
-
Requires-Dist: cryptography>=42.0.0; extra == "server"
|
|
18
|
-
Requires-Dist: langchain>=0.2.0; extra == "server"
|
|
19
|
-
Requires-Dist: chromadb>=0.5.0; extra == "server"
|
|
20
|
-
Requires-Dist: pydantic-settings>=2.2.0; extra == "server"
|
|
21
|
-
Requires-Dist: bcrypt>=4.1.0; extra == "server"
|
|
22
|
-
Requires-Dist: python-multipart>=0.0.9; extra == "server"
|
|
23
|
-
Requires-Dist: greenlet>=3.0.0; extra == "server"
|
|
24
|
-
Requires-Dist: langchain-openai>=0.1.0; extra == "server"
|
|
25
|
-
Requires-Dist: asyncssh>=2.14.0; extra == "server"
|
|
26
|
-
|
|
27
|
-
# DevOps-Copilot 🚀
|
|
28
|
-
|
|
29
|
-
An open-source, AI-driven DevOps Copilot and CLI Client designed to manage raw root/bare-metal servers securely. It features persistent credential encryption, real-time terminal streaming, and semantic security guardrails using a local vector database.
|
|
30
|
-
|
|
31
|
-
---
|
|
32
|
-
|
|
33
|
-
## Key Features
|
|
34
|
-
- **Lean RAG Knowledge Base:** Automatically chunks and indexes executed SSH command outputs, logs, and server configs into separate **ChromaDB** collections, enabling the agent to search past server history before executing new commands.
|
|
35
|
-
- **Semantic Guardrails:** Uses local vector search to intercept and block dangerous terminal commands.
|
|
36
|
-
- **Human-in-the-Loop (HITL):** Enforces admin approval (`[y/N]`) inside the terminal for any state-modifying actions with clean prompt synchronization.
|
|
37
|
-
- **CLI Connection Resilience:** Automatically reconnects to the WebSocket server using exponential backoff if the network drops or the server restarts.
|
|
38
|
-
- **Real-Time Streaming:** Streams LLM thoughts and active SSH `stdout`/`stderr` line-by-line using WebSockets with 30s execution timeouts.
|
|
39
|
-
- **Encrypted Credentials:** Securely encrypts passwords and SSH private keys using Fernet (AES-256).
|
|
40
|
-
- **Server & Session CRUD:** Full REST API support for updating/deleting server connections and deleting chat sessions (with cascade cleanup).
|
|
41
|
-
- **Flexible AI Models:** Powered by **OpenRouter** (supports Llama 3, Gemini, GPT, etc.).
|
|
42
|
-
|
|
43
|
-
---
|
|
44
|
-
|
|
45
|
-
## 📦 Quick Start (Backend Server)
|
|
46
|
-
|
|
47
|
-
### 1. Configure Settings
|
|
48
|
-
Copy the env file and populate keys:
|
|
49
|
-
```bash
|
|
50
|
-
cp .env.example .env
|
|
51
|
-
```
|
|
52
|
-
Make sure to add your `OPENROUTER_API_KEY` and a custom base64 `ENCRYPTION_KEY` in `.env`.
|
|
53
|
-
|
|
54
|
-
### 2. Run with Docker Compose
|
|
55
|
-
```bash
|
|
56
|
-
docker compose up -d --build
|
|
57
|
-
```
|
|
58
|
-
The server will boot on port `8000`. Database tables and security blacklist vectors are automatically seeded on startup.
|
|
59
|
-
|
|
60
|
-
---
|
|
61
|
-
|
|
62
|
-
## 💻 Quick Start (CLI Client)
|
|
63
|
-
|
|
64
|
-
### 1. Install Globally
|
|
65
|
-
Install the package in editable mode from your local repository root:
|
|
66
|
-
```bash
|
|
67
|
-
uv pip install -e .
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
### 2. Authenticate
|
|
71
|
-
Configure the server URL and log in to get your JWT access token:
|
|
72
|
-
```bash
|
|
73
|
-
devops-copilot login
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
### 3. Interactive Chat
|
|
77
|
-
Start the real-time DevOps chat session:
|
|
78
|
-
```bash
|
|
79
|
-
devops-copilot chat
|
|
80
|
-
```
|
|
81
|
-
*Ask the agent to check stats or run actions. Approve state-modifying commands directly in the prompt.*
|
devops_copilot-0.1.0/README.md
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
# DevOps-Copilot 🚀
|
|
2
|
-
|
|
3
|
-
An open-source, AI-driven DevOps Copilot and CLI Client designed to manage raw root/bare-metal servers securely. It features persistent credential encryption, real-time terminal streaming, and semantic security guardrails using a local vector database.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Key Features
|
|
8
|
-
- **Lean RAG Knowledge Base:** Automatically chunks and indexes executed SSH command outputs, logs, and server configs into separate **ChromaDB** collections, enabling the agent to search past server history before executing new commands.
|
|
9
|
-
- **Semantic Guardrails:** Uses local vector search to intercept and block dangerous terminal commands.
|
|
10
|
-
- **Human-in-the-Loop (HITL):** Enforces admin approval (`[y/N]`) inside the terminal for any state-modifying actions with clean prompt synchronization.
|
|
11
|
-
- **CLI Connection Resilience:** Automatically reconnects to the WebSocket server using exponential backoff if the network drops or the server restarts.
|
|
12
|
-
- **Real-Time Streaming:** Streams LLM thoughts and active SSH `stdout`/`stderr` line-by-line using WebSockets with 30s execution timeouts.
|
|
13
|
-
- **Encrypted Credentials:** Securely encrypts passwords and SSH private keys using Fernet (AES-256).
|
|
14
|
-
- **Server & Session CRUD:** Full REST API support for updating/deleting server connections and deleting chat sessions (with cascade cleanup).
|
|
15
|
-
- **Flexible AI Models:** Powered by **OpenRouter** (supports Llama 3, Gemini, GPT, etc.).
|
|
16
|
-
|
|
17
|
-
---
|
|
18
|
-
|
|
19
|
-
## 📦 Quick Start (Backend Server)
|
|
20
|
-
|
|
21
|
-
### 1. Configure Settings
|
|
22
|
-
Copy the env file and populate keys:
|
|
23
|
-
```bash
|
|
24
|
-
cp .env.example .env
|
|
25
|
-
```
|
|
26
|
-
Make sure to add your `OPENROUTER_API_KEY` and a custom base64 `ENCRYPTION_KEY` in `.env`.
|
|
27
|
-
|
|
28
|
-
### 2. Run with Docker Compose
|
|
29
|
-
```bash
|
|
30
|
-
docker compose up -d --build
|
|
31
|
-
```
|
|
32
|
-
The server will boot on port `8000`. Database tables and security blacklist vectors are automatically seeded on startup.
|
|
33
|
-
|
|
34
|
-
---
|
|
35
|
-
|
|
36
|
-
## 💻 Quick Start (CLI Client)
|
|
37
|
-
|
|
38
|
-
### 1. Install Globally
|
|
39
|
-
Install the package in editable mode from your local repository root:
|
|
40
|
-
```bash
|
|
41
|
-
uv pip install -e .
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
### 2. Authenticate
|
|
45
|
-
Configure the server URL and log in to get your JWT access token:
|
|
46
|
-
```bash
|
|
47
|
-
devops-copilot login
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
### 3. Interactive Chat
|
|
51
|
-
Start the real-time DevOps chat session:
|
|
52
|
-
```bash
|
|
53
|
-
devops-copilot chat
|
|
54
|
-
```
|
|
55
|
-
*Ask the agent to check stats or run actions. Approve state-modifying commands directly in the prompt.*
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: devops-copilot
|
|
3
|
-
Version: 0.1.0
|
|
4
|
-
Summary: An AI-driven DevOps Copilot and CLI Client for managing bare-metal servers securely
|
|
5
|
-
Author: irzix
|
|
6
|
-
Requires-Python: >=3.12
|
|
7
|
-
Description-Content-Type: text/markdown
|
|
8
|
-
Requires-Dist: typer>=0.12.0
|
|
9
|
-
Requires-Dist: httpx>=0.27.0
|
|
10
|
-
Requires-Dist: websockets>=12.0
|
|
11
|
-
Provides-Extra: server
|
|
12
|
-
Requires-Dist: fastapi>=0.111.0; extra == "server"
|
|
13
|
-
Requires-Dist: uvicorn>=0.30.0; extra == "server"
|
|
14
|
-
Requires-Dist: sqlmodel>=0.0.22; extra == "server"
|
|
15
|
-
Requires-Dist: pyjwt>=2.8.0; extra == "server"
|
|
16
|
-
Requires-Dist: aiosqlite>=0.20.0; extra == "server"
|
|
17
|
-
Requires-Dist: cryptography>=42.0.0; extra == "server"
|
|
18
|
-
Requires-Dist: langchain>=0.2.0; extra == "server"
|
|
19
|
-
Requires-Dist: chromadb>=0.5.0; extra == "server"
|
|
20
|
-
Requires-Dist: pydantic-settings>=2.2.0; extra == "server"
|
|
21
|
-
Requires-Dist: bcrypt>=4.1.0; extra == "server"
|
|
22
|
-
Requires-Dist: python-multipart>=0.0.9; extra == "server"
|
|
23
|
-
Requires-Dist: greenlet>=3.0.0; extra == "server"
|
|
24
|
-
Requires-Dist: langchain-openai>=0.1.0; extra == "server"
|
|
25
|
-
Requires-Dist: asyncssh>=2.14.0; extra == "server"
|
|
26
|
-
|
|
27
|
-
# DevOps-Copilot 🚀
|
|
28
|
-
|
|
29
|
-
An open-source, AI-driven DevOps Copilot and CLI Client designed to manage raw root/bare-metal servers securely. It features persistent credential encryption, real-time terminal streaming, and semantic security guardrails using a local vector database.
|
|
30
|
-
|
|
31
|
-
---
|
|
32
|
-
|
|
33
|
-
## Key Features
|
|
34
|
-
- **Lean RAG Knowledge Base:** Automatically chunks and indexes executed SSH command outputs, logs, and server configs into separate **ChromaDB** collections, enabling the agent to search past server history before executing new commands.
|
|
35
|
-
- **Semantic Guardrails:** Uses local vector search to intercept and block dangerous terminal commands.
|
|
36
|
-
- **Human-in-the-Loop (HITL):** Enforces admin approval (`[y/N]`) inside the terminal for any state-modifying actions with clean prompt synchronization.
|
|
37
|
-
- **CLI Connection Resilience:** Automatically reconnects to the WebSocket server using exponential backoff if the network drops or the server restarts.
|
|
38
|
-
- **Real-Time Streaming:** Streams LLM thoughts and active SSH `stdout`/`stderr` line-by-line using WebSockets with 30s execution timeouts.
|
|
39
|
-
- **Encrypted Credentials:** Securely encrypts passwords and SSH private keys using Fernet (AES-256).
|
|
40
|
-
- **Server & Session CRUD:** Full REST API support for updating/deleting server connections and deleting chat sessions (with cascade cleanup).
|
|
41
|
-
- **Flexible AI Models:** Powered by **OpenRouter** (supports Llama 3, Gemini, GPT, etc.).
|
|
42
|
-
|
|
43
|
-
---
|
|
44
|
-
|
|
45
|
-
## 📦 Quick Start (Backend Server)
|
|
46
|
-
|
|
47
|
-
### 1. Configure Settings
|
|
48
|
-
Copy the env file and populate keys:
|
|
49
|
-
```bash
|
|
50
|
-
cp .env.example .env
|
|
51
|
-
```
|
|
52
|
-
Make sure to add your `OPENROUTER_API_KEY` and a custom base64 `ENCRYPTION_KEY` in `.env`.
|
|
53
|
-
|
|
54
|
-
### 2. Run with Docker Compose
|
|
55
|
-
```bash
|
|
56
|
-
docker compose up -d --build
|
|
57
|
-
```
|
|
58
|
-
The server will boot on port `8000`. Database tables and security blacklist vectors are automatically seeded on startup.
|
|
59
|
-
|
|
60
|
-
---
|
|
61
|
-
|
|
62
|
-
## 💻 Quick Start (CLI Client)
|
|
63
|
-
|
|
64
|
-
### 1. Install Globally
|
|
65
|
-
Install the package in editable mode from your local repository root:
|
|
66
|
-
```bash
|
|
67
|
-
uv pip install -e .
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
### 2. Authenticate
|
|
71
|
-
Configure the server URL and log in to get your JWT access token:
|
|
72
|
-
```bash
|
|
73
|
-
devops-copilot login
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
### 3. Interactive Chat
|
|
77
|
-
Start the real-time DevOps chat session:
|
|
78
|
-
```bash
|
|
79
|
-
devops-copilot chat
|
|
80
|
-
```
|
|
81
|
-
*Ask the agent to check stats or run actions. Approve state-modifying commands directly in the prompt.*
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|