roundtable-cli 0.4.0__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.
- roundtable/__init__.py +10 -0
- roundtable/agents.py +218 -0
- roundtable/cli.py +722 -0
- roundtable/config.py +265 -0
- roundtable/dashboard.py +533 -0
- roundtable/discovery.py +71 -0
- roundtable/engine.py +714 -0
- roundtable/errors.py +20 -0
- roundtable/insights.py +210 -0
- roundtable/llm.py +1048 -0
- roundtable/mcp.py +248 -0
- roundtable/modelpick.py +309 -0
- roundtable/models.py +202 -0
- roundtable/prompts.py +205 -0
- roundtable/runctl.py +212 -0
- roundtable/scan.py +187 -0
- roundtable/store.py +339 -0
- roundtable_cli-0.4.0.dist-info/METADATA +570 -0
- roundtable_cli-0.4.0.dist-info/RECORD +22 -0
- roundtable_cli-0.4.0.dist-info/WHEEL +4 -0
- roundtable_cli-0.4.0.dist-info/entry_points.txt +4 -0
- roundtable_cli-0.4.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,570 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: roundtable-cli
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: Multi-LLM planning & orchestration that routes work across the terminal AI CLIs you already have: plan -> phases -> tasks, model choosable per role and per task.
|
|
5
|
+
Project-URL: Homepage, https://github.com/arfuhad/roundtable
|
|
6
|
+
Project-URL: Repository, https://github.com/arfuhad/roundtable
|
|
7
|
+
Project-URL: Issues, https://github.com/arfuhad/roundtable/issues
|
|
8
|
+
Author: Abdur Rahman
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: agent-orchestration,ai-agents,claude,cli,code-generation,codex,developer-tools,llm,multi-agent,orchestration
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: MacOS
|
|
17
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
22
|
+
Classifier: Topic :: Software Development
|
|
23
|
+
Requires-Python: >=3.11
|
|
24
|
+
Requires-Dist: pydantic>=2.7
|
|
25
|
+
Requires-Dist: pyyaml>=6.0
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: litellm>=1.83; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
30
|
+
Provides-Extra: litellm
|
|
31
|
+
Requires-Dist: litellm>=1.83; extra == 'litellm'
|
|
32
|
+
Provides-Extra: mcp
|
|
33
|
+
Requires-Dist: mcp>=1.0; extra == 'mcp'
|
|
34
|
+
Description-Content-Type: text/markdown
|
|
35
|
+
|
|
36
|
+
# Roundtable
|
|
37
|
+
|
|
38
|
+
[](https://github.com/arfuhad/roundtable/actions/workflows/ci.yml)
|
|
39
|
+
[](LICENSE)
|
|
40
|
+
[](https://www.python.org/downloads/)
|
|
41
|
+
|
|
42
|
+
> Build reliable, resumable AI coding workflows without blowing your context window
|
|
43
|
+
> or getting pinned to one vendor's usage limits.
|
|
44
|
+
|
|
45
|
+
**Roundtable** is a small, from-scratch **multi-LLM planning and orchestration tool**
|
|
46
|
+
that drives **other LLMs through their terminal CLIs** (Claude Code, Codex, Gemini CLI,
|
|
47
|
+
aider, `llm`, Ollama, …) — routing each part of the work to the model you choose, so no
|
|
48
|
+
single vendor's limit stalls the run.
|
|
49
|
+
|
|
50
|
+
One LLM plans the work and breaks it into **phases → tasks**. You
|
|
51
|
+
approve the plan. Then a **Main Orchestrator** drives execution: for each phase it
|
|
52
|
+
runs a fresh **Phase Orchestrator** that defines and dispatches **Task Agents**,
|
|
53
|
+
collects their work, summarizes the phase, and hands the summary back to Main —
|
|
54
|
+
which keeps the project docs up to date. **Every role's model/agent is choosable**,
|
|
55
|
+
per role *and* per task. It runs **inside your existing project**: agents execute
|
|
56
|
+
with the repo as their working directory, and all roundtable artifacts stay under
|
|
57
|
+
`.roundtable/`.
|
|
58
|
+
|
|
59
|
+
```mermaid
|
|
60
|
+
graph TD
|
|
61
|
+
P[Planner agent] -->|plan.json| GATE{Approve?}
|
|
62
|
+
GATE -->|yes| MO[Main Orchestrator]
|
|
63
|
+
MO -->|OVERVIEW.md| DOCS[(.roundtable/docs)]
|
|
64
|
+
MO -->|per phase, fresh context| PO[Phase Orchestrator]
|
|
65
|
+
PO -->|TASK.md| A1[Task Agent A]
|
|
66
|
+
PO -->|TASK.md| A2[Task Agent B]
|
|
67
|
+
A1 -->|result.md| PO
|
|
68
|
+
A2 -->|result.md| PO
|
|
69
|
+
PO -->|phase-summary.md only| MO
|
|
70
|
+
MO -->|PROGRESS.md / FINAL.md| DOCS
|
|
71
|
+
PO -. context discarded .-> X(( ))
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Key features
|
|
75
|
+
|
|
76
|
+
- **Multi-LLM orchestration:** route planner, main, phase, and task roles to different
|
|
77
|
+
models/providers.
|
|
78
|
+
- **Human approval gate:** inspect the generated plan before any agent changes files.
|
|
79
|
+
- **Context isolation:** phase/task contexts are discarded after each phase; Main only
|
|
80
|
+
receives structured summaries.
|
|
81
|
+
- **Resumable runs:** completed work is reused, and failed/skipped parts can be retried.
|
|
82
|
+
- **Validation gates:** per-task and per-phase commands decide whether work actually
|
|
83
|
+
passed.
|
|
84
|
+
- **Live local dashboard:** watch progress, approve tasks, stop runs, and inspect usage
|
|
85
|
+
without a cloud service.
|
|
86
|
+
- **Full MCP Server Support:** expose init, map, plan, approve, run, stop, status, and
|
|
87
|
+
usage to Claude Desktop, Claude Code, and other MCP clients.
|
|
88
|
+
|
|
89
|
+
## Install
|
|
90
|
+
|
|
91
|
+
### Prerequisites
|
|
92
|
+
|
|
93
|
+
- **Python 3.11+**
|
|
94
|
+
- **macOS or Linux**
|
|
95
|
+
- **Windows via WSL only:** native Windows is not supported because Roundtable uses
|
|
96
|
+
POSIX process control (`SIGTERM`, process groups) and Unix pseudo-terminals for
|
|
97
|
+
`pty: true` agents.
|
|
98
|
+
- **At least one supported AI CLI on `PATH`** for real runs, such as Claude Code,
|
|
99
|
+
Codex, Gemini CLI, aider, `llm`, Ollama, pi, or omp.
|
|
100
|
+
- **uv or pipx** for global installation.
|
|
101
|
+
|
|
102
|
+
Install it as a global tool so `roundtable` works in any project.
|
|
103
|
+
|
|
104
|
+
**From GitHub (recommended):**
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
uv tool install git+https://github.com/arfuhad/roundtable.git
|
|
108
|
+
# or with pipx:
|
|
109
|
+
pipx install git+https://github.com/arfuhad/roundtable.git
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**From source** (to hack on Roundtable itself):
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
git clone https://github.com/arfuhad/roundtable.git && cd roundtable
|
|
116
|
+
uv tool install --editable . # or: pipx install --editable .
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The base install pulls only `pydantic` + `pyyaml` — the default `cli` backend shells
|
|
120
|
+
out to LLM CLIs you already have, so no API SDKs are added. Optional extras append
|
|
121
|
+
the same `@ git+…` reference to the package name:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
# direct API calls via LiteLLM:
|
|
125
|
+
uv tool install "roundtable-cli[litellm] @ git+https://github.com/arfuhad/roundtable.git"
|
|
126
|
+
# expose Roundtable to MCP clients:
|
|
127
|
+
uv tool install "roundtable-cli[mcp] @ git+https://github.com/arfuhad/roundtable.git"
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Not published to PyPI yet, so install from the repo as above.
|
|
131
|
+
|
|
132
|
+
## Quick start (in an existing project)
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
cd my-existing-project
|
|
136
|
+
roundtable init # writes config + lists installed CLIs & their models
|
|
137
|
+
$EDITOR roundtable.config.yaml # pick which CLI agent + model runs each role
|
|
138
|
+
|
|
139
|
+
roundtable plan --goal "Add retry with backoff to the HTTP client"
|
|
140
|
+
# -> .roundtable/plan/plan.json + PLAN.md (status: needs approval)
|
|
141
|
+
|
|
142
|
+
roundtable approve # the human gate
|
|
143
|
+
roundtable run # autonomous: agents work phase by phase
|
|
144
|
+
roundtable status # progress
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
`run` refuses until `approve`. Re-running resumes where it stopped.
|
|
148
|
+
|
|
149
|
+
## Proof of life
|
|
150
|
+
|
|
151
|
+
Roundtable includes both a web dashboard and a terminal watch view, so a run is not a
|
|
152
|
+
black box.
|
|
153
|
+
|
|
154
|
+
| Web dashboard | Terminal watch |
|
|
155
|
+
|---|---|
|
|
156
|
+
|  |  |
|
|
157
|
+
|
|
158
|
+
## Recommended backend: pi
|
|
159
|
+
|
|
160
|
+
Roundtable works best with a **pi-family coding agent** — either upstream
|
|
161
|
+
[**pi**](https://github.com/earendil-works/pi) or the batteries-included fork
|
|
162
|
+
[**oh-my-pi (`omp`)**](https://github.com/can1357/oh-my-pi) (LSP/DAP/subagents). Both
|
|
163
|
+
speak ~40 model providers and share the same CLI contract. With `provider: pi`, **the
|
|
164
|
+
tool handles all LLM connectivity, auth and model routing** — roundtable just
|
|
165
|
+
orchestrates.
|
|
166
|
+
|
|
167
|
+
If `pi` (or `omp`) is on your `PATH`, `roundtable init` scaffolds this backend for you:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
npm install -g @earendil-works/pi-coding-agent # install pi (or: @oh-my-pi/pi-coding-agent for omp)
|
|
171
|
+
pi-ai login anthropic # connect an LLM (or export ANTHROPIC_API_KEY / OPENAI_API_KEY / …)
|
|
172
|
+
cd my-existing-project
|
|
173
|
+
roundtable init # detects pi/omp -> writes the pi backend
|
|
174
|
+
roundtable plan --goal "Add retry with backoff to the HTTP client"
|
|
175
|
+
roundtable approve && roundtable run
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
See [Backend configuration](docs/backends.md) for the full pi/omp config, flavor
|
|
179
|
+
differences, and direct CLI/LiteLLM alternatives.
|
|
180
|
+
|
|
181
|
+
**Don't have pi or omp?** You have two options — roundtable prints both at `init`:
|
|
182
|
+
|
|
183
|
+
1. **Install pi (or omp) and connect it to your LLMs** (recommended).
|
|
184
|
+
2. **Use what you already have:** `provider: cli` drives the terminal CLIs you've
|
|
185
|
+
installed (claude, codex, gemini, …), or `provider: litellm` for direct API calls.
|
|
186
|
+
These backends are unchanged; see below.
|
|
187
|
+
|
|
188
|
+
> Note: pi has no per-action permission gate and task agents share the project
|
|
189
|
+
> directory, so keep `max_concurrency: 1` (the default) unless you isolate tasks.
|
|
190
|
+
|
|
191
|
+
### Planning inputs
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
roundtable plan --goal "..." # from a one-line goal
|
|
195
|
+
roundtable plan --prd docs/PRD.md # from a PRD / requirements file
|
|
196
|
+
roundtable plan --plan old-plan.json # ingest an existing plan (JSON in our schema -> loaded as-is)
|
|
197
|
+
roundtable plan --plan ROADMAP.md # free-form plan/PRD -> structured into our schema by the planner
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Mapping an existing project
|
|
201
|
+
|
|
202
|
+
Don't have a PRD? Point `roundtable map` at an unfamiliar (brownfield) codebase and it
|
|
203
|
+
scans the project into two docs under `.roundtable/docs/`: an `ARCHITECTURE.md` outline
|
|
204
|
+
(purpose, stack, module map, data flow, how to run) and a **reverse-engineered**
|
|
205
|
+
`PRD.md`. You confirm the PRD by reviewing/editing it, then feed it straight into
|
|
206
|
+
planning:
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
roundtable map # scan -> .roundtable/docs/ARCHITECTURE.md + PRD.md
|
|
210
|
+
$EDITOR .roundtable/docs/PRD.md # the human confirmation: fix what's wrong
|
|
211
|
+
roundtable plan --prd .roundtable/docs/PRD.md # the confirmed PRD drives the plan
|
|
212
|
+
roundtable approve && roundtable run
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
`map` builds a compact, provider-agnostic digest of the codebase (pruned file tree +
|
|
216
|
+
key file contents), so it works on every backend; with `provider: cli` the analyst
|
|
217
|
+
agent also reads the real files directly. Flags: `--target DIR` to scan a different
|
|
218
|
+
directory than the project root, `--model agent:model` to override the analyst (default
|
|
219
|
+
is the `main` role), and `--max-files` / `--max-bytes` to size the digest.
|
|
220
|
+
|
|
221
|
+
## Watching a run live
|
|
222
|
+
|
|
223
|
+
`roundtable run` is **live by default**: it prints a web dashboard link up front and
|
|
224
|
+
renders the terminal `watch` view inline as it works — no second terminal needed.
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
roundtable run # runs + shows progress; dashboard link printed at the top
|
|
228
|
+
roundtable run --approve # auto-approve the plan before running
|
|
229
|
+
roundtable run --no-watch # run without the inline terminal view
|
|
230
|
+
roundtable run --no-dashboard # run without serving the web dashboard
|
|
231
|
+
roundtable run --port 9000 # pin the run's dashboard port (default: a free port)
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
A run streams structured events to `.roundtable/runs/run.log`, and `plan.json` is the
|
|
235
|
+
live source of truth — so a viewer just polls the files and stays decoupled from
|
|
236
|
+
the engine. You can also open the standalone local surfaces, both
|
|
237
|
+
zero-dependency (stdlib only):
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
roundtable dashboard # web UI at http://127.0.0.1:8787 (--open to launch a browser)
|
|
241
|
+
roundtable dashboard --port 9000 # pin the local dashboard port
|
|
242
|
+
roundtable watch # live dashboard right in the terminal
|
|
243
|
+
roundtable stop # SIGTERM the in-progress run/process group
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
These show overall
|
|
247
|
+
progress, **what each agent is doing right now** (task, `agent:model`, elapsed),
|
|
248
|
+
per-phase/task status, per-agent task counts + time, task durations (avg /
|
|
249
|
+
slowest), live token usage (estimated on the CLI backend), and a rolling event
|
|
250
|
+
timeline. The web dashboard is also **interactive**:
|
|
251
|
+
approve the plan, start/stop a run, and approve waiting HITL tasks right from the
|
|
252
|
+
page. No build step, no JS framework, no API keys.
|
|
253
|
+
|
|
254
|
+
## REST control API (`roundtable serve`)
|
|
255
|
+
|
|
256
|
+
The dashboard server doubles as a local JSON control API. `roundtable serve` starts
|
|
257
|
+
it headlessly and prints a
|
|
258
|
+
machine-readable JSON line first (`{"event": "serving", "url": ...}`) so tools
|
|
259
|
+
can parse the picked port (`--port 0` = a free one):
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
roundtable serve --project . --port 0
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
| endpoint | what it does |
|
|
266
|
+
|---|---|
|
|
267
|
+
| `GET /api/state` | live run state snapshot (same data as `watch`) |
|
|
268
|
+
| `GET /api/project` | project root, plan/config presence, run pid, waiting tasks |
|
|
269
|
+
| `GET /api/plan` · `PUT /api/plan` | read / save the plan (validated; editing resets approval) |
|
|
270
|
+
| `POST /api/plan/generate` · `GET` | spawn a detached `roundtable plan` (goal/prd/plan_file) · poll it |
|
|
271
|
+
| `POST /api/approve` | validate runners against the config, then approve |
|
|
272
|
+
| `POST /api/run` · `POST /api/stop` | spawn a detached run (guarded by `run.pid`) · stop its process group |
|
|
273
|
+
| `POST /api/resume` | approve a waiting HITL task `{"task": "p1-t2"}` |
|
|
274
|
+
| `POST /api/init` | scaffold `.roundtable/` + default config |
|
|
275
|
+
| `GET /api/config` · `PUT /api/config` | read / save `roundtable.config.yaml` (schema-validated) |
|
|
276
|
+
| `GET /api/agents` | probe installed CLIs + their models (`?timeout=s`) |
|
|
277
|
+
| `GET /api/usage` | provider usage snapshots (calls, tokens, duration) |
|
|
278
|
+
|
|
279
|
+
The dashboard/API binds only to loopback hosts (`127.0.0.1`, `localhost`, or
|
|
280
|
+
`::1`). State-changing browser requests are limited to localhost/Tauri origins,
|
|
281
|
+
and plan/config mutations are rejected while a run is live.
|
|
282
|
+
|
|
283
|
+
With `provider: cli` a CLI returns only stdout, so token counts are **estimated**
|
|
284
|
+
from text length (~4 chars/token) and flagged with `"estimated": true` in the
|
|
285
|
+
usage snapshot; `provider: litellm` reports exact counts from the API.
|
|
286
|
+
|
|
287
|
+
## How "terminal access to other LLMs" works
|
|
288
|
+
|
|
289
|
+
With `provider: cli`, each role is a **`{agent, model}` pair**: `agent` names an
|
|
290
|
+
entry in the `agents` map (a terminal command run in your project directory), and
|
|
291
|
+
`model` is substituted into that command's `{model}` token. So one agent command
|
|
292
|
+
serves many models, and you can mix CLIs *and* models freely per role — e.g. the
|
|
293
|
+
Main Orchestrator on Claude/Opus, Phase Orchestrators on Antigravity/Gemini, Task
|
|
294
|
+
Agents on OpenCode/Mimo. stdout is the response.
|
|
295
|
+
|
|
296
|
+
```yaml
|
|
297
|
+
provider: cli
|
|
298
|
+
|
|
299
|
+
models:
|
|
300
|
+
planner: { agent: claude, model: opus-4.8 }
|
|
301
|
+
main: { agent: claude, model: opus-4.8 }
|
|
302
|
+
phase: { agent: antigravity, model: gemini-3.5-flash }
|
|
303
|
+
task: { agent: opencode, model: mimo-v2.5-pro } # different CLI + model per role/task
|
|
304
|
+
|
|
305
|
+
agents:
|
|
306
|
+
claude:
|
|
307
|
+
command: ["claude", "-p", "{prompt}", "--model", "{model}"]
|
|
308
|
+
codex:
|
|
309
|
+
command: ["codex", "exec", "--model", "{model}", "{prompt}"]
|
|
310
|
+
antigravity: # Antigravity CLI, binary `agy`
|
|
311
|
+
command: ["agy", "-p", "{prompt}", "--model", "{model}"]
|
|
312
|
+
opencode:
|
|
313
|
+
command: ["opencode", "run", "--model", "{model}", "{prompt}"]
|
|
314
|
+
ollama:
|
|
315
|
+
command: ["ollama", "run", "{model}"]
|
|
316
|
+
stdin: true # pipe the prompt on stdin instead of via {prompt}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
- `command` is an **argv list** (no shell, so no injection). Tokens may contain
|
|
320
|
+
`{prompt}`, `{system}` and `{model}`. If `{system}` is absent, the system text
|
|
321
|
+
is prepended to the prompt. With `stdin: true`, the prompt is piped on stdin.
|
|
322
|
+
- `pty: true` allocates a real pseudo-terminal for the subprocess — use this when
|
|
323
|
+
a CLI detects whether it's connected to a TTY and refuses to run (or switches to
|
|
324
|
+
a degraded mode) without one.
|
|
325
|
+
- The flags above are illustrative — check each tool's own docs for the exact
|
|
326
|
+
model-selection and non-interactive flags.
|
|
327
|
+
- A role value also accepts the shorthand string `agent:model` (e.g.
|
|
328
|
+
`opencode:mimo-v2.5-pro`) or a bare `agent` (no model). CLI-specific extras like
|
|
329
|
+
a reasoning level go in the model token or as a flag in the agent `command`.
|
|
330
|
+
- Per-phase / per-task `runner` objects live in `plan.json` and override the role
|
|
331
|
+
defaults — edit them before `approve` to assign a different agent/model to a
|
|
332
|
+
specific task:
|
|
333
|
+
|
|
334
|
+
```json
|
|
335
|
+
"runner": { "agent": "opencode", "model": "mimo-v2.5-pro" }
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
Set the top-level `project_context` key (free text) to inject stack, conventions,
|
|
339
|
+
and working-directory notes into every task/phase prompt. Pass `-v`/`--verbose` to
|
|
340
|
+
any command for debug logging.
|
|
341
|
+
|
|
342
|
+
### Picking models per role (`roundtable models`)
|
|
343
|
+
|
|
344
|
+
Instead of hand-editing `models:`, run **`roundtable models`** to choose a model for
|
|
345
|
+
each role from the ones your backend is actually connected to — a two-step
|
|
346
|
+
**provider → model** prompt in the terminal that writes your picks back into the
|
|
347
|
+
config (leaving the rest of the file untouched). `roundtable init` offers the same
|
|
348
|
+
picker interactively when run in a TTY.
|
|
349
|
+
|
|
350
|
+
```bash
|
|
351
|
+
roundtable models # interactive: pick planner / main / phase / task
|
|
352
|
+
roundtable models --list # just print the connected models, grouped by provider
|
|
353
|
+
roundtable models --json # machine-readable
|
|
354
|
+
roundtable models --verify # after picking, send one tiny call to each model to confirm it works
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
It works for both backends: on `provider: pi` the list comes from the tool itself
|
|
358
|
+
(`omp models --json`, or `pi --list-models`) and "provider" is the model's provider
|
|
359
|
+
(`anthropic`, `opencode-go`, …); on `provider: cli` it comes from each agent's
|
|
360
|
+
`models_command` and "provider" is the agent (`claude`, `opencode`, …). Because the
|
|
361
|
+
list is the tool's *real* catalog, you can't fat-finger an unsupported id — and
|
|
362
|
+
`--verify` catches models that are listed but error at call time.
|
|
363
|
+
|
|
364
|
+
### Seeing what you can assign
|
|
365
|
+
|
|
366
|
+
`roundtable init` (and `roundtable agents`) probes the configured CLIs and shows which
|
|
367
|
+
are installed and which models they offer, so you know what to put in `models:`:
|
|
368
|
+
|
|
369
|
+
```
|
|
370
|
+
$ roundtable agents
|
|
371
|
+
[x] antigravity (agy) — 8 model(s):
|
|
372
|
+
Gemini 3.5 Flash (High)
|
|
373
|
+
...
|
|
374
|
+
[x] claude (claude) — models: n/a (no models_command)
|
|
375
|
+
[x] opencode (opencode) — 358 model(s):
|
|
376
|
+
opencode-go/mimo-v2.5-pro
|
|
377
|
+
...
|
|
378
|
+
[ ] cursor-agent (cursor-agent) — not on PATH
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
An agent reports its models when its spec has an optional `models_command`:
|
|
382
|
+
|
|
383
|
+
```yaml
|
|
384
|
+
agents:
|
|
385
|
+
opencode:
|
|
386
|
+
command: ["opencode", "run", "--model", "{model}", "{prompt}"]
|
|
387
|
+
models_command: ["opencode", "models"]
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
These commands often hit the network/auth and can be slow, so each runs with a
|
|
391
|
+
bounded timeout (`--models-timeout` on init, `--timeout` on agents) and any
|
|
392
|
+
failure degrades to a note — it never blocks. Tools without an enumeration
|
|
393
|
+
command (claude, codex) just show `n/a`; pass the model to `--model` yourself.
|
|
394
|
+
`roundtable init --no-models` skips probing; `roundtable agents --json` is
|
|
395
|
+
machine-readable.
|
|
396
|
+
|
|
397
|
+
### Letting agents edit files
|
|
398
|
+
|
|
399
|
+
Task Agents run with your project as their working directory, so they can read and
|
|
400
|
+
modify real files — **if their CLI is allowed to**. Read-only/"print" modes only
|
|
401
|
+
return text. Configure the command with the flags your tool needs to apply edits,
|
|
402
|
+
e.g.:
|
|
403
|
+
|
|
404
|
+
```yaml
|
|
405
|
+
agents:
|
|
406
|
+
claude:
|
|
407
|
+
command: ["claude", "-p", "{prompt}", "--model", "{model}", "--permission-mode", "acceptEdits"]
|
|
408
|
+
codex:
|
|
409
|
+
command: ["codex", "exec", "--full-auto", "--model", "{model}", "{prompt}"]
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
(Check each tool's own docs for the exact non-interactive / auto-edit flags.)
|
|
413
|
+
|
|
414
|
+
### Per-task and per-phase controls in plan.json
|
|
415
|
+
|
|
416
|
+
Two optional fields can be added to any task object in `plan.json` before running
|
|
417
|
+
`roundtable approve`:
|
|
418
|
+
|
|
419
|
+
```json
|
|
420
|
+
{
|
|
421
|
+
"id": "p1-t2",
|
|
422
|
+
"title": "Deploy to staging",
|
|
423
|
+
"runner": { "agent": "claude", "model": "opus-4.8" },
|
|
424
|
+
"validate_command": ["pytest", "tests/smoke/", "-q"],
|
|
425
|
+
"requires_approval": true
|
|
426
|
+
}
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
- **`validate_command`** — an argv list that runs in the project root after the task
|
|
430
|
+
agent finishes. A non-zero exit marks the task as failed (feeding into the retry
|
|
431
|
+
loop and re-planning); exit 0 means success.
|
|
432
|
+
- **`requires_approval`** — when `true`, the run pauses before executing this task
|
|
433
|
+
and waits for a human to type:
|
|
434
|
+
```bash
|
|
435
|
+
roundtable resume --task p1-t2
|
|
436
|
+
```
|
|
437
|
+
The engine prints the exact command. Other concurrent tasks in the same wave are
|
|
438
|
+
unaffected (the semaphore slot is not held while waiting).
|
|
439
|
+
|
|
440
|
+
A **phase object** accepts `validate_command` too — the phase **completion
|
|
441
|
+
gate**. It runs in the project root after *all* of the phase's tasks succeed
|
|
442
|
+
(e.g. the phase's test suite); a non-zero exit marks the phase `failed` even
|
|
443
|
+
though its tasks are `done`. On re-run the completed tasks are reused and only
|
|
444
|
+
the gate re-runs, so fixing the project and re-running heals the phase.
|
|
445
|
+
Validation commands time out after `defaults.validate_timeout` (120s default).
|
|
446
|
+
|
|
447
|
+
## Other backends
|
|
448
|
+
|
|
449
|
+
```yaml
|
|
450
|
+
provider: pi # recommended: drive the pi coding agent (see "Recommended backend: pi")
|
|
451
|
+
provider: cli # reach other LLMs through their terminal CLIs (default without pi)
|
|
452
|
+
provider: litellm # direct API calls, needs API keys
|
|
453
|
+
provider: scripted # deterministic offline backend (demo/tests, no network)
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
With `provider: litellm` there is no terminal command, so a role's `model` is the
|
|
457
|
+
litellm model string (`openai/gpt-4o`, `anthropic/claude-3-5-sonnet-latest`,
|
|
458
|
+
`ollama/llama3`, …) and `agent` is ignored — e.g. `main: { model: openai/gpt-4o }`
|
|
459
|
+
(a bare string `openai/gpt-4o` works too). `litellm` needs the `litellm` extra —
|
|
460
|
+
see [Install](#install) — and the usual provider API keys in your environment
|
|
461
|
+
(`OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, …).
|
|
462
|
+
|
|
463
|
+
## Driving it from an MCP client
|
|
464
|
+
|
|
465
|
+
Expose the whole workflow to an MCP client (Claude Code, Claude Desktop) so an
|
|
466
|
+
agent can plan and run the roundtable as tool calls:
|
|
467
|
+
|
|
468
|
+
```bash
|
|
469
|
+
roundtable mcp # stdio MCP server (needs the mcp extra — see Install)
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
Tools: `roundtable_init`, `roundtable_map`, `roundtable_plan`, `roundtable_approve`,
|
|
473
|
+
`roundtable_run` (non-blocking; guarded against duplicate launches via a `run.pid`),
|
|
474
|
+
`roundtable_stop`, `roundtable_status`, and `roundtable_usage` (token/cost tally); plus
|
|
475
|
+
read-only `roundtable://plan`, `roundtable://state`, and `roundtable://logs` resources.
|
|
476
|
+
Register it in Claude Code's `.claude/settings.json`:
|
|
477
|
+
|
|
478
|
+
```json
|
|
479
|
+
{ "mcpServers": { "roundtable": { "command": "roundtable-mcp" } } }
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
## Project layout produced by a run
|
|
483
|
+
|
|
484
|
+
```
|
|
485
|
+
my-project/
|
|
486
|
+
roundtable.config.yaml # provider + choosable {agent, model} per role
|
|
487
|
+
.roundtable/
|
|
488
|
+
plan/{BRIEF.md, PLAN.md, plan.json} # plan.json = source-of-truth manifest
|
|
489
|
+
phases/
|
|
490
|
+
phase-01-<slug>/
|
|
491
|
+
PHASE.md
|
|
492
|
+
phase-summary.md # Phase Orchestrator -> Main report
|
|
493
|
+
tasks/task-01-<slug>/
|
|
494
|
+
TASK.md # the task's work definition
|
|
495
|
+
result.md # the agent's completed work
|
|
496
|
+
output/ # artifacts the agent produced
|
|
497
|
+
docs/{OVERVIEW.md, PROGRESS.md, FINAL.md} # maintained by the Main Orchestrator
|
|
498
|
+
runs/run.log # append-only structured JSONL events (feeds the dashboard)
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
Your own source files are never touched by the roundtable itself — only by the agents
|
|
502
|
+
you point at them.
|
|
503
|
+
|
|
504
|
+
## Design notes
|
|
505
|
+
|
|
506
|
+
- **Deterministic control flow, LLM cognition.** The engine (which agent runs
|
|
507
|
+
when, dependency scheduling, file layout, status) is plain code. Each role uses
|
|
508
|
+
its agent only for its own thinking.
|
|
509
|
+
- **Context cleaning is a hard invariant.** A Phase Orchestrator and its Task
|
|
510
|
+
Agents are created per phase and dropped afterward; the Main Orchestrator only
|
|
511
|
+
ever receives the phase *summary*, never task transcripts — so its context stays
|
|
512
|
+
small across long runs. Enforced by the engine, covered by tests.
|
|
513
|
+
- **Dependency-aware execution.** `depends_on` forms a DAG; tasks run in
|
|
514
|
+
dependency-ordered concurrent waves (`max_concurrency`) and dependents receive
|
|
515
|
+
upstream results as context. A dep may reference a task in the **same phase or
|
|
516
|
+
any earlier phase**; forward references, cycles, and unknown/duplicate ids are
|
|
517
|
+
rejected at plan time. (Phases still run in order — cross-phase deps flow
|
|
518
|
+
*results*, not cross-phase parallelism.)
|
|
519
|
+
- **Failure isolation.** A task that exhausts its retries — or fails its
|
|
520
|
+
`validate_command` — is marked `failed`; every dependent (same or a later phase)
|
|
521
|
+
is `skipped`; its phase and the overall run end `failed`, and no `FINAL.md` is
|
|
522
|
+
written. A phase whose own `validate_command` fails is marked `failed` even when
|
|
523
|
+
all its tasks completed. Provider exit codes are the failure signal, not output
|
|
524
|
+
heuristics.
|
|
525
|
+
- **Resumable.** Completed phases/tasks are skipped and their on-disk results
|
|
526
|
+
reused as dependency context; re-running retries failed/skipped work.
|
|
527
|
+
- **Dynamic re-planning.** After each dependency wave, if any task failed and
|
|
528
|
+
tasks remain in the phase, the Phase Orchestrator is asked to adapt the
|
|
529
|
+
remaining tasks' descriptions before they run — without touching the overall
|
|
530
|
+
plan structure.
|
|
531
|
+
|
|
532
|
+
## Architecture (modules)
|
|
533
|
+
|
|
534
|
+
| module | responsibility |
|
|
535
|
+
|---|---|
|
|
536
|
+
| `roundtable/models.py` | `AgentRef` + `Plan/Phase/Task` models + graph validation (intra- & cross-phase deps) |
|
|
537
|
+
| `roundtable/errors.py` | `RoundtableError` (user-facing) + `TaskFailed` (per-task failure signal) |
|
|
538
|
+
| `roundtable/config.py` | `roundtable.config.yaml`: provider, role `{agent, model}` runners, `agents` map, `project_context` |
|
|
539
|
+
| `roundtable/store.py` | `.roundtable/` layout, manifest IO, structured event log, all writers |
|
|
540
|
+
| `roundtable/llm.py` | `LLMProvider` protocol; `PiProvider` / `CLIProvider` / `LiteLLMProvider` / `ScriptedProvider`; JSON extraction; `RunStats` (tokens + cost) |
|
|
541
|
+
| `roundtable/discovery.py` | detect installed CLIs + list their models (`init` / `agents`) |
|
|
542
|
+
| `roundtable/modelpick.py` | list connected models + interactive per-role picker (`models` / `init`) |
|
|
543
|
+
| `roundtable/insights.py` | `build_state` analytics over `plan.json` + events; terminal rendering |
|
|
544
|
+
| `roundtable/dashboard.py` | zero-dep web dashboard + REST control API (stdlib `http.server`) |
|
|
545
|
+
| `roundtable/runctl.py` | `run.pid` protocol: detached run/plan launches, stop, HITL approve |
|
|
546
|
+
| `roundtable/scan.py` | stdlib codebase digest (pruned tree + key files) for `map` |
|
|
547
|
+
| `roundtable/prompts.py` | per-role system prompts |
|
|
548
|
+
| `roundtable/agents.py` | `Planner`, `Analyst`, `MainOrchestrator`, `PhaseOrchestrator`, `TaskAgent` |
|
|
549
|
+
| `roundtable/engine.py` | dependency scheduler + run loop + context-clean boundary + failure/HITL handling |
|
|
550
|
+
| `roundtable/cli.py` | `init` / `agents` / `models` / `map` / `plan` / `approve` / `run` / `resume` / `stop` / `status` / `dashboard` / `serve` / `watch` / `mcp` |
|
|
551
|
+
| `roundtable/mcp.py` | MCP server (`roundtable mcp` / `roundtable-mcp`) exposing the workflow as tools + resources |
|
|
552
|
+
|
|
553
|
+
## Tests
|
|
554
|
+
|
|
555
|
+
```bash
|
|
556
|
+
pip install -e ".[dev]"
|
|
557
|
+
pytest -q
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
Covers model validation (incl. cross-phase deps, forward-ref/duplicate-id
|
|
561
|
+
rejection), the `.roundtable/` store, JSON extraction (objects, arrays, double-fenced
|
|
562
|
+
blocks), the **CLIProvider against real subprocesses** (streaming output, cwd,
|
|
563
|
+
missing-command and nonzero-exit handling), existing-plan ingestion + non-pollution
|
|
564
|
+
layout, and full offline engine runs asserting the orchestration contract —
|
|
565
|
+
dependency flow, wave ordering, cross-phase result flow, the context-clean
|
|
566
|
+
invariant, the approval gate (HITL `waiting` → `resume`), failure propagation
|
|
567
|
+
(failed task → skipped dependents → failed run), the phase completion gate
|
|
568
|
+
(phase `validate_command` failing/healing across re-runs), and resumability.
|
|
569
|
+
|
|
570
|
+
[litellm]: https://github.com/BerriAI/litellm
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
roundtable/__init__.py,sha256=pABzBsB3dohy2FKHto2OtMY3kDKL67Ar2NHh3NuOkyc,366
|
|
2
|
+
roundtable/agents.py,sha256=iEi-h1T4FeQx-qk1iucWIqW4WGhPVkyd8jY7U0ebDW8,10067
|
|
3
|
+
roundtable/cli.py,sha256=xiA8IAeuwN1TvpfQg2fVqcXKcctWvj8lOfdopzAAZUE,30330
|
|
4
|
+
roundtable/config.py,sha256=PZL4Vz07LQnKTlzB_hl0En5__zz6vWPzwmRW-g3Kh9M,12838
|
|
5
|
+
roundtable/dashboard.py,sha256=09EFGQLVftMb6opWignC7HwcrVy9r13WDkSxL4-UHFM,24004
|
|
6
|
+
roundtable/discovery.py,sha256=nXn1jTgNuejQDyeHGlDmB7UgYjn7TX85-UcgSoEpR6w,2681
|
|
7
|
+
roundtable/engine.py,sha256=BdYBEe64G2bMNCVE-crXOeGz1zkyj-ehIJ6fEBDL4Ng,30730
|
|
8
|
+
roundtable/errors.py,sha256=EgLZ9E3x0r59OUl7V1KIFMQh_geMk8Waa3fG5jqAyBw,650
|
|
9
|
+
roundtable/insights.py,sha256=j-U1FCB9YXFN4WeEJqrn5RbW-Ry3GfvlYvy9S1LdFdI,8150
|
|
10
|
+
roundtable/llm.py,sha256=o-2hhCLel1Of7H9eqJRAg02BjqsgzMX_gLos7mGPUy8,40450
|
|
11
|
+
roundtable/mcp.py,sha256=a0WF-TWset8ZMBlMJAGQTVe0GICxKvMG7t8yNDmAsps,8925
|
|
12
|
+
roundtable/modelpick.py,sha256=tSNnMNFk2mzUrvyD9AFYZoHLFw-Vm2i93yLwHeLh9FY,12844
|
|
13
|
+
roundtable/models.py,sha256=JGntf9AebYpXrwbfs4s99ZBmKnpBI9JlCbK53uLkZCo,7418
|
|
14
|
+
roundtable/prompts.py,sha256=qXGMsJ85UfkI-0XrHZtltDwSO8GYcJtynzKj0lC-Hqk,8498
|
|
15
|
+
roundtable/runctl.py,sha256=xVfottk5Y2b7slpFCsdpZWDlNq8yNz1suZPf89t6lTw,7102
|
|
16
|
+
roundtable/scan.py,sha256=gxN7tFUmwFQyF1nvwvV-CrDGC7lUuYePtDwm-pTrWAo,6522
|
|
17
|
+
roundtable/store.py,sha256=ZSsh86GatjqFuTSHVtpuyuYBkt476SHgyztyfJnWcBs,12152
|
|
18
|
+
roundtable_cli-0.4.0.dist-info/METADATA,sha256=E8aer5YbC3QjnyIhkC6GVLqp5FnGixqPwIMg-HLP19M,26910
|
|
19
|
+
roundtable_cli-0.4.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
20
|
+
roundtable_cli-0.4.0.dist-info/entry_points.txt,sha256=erLYm3ZXpyN4IDeoallKbr0kYhoq5C4ATB5nGH5h6Vc,119
|
|
21
|
+
roundtable_cli-0.4.0.dist-info/licenses/LICENSE,sha256=ihK6PoseDFzaZP_LAfeKD-FjcWcIMThpe-TmjwLPmqg,1069
|
|
22
|
+
roundtable_cli-0.4.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Abdur Rahman
|
|
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.
|