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.
Files changed (41) hide show
  1. devops_copilot-0.1.1/PKG-INFO +139 -0
  2. devops_copilot-0.1.1/README.md +113 -0
  3. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/cli/main.py +41 -0
  4. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/chat/agent.py +93 -13
  5. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/chat/router.py +77 -4
  6. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/knowledge/service.py +52 -1
  7. devops_copilot-0.1.1/devops_copilot.egg-info/PKG-INFO +139 -0
  8. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/pyproject.toml +1 -1
  9. devops_copilot-0.1.0/PKG-INFO +0 -81
  10. devops_copilot-0.1.0/README.md +0 -55
  11. devops_copilot-0.1.0/devops_copilot.egg-info/PKG-INFO +0 -81
  12. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/__init__.py +0 -0
  13. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/cli/__init__.py +0 -0
  14. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/cli/config.py +0 -0
  15. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/core/config.py +0 -0
  16. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/core/database/__init__.py +0 -0
  17. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/core/security.py +0 -0
  18. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/main.py +0 -0
  19. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/__init__.py +0 -0
  20. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/auth/__init__.py +0 -0
  21. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/auth/router.py +0 -0
  22. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/auth/schema.py +0 -0
  23. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/auth/service.py +0 -0
  24. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/chat/__init__.py +0 -0
  25. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/chat/models.py +0 -0
  26. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/chat/schema.py +0 -0
  27. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/guardrails/__init__.py +0 -0
  28. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/guardrails/schema.py +0 -0
  29. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/guardrails/service.py +0 -0
  30. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/knowledge/__init__.py +0 -0
  31. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/servers/__init__.py +0 -0
  32. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/servers/models.py +0 -0
  33. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/servers/router.py +0 -0
  34. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/servers/schema.py +0 -0
  35. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/app/modules/servers/service.py +0 -0
  36. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/devops_copilot.egg-info/SOURCES.txt +0 -0
  37. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/devops_copilot.egg-info/dependency_links.txt +0 -0
  38. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/devops_copilot.egg-info/entry_points.txt +0 -0
  39. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/devops_copilot.egg-info/requires.txt +0 -0
  40. {devops_copilot-0.1.0 → devops_copilot-0.1.1}/devops_copilot.egg-info/top_level.txt +0 -0
  41. {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
- from app.modules.knowledge.service import search
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 past knowledge.
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. Use `search_knowledge` to recall past command outputs, logs, or configs before re-running commands.
426
- 3. Use `fetch_server_logs` to pull and index server logs (journalctl, syslog, etc.).
427
- 4. Use `fetch_server_config` to read and index config files (nginx, systemd, etc.).
428
- 5. Any command you execute will be checked by a semantic guardrail.
429
- 6. If a tool returns 'PAUSED: REQUIRES_APPROVAL: <action_id>', you MUST:
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
- 7. Be concise and report the final outputs clearly.
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=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=resume_prompt)]
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
- # --- 3 Separate Collections ---
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
+ ```
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "devops-copilot"
3
- version = "0.1.0"
3
+ version = "0.1.1"
4
4
  description = "An AI-driven DevOps Copilot and CLI Client for managing bare-metal servers securely"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -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.*
@@ -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