meredith-agent 0.2.6__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.
- meredith_agent-0.2.6/.env.example +23 -0
- meredith_agent-0.2.6/.github/workflows/ci.yml +57 -0
- meredith_agent-0.2.6/.github/workflows/codeql.yml +22 -0
- meredith_agent-0.2.6/.gitignore +65 -0
- meredith_agent-0.2.6/.pre-commit-config.yaml +21 -0
- meredith_agent-0.2.6/.secrets.baseline +150 -0
- meredith_agent-0.2.6/AGENTS.md +108 -0
- meredith_agent-0.2.6/LICENSE +182 -0
- meredith_agent-0.2.6/Makefile +50 -0
- meredith_agent-0.2.6/PKG-INFO +327 -0
- meredith_agent-0.2.6/README.md +299 -0
- meredith_agent-0.2.6/assets/meredith.svg +90 -0
- meredith_agent-0.2.6/config/base.yaml +80 -0
- meredith_agent-0.2.6/config/large_model.yaml +35 -0
- meredith_agent-0.2.6/config/local_model.yaml +48 -0
- meredith_agent-0.2.6/pyproject.toml +59 -0
- meredith_agent-0.2.6/skills/code_review/SKILL.md +96 -0
- meredith_agent-0.2.6/skills/debugging/SKILL.md +77 -0
- meredith_agent-0.2.6/src/coding_agent/__init__.py +38 -0
- meredith_agent-0.2.6/src/coding_agent/acp/__init__.py +12 -0
- meredith_agent-0.2.6/src/coding_agent/acp/server.py +269 -0
- meredith_agent-0.2.6/src/coding_agent/agent/__init__.py +20 -0
- meredith_agent-0.2.6/src/coding_agent/agent/core.py +545 -0
- meredith_agent-0.2.6/src/coding_agent/agent/planner.py +388 -0
- meredith_agent-0.2.6/src/coding_agent/agent/verifier.py +273 -0
- meredith_agent-0.2.6/src/coding_agent/config.py +362 -0
- meredith_agent-0.2.6/src/coding_agent/context/__init__.py +17 -0
- meredith_agent-0.2.6/src/coding_agent/context/budget.py +184 -0
- meredith_agent-0.2.6/src/coding_agent/context/compressor.py +323 -0
- meredith_agent-0.2.6/src/coding_agent/context/manager.py +327 -0
- meredith_agent-0.2.6/src/coding_agent/llm/__init__.py +26 -0
- meredith_agent-0.2.6/src/coding_agent/llm/base.py +216 -0
- meredith_agent-0.2.6/src/coding_agent/llm/local.py +527 -0
- meredith_agent-0.2.6/src/coding_agent/llm/remote.py +304 -0
- meredith_agent-0.2.6/src/coding_agent/main.py +212 -0
- meredith_agent-0.2.6/src/coding_agent/memory/__init__.py +15 -0
- meredith_agent-0.2.6/src/coding_agent/memory/store.py +358 -0
- meredith_agent-0.2.6/src/coding_agent/rag/__init__.py +18 -0
- meredith_agent-0.2.6/src/coding_agent/rag/chunker.py +484 -0
- meredith_agent-0.2.6/src/coding_agent/rag/indexer.py +515 -0
- meredith_agent-0.2.6/src/coding_agent/rag/retriever.py +390 -0
- meredith_agent-0.2.6/src/coding_agent/recovery/__init__.py +14 -0
- meredith_agent-0.2.6/src/coding_agent/recovery/detector.py +303 -0
- meredith_agent-0.2.6/src/coding_agent/recovery/strategies.py +288 -0
- meredith_agent-0.2.6/src/coding_agent/tools/__init__.py +18 -0
- meredith_agent-0.2.6/src/coding_agent/tools/base.py +395 -0
- meredith_agent-0.2.6/src/coding_agent/tools/fs.py +419 -0
- meredith_agent-0.2.6/src/coding_agent/tools/git.py +201 -0
- meredith_agent-0.2.6/src/coding_agent/tools/router.py +248 -0
- meredith_agent-0.2.6/src/coding_agent/tools/search.py +487 -0
- meredith_agent-0.2.6/src/coding_agent/tools/web.py +419 -0
- meredith_agent-0.2.6/src/coding_agent/types.py +430 -0
- meredith_agent-0.2.6/tests/__init__.py +0 -0
- meredith_agent-0.2.6/tests/conftest.py +89 -0
- meredith_agent-0.2.6/tests/test_budget.py +166 -0
- meredith_agent-0.2.6/tests/test_compressor.py +148 -0
- meredith_agent-0.2.6/tests/test_config.py +298 -0
- meredith_agent-0.2.6/tests/test_context_manager.py +118 -0
- meredith_agent-0.2.6/tests/test_detector.py +154 -0
- meredith_agent-0.2.6/tests/test_import.py +9 -0
- meredith_agent-0.2.6/tests/test_llm_base.py +206 -0
- meredith_agent-0.2.6/tests/test_memory.py +112 -0
- meredith_agent-0.2.6/tests/test_planner.py +108 -0
- meredith_agent-0.2.6/tests/test_router.py +155 -0
- meredith_agent-0.2.6/tests/test_strategies.py +92 -0
- meredith_agent-0.2.6/tests/test_tool_base.py +58 -0
- meredith_agent-0.2.6/tests/test_types.py +348 -0
- meredith_agent-0.2.6/tests/test_verifier.py +107 -0
- meredith_agent-0.2.6/uv.lock +1320 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# ── API Keys ──────────────────────────────────────────
|
|
2
|
+
# Copy this file to .env and fill in your actual keys.
|
|
3
|
+
# NEVER commit .env or any file containing real keys!
|
|
4
|
+
|
|
5
|
+
# LLM provider (any OpenAI-compatible API)
|
|
6
|
+
# Used by: llm/provider = "remote", api_key_env in config YAML
|
|
7
|
+
# Supports OpenAI, Anthropic, Together, Opencode, Fireworks, Azure, etc.
|
|
8
|
+
LLM_API_KEY=sk-your-key-here
|
|
9
|
+
|
|
10
|
+
# Web search backends (pick one)
|
|
11
|
+
# Copy the API key for your chosen backend from config YAML
|
|
12
|
+
|
|
13
|
+
# Brave Search (default for local_model)
|
|
14
|
+
# Get at: https://brave.com/search/api/
|
|
15
|
+
BRAVE_API_KEY=
|
|
16
|
+
|
|
17
|
+
# Tavily Search (default for large_model)
|
|
18
|
+
# Get at: https://tavily.com/api
|
|
19
|
+
TAVILY_API_KEY=
|
|
20
|
+
|
|
21
|
+
# Exa Search (alternative)
|
|
22
|
+
# Get at: https://exa.ai
|
|
23
|
+
EXA_API_KEY=
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
release:
|
|
9
|
+
types: [published]
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
lint:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: astral-sh/setup-uv@v3
|
|
17
|
+
with:
|
|
18
|
+
version: "0.6.x"
|
|
19
|
+
- run: uv sync --extra dev
|
|
20
|
+
- run: uv run ruff check src/
|
|
21
|
+
|
|
22
|
+
typecheck:
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v4
|
|
26
|
+
- uses: astral-sh/setup-uv@v3
|
|
27
|
+
with:
|
|
28
|
+
version: "0.6.x"
|
|
29
|
+
- run: uv sync --extra dev
|
|
30
|
+
- run: uv run mypy src/ --strict
|
|
31
|
+
|
|
32
|
+
test:
|
|
33
|
+
runs-on: ubuntu-latest
|
|
34
|
+
steps:
|
|
35
|
+
- uses: actions/checkout@v4
|
|
36
|
+
- uses: astral-sh/setup-uv@v3
|
|
37
|
+
with:
|
|
38
|
+
version: "0.6.x"
|
|
39
|
+
- run: uv sync --extra dev
|
|
40
|
+
- run: uv run pytest tests/ -v --cov=coding_agent
|
|
41
|
+
|
|
42
|
+
build:
|
|
43
|
+
runs-on: ubuntu-latest
|
|
44
|
+
needs: [lint, typecheck, test]
|
|
45
|
+
if: github.event_name == 'release'
|
|
46
|
+
environment:
|
|
47
|
+
name: pypi
|
|
48
|
+
permissions:
|
|
49
|
+
id-token: write
|
|
50
|
+
contents: read
|
|
51
|
+
steps:
|
|
52
|
+
- uses: actions/checkout@v4
|
|
53
|
+
- uses: astral-sh/setup-uv@v3
|
|
54
|
+
with:
|
|
55
|
+
version: "0.6.x"
|
|
56
|
+
- run: uv build
|
|
57
|
+
- run: uv publish
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
name: CodeQL
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
schedule:
|
|
9
|
+
- cron: "0 12 * * 1" # Weekly: Monday noon
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
analyze:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
permissions:
|
|
15
|
+
security-events: write
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
- uses: github/codeql-action/init@v3
|
|
19
|
+
with:
|
|
20
|
+
languages: python
|
|
21
|
+
queries: security-and-quality
|
|
22
|
+
- uses: github/codeql-action/analyze@v3
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# ── Python ──────────────────────────────────────────────
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
dist/
|
|
6
|
+
build/
|
|
7
|
+
*.egg
|
|
8
|
+
.venv/
|
|
9
|
+
venv/
|
|
10
|
+
env/
|
|
11
|
+
|
|
12
|
+
# ── Runtime data ────────────────────────────────────────
|
|
13
|
+
.agent/
|
|
14
|
+
*.db
|
|
15
|
+
*.log
|
|
16
|
+
|
|
17
|
+
# ── IDE / Editor ───────────────────────────────────────
|
|
18
|
+
.vscode/
|
|
19
|
+
.idea/
|
|
20
|
+
*.swp
|
|
21
|
+
*.swo
|
|
22
|
+
*~
|
|
23
|
+
.DS_Store
|
|
24
|
+
|
|
25
|
+
# ── Tooling artifacts ──────────────────────────────────
|
|
26
|
+
.ruff_cache/
|
|
27
|
+
.mypy_cache/
|
|
28
|
+
.pytest_cache/
|
|
29
|
+
htmlcov/
|
|
30
|
+
.coverage
|
|
31
|
+
coverage/
|
|
32
|
+
|
|
33
|
+
# ── Secrets / credentials ─────────────────────────────
|
|
34
|
+
.env
|
|
35
|
+
.env.*
|
|
36
|
+
.env.local
|
|
37
|
+
.env.production
|
|
38
|
+
.env.development
|
|
39
|
+
*.pem
|
|
40
|
+
*.key
|
|
41
|
+
**/secrets/**
|
|
42
|
+
**/credentials/**
|
|
43
|
+
!**/.env.example
|
|
44
|
+
|
|
45
|
+
# ── OS files ───────────────────────────────────────────
|
|
46
|
+
.DS_Store
|
|
47
|
+
Thumbs.db
|
|
48
|
+
|
|
49
|
+
# ── Cloud provider credentials ────────────────────────
|
|
50
|
+
.aws/
|
|
51
|
+
.gcp/
|
|
52
|
+
.azure/
|
|
53
|
+
google-cloud-sdk/
|
|
54
|
+
.gcloud/
|
|
55
|
+
|
|
56
|
+
# ── Local config / identities ─────────────────────────
|
|
57
|
+
.ssh/
|
|
58
|
+
.kube/
|
|
59
|
+
config.json # Docker auth
|
|
60
|
+
.docker/
|
|
61
|
+
.npmrc
|
|
62
|
+
.netrc
|
|
63
|
+
.gitconfig.local
|
|
64
|
+
.git-credentials
|
|
65
|
+
*.local
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# ── Pre-commit hooks ──────────────────────────────────
|
|
2
|
+
# Install: uv run pre-commit install
|
|
3
|
+
# Run all: uv run pre-commit run --all-files
|
|
4
|
+
# ──────────────────────────────────────────────────────
|
|
5
|
+
repos:
|
|
6
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
7
|
+
rev: v5.0.0
|
|
8
|
+
hooks:
|
|
9
|
+
- id: trailing-whitespace
|
|
10
|
+
- id: end-of-file-fixer
|
|
11
|
+
- id: check-yaml
|
|
12
|
+
- id: check-added-large-files
|
|
13
|
+
args: [--maxkb=500]
|
|
14
|
+
- id: detect-private-key
|
|
15
|
+
|
|
16
|
+
- repo: https://github.com/Yelp/detect-secrets
|
|
17
|
+
rev: v1.5.0
|
|
18
|
+
hooks:
|
|
19
|
+
- id: detect-secrets
|
|
20
|
+
args: [--baseline, .secrets.baseline]
|
|
21
|
+
exclude: \.env\.example$
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.5.0",
|
|
3
|
+
"plugins_used": [
|
|
4
|
+
{
|
|
5
|
+
"name": "ArtifactoryDetector"
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
"name": "AWSKeyDetector"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"name": "AzureStorageKeyDetector"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"name": "Base64HighEntropyString",
|
|
15
|
+
"limit": 4.5
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "BasicAuthDetector"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"name": "CloudantDetector"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"name": "DiscordBotTokenDetector"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"name": "GitHubTokenDetector"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"name": "GitLabTokenDetector"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"name": "HexHighEntropyString",
|
|
34
|
+
"limit": 3.0
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"name": "IbmCloudIamDetector"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"name": "IbmCosHmacDetector"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"name": "IPPublicDetector"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"name": "JwtTokenDetector"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"name": "KeywordDetector",
|
|
50
|
+
"keyword_exclude": ""
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"name": "MailchimpDetector"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"name": "NpmDetector"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"name": "OpenAIDetector"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"name": "PrivateKeyDetector"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"name": "PypiTokenDetector"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"name": "SendGridDetector"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"name": "SlackDetector"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"name": "SoftlayerDetector"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"name": "SquareOAuthDetector"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"name": "StripeDetector"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"name": "TelegramBotTokenDetector"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"name": "TwilioKeyDetector"
|
|
87
|
+
}
|
|
88
|
+
],
|
|
89
|
+
"filters_used": [
|
|
90
|
+
{
|
|
91
|
+
"path": "detect_secrets.filters.allowlist.is_line_allowlisted"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"path": "detect_secrets.filters.common.is_baseline_file",
|
|
95
|
+
"filename": ".secrets.baseline"
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies",
|
|
99
|
+
"min_level": 2
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"path": "detect_secrets.filters.heuristic.is_indirect_reference"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"path": "detect_secrets.filters.heuristic.is_likely_id_string"
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"path": "detect_secrets.filters.heuristic.is_lock_file"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"path": "detect_secrets.filters.heuristic.is_not_alphanumeric_string"
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"path": "detect_secrets.filters.heuristic.is_potential_uuid"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"path": "detect_secrets.filters.heuristic.is_prefixed_with_dollar_sign"
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"path": "detect_secrets.filters.heuristic.is_sequential_string"
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"path": "detect_secrets.filters.heuristic.is_swagger_file"
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"path": "detect_secrets.filters.heuristic.is_templated_secret"
|
|
127
|
+
}
|
|
128
|
+
],
|
|
129
|
+
"results": {
|
|
130
|
+
"README.md": [
|
|
131
|
+
{
|
|
132
|
+
"type": "Secret Keyword",
|
|
133
|
+
"filename": "README.md",
|
|
134
|
+
"hashed_secret": "ec3810e10fb78db55ce38b9c18d1c3eb1db739e0",
|
|
135
|
+
"is_verified": false,
|
|
136
|
+
"line_number": 55
|
|
137
|
+
}
|
|
138
|
+
],
|
|
139
|
+
"config/large_model.yaml": [
|
|
140
|
+
{
|
|
141
|
+
"type": "Secret Keyword",
|
|
142
|
+
"filename": "config/large_model.yaml",
|
|
143
|
+
"hashed_secret": "5376e4b0871e1d739b9157a0b6cbdcf26ec28a97",
|
|
144
|
+
"is_verified": false,
|
|
145
|
+
"line_number": 10
|
|
146
|
+
}
|
|
147
|
+
]
|
|
148
|
+
},
|
|
149
|
+
"generated_at": "2026-06-27T15:37:32Z"
|
|
150
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# AGENTS.md — Project Instructions for AI Coding Agents
|
|
2
|
+
|
|
3
|
+
## Project Overview
|
|
4
|
+
|
|
5
|
+
This is meredith: a modern AI coding agent with RAG,
|
|
6
|
+
ACP (Agent Client Protocol) integration, and smart context
|
|
7
|
+
management. It supports both large remote models via any
|
|
8
|
+
OpenAI-compatible API (Claude, GPT, Opencode, etc.) and
|
|
9
|
+
local models (Ollama on Linux/macOS/Windows, MLX on Apple Silicon).
|
|
10
|
+
|
|
11
|
+
## Tech Stack
|
|
12
|
+
|
|
13
|
+
- Language: Python 3.13+
|
|
14
|
+
- Package manager: uv
|
|
15
|
+
- Async framework: asyncio
|
|
16
|
+
- HTTP client: httpx
|
|
17
|
+
- Token counting: tiktoken (cl100k_base)
|
|
18
|
+
- Code parsing: tree-sitter-languages (optional, no cp313 wheel)
|
|
19
|
+
- Database: SQLite (via stdlib)
|
|
20
|
+
- Search: ripgrep (preferred) or grep
|
|
21
|
+
|
|
22
|
+
## Development Environment
|
|
23
|
+
|
|
24
|
+
- Install: uv sync --extra dev
|
|
25
|
+
- Lint: uv run ruff check src/
|
|
26
|
+
- Format: uv run ruff format src/
|
|
27
|
+
- Type check: uv run mypy src/ (if configured)
|
|
28
|
+
- Test: uv run pytest tests/ -v
|
|
29
|
+
|
|
30
|
+
## Code Style
|
|
31
|
+
|
|
32
|
+
- Use Python 3.13+ syntax: X | Y unions, type statements, slots=True
|
|
33
|
+
- Use from __future__ import annotations in all files
|
|
34
|
+
- All functions and classes must have docstrings (triple double-quotes)
|
|
35
|
+
- Use async/await for all I/O operations
|
|
36
|
+
- Never use pandas — prefer built-in types and stdlib
|
|
37
|
+
- Never hardcode values that users might change — put them in config YAML
|
|
38
|
+
|
|
39
|
+
## Project Structure
|
|
40
|
+
|
|
41
|
+
- config/ — YAML configuration files (base, large_model, local_model)
|
|
42
|
+
- src/coding_agent/ — Main package
|
|
43
|
+
- agent/ — Core loop, planner, verifier
|
|
44
|
+
- context/ — Context window management
|
|
45
|
+
- tools/ — Tool definitions and executors
|
|
46
|
+
- rag/ — Retrieval-Augmented Generation subsystem
|
|
47
|
+
- recovery/ — Loop detection and escape strategies
|
|
48
|
+
- llm/ — LLM client abstractions (remote, local/MLX)
|
|
49
|
+
- memory/ — Cross-session memory store
|
|
50
|
+
- acp/ — ACP server for editor integration
|
|
51
|
+
- skills/ — SKILL.md files for agent capabilities
|
|
52
|
+
- .agent/ — Runtime data (index, memory DB, logs) — do not edit manually
|
|
53
|
+
|
|
54
|
+
## Testing Instructions
|
|
55
|
+
|
|
56
|
+
- Run all tests: uv run pytest tests/ -v
|
|
57
|
+
- Run a single test: uv run pytest tests/test_specific.py -v
|
|
58
|
+
- Run with coverage: uv run pytest tests/ --cov=coding_agent
|
|
59
|
+
|
|
60
|
+
## PR Instructions
|
|
61
|
+
|
|
62
|
+
- Title format: [area] Description (e.g. [rag] Add AST chunker for Go)
|
|
63
|
+
- Run uv run ruff check src/ and uv run pytest tests/ -v before committing
|
|
64
|
+
- Keep PRs focused — one concern per PR
|
|
65
|
+
- Document any new config keys in the appropriate YAML file
|
|
66
|
+
|
|
67
|
+
## Security Considerations
|
|
68
|
+
|
|
69
|
+
### Credential Management
|
|
70
|
+
- API keys are read from environment variables (e.g. `LLM_API_KEY`, `BRAVE_API_KEY`), never from source code, config files, or `.env` files within the project tree.
|
|
71
|
+
- The LLM client factory reads `api_key_env` from config and resolves it at runtime from the process environment — keys never appear in logs, dumps, or context windows.
|
|
72
|
+
- Git credentials used by the git tool are inherited from the host environment (git-credential-osxkeychain, etc.), never stored or forwarded by the agent.
|
|
73
|
+
- The memory store (SQLite) does not persist authentication tokens, session keys, or credentials of any kind.
|
|
74
|
+
|
|
75
|
+
### PII / Sensitive Data Protection
|
|
76
|
+
- Tool outputs (file contents, git diffs, search results, web responses) are **not automatically scrubbed** — the agent may process sensitive data present in the working directory. This is by design (the agent needs file contents to do its job).
|
|
77
|
+
- However, the context compressor may truncate long outputs, which provides a natural volume-based limit on how much raw data enters the LLM context window at once.
|
|
78
|
+
- The cross-session memory store explicitly excludes any content containing email addresses, API keys, tokens, or secrets patterns (`sk-...`, `ghp_...`, `-----BEGIN.*KEY-----`). See `memory/store.py:save_session`.
|
|
79
|
+
- All log files are written to `.agent/agent.log` (gitignored) and are local-only. Logs do not contain environment variable values or full API responses.
|
|
80
|
+
|
|
81
|
+
### Prompt Injection Mitigation
|
|
82
|
+
- Tool outputs are presented to the LLM as `TOOL`-role messages, which most frontier models treat as system-controlled rather than user-controlled content.
|
|
83
|
+
- The system prompt instructs the agent to treat file contents as data, not instructions. No tool output is ever interpreted as a directive to the agent loop itself.
|
|
84
|
+
- Web-fetched content is stripped of script tags and rendered to plain text before entering the context window.
|
|
85
|
+
|
|
86
|
+
### File System Safety
|
|
87
|
+
- All file operations (`read_file`, `edit_file`, `write_file`, `list_directory`) are scoped to the configured `working_directory`. Path traversal sequences (`..`) are explicitly rejected.
|
|
88
|
+
- The `write_file` and `edit_file` tools refuse to create symlinks outside the working tree.
|
|
89
|
+
- File writes are validated for encoding (UTF-8) before proceeding; binary files are not written through the agent tools.
|
|
90
|
+
- The `run_command` tool enforces a configurable timeout (default 120s) to prevent runaway processes.
|
|
91
|
+
|
|
92
|
+
### Subprocess & Shell Safety
|
|
93
|
+
- Shell commands are executed via `asyncio.create_subprocess_shell` with no shell injection surface — the entire command string is user-provided and passed to the shell directly. This is an accepted risk of the `run_command` tool; the agent is trusted within the working directory.
|
|
94
|
+
- The ACP server communicates exclusively over stdio (not TCP), eliminating network-based attack surface for editor integration.
|
|
95
|
+
|
|
96
|
+
### Data at Rest
|
|
97
|
+
- The RAG index and memory store are SQLite databases stored in `.agent/` (gitignored). They contain file paths, code chunks, and agent observations — not credentials.
|
|
98
|
+
- Users should ensure `.agent/` is excluded from backups that leave their security boundary.
|
|
99
|
+
|
|
100
|
+
### Supply Chain
|
|
101
|
+
- Dependencies are pinned to minor/major ranges (e.g. `httpx>=0.27,<1`) and managed via `uv.lock` for reproducible builds.
|
|
102
|
+
- The build process uses Hatchling (pure Python, no compiled extensions in the toolchain).
|
|
103
|
+
- CI runs `uv run ruff check`, `uv run mypy --strict`, and `uv run pytest --cov` on every PR to catch regressions.
|
|
104
|
+
|
|
105
|
+
### Rate Limiting & Resource Protection
|
|
106
|
+
- The `web_fetch` and `web_search` tools have configurable timeouts (default 15s) and result limits.
|
|
107
|
+
- The agent loop has a hard cap at `max_steps` (default 50) to prevent runaway token consumption.
|
|
108
|
+
- The context budget system prevents any single step from consuming more than 10% of the remaining budget.
|