ops-copilot 0.1.0__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.
- ops_copilot-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +30 -0
- ops_copilot-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +23 -0
- ops_copilot-0.1.0/.github/dependabot.yml +10 -0
- ops_copilot-0.1.0/.github/pull_request_template.md +11 -0
- ops_copilot-0.1.0/.github/workflows/build.yml +27 -0
- ops_copilot-0.1.0/.github/workflows/ci.yml +25 -0
- ops_copilot-0.1.0/.github/workflows/publish.yml +22 -0
- ops_copilot-0.1.0/.github/workflows/smoke.yml +23 -0
- ops_copilot-0.1.0/.gitignore +13 -0
- ops_copilot-0.1.0/CHANGELOG.md +19 -0
- ops_copilot-0.1.0/CONTRIBUTING.md +36 -0
- ops_copilot-0.1.0/LICENSE +21 -0
- ops_copilot-0.1.0/MAINTAINERS.md +21 -0
- ops_copilot-0.1.0/PKG-INFO +192 -0
- ops_copilot-0.1.0/README.md +138 -0
- ops_copilot-0.1.0/SECURITY.md +15 -0
- ops_copilot-0.1.0/docs/maintenance-workflows.md +30 -0
- ops_copilot-0.1.0/docs/release-process.md +30 -0
- ops_copilot-0.1.0/docs/security-model.md +69 -0
- ops_copilot-0.1.0/docs/server.md +66 -0
- ops_copilot-0.1.0/docs/writing-tools.md +75 -0
- ops_copilot-0.1.0/examples/custom_tool.py +19 -0
- ops_copilot-0.1.0/examples/local_demo.py +39 -0
- ops_copilot-0.1.0/examples/run_agent.py +32 -0
- ops_copilot-0.1.0/examples/tools.yaml +33 -0
- ops_copilot-0.1.0/pyproject.toml +63 -0
- ops_copilot-0.1.0/scripts/smoke.py +30 -0
- ops_copilot-0.1.0/src/ops_copilot/__init__.py +17 -0
- ops_copilot-0.1.0/src/ops_copilot/graph.py +191 -0
- ops_copilot-0.1.0/src/ops_copilot/sanitizers.py +46 -0
- ops_copilot-0.1.0/src/ops_copilot/secrets.py +62 -0
- ops_copilot-0.1.0/src/ops_copilot/server.py +62 -0
- ops_copilot-0.1.0/src/ops_copilot/ssh.py +90 -0
- ops_copilot-0.1.0/src/ops_copilot/tools/__init__.py +6 -0
- ops_copilot-0.1.0/src/ops_copilot/tools/base.py +34 -0
- ops_copilot-0.1.0/src/ops_copilot/tools/executor.py +67 -0
- ops_copilot-0.1.0/src/ops_copilot/tools/registry.py +71 -0
- ops_copilot-0.1.0/src/ops_copilot/tools/shell.py +38 -0
- ops_copilot-0.1.0/tests/test_executor.py +54 -0
- ops_copilot-0.1.0/tests/test_graph.py +45 -0
- ops_copilot-0.1.0/tests/test_registry.py +67 -0
- ops_copilot-0.1.0/tests/test_sanitizers.py +32 -0
- ops_copilot-0.1.0/tests/test_secrets.py +43 -0
- ops_copilot-0.1.0/uv.lock +2581 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: Report an investigation, tool execution, SSH, or streaming issue.
|
|
3
|
+
title: "[Bug]: "
|
|
4
|
+
labels: [bug]
|
|
5
|
+
body:
|
|
6
|
+
- type: textarea
|
|
7
|
+
id: scenario
|
|
8
|
+
attributes:
|
|
9
|
+
label: Scenario
|
|
10
|
+
description: What were you trying to investigate?
|
|
11
|
+
validations:
|
|
12
|
+
required: true
|
|
13
|
+
- type: textarea
|
|
14
|
+
id: tool_config
|
|
15
|
+
attributes:
|
|
16
|
+
label: Tool configuration
|
|
17
|
+
description: Paste a minimal redacted YAML snippet if relevant.
|
|
18
|
+
render: yaml
|
|
19
|
+
- type: textarea
|
|
20
|
+
id: expected
|
|
21
|
+
attributes:
|
|
22
|
+
label: Expected behavior
|
|
23
|
+
validations:
|
|
24
|
+
required: true
|
|
25
|
+
- type: textarea
|
|
26
|
+
id: actual
|
|
27
|
+
attributes:
|
|
28
|
+
label: Actual behavior
|
|
29
|
+
validations:
|
|
30
|
+
required: true
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: Suggest a new SRE workflow, tool type, or safety control.
|
|
3
|
+
title: "[Feature]: "
|
|
4
|
+
labels: [enhancement]
|
|
5
|
+
body:
|
|
6
|
+
- type: textarea
|
|
7
|
+
id: workflow
|
|
8
|
+
attributes:
|
|
9
|
+
label: Workflow
|
|
10
|
+
description: Which maintenance or incident workflow would this improve?
|
|
11
|
+
validations:
|
|
12
|
+
required: true
|
|
13
|
+
- type: textarea
|
|
14
|
+
id: proposal
|
|
15
|
+
attributes:
|
|
16
|
+
label: Proposal
|
|
17
|
+
validations:
|
|
18
|
+
required: true
|
|
19
|
+
- type: textarea
|
|
20
|
+
id: safety
|
|
21
|
+
attributes:
|
|
22
|
+
label: Safety considerations
|
|
23
|
+
description: Any command, SSH, secret, or permission risks?
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
|
|
3
|
+
## Safety checklist
|
|
4
|
+
|
|
5
|
+
- [ ] Added or updated tests.
|
|
6
|
+
- [ ] `uv run ruff check .` passes.
|
|
7
|
+
- [ ] `uv run pytest` passes.
|
|
8
|
+
- [ ] No real hostnames, private IPs, credentials, tokens, or internal service names were added.
|
|
9
|
+
- [ ] Tool output is redacted before it reaches the LLM or SSE stream.
|
|
10
|
+
- [ ] New shell commands are narrow, documented, and non-destructive.
|
|
11
|
+
- [ ] Security assumptions are documented when behavior changes.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
name: Build
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
tags: ["v*"]
|
|
7
|
+
pull_request:
|
|
8
|
+
branches: [main]
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
build:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
- name: Install uv
|
|
16
|
+
uses: astral-sh/setup-uv@v5
|
|
17
|
+
- name: Set up Python
|
|
18
|
+
uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: "3.11"
|
|
21
|
+
- name: Build package
|
|
22
|
+
run: uv build
|
|
23
|
+
- name: Upload distributions
|
|
24
|
+
uses: actions/upload-artifact@v4
|
|
25
|
+
with:
|
|
26
|
+
name: dist
|
|
27
|
+
path: dist/*
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
- name: Install uv
|
|
15
|
+
uses: astral-sh/setup-uv@v5
|
|
16
|
+
- name: Set up Python
|
|
17
|
+
uses: actions/setup-python@v5
|
|
18
|
+
with:
|
|
19
|
+
python-version: "3.11"
|
|
20
|
+
- name: Install dependencies
|
|
21
|
+
run: uv sync --dev
|
|
22
|
+
- name: Lint
|
|
23
|
+
run: uv run ruff check .
|
|
24
|
+
- name: Test
|
|
25
|
+
run: uv run pytest
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
release:
|
|
6
|
+
types: [published]
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
publish:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
environment: pypi
|
|
12
|
+
permissions:
|
|
13
|
+
id-token: write
|
|
14
|
+
contents: read
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- name: Install uv
|
|
18
|
+
uses: astral-sh/setup-uv@v5
|
|
19
|
+
- name: Build package
|
|
20
|
+
run: uv build
|
|
21
|
+
- name: Publish package
|
|
22
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
name: Smoke
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
smoke:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
- name: Install uv
|
|
15
|
+
uses: astral-sh/setup-uv@v5
|
|
16
|
+
- name: Set up Python
|
|
17
|
+
uses: actions/setup-python@v5
|
|
18
|
+
with:
|
|
19
|
+
python-version: "3.11"
|
|
20
|
+
- name: Install dependencies
|
|
21
|
+
run: uv sync --dev
|
|
22
|
+
- name: Run smoke test
|
|
23
|
+
run: uv run python scripts/smoke.py
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
- Added maintainer documentation, security policy, release process, and issue/PR templates.
|
|
6
|
+
- Added security model, tool-writing, server, and maintenance-workflow documentation.
|
|
7
|
+
- Added local demo and custom tool examples.
|
|
8
|
+
- Added build and manual publish workflows.
|
|
9
|
+
|
|
10
|
+
## 0.1.0
|
|
11
|
+
|
|
12
|
+
Initial public release.
|
|
13
|
+
|
|
14
|
+
- Added SSH client with lazy reconnect and command timeout handling.
|
|
15
|
+
- Added YAML-driven shell tools and injectable custom tool registry.
|
|
16
|
+
- Added LangGraph investigation loop with streaming events.
|
|
17
|
+
- Added FastAPI SSE integration helper.
|
|
18
|
+
- Added input/output sanitization and secret redaction.
|
|
19
|
+
- Added examples, tests, and CI.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thanks for helping improve `ops-copilot`.
|
|
4
|
+
|
|
5
|
+
## Development setup
|
|
6
|
+
|
|
7
|
+
`ops-copilot` depends on `langchain-content-normalizer`. Before that package is published to a package index, use the sibling checkout during local development:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
PYTHONPATH="../langchain-content-normalizer/src" uv run --no-sync ruff check .
|
|
11
|
+
PYTHONPATH="../langchain-content-normalizer/src" uv run --no-sync pytest
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Once the dependency is available through the configured Git URL, the normal workflow is:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
uv sync --dev
|
|
18
|
+
uv run ruff check .
|
|
19
|
+
uv run pytest
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Contribution guidelines
|
|
23
|
+
|
|
24
|
+
- Treat YAML tool definitions as privileged code.
|
|
25
|
+
- Add tests for every new command renderer, sanitizer, or graph event behavior.
|
|
26
|
+
- Never add real hostnames, credentials, private IPs, or internal service names.
|
|
27
|
+
- Keep tool outputs redacted before they reach the LLM or SSE stream.
|
|
28
|
+
- Prefer narrow, explicit parameters over free-form shell fragments.
|
|
29
|
+
- Document security assumptions in `docs/security-model.md`.
|
|
30
|
+
|
|
31
|
+
## Useful PRs
|
|
32
|
+
|
|
33
|
+
- Safer command policy and allowlist validation.
|
|
34
|
+
- Built-in systemd and Docker tool packs.
|
|
35
|
+
- More fake incident fixtures for tests.
|
|
36
|
+
- Better documentation for custom tools and server deployment.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Benjamin Jornet
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Maintainers
|
|
2
|
+
|
|
3
|
+
## Primary maintainer
|
|
4
|
+
|
|
5
|
+
- Benjamin Jornet (`@BenjaminJornet`)
|
|
6
|
+
|
|
7
|
+
## Maintainer responsibilities
|
|
8
|
+
|
|
9
|
+
- Review pull requests that add tools, command templates, graph behavior, or server endpoints.
|
|
10
|
+
- Triage issues with redacted YAML snippets and reproduction steps.
|
|
11
|
+
- Maintain the security model for SSH and LLM-driven tool execution.
|
|
12
|
+
- Keep examples runnable without private infrastructure.
|
|
13
|
+
- Publish releases and maintain `CHANGELOG.md`.
|
|
14
|
+
|
|
15
|
+
## Review priorities
|
|
16
|
+
|
|
17
|
+
1. No real hostnames, private IPs, credentials, tokens, or internal service names.
|
|
18
|
+
2. Tool output must be redacted before it reaches the LLM or SSE stream.
|
|
19
|
+
3. Shell commands should be narrow, documented, and non-destructive.
|
|
20
|
+
4. New graph/server behaviors need tests.
|
|
21
|
+
5. Security assumptions must be documented.
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ops-copilot
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Self-hosted SRE investigation copilot with YAML tools, SSH execution, SSE streaming, and secret redaction.
|
|
5
|
+
Project-URL: Homepage, https://github.com/benjaminjornet/ops-copilot
|
|
6
|
+
Project-URL: Issues, https://github.com/benjaminjornet/ops-copilot/issues
|
|
7
|
+
Author-email: Benjamin Jornet <benjamin.jornet@gmail.com>
|
|
8
|
+
License: MIT License
|
|
9
|
+
|
|
10
|
+
Copyright (c) 2026 Benjamin Jornet
|
|
11
|
+
|
|
12
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
13
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
14
|
+
in the Software without restriction, including without limitation the rights
|
|
15
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
16
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
17
|
+
furnished to do so, subject to the following conditions:
|
|
18
|
+
|
|
19
|
+
The above copyright notice and this permission notice shall be included in all
|
|
20
|
+
copies or substantial portions of the Software.
|
|
21
|
+
|
|
22
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
23
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
24
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
25
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
26
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
27
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
28
|
+
SOFTWARE.
|
|
29
|
+
License-File: LICENSE
|
|
30
|
+
Keywords: incident-response,langgraph,llm,ops,sre,ssh
|
|
31
|
+
Classifier: Development Status :: 3 - Alpha
|
|
32
|
+
Classifier: Intended Audience :: Developers
|
|
33
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
34
|
+
Classifier: Programming Language :: Python :: 3
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
38
|
+
Requires-Python: >=3.11
|
|
39
|
+
Requires-Dist: asyncssh>=2.14
|
|
40
|
+
Requires-Dist: langchain-content-normalizer>=0.1.0
|
|
41
|
+
Requires-Dist: langchain-core>=0.3
|
|
42
|
+
Requires-Dist: langgraph>=0.2
|
|
43
|
+
Requires-Dist: pydantic>=2
|
|
44
|
+
Requires-Dist: pyyaml>=6
|
|
45
|
+
Provides-Extra: ollama
|
|
46
|
+
Requires-Dist: langchain-community>=0.3; extra == 'ollama'
|
|
47
|
+
Provides-Extra: openai
|
|
48
|
+
Requires-Dist: langchain-openai>=0.2; extra == 'openai'
|
|
49
|
+
Provides-Extra: server
|
|
50
|
+
Requires-Dist: fastapi>=0.115; extra == 'server'
|
|
51
|
+
Requires-Dist: sse-starlette>=2; extra == 'server'
|
|
52
|
+
Requires-Dist: uvicorn>=0.32; extra == 'server'
|
|
53
|
+
Description-Content-Type: text/markdown
|
|
54
|
+
|
|
55
|
+
# ops-copilot
|
|
56
|
+
|
|
57
|
+
[](https://github.com/BenjaminJornet/ops-copilot/actions/workflows/ci.yml)
|
|
58
|
+
[](LICENSE)
|
|
59
|
+
[](pyproject.toml)
|
|
60
|
+
|
|
61
|
+
Self-hosted SRE investigation copilot for production systems.
|
|
62
|
+
|
|
63
|
+
`ops-copilot` lets an LLM call tools defined in YAML, execute safe remote commands over SSH, redact secrets from outputs, and stream investigation events through LangGraph or an optional FastAPI SSE server.
|
|
64
|
+
|
|
65
|
+
## Architecture
|
|
66
|
+
|
|
67
|
+
```text
|
|
68
|
+
User question -> InvestigationGraph -> LLM -> YAML tools -> SSH host
|
|
69
|
+
<- redacted tool output <- command result
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The package is intentionally generic. You can start with shell tools from YAML, then inject custom Python `RemoteTool` classes for richer workflows.
|
|
73
|
+
|
|
74
|
+
## Install
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
uv add ops-copilot
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Optional extras:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
uv add 'ops-copilot[server]'
|
|
84
|
+
uv add 'ops-copilot[openai]'
|
|
85
|
+
uv add 'ops-copilot[ollama]'
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## YAML tools
|
|
89
|
+
|
|
90
|
+
```yaml
|
|
91
|
+
tools:
|
|
92
|
+
- name: disk_usage
|
|
93
|
+
type: shell
|
|
94
|
+
description: Show filesystem usage.
|
|
95
|
+
command: df -h
|
|
96
|
+
|
|
97
|
+
- name: journalctl_service
|
|
98
|
+
type: shell
|
|
99
|
+
description: Show recent logs for a systemd service.
|
|
100
|
+
command: journalctl -u {service} --since '{since}' --no-pager
|
|
101
|
+
parameters:
|
|
102
|
+
service:
|
|
103
|
+
type: string
|
|
104
|
+
since:
|
|
105
|
+
type: string
|
|
106
|
+
required: false
|
|
107
|
+
default: "30 minutes ago"
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Minimal usage
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
from ops_copilot import InvestigationGraph, SSHClient, ToolRegistry
|
|
114
|
+
|
|
115
|
+
ssh = SSHClient(host="server.example.com", user="deploy", key_path="~/.ssh/id_ed25519")
|
|
116
|
+
tools = ToolRegistry(ssh, config_path="tools.yaml").load()
|
|
117
|
+
|
|
118
|
+
graph = InvestigationGraph(
|
|
119
|
+
llm=your_langchain_chat_model,
|
|
120
|
+
tools=tools,
|
|
121
|
+
system_prompt="You are an SRE copilot. Investigate safely and report evidence.",
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
async for event in graph.stream("The API is slow. What should I check?"):
|
|
125
|
+
print(event)
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Streaming events
|
|
129
|
+
|
|
130
|
+
`InvestigationGraph.stream()` yields dictionaries with these event names:
|
|
131
|
+
|
|
132
|
+
| Event | Meaning |
|
|
133
|
+
| --- | --- |
|
|
134
|
+
| `token` | streamed model text |
|
|
135
|
+
| `tool_start` | tool call started with input and step id |
|
|
136
|
+
| `tool_end` | tool call finished with redacted output |
|
|
137
|
+
| `error` | graph or stream error |
|
|
138
|
+
| `done` | investigation complete |
|
|
139
|
+
|
|
140
|
+
## Optional FastAPI server
|
|
141
|
+
|
|
142
|
+
The `ops_copilot.server.create_app()` helper exposes:
|
|
143
|
+
|
|
144
|
+
- `POST /investigate`
|
|
145
|
+
- `POST /investigate/stream`
|
|
146
|
+
|
|
147
|
+
If `OPS_COPILOT_API_KEY` is set, clients must send `X-API-Key`.
|
|
148
|
+
|
|
149
|
+
## Security notes
|
|
150
|
+
|
|
151
|
+
This project executes commands on servers you control. Treat `tools.yaml` as privileged code.
|
|
152
|
+
|
|
153
|
+
Recommendations:
|
|
154
|
+
|
|
155
|
+
- Use SSH key auth with least-privilege users.
|
|
156
|
+
- Review every command template before exposing it to an LLM.
|
|
157
|
+
- Avoid destructive commands in YAML.
|
|
158
|
+
- Keep parameterized commands narrow.
|
|
159
|
+
- Store no secrets in YAML or prompts.
|
|
160
|
+
- Rely on built-in redaction as a safety net, not as your only control.
|
|
161
|
+
|
|
162
|
+
Built-in redaction covers env-style secret lines, Bearer tokens, OpenAI-style keys, JWTs, long hex runs, and inline image data URLs.
|
|
163
|
+
|
|
164
|
+
## Documentation and examples
|
|
165
|
+
|
|
166
|
+
- `docs/security-model.md` documents threat boundaries and deployment controls.
|
|
167
|
+
- `docs/writing-tools.md` explains YAML and custom Python tools.
|
|
168
|
+
- `docs/server.md` covers the optional FastAPI/SSE integration.
|
|
169
|
+
- `docs/maintenance-workflows.md` describes maintainer workflows and review checklists.
|
|
170
|
+
- `examples/local_demo.py` runs without a real SSH host using fake outputs.
|
|
171
|
+
- `examples/custom_tool.py` shows how to inject a custom `RemoteTool` class.
|
|
172
|
+
|
|
173
|
+
## Roadmap
|
|
174
|
+
|
|
175
|
+
- Command allowlist validation for shell tools.
|
|
176
|
+
- Built-in Docker and systemd tool packs.
|
|
177
|
+
- Persistent investigation sessions.
|
|
178
|
+
- Audit log export.
|
|
179
|
+
- More fake incident fixtures for regression tests.
|
|
180
|
+
|
|
181
|
+
## Development
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
uv sync --dev
|
|
185
|
+
uv run ruff check .
|
|
186
|
+
uv run pytest
|
|
187
|
+
uv run python scripts/smoke.py
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## License
|
|
191
|
+
|
|
192
|
+
MIT
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# ops-copilot
|
|
2
|
+
|
|
3
|
+
[](https://github.com/BenjaminJornet/ops-copilot/actions/workflows/ci.yml)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
[](pyproject.toml)
|
|
6
|
+
|
|
7
|
+
Self-hosted SRE investigation copilot for production systems.
|
|
8
|
+
|
|
9
|
+
`ops-copilot` lets an LLM call tools defined in YAML, execute safe remote commands over SSH, redact secrets from outputs, and stream investigation events through LangGraph or an optional FastAPI SSE server.
|
|
10
|
+
|
|
11
|
+
## Architecture
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
User question -> InvestigationGraph -> LLM -> YAML tools -> SSH host
|
|
15
|
+
<- redacted tool output <- command result
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The package is intentionally generic. You can start with shell tools from YAML, then inject custom Python `RemoteTool` classes for richer workflows.
|
|
19
|
+
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
uv add ops-copilot
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Optional extras:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
uv add 'ops-copilot[server]'
|
|
30
|
+
uv add 'ops-copilot[openai]'
|
|
31
|
+
uv add 'ops-copilot[ollama]'
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## YAML tools
|
|
35
|
+
|
|
36
|
+
```yaml
|
|
37
|
+
tools:
|
|
38
|
+
- name: disk_usage
|
|
39
|
+
type: shell
|
|
40
|
+
description: Show filesystem usage.
|
|
41
|
+
command: df -h
|
|
42
|
+
|
|
43
|
+
- name: journalctl_service
|
|
44
|
+
type: shell
|
|
45
|
+
description: Show recent logs for a systemd service.
|
|
46
|
+
command: journalctl -u {service} --since '{since}' --no-pager
|
|
47
|
+
parameters:
|
|
48
|
+
service:
|
|
49
|
+
type: string
|
|
50
|
+
since:
|
|
51
|
+
type: string
|
|
52
|
+
required: false
|
|
53
|
+
default: "30 minutes ago"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Minimal usage
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
from ops_copilot import InvestigationGraph, SSHClient, ToolRegistry
|
|
60
|
+
|
|
61
|
+
ssh = SSHClient(host="server.example.com", user="deploy", key_path="~/.ssh/id_ed25519")
|
|
62
|
+
tools = ToolRegistry(ssh, config_path="tools.yaml").load()
|
|
63
|
+
|
|
64
|
+
graph = InvestigationGraph(
|
|
65
|
+
llm=your_langchain_chat_model,
|
|
66
|
+
tools=tools,
|
|
67
|
+
system_prompt="You are an SRE copilot. Investigate safely and report evidence.",
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
async for event in graph.stream("The API is slow. What should I check?"):
|
|
71
|
+
print(event)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Streaming events
|
|
75
|
+
|
|
76
|
+
`InvestigationGraph.stream()` yields dictionaries with these event names:
|
|
77
|
+
|
|
78
|
+
| Event | Meaning |
|
|
79
|
+
| --- | --- |
|
|
80
|
+
| `token` | streamed model text |
|
|
81
|
+
| `tool_start` | tool call started with input and step id |
|
|
82
|
+
| `tool_end` | tool call finished with redacted output |
|
|
83
|
+
| `error` | graph or stream error |
|
|
84
|
+
| `done` | investigation complete |
|
|
85
|
+
|
|
86
|
+
## Optional FastAPI server
|
|
87
|
+
|
|
88
|
+
The `ops_copilot.server.create_app()` helper exposes:
|
|
89
|
+
|
|
90
|
+
- `POST /investigate`
|
|
91
|
+
- `POST /investigate/stream`
|
|
92
|
+
|
|
93
|
+
If `OPS_COPILOT_API_KEY` is set, clients must send `X-API-Key`.
|
|
94
|
+
|
|
95
|
+
## Security notes
|
|
96
|
+
|
|
97
|
+
This project executes commands on servers you control. Treat `tools.yaml` as privileged code.
|
|
98
|
+
|
|
99
|
+
Recommendations:
|
|
100
|
+
|
|
101
|
+
- Use SSH key auth with least-privilege users.
|
|
102
|
+
- Review every command template before exposing it to an LLM.
|
|
103
|
+
- Avoid destructive commands in YAML.
|
|
104
|
+
- Keep parameterized commands narrow.
|
|
105
|
+
- Store no secrets in YAML or prompts.
|
|
106
|
+
- Rely on built-in redaction as a safety net, not as your only control.
|
|
107
|
+
|
|
108
|
+
Built-in redaction covers env-style secret lines, Bearer tokens, OpenAI-style keys, JWTs, long hex runs, and inline image data URLs.
|
|
109
|
+
|
|
110
|
+
## Documentation and examples
|
|
111
|
+
|
|
112
|
+
- `docs/security-model.md` documents threat boundaries and deployment controls.
|
|
113
|
+
- `docs/writing-tools.md` explains YAML and custom Python tools.
|
|
114
|
+
- `docs/server.md` covers the optional FastAPI/SSE integration.
|
|
115
|
+
- `docs/maintenance-workflows.md` describes maintainer workflows and review checklists.
|
|
116
|
+
- `examples/local_demo.py` runs without a real SSH host using fake outputs.
|
|
117
|
+
- `examples/custom_tool.py` shows how to inject a custom `RemoteTool` class.
|
|
118
|
+
|
|
119
|
+
## Roadmap
|
|
120
|
+
|
|
121
|
+
- Command allowlist validation for shell tools.
|
|
122
|
+
- Built-in Docker and systemd tool packs.
|
|
123
|
+
- Persistent investigation sessions.
|
|
124
|
+
- Audit log export.
|
|
125
|
+
- More fake incident fixtures for regression tests.
|
|
126
|
+
|
|
127
|
+
## Development
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
uv sync --dev
|
|
131
|
+
uv run ruff check .
|
|
132
|
+
uv run pytest
|
|
133
|
+
uv run python scripts/smoke.py
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## License
|
|
137
|
+
|
|
138
|
+
MIT
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported versions
|
|
4
|
+
|
|
5
|
+
Only the latest minor release receives security fixes while the project is pre-1.0.
|
|
6
|
+
|
|
7
|
+
## Reporting a vulnerability
|
|
8
|
+
|
|
9
|
+
Please open a private GitHub security advisory if available, or contact the maintainer through GitHub.
|
|
10
|
+
|
|
11
|
+
## Security model summary
|
|
12
|
+
|
|
13
|
+
`ops-copilot` executes commands over SSH on systems you control. The project reduces accidental exposure with secret redaction, input/output sanitizers, and explicit tool definitions, but it does not make arbitrary shell commands safe.
|
|
14
|
+
|
|
15
|
+
Review `docs/security-model.md` before deploying the server or exposing tools to an LLM.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Maintenance Workflows
|
|
2
|
+
|
|
3
|
+
`ops-copilot` is designed to be maintained with the same workflows it supports: structured investigation, explicit tools, safety review, and repeatable releases.
|
|
4
|
+
|
|
5
|
+
## Codex-assisted maintenance use cases
|
|
6
|
+
|
|
7
|
+
- Review pull requests that add YAML tools or custom `RemoteTool` classes.
|
|
8
|
+
- Generate edge-case tests for command rendering and redaction.
|
|
9
|
+
- Review SSH and command-execution safety boundaries.
|
|
10
|
+
- Draft release notes from merged changes.
|
|
11
|
+
- Triage issues by reproducing reported tool configurations against fake SSH clients.
|
|
12
|
+
- Improve documentation for operational workflows.
|
|
13
|
+
|
|
14
|
+
## Review checklist for tool PRs
|
|
15
|
+
|
|
16
|
+
- Is the command read-only or clearly documented?
|
|
17
|
+
- Are parameters narrow and typed?
|
|
18
|
+
- Could a parameter inject arbitrary shell syntax?
|
|
19
|
+
- Is output redacted before it reaches the graph or stream?
|
|
20
|
+
- Is there a test for the command template?
|
|
21
|
+
- Does the README or docs explain the workflow?
|
|
22
|
+
|
|
23
|
+
## Release checklist
|
|
24
|
+
|
|
25
|
+
- Run `uv run ruff check .`.
|
|
26
|
+
- Run `uv run pytest`.
|
|
27
|
+
- Scan source files for hostnames, private IPs, credentials, and client-specific names.
|
|
28
|
+
- Update `CHANGELOG.md`.
|
|
29
|
+
- Tag the release.
|
|
30
|
+
- Publish release notes.
|