korgex 0.6.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- korgex-0.6.1.dist-info/METADATA +701 -0
- korgex-0.6.1.dist-info/RECORD +46 -0
- korgex-0.6.1.dist-info/WHEEL +5 -0
- korgex-0.6.1.dist-info/entry_points.txt +2 -0
- korgex-0.6.1.dist-info/licenses/LICENSE +21 -0
- korgex-0.6.1.dist-info/top_level.txt +1 -0
- src/__init__.py +31 -0
- src/agent.py +1157 -0
- src/cli.py +591 -0
- src/context_compression.py +131 -0
- src/dashboard.py +384 -0
- src/dependency_graph.py +185 -0
- src/diff_engine.py +252 -0
- src/feature_flags.py +146 -0
- src/github_api.py +116 -0
- src/google_auth.py +284 -0
- src/guardrails.py +66 -0
- src/hooks.py +178 -0
- src/import_adapters.py +195 -0
- src/interactive.py +657 -0
- src/introspect.py +238 -0
- src/korg_ledger.py +798 -0
- src/korgantic.py +313 -0
- src/korgex_bench.py +193 -0
- src/ledger_spec.py +125 -0
- src/mcp_client.py +563 -0
- src/mcp_server.py +175 -0
- src/memory.py +320 -0
- src/memory_drift.py +193 -0
- src/mode_schemas.py +263 -0
- src/model_router.py +514 -0
- src/profiler.py +103 -0
- src/recall.py +237 -0
- src/sandbox.py +246 -0
- src/self_healing.py +264 -0
- src/strict_pairing.py +337 -0
- src/structured_output.py +107 -0
- src/swarm.py +291 -0
- src/system_prompt.py +179 -0
- src/test_gate.py +65 -0
- src/tool_abstraction.py +401 -0
- src/tool_base.py +133 -0
- src/tools_impl.py +913 -0
- src/vision.py +108 -0
- src/webhook_server.py +160 -0
- src/workspace.py +153 -0
|
@@ -0,0 +1,701 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: korgex
|
|
3
|
+
Version: 0.6.1
|
|
4
|
+
Summary: Autonomous AI coding agent — provider-agnostic, MCP-native, plan-first
|
|
5
|
+
Author: New1Direction
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/New1Direction/Korgex
|
|
8
|
+
Project-URL: Repository, https://github.com/New1Direction/Korgex
|
|
9
|
+
Project-URL: Issues, https://github.com/New1Direction/Korgex/issues
|
|
10
|
+
Keywords: ai,agent,coding,llm,claude,openai,mcp,anthropic
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Software Development
|
|
22
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: anthropic>=0.40.0
|
|
27
|
+
Requires-Dist: openai>=1.0.0
|
|
28
|
+
Requires-Dist: rich>=13.0.0
|
|
29
|
+
Requires-Dist: fastapi>=0.100.0
|
|
30
|
+
Requires-Dist: uvicorn>=0.20.0
|
|
31
|
+
Requires-Dist: websockets>=11.0
|
|
32
|
+
Requires-Dist: httpx>=0.24.0
|
|
33
|
+
Requires-Dist: pyyaml>=6.0
|
|
34
|
+
Provides-Extra: dev
|
|
35
|
+
Requires-Dist: pytest<9.0.0,>=8.0.0; extra == "dev"
|
|
36
|
+
Requires-Dist: ruff<1.0.0,>=0.1.0; extra == "dev"
|
|
37
|
+
Requires-Dist: build<2.0.0,>=1.0.0; extra == "dev"
|
|
38
|
+
Requires-Dist: twine<7.0.0,>=5.0.0; extra == "dev"
|
|
39
|
+
Dynamic: license-file
|
|
40
|
+
|
|
41
|
+
# korgex
|
|
42
|
+
|
|
43
|
+
**Autonomous coding agent. Provider-agnostic. MCP-native. Plan-first.**
|
|
44
|
+
|
|
45
|
+
A terminal-native AI engineer that reads your codebase, edits files, runs commands, and ships work. Speaks both Anthropic and OpenAI tool-use protocols. Connects to any MCP server. Streams output live to your terminal. Open source, MIT-licensed, no vendor lock-in.
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
$ korgex "add a /healthz endpoint that returns 200 with uptime"
|
|
49
|
+
➤ Read(file_path=/app/routes.py)
|
|
50
|
+
➤ Edit(file_path=/app/routes.py, old_string=..., new_string=...)
|
|
51
|
+
➤ Bash(command=pytest tests/test_routes.py -q)
|
|
52
|
+
✓ Added GET /healthz returning {"status": "ok", "uptime_seconds": ...}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Table of Contents
|
|
58
|
+
|
|
59
|
+
- [Install](#install)
|
|
60
|
+
- [Quickstart](#quickstart)
|
|
61
|
+
- [How it works](#how-it-works)
|
|
62
|
+
- [Verifiable cognition](#verifiable-cognition)
|
|
63
|
+
- [CLI reference](#cli-reference)
|
|
64
|
+
- [Tools](#tools)
|
|
65
|
+
- [Environment variables](#environment-variables)
|
|
66
|
+
- [Multi-model routing](#multi-model-routing)
|
|
67
|
+
- [MCP integration](#mcp-integration)
|
|
68
|
+
- [Streaming TUI](#streaming-tui)
|
|
69
|
+
- [VS Code sidecar](#vs-code-sidecar)
|
|
70
|
+
- [Dashboard API](#dashboard-api)
|
|
71
|
+
- [Architecture](#architecture)
|
|
72
|
+
- [Project structure](#project-structure)
|
|
73
|
+
- [Development](#development)
|
|
74
|
+
- [Testing](#testing)
|
|
75
|
+
- [Building & releasing](#building--releasing)
|
|
76
|
+
- [Troubleshooting](#troubleshooting)
|
|
77
|
+
- [Known limitations](#known-limitations)
|
|
78
|
+
- [License](#license)
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Install
|
|
83
|
+
|
|
84
|
+
### From GitHub Release (recommended today)
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
pip install https://github.com/New1Direction/korgex/releases/download/v0.6.1/korgex-0.6.1-py3-none-any.whl
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### From source
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
git clone https://github.com/New1Direction/korgex.git
|
|
94
|
+
cd korgex
|
|
95
|
+
pip install -e .
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### From `git+https` (latest `main`)
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
pip install git+https://github.com/New1Direction/korgex.git
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### From PyPI
|
|
105
|
+
|
|
106
|
+
Planned. Until then use one of the above.
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## Quickstart
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
# 1. Set an API key — either provider works
|
|
114
|
+
export ANTHROPIC_API_KEY="sk-ant-..."
|
|
115
|
+
# or
|
|
116
|
+
export OPENAI_API_KEY="sk-proj-..."
|
|
117
|
+
# or via OpenRouter (OpenAI-compatible, many models)
|
|
118
|
+
export KORGEX_API_KEY="sk-or-v1-..."
|
|
119
|
+
export KORGEX_API_URL="https://openrouter.ai/api/v1"
|
|
120
|
+
|
|
121
|
+
# 2. Run the agent on a naked prompt
|
|
122
|
+
korgex "fix the failing test in tests/test_auth.py"
|
|
123
|
+
|
|
124
|
+
# 3. Or pick a specific model / mode
|
|
125
|
+
korgex --model claude-sonnet-4-6 "refactor src/handler.py"
|
|
126
|
+
korgex --mode plan "design a rate limiter for the API"
|
|
127
|
+
korgex --quiet "list the python files in src/"
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## How it works
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
┌──────────────────────────────────────────────────────────────────┐
|
|
136
|
+
│ KORGEX AGENT LOOP │
|
|
137
|
+
│ │
|
|
138
|
+
│ user prompt │
|
|
139
|
+
│ │ │
|
|
140
|
+
│ ▼ │
|
|
141
|
+
│ ┌─────────────────────────┐ │
|
|
142
|
+
│ │ KorgexAgent.run_task() │ │
|
|
143
|
+
│ └─────────────────────────┘ │
|
|
144
|
+
│ │ │
|
|
145
|
+
│ ▼ │
|
|
146
|
+
│ ┌──────────────────────────────────────────────────────────┐ │
|
|
147
|
+
│ │ for i in range(max_iter): │ │
|
|
148
|
+
│ │ response = LLM.send(messages, tools) │ │
|
|
149
|
+
│ │ if no tool_calls → return final text │ │
|
|
150
|
+
│ │ for call in tool_calls: │ │
|
|
151
|
+
│ │ result = route_tool_call(name, args) │ │
|
|
152
|
+
│ │ messages.append(tool_result) │ │
|
|
153
|
+
│ └──────────────────────────────────────────────────────────┘ │
|
|
154
|
+
│ │ │
|
|
155
|
+
│ ▼ │
|
|
156
|
+
│ ┌─────────────────────────────────────────┐ │
|
|
157
|
+
│ │ Provider branching │ │
|
|
158
|
+
│ │ - "claude" in model → Anthropic SDK │ │
|
|
159
|
+
│ │ - else → OpenAI SDK (works for │ │
|
|
160
|
+
│ │ OpenAI, OpenRouter, Ollama, etc.) │ │
|
|
161
|
+
│ └─────────────────────────────────────────┘ │
|
|
162
|
+
│ │ │
|
|
163
|
+
│ ▼ │
|
|
164
|
+
│ ┌─────────────────────────────────────────┐ │
|
|
165
|
+
│ │ Tool routing (src/tool_abstraction.py) │ │
|
|
166
|
+
│ │ - 12 Claude-Code-style user tools │ │
|
|
167
|
+
│ │ - Adapter layer → Jules-style handlers │ │
|
|
168
|
+
│ │ - MCP-sourced tools → MCP manager │ │
|
|
169
|
+
│ └─────────────────────────────────────────┘ │
|
|
170
|
+
└──────────────────────────────────────────────────────────────────┘
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
The agent is provider-agnostic by design: tool schemas are translated per provider (`{name, description, input_schema}` for Anthropic, `{type: "function", function: {...}}` for OpenAI), responses are normalized into a common shape, and tool results are formatted in whichever message structure the provider expects.
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Verifiable cognition
|
|
178
|
+
|
|
179
|
+
What sets korgex apart: every run is recorded to a **tamper-evident causal ledger**, not an opaque log. Each event is hash-linked (`prev_hash`/`entry_hash`) to the previous one, so a whole session can be cryptographically proven intact — any edit, deletion, reorder, or splice is detected and localized to the offending event.
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
# Prove a recorded run was not altered after the fact
|
|
183
|
+
korgex verify .korg/journal.jsonl
|
|
184
|
+
# ✓ ledger intact — 7 events, hash-chain verified (exit 0; exit 1 + the bad seq_id if tampered)
|
|
185
|
+
|
|
186
|
+
# Set KORG_LEDGER_HMAC_KEY to make the chain tamper-PROOF, not just tamper-evident
|
|
187
|
+
export KORG_LEDGER_HMAC_KEY=…
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
On top of the chain, korgex tracks **memory drift**: a remembered fact is anchored to a sha256 baseline of its source, so when the source moves on the staleness is an exact signal — and the keep/refresh/discard reconcile decision is itself recorded to the ledger.
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
# Scan persistent memories for drift against their recorded source baselines
|
|
194
|
+
korgex drift
|
|
195
|
+
# ✗ memory DRIFT — 1 drifted … reconcile is recorded to the ledger (exit 0 if none, 1 if drift)
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
See [Self-Coding Bench](docs/self-coding-bench.md) for live reliability data across five models.
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## CLI reference
|
|
203
|
+
|
|
204
|
+
```
|
|
205
|
+
$ korgex --help
|
|
206
|
+
|
|
207
|
+
usage: korgex [-h] SUBCOMMAND ...
|
|
208
|
+
|
|
209
|
+
korgex — autonomous coding agent. Pass a naked prompt to run the agent,
|
|
210
|
+
or use a subcommand.
|
|
211
|
+
|
|
212
|
+
positional arguments:
|
|
213
|
+
SUBCOMMAND
|
|
214
|
+
serve Start dashboard + open VS Code with the sidecar.
|
|
215
|
+
dashboard Start the web dashboard only.
|
|
216
|
+
init Install Python deps + compile the VS Code extension.
|
|
217
|
+
status Check if the backend is running.
|
|
218
|
+
stop Stop the running backend.
|
|
219
|
+
install-extension
|
|
220
|
+
Install the .vsix into VS Code.
|
|
221
|
+
verify Prove the cognition ledger is intact (hash-chain proof).
|
|
222
|
+
drift Scan memories for drift vs their source baselines.
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Naked-prompt invocation (the default)
|
|
226
|
+
|
|
227
|
+
Any non-subcommand argument is treated as a prompt:
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
korgex "create a hello.txt with the text 'hi'"
|
|
231
|
+
korgex --mode plan "redesign the data model"
|
|
232
|
+
korgex --model gpt-4o "write the test for this fix"
|
|
233
|
+
korgex --quiet "list all functions called from main()"
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Flags
|
|
237
|
+
|
|
238
|
+
| Flag | Purpose |
|
|
239
|
+
|---|---|
|
|
240
|
+
| `--model MODEL` | Override the model (e.g. `claude-sonnet-4-6`, `gpt-4o`, `openai/gpt-4o-mini`). Always wins over `--mode`. |
|
|
241
|
+
| `--mode {plan,execute,explore,review,debug,research}` | Mode-based model selection (see [Multi-model routing](#multi-model-routing)). |
|
|
242
|
+
| `--mcp` | Load MCP servers from `mcp.json` at startup. |
|
|
243
|
+
| `--quiet` / `-q` | Disable the streaming TUI. Only the final result text prints. Use this in pipes, scripts, CI. |
|
|
244
|
+
| `--resume` | Not yet implemented — exits with code 2 so scripts don't silently lose state. |
|
|
245
|
+
|
|
246
|
+
### Subcommands
|
|
247
|
+
|
|
248
|
+
| Subcommand | Behavior |
|
|
249
|
+
|---|---|
|
|
250
|
+
| `korgex serve` | Starts the FastAPI dashboard on `localhost:8090` and opens VS Code with the sidecar. |
|
|
251
|
+
| `korgex dashboard` | Starts the dashboard only (no editor). |
|
|
252
|
+
| `korgex init` | One-shot setup: pip-installs deps, npm-installs + compiles the VS Code extension. |
|
|
253
|
+
| `korgex status` | Reports whether the background backend is running. |
|
|
254
|
+
| `korgex stop` | Terminates the background backend (SIGTERM, then SIGKILL if needed). |
|
|
255
|
+
| `korgex install-extension` | Installs the compiled `.vsix` into your local VS Code. |
|
|
256
|
+
| `korgex verify [journal]` | Verify the ledger's hash-chain is intact — proves the recorded run wasn't edited, deleted, reordered, or spliced (exit 0/1, CI-friendly). |
|
|
257
|
+
| `korgex drift` | Scan persistent memories for drift against their recorded source baselines (exit 0/1). |
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## Tools
|
|
262
|
+
|
|
263
|
+
The agent sees ~12 high-level tools (Claude-Code style), each with a deep description that includes usage guidance, edge cases, and anti-patterns:
|
|
264
|
+
|
|
265
|
+
| Tool | Purpose |
|
|
266
|
+
|---|---|
|
|
267
|
+
| **Read** | Read a file from disk, optionally with line offset/limit. |
|
|
268
|
+
| **Write** | Create a new file or overwrite an existing one with full content. |
|
|
269
|
+
| **Edit** | Surgical string replacement in an existing file. Auto-converted to SEARCH/REPLACE block internally. |
|
|
270
|
+
| **Bash** | Execute a shell command with timeout. |
|
|
271
|
+
| **Grep** | Search file contents by regex (uses ripgrep where available). |
|
|
272
|
+
| **Glob** | List files matching a pattern. |
|
|
273
|
+
| **Agent** | Delegate a sub-task to a specialized sub-agent. |
|
|
274
|
+
| **AskUserQuestion** | Ask the user a clarifying question with optional multiple-choice. |
|
|
275
|
+
| **TaskCreate** | Track multi-step work via a task list. |
|
|
276
|
+
| **Skill** | Invoke an installed skill by name. |
|
|
277
|
+
| **ToolSearch** | Discover tools at runtime by keyword. |
|
|
278
|
+
|
|
279
|
+
Under the hood these route to 49+ internal handlers (file ops, git, GitHub API, sandbox execution, web fetch, dependency analysis, profiler, etc.) — see `src/tools_impl.py`.
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## Environment variables
|
|
284
|
+
|
|
285
|
+
| Variable | Purpose | Default |
|
|
286
|
+
|---|---|---|
|
|
287
|
+
| `ANTHROPIC_API_KEY` | Used when the model name contains "claude" or starts with "anthropic/". | — |
|
|
288
|
+
| `OPENAI_API_KEY` | Used for any non-Anthropic model. | — |
|
|
289
|
+
| `KORGEX_API_KEY` | Generic fallback if a provider-specific key isn't set. Useful for OpenRouter. | — |
|
|
290
|
+
| `KORGEX_API_URL` | Base URL for OpenAI-compatible endpoints (set for OpenRouter, Ollama, etc.). | `https://api.openai.com/v1` |
|
|
291
|
+
| `KORGEX_MODEL` | Default model when neither `--model` nor `--mode` is given. | `claude-sonnet-4-6` |
|
|
292
|
+
| `KORGEX_MAX_ITERATIONS` | Maximum agent loop iterations before giving up. | `30` |
|
|
293
|
+
| `KORGEX_MCP` | Set to `1` to auto-load MCP servers from `mcp.json` (equivalent to `--mcp`). | unset |
|
|
294
|
+
| `KORGEX_SANDBOX` | `modal` \| `docker` \| `direct` \| `auto`. Controls bash sandbox isolation. | `auto` |
|
|
295
|
+
| `KORGEX_PROVIDER` | Force the transport (`openai` \| `anthropic`), overriding model-id autodetect — e.g. drive `anthropic/*` or `google/*` models through OpenRouter. | autodetect |
|
|
296
|
+
| `KORG_JOURNAL_PATH` | Path to the durable JSONL ledger journal; content-addressed blobs are written beside it. | `.korg/journal.jsonl` |
|
|
297
|
+
| `KORG_LEDGER_HMAC_KEY` | If set, the ledger hash-chain is HMAC-keyed — tamper-*proof*, not just tamper-evident. | unset |
|
|
298
|
+
|
|
299
|
+
Provider-detection rule: if the model id contains `"claude"` or starts with `"anthropic/"`, the agent uses the Anthropic SDK. Otherwise it uses the OpenAI SDK (which works against OpenAI, OpenRouter, Ollama, DeepSeek, vLLM, and anything else that speaks OpenAI's chat-completions protocol). Set `KORGEX_PROVIDER=openai` to force the OpenAI-compatible transport even for a `claude`/`anthropic/` model id — e.g. to drive Claude through OpenRouter.
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## Multi-model routing
|
|
304
|
+
|
|
305
|
+
`--mode` picks a model appropriate for the work type:
|
|
306
|
+
|
|
307
|
+
| Mode | Model | Generation params |
|
|
308
|
+
|---|---|---|
|
|
309
|
+
| `plan` | Opus 4.7 | `max_tokens=64000`, `thinking={budget_tokens: 20000}`, `temperature=0.7` |
|
|
310
|
+
| `execute` | Sonnet 4.6 | `max_tokens=64000`, `temperature=0.3` |
|
|
311
|
+
| `explore` | Opus 4.7 | `max_tokens=32000`, `temperature=0.5` |
|
|
312
|
+
| `review` | Sonnet 4.6 | `max_tokens=16000`, `temperature=0.3` |
|
|
313
|
+
| `debug` | Haiku 4.5 | `max_tokens=16000`, `temperature=0.2` |
|
|
314
|
+
| `research` | Opus 4.7 | `max_tokens=32000`, `temperature=0.7` |
|
|
315
|
+
|
|
316
|
+
Explicit `--model` always wins over `--mode`. Default (neither set) is Sonnet 4.6.
|
|
317
|
+
|
|
318
|
+
```bash
|
|
319
|
+
korgex --mode plan "architect a multi-tenant billing system"
|
|
320
|
+
korgex --mode debug "trace why this 500 is happening"
|
|
321
|
+
korgex --mode execute "implement the plan we just made"
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
## MCP integration
|
|
327
|
+
|
|
328
|
+
korgex includes a native MCP (Model Context Protocol) client. Any MCP server in your `mcp.json` becomes part of the agent's tool surface.
|
|
329
|
+
|
|
330
|
+
### As an MCP server (verify / audit / import from any host)
|
|
331
|
+
|
|
332
|
+
korgex also *is* an MCP server — `korgex mcp-server` exposes the verifiable-cognition substrate over JSON-RPC/stdio so any MCP host (Claude Desktop, Cursor, …) can call:
|
|
333
|
+
|
|
334
|
+
- **`korg_verify`** — prove a korg-ledger journal is tamper-evident-intact;
|
|
335
|
+
- **`korg_audit`** — audit the host agent's own Claude Code logs (import + verify), zero-config;
|
|
336
|
+
- **`korg_import`** — import a vendor session transcript into a verifiable chained ledger.
|
|
337
|
+
|
|
338
|
+
Wire it into your host's MCP config:
|
|
339
|
+
|
|
340
|
+
```json
|
|
341
|
+
{ "mcpServers": { "korg-ledger": { "command": "korgex", "args": ["mcp-server"] } } }
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### Configure
|
|
345
|
+
|
|
346
|
+
Place an `mcp.json` in your repo root (matches the VS Code convention):
|
|
347
|
+
|
|
348
|
+
```json
|
|
349
|
+
{
|
|
350
|
+
"mcpServers": {
|
|
351
|
+
"github": {
|
|
352
|
+
"command": "npx",
|
|
353
|
+
"args": ["-y", "@modelcontextprotocol/server-github"],
|
|
354
|
+
"env": {
|
|
355
|
+
"GITHUB_TOKEN": "ghp_..."
|
|
356
|
+
}
|
|
357
|
+
},
|
|
358
|
+
"filesystem": {
|
|
359
|
+
"command": "npx",
|
|
360
|
+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### Use
|
|
367
|
+
|
|
368
|
+
```bash
|
|
369
|
+
korgex --mcp "create a GitHub issue summarizing today's bug"
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
The agent discovers each server's tools at startup, registers them into the user-facing tool list, and routes calls back to the originating server. Server failures are logged and skipped — they never crash the agent.
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
## Streaming TUI
|
|
377
|
+
|
|
378
|
+
When stdout is a TTY, the agent streams output live via [Rich](https://rich.readthedocs.io/):
|
|
379
|
+
|
|
380
|
+
- **Thinking blocks** render in dimmed italic gray (Anthropic only)
|
|
381
|
+
- **Text** streams character-by-character
|
|
382
|
+
- **Tool calls** show a transient spinner: `⠋ Read(file_path=src/foo.py)`
|
|
383
|
+
- **Diffs** for Edit/Write on critical files prompt `[y/N]` confirmation
|
|
384
|
+
- **Ctrl+C** sends a graceful interrupt; double Ctrl+C force-kills
|
|
385
|
+
|
|
386
|
+
Streaming auto-disables when stdout is piped (e.g. `korgex "..." | tee log`), in CI, or with `--quiet`.
|
|
387
|
+
|
|
388
|
+
OpenAI/OpenRouter streaming works just like Anthropic: text deltas pipe through the same renderer, tool-call deltas are accumulated across chunks into a complete tool call.
|
|
389
|
+
|
|
390
|
+
---
|
|
391
|
+
|
|
392
|
+
## VS Code sidecar
|
|
393
|
+
|
|
394
|
+
`korgex-vscode/` contains a TypeScript extension that adds four commands (Cmd+Shift+P → "korgex"):
|
|
395
|
+
|
|
396
|
+
| Command | Action |
|
|
397
|
+
|---|---|
|
|
398
|
+
| `korgex: Refactor Current File` | POSTs to `/api/swarm/refactor` |
|
|
399
|
+
| `korgex: Run TDD Healer on Current File` | POSTs to `/api/swarm/heal` |
|
|
400
|
+
| `korgex: Profile Test Suite` | POSTs to `/api/swarm/profile` |
|
|
401
|
+
| `korgex: Open the Swarm Dashboard` | Opens `http://localhost:8090/dashboard` |
|
|
402
|
+
|
|
403
|
+
To install:
|
|
404
|
+
|
|
405
|
+
```bash
|
|
406
|
+
korgex init # compiles the .vsix
|
|
407
|
+
korgex install-extension # installs it into your local VS Code
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
The extension connects to `http://localhost:8090` by default, which matches the dashboard port. Adjust via the VS Code setting `korgex.backendUrl` if you change the port.
|
|
411
|
+
|
|
412
|
+
---
|
|
413
|
+
|
|
414
|
+
## Dashboard API
|
|
415
|
+
|
|
416
|
+
`korgex serve` (or `korgex dashboard`) starts a FastAPI server on `:8090` with these endpoints:
|
|
417
|
+
|
|
418
|
+
| Route | Method | Purpose |
|
|
419
|
+
|---|---|---|
|
|
420
|
+
| `/` | GET | HTML dashboard |
|
|
421
|
+
| `/health` | GET | `{status: "ok"}` for liveness checks |
|
|
422
|
+
| `/api/state` | GET | Current dashboard state (current task, plan, logs) |
|
|
423
|
+
| `/api/new-task` | POST `{description}` | Start a new agent task in a background thread |
|
|
424
|
+
| `/api/approve-plan` | POST | Approve a pending plan |
|
|
425
|
+
| `/api/send-feedback` | POST `{feedback}` | Send mid-task feedback to the agent |
|
|
426
|
+
| `/api/swarm/refactor` | POST `{filepath}` | Spin a one-shot agent that refactors the given file |
|
|
427
|
+
| `/api/swarm/heal` | POST `{filepath, command}` | Spin a one-shot agent that fixes failing tests |
|
|
428
|
+
| `/api/swarm/profile` | POST `{command}` | Run `cProfile` via `PerformanceProfiler` and return top-N slowest functions |
|
|
429
|
+
| `/ws/logs` | WebSocket | Live log stream |
|
|
430
|
+
|
|
431
|
+
All swarm endpoints are synchronous (FastAPI thread-pools them) and return JSON: `{success, output, ...}` or `{success: false, error}` if a key is missing or the agent crashes.
|
|
432
|
+
|
|
433
|
+
---
|
|
434
|
+
|
|
435
|
+
## Architecture
|
|
436
|
+
|
|
437
|
+
### Tool routing — Claude-Code-style → Jules-style
|
|
438
|
+
|
|
439
|
+
```
|
|
440
|
+
User tool call (LLM-visible): Internal handler (in src/tools_impl.py):
|
|
441
|
+
───────────────────────────── ────────────────────────────────────────
|
|
442
|
+
Read(file_path=...) → tool_read_file(filepath=..., context=...)
|
|
443
|
+
Write(file_path=..., ...) → tool_write_file(filepath=..., ...)
|
|
444
|
+
Edit(file_path, old, new) → tool_replace_with_git_merge_diff(
|
|
445
|
+
filepath=...,
|
|
446
|
+
merge_diff="<<<<<<< SEARCH\n...")
|
|
447
|
+
Bash(command=...) → tool_run_in_bash_session(command=...)
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
The router (`src/tool_abstraction.py`):
|
|
451
|
+
|
|
452
|
+
- Looks up the user-facing tool name in `_TOOL_ROUTING`
|
|
453
|
+
- Applies a `param_map` (rename kwargs like `file_path → filepath`)
|
|
454
|
+
- Or applies a custom `adapter` for structural transforms (Edit → SEARCH/REPLACE)
|
|
455
|
+
- Filters out kwargs the handler doesn't accept (so schema fields like `Read.offset` don't crash handlers that haven't grown them yet)
|
|
456
|
+
- Auto-injects `context={'repo_root': cwd}`
|
|
457
|
+
- Catches exceptions and returns `{"error": ...}` so a single tool failure never kills the agent loop
|
|
458
|
+
|
|
459
|
+
MCP-sourced tools bypass `_TOOL_ROUTING` and dispatch through `MCPServerManager.call_tool()` instead.
|
|
460
|
+
|
|
461
|
+
### Provider branching
|
|
462
|
+
|
|
463
|
+
```
|
|
464
|
+
KorgexAgent(model="claude-sonnet-4-6") → provider="anthropic"
|
|
465
|
+
KorgexAgent(model="anthropic/claude-...")→ provider="anthropic" (OpenRouter)
|
|
466
|
+
KorgexAgent(model="gpt-4o") → provider="openai"
|
|
467
|
+
KorgexAgent(model="openai/gpt-4o-mini") → provider="openai" (OpenRouter)
|
|
468
|
+
KorgexAgent(model="llama3:8b") → provider="openai" (Ollama)
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
Each provider gets:
|
|
472
|
+
- Its own tool-schema shape
|
|
473
|
+
- Its own request method (`messages.create` vs `chat.completions.create`)
|
|
474
|
+
- Its own streaming chunk parser
|
|
475
|
+
- Its own assistant/tool-result message format
|
|
476
|
+
|
|
477
|
+
### Plan-first system prompt
|
|
478
|
+
|
|
479
|
+
The default system prompt directs the agent to plan, verify, diagnose-before-changing, and never modify build artifacts. See `SYSTEM_PROMPT` in `src/agent.py`.
|
|
480
|
+
|
|
481
|
+
---
|
|
482
|
+
|
|
483
|
+
## Project structure
|
|
484
|
+
|
|
485
|
+
```
|
|
486
|
+
korgex/
|
|
487
|
+
├── src/
|
|
488
|
+
│ ├── agent.py # KorgexAgent class — main loop, provider branching, streaming
|
|
489
|
+
│ ├── cli.py # argparse dispatch (naked-prompt + subcommands)
|
|
490
|
+
│ ├── tool_abstraction.py # USER_TOOLS registry + router + MCP integration
|
|
491
|
+
│ ├── tools_impl.py # ~49 internal handlers (tool_read_file, tool_bash, ...)
|
|
492
|
+
│ ├── tool_base.py # Legacy Jules-style tool registry (still in use)
|
|
493
|
+
│ ├── interactive.py # Streaming TUI: Rich-based renderer, spinner, interrupt handler
|
|
494
|
+
│ ├── model_router.py # Mode → model mapping (plan/execute/debug/...)
|
|
495
|
+
│ ├── mcp_client.py # Native MCP client (stdio JSON-RPC 2.0)
|
|
496
|
+
│ ├── dashboard.py # FastAPI dashboard + /api/swarm/* endpoints
|
|
497
|
+
│ ├── sandbox.py # Docker / Modal / direct subprocess sandbox
|
|
498
|
+
│ ├── swarm.py # Multi-agent swarm orchestration
|
|
499
|
+
│ ├── self_healing.py # TDD self-healing loop
|
|
500
|
+
│ ├── profiler.py # cProfile-based perf profiler
|
|
501
|
+
│ ├── dependency_graph.py # AST-based import/symbol graph
|
|
502
|
+
│ ├── context_compression.py# AST minimization for large files
|
|
503
|
+
│ ├── diff_engine.py # SEARCH/REPLACE diff parser
|
|
504
|
+
│ ├── github_api.py # GitHub PR / issue helpers
|
|
505
|
+
│ ├── memory.py # Cross-session memory (planned)
|
|
506
|
+
│ ├── vision.py # Image attachment handling
|
|
507
|
+
│ └── ...
|
|
508
|
+
├── korgex-vscode/ # VS Code sidecar extension (TypeScript)
|
|
509
|
+
│ ├── src/extension.ts # 4 registered commands
|
|
510
|
+
│ ├── korgex-sidecar.vsix # Compiled artifact (after `korgex init`)
|
|
511
|
+
│ └── package.json
|
|
512
|
+
├── tests/
|
|
513
|
+
│ └── test_bridge.py # 27 tests covering router, providers, MCP, streaming, dashboard
|
|
514
|
+
├── docs/ # CLI reference, comparison, getting-started
|
|
515
|
+
├── scripts/ # Build helpers (package-vsix.sh, MCP conformance test)
|
|
516
|
+
├── packages/
|
|
517
|
+
│ └── mcp-native-client/ # Standalone reusable MCP client package
|
|
518
|
+
├── dist/ # Built wheels and sdists
|
|
519
|
+
├── mcp.json # Default MCP server config
|
|
520
|
+
├── pyproject.toml # Package metadata
|
|
521
|
+
└── requirements.txt # Pinned runtime deps
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
---
|
|
525
|
+
|
|
526
|
+
## Development
|
|
527
|
+
|
|
528
|
+
### Setup
|
|
529
|
+
|
|
530
|
+
```bash
|
|
531
|
+
git clone https://github.com/New1Direction/korgex.git
|
|
532
|
+
cd korgex
|
|
533
|
+
|
|
534
|
+
# Create venv (uv recommended; falls back to python -m venv if you don't have uv)
|
|
535
|
+
uv venv .venv
|
|
536
|
+
source .venv/bin/activate
|
|
537
|
+
|
|
538
|
+
# Install with dev extras (pytest, twine, build, ruff)
|
|
539
|
+
uv pip install -e ".[dev]"
|
|
540
|
+
|
|
541
|
+
# Or with plain pip
|
|
542
|
+
pip install -e ".[dev]"
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
### Run the agent in editable mode
|
|
546
|
+
|
|
547
|
+
After `pip install -e .`, `korgex` is on your PATH and reflects live source edits:
|
|
548
|
+
|
|
549
|
+
```bash
|
|
550
|
+
export ANTHROPIC_API_KEY=sk-ant-...
|
|
551
|
+
korgex "explain what src/agent.py does"
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
### Code style
|
|
555
|
+
|
|
556
|
+
The project uses [ruff](https://docs.astral.sh/ruff/):
|
|
557
|
+
|
|
558
|
+
```bash
|
|
559
|
+
ruff check src/
|
|
560
|
+
ruff format src/
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
---
|
|
564
|
+
|
|
565
|
+
## Testing
|
|
566
|
+
|
|
567
|
+
```bash
|
|
568
|
+
# Run the full test suite
|
|
569
|
+
pytest tests/ -v
|
|
570
|
+
|
|
571
|
+
# Run a specific test
|
|
572
|
+
pytest tests/test_bridge.py::test_write_routes_to_disk -v
|
|
573
|
+
|
|
574
|
+
# With coverage
|
|
575
|
+
pytest tests/ --cov=src --cov-report=term-missing
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
### What the tests cover (27 cases)
|
|
579
|
+
|
|
580
|
+
- **Router** (5): Read/Write/Edit route to handlers and produce filesystem effects; unknown tools return errors gracefully; the Edit adapter constructs valid SEARCH/REPLACE blocks; unsupported kwargs (Read.offset/limit) are filtered, not crashed.
|
|
581
|
+
- **Provider schemas** (4): Anthropic and OpenAI tool-schema shapes are correct; OpenRouter `anthropic/...` IDs are detected; missing API keys raise `RuntimeError` cleanly.
|
|
582
|
+
- **Mode routing** (5): `--mode plan` picks Opus, `--mode execute` picks Sonnet, `--mode debug` picks Haiku, explicit `--model` overrides, default falls back to Sonnet.
|
|
583
|
+
- **MCP** (3): MCP tools register into `USER_TOOLS` correctly; the router dispatches them to the MCP manager; full connect→discover→call→disconnect round-trip against a real stub subprocess.
|
|
584
|
+
- **Streaming** (5): Interactive mode auto-detects TTY; sessions are lazily constructed; OpenAI streaming accumulates text + multi-chunk tool calls into the right shape; text-only responses pass through.
|
|
585
|
+
- **Dashboard** (5): `/health` returns ok; swarm endpoints reject missing args with 400; swarm endpoints return clean JSON errors when no API key is set.
|
|
586
|
+
|
|
587
|
+
No live LLM calls in the test suite — everything is unit-tested.
|
|
588
|
+
|
|
589
|
+
---
|
|
590
|
+
|
|
591
|
+
## Building & releasing
|
|
592
|
+
|
|
593
|
+
### Build the wheel and sdist
|
|
594
|
+
|
|
595
|
+
```bash
|
|
596
|
+
rm -rf dist build
|
|
597
|
+
python -m build
|
|
598
|
+
# → dist/korgex-X.Y.Z-py3-none-any.whl
|
|
599
|
+
# → dist/korgex-X.Y.Z.tar.gz
|
|
600
|
+
|
|
601
|
+
# Validate PyPI metadata
|
|
602
|
+
python -m twine check dist/*
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
### Cut a GitHub Release
|
|
606
|
+
|
|
607
|
+
```bash
|
|
608
|
+
gh release create vX.Y.Z \
|
|
609
|
+
dist/korgex-X.Y.Z-py3-none-any.whl \
|
|
610
|
+
dist/korgex-X.Y.Z.tar.gz \
|
|
611
|
+
--title "korgex X.Y.Z" \
|
|
612
|
+
--notes "Release notes here"
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
### Publish to PyPI
|
|
616
|
+
|
|
617
|
+
```bash
|
|
618
|
+
python -m twine upload dist/*
|
|
619
|
+
# username: __token__
|
|
620
|
+
# password: pypi-... (token from https://pypi.org/manage/account/token/)
|
|
621
|
+
```
|
|
622
|
+
|
|
623
|
+
For the first upload of a new package, use an "Entire account" scoped token. After the package exists on PyPI, project-scoped tokens work.
|
|
624
|
+
|
|
625
|
+
---
|
|
626
|
+
|
|
627
|
+
## Troubleshooting
|
|
628
|
+
|
|
629
|
+
### `korgex: No API key found`
|
|
630
|
+
|
|
631
|
+
Set one of `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, or `KORGEX_API_KEY` (with `KORGEX_API_URL` for non-OpenAI endpoints).
|
|
632
|
+
|
|
633
|
+
### `ModuleNotFoundError: No module named 'anthropic'` (or `openai`, or `rich`)
|
|
634
|
+
|
|
635
|
+
The dependency wasn't installed. Either:
|
|
636
|
+
|
|
637
|
+
```bash
|
|
638
|
+
pip install -e . # picks up everything from pyproject.toml
|
|
639
|
+
# or
|
|
640
|
+
pip install anthropic openai rich
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
### Agent loops forever on tool calls
|
|
644
|
+
|
|
645
|
+
The default `KORGEX_MAX_ITERATIONS` is 30. If the agent genuinely can't finish:
|
|
646
|
+
|
|
647
|
+
```bash
|
|
648
|
+
export KORGEX_MAX_ITERATIONS=10 # cap it harder
|
|
649
|
+
korgex --quiet "..." # see only the final state
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
### `--mcp` takes a long time to start
|
|
653
|
+
|
|
654
|
+
The MCP client connects to each server synchronously at startup and waits up to 60s per server for the handshake. If your `mcp.json` references unreachable servers (missing `GITHUB_TOKEN`, `npx` not installed, network blocked), each one times out before being skipped. Remove unreachable entries from `mcp.json`, or reduce the per-server `timeout` value.
|
|
655
|
+
|
|
656
|
+
### Streaming TUI swallows my prompt's output
|
|
657
|
+
|
|
658
|
+
`korgex "..."` streams to stdout. If you need machine-readable output (e.g. piping to `jq`), use `--quiet`:
|
|
659
|
+
|
|
660
|
+
```bash
|
|
661
|
+
korgex --quiet "..." | tee transcript.txt
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
### `403 Forbidden` from `twine upload`
|
|
665
|
+
|
|
666
|
+
For a brand-new package on PyPI, you need an **"Entire account"** scoped token, not a project-scoped one. Project-scoped tokens can't create a package they don't yet own. Re-create the token at https://pypi.org/manage/account/token/ with the wider scope, upload, then narrow the token for future releases.
|
|
667
|
+
|
|
668
|
+
### VS Code extension commands do nothing
|
|
669
|
+
|
|
670
|
+
The extension POSTs to `http://localhost:8090/api/swarm/*` by default (matches the dashboard). Make sure:
|
|
671
|
+
1. The backend is running: `korgex serve` or `korgex dashboard`
|
|
672
|
+
2. The `korgex.backendUrl` setting in VS Code matches the port korgex is listening on (default `8090` on both sides)
|
|
673
|
+
|
|
674
|
+
---
|
|
675
|
+
|
|
676
|
+
## Known limitations
|
|
677
|
+
|
|
678
|
+
These exist today; PRs welcome.
|
|
679
|
+
|
|
680
|
+
- **OpenAI streaming has fewer rendered events than Anthropic.** Anthropic emits thinking blocks, content-block-start/stop, and message-delta usage events; OpenAI emits only text and tool-call chunks. The TUI renders both correctly but is richer for Anthropic.
|
|
681
|
+
- **`--resume` is not yet implemented.** Exits with code 2 rather than silently starting fresh, so scripts and CI that rely on it fail loudly.
|
|
682
|
+
- **Memory module is a stub.** `src/memory.py` exists but isn't wired into the agent loop.
|
|
683
|
+
- **Swarm endpoints share the agent's single-context loop.** They don't actually run sub-agents in parallel sandboxes (the `swarm.py` module supports it, but the `/api/swarm/*` endpoints don't use it yet).
|
|
684
|
+
- **TDD self-healing requires explicit invocation.** It's not yet triggered automatically on test failure.
|
|
685
|
+
- **Dashboard authentication is not implemented.** Don't expose port 8090 publicly without putting a reverse proxy with auth in front of it.
|
|
686
|
+
- **Dependency-graph and AST-compression tools (`src/dependency_graph.py`, `src/context_compression.py`) are not yet bridged into `USER_TOOLS`.** They're callable directly but not exposed to the agent.
|
|
687
|
+
|
|
688
|
+
---
|
|
689
|
+
|
|
690
|
+
## License
|
|
691
|
+
|
|
692
|
+
MIT — see [LICENSE](LICENSE).
|
|
693
|
+
|
|
694
|
+
---
|
|
695
|
+
|
|
696
|
+
## Related projects
|
|
697
|
+
|
|
698
|
+
- **[korg](https://github.com/New1Direction/korg)** — deterministic cognitive runtime for AI agents (Rust). korgex v0.3.0+ records every tool call into a korg ledger via the `korg_bridge` PyO3 extension; the ledger is what korg-tui rewinds and korgchat builds on.
|
|
699
|
+
- **[korgchat](https://github.com/New1Direction/korgchat)** — chat product built on the same ledger; runs in the same `.korg/journal.json` as a korgex agent run, so you can interleave chat and autonomous edits.
|
|
700
|
+
- **[thumper](https://github.com/New1Direction/thumper)** — local execution + recovery substrate that runs under korgex; pre-warmed sandbox pools, persistent LSP, sub-second compile-error healing.
|
|
701
|
+
- **[Model Context Protocol](https://modelcontextprotocol.io/)** — the open MCP standard korgex implements.
|