monkeybot-cli 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- monkeybot_cli-0.2.1/.gitignore +64 -0
- monkeybot_cli-0.2.1/PKG-INFO +10 -0
- monkeybot_cli-0.2.1/pyproject.toml +42 -0
- monkeybot_cli-0.2.1/skills/monkeybot/SKILL.md +197 -0
- monkeybot_cli-0.2.1/skills/monkeybot/references/config-sections.md +160 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/__init__.py +3 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/chat_renderer.py +87 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/chat_session.py +911 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/chat_status_bar.py +205 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/chat_theme.py +91 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/chat_tool_display.py +334 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/chat_tui.py +1491 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/chat_tui_widgets.py +996 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/commands/__init__.py +1 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/commands/chat.py +817 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/commands/doctor.py +293 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/commands/loop.py +207 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/commands/new.py +207 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/commands/run_cmd.py +41 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/commands/talk.py +102 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/commands/validate.py +385 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/compat.py +7 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/config_resolve.py +55 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/exit_commands.py +13 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/extras_catalog.py +95 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/gateway_health.py +34 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/main.py +38 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/opensandbox_lifecycle.py +314 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/output.py +110 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/providers.py +112 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/realtime/__init__.py +13 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/realtime/audio_io.py +147 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/realtime/client.py +17 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/realtime/gateway_manager.py +142 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/realtime/push_to_talk.py +128 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/realtime/session.py +256 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/realtime/session_controller.py +501 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/realtime/talk_ui.py +243 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/realtime/wire_encode.py +39 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/runtime_python.py +91 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/scaffold.py +287 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/scaffold_defaults/AGENT.md +56 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/scaffold_defaults/__init__.py +1 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/scaffold_defaults/command_allowlist.yaml +57 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/scaffold_defaults/env.example +35 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/scaffold_defaults/mcp.json +49 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/scaffold_defaults/monkeybot.example.yaml +191 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/scaffold_defaults/otel-collector.example.yaml +57 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/scaffold_defaults/permissions.yaml +32 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/scaffold_defaults/setup-workspace.sh +24 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/session_controller.py +7 -0
- monkeybot_cli-0.2.1/src/monkeybot_cli/terminal_markdown.py +48 -0
- monkeybot_cli-0.2.1/tests/test_chat_e2e.py +86 -0
- monkeybot_cli-0.2.1/tests/test_chat_errors.py +218 -0
- monkeybot_cli-0.2.1/tests/test_chat_grounding.py +54 -0
- monkeybot_cli-0.2.1/tests/test_chat_renderer_parity.py +26 -0
- monkeybot_cli-0.2.1/tests/test_chat_session.py +363 -0
- monkeybot_cli-0.2.1/tests/test_chat_status_bar.py +149 -0
- monkeybot_cli-0.2.1/tests/test_chat_theme.py +71 -0
- monkeybot_cli-0.2.1/tests/test_chat_tool_display.py +154 -0
- monkeybot_cli-0.2.1/tests/test_chat_tui.py +1243 -0
- monkeybot_cli-0.2.1/tests/test_cli.py +132 -0
- monkeybot_cli-0.2.1/tests/test_config_resolve.py +21 -0
- monkeybot_cli-0.2.1/tests/test_doctor.py +49 -0
- monkeybot_cli-0.2.1/tests/test_extras_catalog.py +87 -0
- monkeybot_cli-0.2.1/tests/test_opensandbox_lifecycle.py +41 -0
- monkeybot_cli-0.2.1/tests/test_realtime_session_controller.py +301 -0
- monkeybot_cli-0.2.1/tests/test_run_cmd.py +79 -0
- monkeybot_cli-0.2.1/tests/test_runtime_python.py +109 -0
- monkeybot_cli-0.2.1/tests/test_scaffold.py +115 -0
- monkeybot_cli-0.2.1/tests/test_terminal_markdown.py +47 -0
- monkeybot_cli-0.2.1/uv.lock +1612 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Internal (not shipped in OSS)
|
|
2
|
+
internal/
|
|
3
|
+
|
|
4
|
+
# Environment
|
|
5
|
+
.env
|
|
6
|
+
.env.*
|
|
7
|
+
!.env.example
|
|
8
|
+
|
|
9
|
+
# Local scaffolded harness config (defaults ship in monkeybot-cli scaffold_defaults/)
|
|
10
|
+
/monkeybot_config/
|
|
11
|
+
|
|
12
|
+
# Demo agent live config (materialized from monkeybot_config_example/ by demo_agent/run.sh)
|
|
13
|
+
demo_agent/monkeybot_config/
|
|
14
|
+
|
|
15
|
+
# Live eval run artifacts (only evals/baselines/ is versioned)
|
|
16
|
+
/evals/runs/
|
|
17
|
+
|
|
18
|
+
# Python
|
|
19
|
+
__pycache__/
|
|
20
|
+
*.py[cod]
|
|
21
|
+
*.pyo
|
|
22
|
+
*.pyd
|
|
23
|
+
.Python
|
|
24
|
+
*.egg-info/
|
|
25
|
+
dist/
|
|
26
|
+
build/
|
|
27
|
+
.eggs/
|
|
28
|
+
*.egg
|
|
29
|
+
|
|
30
|
+
# uv
|
|
31
|
+
.venv/
|
|
32
|
+
.uv/
|
|
33
|
+
|
|
34
|
+
# Data (SQLite DB + memory files — never commit)
|
|
35
|
+
data/
|
|
36
|
+
|
|
37
|
+
# Testing & coverage
|
|
38
|
+
.pytest_cache/
|
|
39
|
+
.coverage
|
|
40
|
+
htmlcov/
|
|
41
|
+
.mypy_cache/
|
|
42
|
+
.ruff_cache/
|
|
43
|
+
|
|
44
|
+
# macOS
|
|
45
|
+
.DS_Store
|
|
46
|
+
|
|
47
|
+
# IDEs
|
|
48
|
+
.idea/
|
|
49
|
+
.vscode/
|
|
50
|
+
*.swp
|
|
51
|
+
*.swo
|
|
52
|
+
|
|
53
|
+
# Docker
|
|
54
|
+
docker/data/
|
|
55
|
+
|
|
56
|
+
# Planning Documents
|
|
57
|
+
.prt/
|
|
58
|
+
.monkeymode/
|
|
59
|
+
|
|
60
|
+
# Reference clones (read-only)
|
|
61
|
+
code/
|
|
62
|
+
|
|
63
|
+
# Local venv for evals dependency experiments
|
|
64
|
+
.evals-venv/
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: monkeybot-cli
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: CLI to create, configure, validate, and chat with monkeybot agents.
|
|
5
|
+
Requires-Python: >=3.11
|
|
6
|
+
Requires-Dist: httpx>=0.27.0
|
|
7
|
+
Requires-Dist: monkeybot[cli]<3,>=2.1.0
|
|
8
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
9
|
+
Requires-Dist: pyyaml>=6.0.2
|
|
10
|
+
Requires-Dist: textual>=8.2.8
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "monkeybot-cli"
|
|
7
|
+
version = "0.2.1"
|
|
8
|
+
description = "CLI to create, configure, validate, and chat with monkeybot agents."
|
|
9
|
+
requires-python = ">=3.11"
|
|
10
|
+
dependencies = [
|
|
11
|
+
# `cli` pulls realtime + typer so `monkeybot talk` works out of the box (text mode).
|
|
12
|
+
# Audio mic/PTT needs the agent (or this env) to also install monkeybot[cli-realtime].
|
|
13
|
+
"monkeybot[cli]>=2.1.0,<3",
|
|
14
|
+
"httpx>=0.27.0",
|
|
15
|
+
"pyyaml>=6.0.2",
|
|
16
|
+
"python-dotenv>=1.0.0",
|
|
17
|
+
"textual>=8.2.8",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
[project.scripts]
|
|
21
|
+
monkeybot = "monkeybot_cli.main:main"
|
|
22
|
+
|
|
23
|
+
[tool.uv.sources]
|
|
24
|
+
monkeybot = { path = "..", editable = true }
|
|
25
|
+
|
|
26
|
+
[dependency-groups]
|
|
27
|
+
dev = [
|
|
28
|
+
"pexpect>=4.9.0",
|
|
29
|
+
"pytest>=8.3.0",
|
|
30
|
+
"ruff>=0.8.0",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[tool.hatch.build.targets.wheel]
|
|
34
|
+
packages = ["src/monkeybot_cli"]
|
|
35
|
+
|
|
36
|
+
[tool.ruff]
|
|
37
|
+
line-length = 100
|
|
38
|
+
target-version = "py311"
|
|
39
|
+
|
|
40
|
+
[tool.ruff.lint]
|
|
41
|
+
select = ["E", "F", "I", "N", "W", "UP"]
|
|
42
|
+
ignore = ["E501"]
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: monkeybot
|
|
3
|
+
description: Entry point for monkeybot — install the CLI from PyPI if needed, then scaffold, configure, validate, and chat with an agent. Use when a user installs this skill via `npx skills add human-plus-machine/monkeybot --skill monkeybot`, sets up monkeybot for the first time, installs the monkeybot CLI, scaffolds monkeybot_config/, explains monkeybot.yaml options, or smoke-tests from the terminal.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# monkeybot
|
|
7
|
+
|
|
8
|
+
Guide a new user from **only this skill** to a working agent. Installing the skill (`npx skills add …`) gives you these instructions — it does **not** install the monkeybot CLI. **Always run Tier 0 first** unless you already know the toolchain is ready. Day-1 users do **not** need to clone the monkeybot repo.
|
|
9
|
+
|
|
10
|
+
## Tier 0 — Bootstrap toolchain
|
|
11
|
+
|
|
12
|
+
Run these checks before anything else. Do not skip to Tier 1 until the CLI probe succeeds.
|
|
13
|
+
|
|
14
|
+
### 0. Detect what's already installed
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
command -v monkeybot && monkeybot --help
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
If that works, skip to Tier 1.
|
|
21
|
+
|
|
22
|
+
### 1. Install prerequisites (only if missing)
|
|
23
|
+
|
|
24
|
+
| Tool | Check | Install |
|
|
25
|
+
|---|---|---|
|
|
26
|
+
| **uv** | `command -v uv` | `curl -LsSf https://astral.sh/uv/install.sh \| sh` then `export PATH="$HOME/.local/bin:$PATH"` |
|
|
27
|
+
| **Python 3.11+** | `uv python find 3.11` or `python3 --version` | `uv python install 3.12` |
|
|
28
|
+
|
|
29
|
+
Tell the user what you're installing and why. On macOS/Linux you can run these yourself; on Windows, point them at [uv](https://docs.astral.sh/uv/).
|
|
30
|
+
|
|
31
|
+
### 2. Install the global CLI
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
uv tool install monkeybot-cli
|
|
35
|
+
monkeybot --help
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Upgrade later with `uv tool upgrade monkeybot-cli`.
|
|
39
|
+
|
|
40
|
+
**Do not** tell day-1 users to clone `human-plus-machine/monkeybot` unless they are contributing to the harness itself (see Contributing below).
|
|
41
|
+
|
|
42
|
+
### 3. Skill-only users
|
|
43
|
+
|
|
44
|
+
If the user arrived via skills.sh:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npx skills add human-plus-machine/monkeybot --skill monkeybot
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
…they have **this skill only**. Walk them through Tier 0: install `uv` → `uv tool install monkeybot-cli` → verify `monkeybot --help`. Then continue to Tier 1.
|
|
51
|
+
|
|
52
|
+
## How config works (tell the user this first)
|
|
53
|
+
|
|
54
|
+
- **CLI scaffolds, YAML customizes, then validate.** `monkeybot new` copies packaged defaults from the `monkeybot-cli` package (`monkeybot_cli.scaffold_defaults`) and sets `model.provider` / `model.name`. After that, customization happens by editing `monkeybot_config/monkeybot.yaml` and `.env`, then re-running `monkeybot validate --json`.
|
|
55
|
+
- **Three config surfaces:**
|
|
56
|
+
- `monkeybot_config/monkeybot.yaml` — non-secret settings (model, paths, gateway, behavior).
|
|
57
|
+
- `.env` — secrets and machine-local paths (API keys, GCP project, DB URL).
|
|
58
|
+
- sidecars: `monkeybot_config/AGENT.md` (system prompt), `mcp.json` (MCP servers), `command_allowlist.yaml`.
|
|
59
|
+
- **Precedence — important:** environment variables and `.env` win over `monkeybot.yaml`. If a user edits YAML but nothing changes, suspect a stale `.env` shadowing it (the YAML→env mapping lives in `runtime_env.py:ENV_MAP`).
|
|
60
|
+
- **Defaults are fine on day one.** Most first-time users only touch `model`, `.env` credentials, and `AGENT.md`.
|
|
61
|
+
|
|
62
|
+
## Running CLI commands
|
|
63
|
+
|
|
64
|
+
After Tier 0, every command below uses `monkeybot` on PATH.
|
|
65
|
+
|
|
66
|
+
## Tier 1 — Get it talking
|
|
67
|
+
|
|
68
|
+
The minimum path to one successful chat turn. Do this for every new user.
|
|
69
|
+
|
|
70
|
+
### 1. Quick interview
|
|
71
|
+
|
|
72
|
+
Ask (or infer):
|
|
73
|
+
|
|
74
|
+
- Bot purpose / name → goes in `AGENT.md`
|
|
75
|
+
- Provider + model (see provider table below)
|
|
76
|
+
- Optional features (postgres, sandbox, observability, …) → `--with` or interactive menus
|
|
77
|
+
|
|
78
|
+
### 2. Scaffold
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
monkeybot new --dest /path/to/bot --provider openai --yes
|
|
82
|
+
# Interactive (menus for provider + extras):
|
|
83
|
+
# monkeybot new --dest /path/to/bot
|
|
84
|
+
# Non-interactive extras:
|
|
85
|
+
# monkeybot new --dest /path/to/bot --provider openai --with postgres,sandbox --yes
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Creates `monkeybot_config/`, `workspace/` (file-tool sandbox), `workspace/skills` → `skills/`, `data/memory/`, `.env.example`, `scripts/setup-workspace.sh`, and an agent `pyproject.toml`. Use `--force` only when overwriting is explicitly requested.
|
|
89
|
+
|
|
90
|
+
Then:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
cd /path/to/bot
|
|
94
|
+
uv sync
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### 3. Credentials + system prompt
|
|
98
|
+
|
|
99
|
+
- Copy `.env.example` → `.env` and fill in the keys for your provider (table below).
|
|
100
|
+
- Edit `monkeybot_config/AGENT.md` with the bot's system prompt. **Never put secrets in YAML.**
|
|
101
|
+
|
|
102
|
+
### Provider table
|
|
103
|
+
|
|
104
|
+
| YAML `model.provider` | `.env` credentials (any one) | Add to agent `pyproject.toml` deps, then `uv sync` |
|
|
105
|
+
|---|---|---|
|
|
106
|
+
| `gemini` (or `vertex`) | `GEMINI_API_KEY`, or `GOOGLE_APPLICATION_CREDENTIALS`, or `GCP_PROJECT_ID` / `GOOGLE_CLOUD_PROJECT` (ADC) | `monkeybot[gemini]` |
|
|
107
|
+
| `openai` | `OPENAI_API_KEY` | `monkeybot[openai]` |
|
|
108
|
+
| `anthropic` | `ANTHROPIC_API_KEY` | `monkeybot[claude]` |
|
|
109
|
+
| `vertex-claude` | `GCP_PROJECT_ID` / `GOOGLE_CLOUD_PROJECT` / `ANTHROPIC_VERTEX_PROJECT_ID` (ADC) | `monkeybot[vertex-claude]` |
|
|
110
|
+
| `aws_bedrock` | `AWS_ACCESS_KEY_ID` / `AWS_PROFILE` + `AWS_REGION` | `monkeybot[bedrock]` |
|
|
111
|
+
| `huggingface` | `HF_TOKEN` (or `HUGGINGFACE_API_KEY`) | `monkeybot[huggingface]` |
|
|
112
|
+
| `ollama` | None required — `OLLAMA_BASE_URL` (default `http://localhost:11434`) for a non-default server | `monkeybot[ollama]` |
|
|
113
|
+
|
|
114
|
+
**Agent-first dependencies.** The CLI is thin — it does **not** install provider/storage extras globally. `monkeybot new` scaffolds a `pyproject.toml` with the selected provider (and any `--with` extras). Run plain `uv sync` in the agent directory. `monkeybot run` / `chat` spawn the gateway from that project's interpreter (`.venv/bin/python`, else `uv run python`), and `doctor` checks extras in that same interpreter. For a config-only tree (just `monkeybot_config/`, no `pyproject.toml`) the gateway falls back to the CLI's interpreter, so extras must be installed in the CLI env (`uv tool install --with 'monkeybot[<extra>]' monkeybot-cli`).
|
|
115
|
+
|
|
116
|
+
`doctor` is the source of truth for credentials and extras — when in doubt, run it and read the `remediation` field (add `monkeybot[<extra>]` to agent deps + `uv sync`).
|
|
117
|
+
|
|
118
|
+
### 4. Validate (loop until clean)
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
monkeybot validate --json --cwd /path/to/bot
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
- Exit `0` + `"ok": true` → proceed.
|
|
125
|
+
- On failure: read `checks[]` by stable `id`, apply `remediation`, re-run.
|
|
126
|
+
|
|
127
|
+
### 5. Doctor
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
monkeybot doctor --json --cwd /path/to/bot
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Confirms Python version, provider extra installed, credentials present, and port free.
|
|
134
|
+
|
|
135
|
+
### 6. Smoke test
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
monkeybot chat --cwd /path/to/bot
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Or split terminals: `monkeybot run --cwd /path/to/bot` then `monkeybot chat --attach --cwd /path/to/bot`.
|
|
142
|
+
|
|
143
|
+
One successful turn confirms Tier 1.
|
|
144
|
+
|
|
145
|
+
## Tier 2 — Customize (on demand)
|
|
146
|
+
|
|
147
|
+
Only reach for these when the interview surfaces a need. Each maps to a `monkeybot.yaml` section. **For purpose, defaults, examples, and the `validate`/`doctor` check id of every option, read [`references/config-sections.md`](references/config-sections.md).** Don't inline that reference here.
|
|
148
|
+
|
|
149
|
+
Decision → config map:
|
|
150
|
+
|
|
151
|
+
| User says… | Change |
|
|
152
|
+
|---|---|
|
|
153
|
+
| "Run many subagents in parallel" | `paths.db_url` → Postgres (SQLite locks under concurrency) |
|
|
154
|
+
| "I have a custom web UI" | `gateway.cors_allow_origins` |
|
|
155
|
+
| "Search the web" | `web_search.backend` + `.env` keys (Tavily/Firecrawl) |
|
|
156
|
+
| "Run untrusted code" | `sandbox.enabled` + `SANDBOX_API_KEY` |
|
|
157
|
+
| "Use specialist agents" | `subagents[]` + `monkeybot_config/agents/*.md` |
|
|
158
|
+
| "Connect external tools" | `mcp.json` (`mcpServers` object), then `validate --check-mcp` |
|
|
159
|
+
| "Control cost / context size" | `model.*`, `context_curation.*` |
|
|
160
|
+
| "Restrict dangerous commands" | `tools.denied_patterns`, `command_allowlist.yaml` |
|
|
161
|
+
| "Multiple environments" | top-level `includes:` fragments |
|
|
162
|
+
|
|
163
|
+
**Subagents (`task` tool):** share the parent `AGENT.md` (or `subagent.agent_md`). Relative paths resolve from the bot project root, not `workspace/`. Specialize via `task` / `context`, not separate agent type folders. For parallel `task` fan-out, prefer Postgres: add `monkeybot[postgres]` to the **agent** `pyproject.toml` dependencies, run `uv sync`, then set `DB_URL=postgresql://...` in `.env`.
|
|
164
|
+
|
|
165
|
+
**Observability** is mostly env + add `monkeybot[observability]` to agent deps + `uv sync` + an OTel collector — not `monkeybot.yaml`. See `docs/observability-runbook.md`.
|
|
166
|
+
|
|
167
|
+
## Contributing / developing the harness
|
|
168
|
+
|
|
169
|
+
Only if the user is changing monkeybot itself (not creating an agent):
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
git clone https://github.com/human-plus-machine/monkeybot.git
|
|
173
|
+
cd monkeybot && uv sync
|
|
174
|
+
cd cli && uv sync
|
|
175
|
+
uv tool install --editable .
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Rules
|
|
179
|
+
|
|
180
|
+
- **Tier 0 before Tier 1** — verify or install the global CLI before scaffolding a bot.
|
|
181
|
+
- **CLI owns scaffolding** — do not duplicate template files manually.
|
|
182
|
+
- **Secrets in `.env` only** — never commit API keys to `monkeybot.yaml`.
|
|
183
|
+
- **Validate after every edit** — re-run `validate --json` whenever you change config.
|
|
184
|
+
- **Parse JSON** — key off `checks[].id`, not free-form messages.
|
|
185
|
+
- **HTTP/SSE for chat** — the CLI talks to the gateway process; do not import harness gateway code.
|
|
186
|
+
- **No clone for day-1 users** — clone is for harness contributors only.
|
|
187
|
+
|
|
188
|
+
## Command reference
|
|
189
|
+
|
|
190
|
+
| Command | Purpose |
|
|
191
|
+
|---------|---------|
|
|
192
|
+
| `new` | Scaffold `monkeybot_config/`, `workspace/`, `data/memory/`, `skills/`, `pyproject.toml`, `.env.example` |
|
|
193
|
+
| `validate` | Config + paths + MCP shape (`--check-mcp` for network) |
|
|
194
|
+
| `doctor` | Python, provider extra, credentials, port |
|
|
195
|
+
| `run` | Start SSE gateway subprocess |
|
|
196
|
+
| `chat` | Interactive terminal client (SSE) |
|
|
197
|
+
| `talk` | Realtime WebSocket client (audio/text) |
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# monkeybot.yaml configuration reference
|
|
2
|
+
|
|
3
|
+
Deep reference for every `monkeybot.yaml` section. Load this only when a user needs to customize beyond Tier 1. The canonical, fully-commented template lives at `cli/src/monkeybot_cli/scaffold_defaults/monkeybot.example.yaml` in the monkeybot repo (copied to `monkeybot_config/monkeybot.example.yaml` when you scaffold); this file adds the **"when would I change this?"** context the comments don't.
|
|
4
|
+
|
|
5
|
+
**Precedence:** env vars and `.env` win over YAML. The YAML→env mapping is `ENV_MAP` in `src/monkeybot/core/config/runtime_env.py`. If a YAML edit has no effect, check for a shadowing env var.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## `runtime`
|
|
10
|
+
|
|
11
|
+
| Field | Default | When to change |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| `log_level` | `INFO` | `DEBUG` while troubleshooting; `WARNING`/`ERROR` to quiet logs |
|
|
14
|
+
| `port` | `8080` | Port conflict, or running multiple bots locally |
|
|
15
|
+
| `gateway_port` | (unset) | Only if a code path needs `GATEWAY_PORT` separate from `PORT` |
|
|
16
|
+
|
|
17
|
+
Validate/doctor: `doctor` → `runtime.port.free`.
|
|
18
|
+
|
|
19
|
+
## `paths`
|
|
20
|
+
|
|
21
|
+
| Field | Default | When to change |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| `agent_md` | `./monkeybot_config/AGENT.md` | Alternate system-prompt location |
|
|
24
|
+
| `memory_storage_uri` | `local://./data/memory` | `gcs://…` for shared/cloud memory (requires GCP project) |
|
|
25
|
+
| `skills_path` | `./skills` | Point at a different skills tree |
|
|
26
|
+
| `db_url` | `sqlite:///data/monkeybot.db` | **Postgres for parallel subagents** — SQLite hits `database is locked` under concurrency |
|
|
27
|
+
| `auto_schema` | `true` | Set `false` when migrations own the schema (managed Postgres with DML-only runtime user) |
|
|
28
|
+
| `mcp_config` | `./monkeybot_config/mcp.json` | Relocate MCP definitions |
|
|
29
|
+
| `command_allowlist_config` | `./monkeybot_config/command_allowlist.yaml` | Relocate the shell allowlist |
|
|
30
|
+
| `workspace_root` | `./workspace` (if present) | Change the file-tool sandbox root |
|
|
31
|
+
|
|
32
|
+
Validate check ids: `paths.agent_md.exists`, `paths.skills_path.exists`, `paths.mcp_config.exists`, `paths.command_allowlist.exists`, `paths.db_url.writable`, `memory.backend.supported`, `gcp.project.required` (for `gcs://` memory).
|
|
33
|
+
|
|
34
|
+
## `model`
|
|
35
|
+
|
|
36
|
+
| Field | Default | When to change |
|
|
37
|
+
|---|---|---|
|
|
38
|
+
| `provider` | `gemini` | Switch LLM vendor (see provider table in SKILL.md) |
|
|
39
|
+
| `name` | `gemini-3-flash` | Pick a specific model id |
|
|
40
|
+
| `temperature` | `0.7` | Lower for deterministic output, higher for creative |
|
|
41
|
+
| `max_tokens` | `60000` | Cap per-response length |
|
|
42
|
+
| `thinking_budget` | `-1` | Gemini: `-1` model default, `0` off, `N` token budget. Ollama reasoning models: `-1` server default, `0` off (`reasoning_effort: none`) |
|
|
43
|
+
| `context_window` | `1000000` | Summarization trigger threshold (tokens) |
|
|
44
|
+
| `max_turns` | `50` | Hard cap on turns per run |
|
|
45
|
+
| `summarization_model` | (main model) | Cheaper model for history summarization (env `CONTEXT_SUMMARIZATION_MODEL`) |
|
|
46
|
+
|
|
47
|
+
Validate check ids: `model.provider.supported`, `model.name.present`. Supported YAML providers: `gemini`/`vertex`, `openai`, `anthropic`, `vertex-claude`, `huggingface`, `ollama`, `aws_bedrock`, `fake`.
|
|
48
|
+
|
|
49
|
+
## `gcp` / `anthropic_vertex` (non-secret identifiers)
|
|
50
|
+
|
|
51
|
+
Prefer `.env` for secrets and the ADC path; use these blocks only for non-secret project/region identifiers.
|
|
52
|
+
|
|
53
|
+
```yaml
|
|
54
|
+
gcp:
|
|
55
|
+
project_id: your-gcp-project
|
|
56
|
+
location: us-central1
|
|
57
|
+
anthropic_vertex:
|
|
58
|
+
project_id: your-gcp-project
|
|
59
|
+
region: us-east5
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Required when `memory_storage_uri` is `gcs://…` or `provider: vertex-claude` (validate `gcp.project.required`).
|
|
63
|
+
|
|
64
|
+
## `gateway`
|
|
65
|
+
|
|
66
|
+
| Field | Default | When to change |
|
|
67
|
+
|---|---|---|
|
|
68
|
+
| `pending_response_timeout_sec` | `300` | Long-running turns time out too early |
|
|
69
|
+
| `sse_replay_max` | `256` | Tune SSE replay buffer |
|
|
70
|
+
| `graceful_shutdown_timeout_sec` | `5` | Allow longer drain on shutdown |
|
|
71
|
+
| `cors_allow_origins` | `http://localhost:5173` | **Custom web UI** — set its origin, or `"*"` for any |
|
|
72
|
+
|
|
73
|
+
## `context_curation`
|
|
74
|
+
|
|
75
|
+
Trims memory injected into context. `enabled: true` by default.
|
|
76
|
+
|
|
77
|
+
Recent window by default; LLM curator only when the index is token-heavy. On curator failure, falls back to the window.
|
|
78
|
+
|
|
79
|
+
| Field | Default | Notes |
|
|
80
|
+
|---|---|---|
|
|
81
|
+
| `memory_window_lines` | `12` | Recent index lines injected; also caps curator-selected lines |
|
|
82
|
+
| `memory_index_cap` | `200` | Organizer keeps this many INDEX.md entries; older rows move to `INDEX.archive.md` |
|
|
83
|
+
| `memory_token_threshold` | `2000` | Call curator when estimated index tokens exceed this |
|
|
84
|
+
| `curator_model` | `gemini-3-flash` | Separate small model; empty = main model |
|
|
85
|
+
| `timeout_sec` | `10` | Curator call timeout |
|
|
86
|
+
|
|
87
|
+
When the prompt shows fewer entries than exist, a structural confidence score triggers a `search_memory` nudge. Skill names are always shown in full in the prompt; use `list_skills` to get the skills root path.
|
|
88
|
+
|
|
89
|
+
## `memory_hook`
|
|
90
|
+
|
|
91
|
+
`enabled: true` — automatic memory capture after turns. Disable to manage memory manually.
|
|
92
|
+
|
|
93
|
+
## `subagent` and `subagents`
|
|
94
|
+
|
|
95
|
+
`subagent` sets defaults for `task` calls:
|
|
96
|
+
|
|
97
|
+
| Field | Default | Notes |
|
|
98
|
+
|---|---|---|
|
|
99
|
+
| `timeout_sec` | `600` | Per-subagent timeout |
|
|
100
|
+
| `max_turns` | `25` | Per-subagent turn cap |
|
|
101
|
+
| `vertex_google_search` | `false` | **Gemini only.** Enables native `google_search` grounding for subagent `task` runs. Config-file only. |
|
|
102
|
+
| `agent_md` | (parent `AGENT.md`) | Default prompt when `task` omits `subagent_type` |
|
|
103
|
+
|
|
104
|
+
`subagents[]` defines named personas the parent selects via `task(subagent_type=...)`:
|
|
105
|
+
|
|
106
|
+
```yaml
|
|
107
|
+
subagents:
|
|
108
|
+
- name: researcher
|
|
109
|
+
description: "Deep-dives a topic and returns a structured summary."
|
|
110
|
+
agent_md: ./monkeybot_config/agents/researcher.md
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Relative paths resolve from the bot project root, not `workspace/`. For parallel fan-out, use Postgres (`db_url`).
|
|
114
|
+
|
|
115
|
+
## `tools`
|
|
116
|
+
|
|
117
|
+
| Field | Default | When to change |
|
|
118
|
+
|---|---|---|
|
|
119
|
+
| `denied_patterns` | (none) | Block substrings in tool args, e.g. `"rm -rf"` (also env `MONKEYBOT_TOOL_DENIED_PATTERNS`) |
|
|
120
|
+
| `read_max_lines` / `read_default_lines` | (code defaults) | Tune file-read limits |
|
|
121
|
+
| `spill_read_max_lines` / `spill_min_chars` | (code defaults) | Tune large-result spill behavior |
|
|
122
|
+
| `result_budget_fraction` / `result_budget_floor_tokens` | (code defaults) | Advanced result-budgeting; rarely needed |
|
|
123
|
+
|
|
124
|
+
For shell-command safety, pair `denied_patterns` with `monkeybot_config/command_allowlist.yaml`.
|
|
125
|
+
|
|
126
|
+
## `web_search`
|
|
127
|
+
|
|
128
|
+
| Field | Default | Notes |
|
|
129
|
+
|---|---|---|
|
|
130
|
+
| `backend` | `duckduckgo` | `duckduckgo` (no key) \| `tavily` \| `firecrawl` \| `none` |
|
|
131
|
+
| `max_results` | `5` | Result cap |
|
|
132
|
+
| `vertex_google_search` | `false` | **Gemini only.** Additive to `backend` — enables Vertex Gemini's native `google_search` grounding tool for **main agent** turns only (not summarization, memory organizer, or curator). Ignored for other model providers. Config-file only — no env var override (like `paths.auto_schema`). |
|
|
133
|
+
|
|
134
|
+
Tavily/Firecrawl need `TAVILY_API_KEY` / `FIRECRAWL_API_KEY` in `.env`. Doctor check: `web_search.backend.ready` (`duckduckgo` needs the `web-search` extra).
|
|
135
|
+
|
|
136
|
+
## `sandbox`
|
|
137
|
+
|
|
138
|
+
| Field | Default | When to change |
|
|
139
|
+
|---|---|---|
|
|
140
|
+
| `enabled` | `false` | Enable to run untrusted code in isolation |
|
|
141
|
+
| `server_url` | `http://localhost:8080` | Sandbox service endpoint |
|
|
142
|
+
| `image` | `python:3.12` | Execution image |
|
|
143
|
+
| `ttl_seconds` | `1800` | Sandbox lifetime |
|
|
144
|
+
|
|
145
|
+
Needs `SANDBOX_API_KEY` in `.env`.
|
|
146
|
+
|
|
147
|
+
## `includes`
|
|
148
|
+
|
|
149
|
+
Top-level list of YAML fragments (paths relative to the config file's directory). Later files deep-merge over earlier ones — useful for per-environment overrides:
|
|
150
|
+
|
|
151
|
+
```yaml
|
|
152
|
+
includes:
|
|
153
|
+
- includes/local.yaml
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Validate check: `config.includes.resolve`.
|
|
157
|
+
|
|
158
|
+
## `fake_provider`
|
|
159
|
+
|
|
160
|
+
Test-only. `events_json` feeds `MODEL_PROVIDER=fake` scripted runs (env `MONKEYBOT_FAKE_PROVIDER_EVENTS`). Not for production.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""Shared chat renderer contract and session controller protocol."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Protocol, runtime_checkable
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from monkeybot_cli.chat_session import ChatUiEvent, HitlAnswer
|
|
9
|
+
from monkeybot_cli.chat_status_bar import UsageStore
|
|
10
|
+
|
|
11
|
+
# Every kind emitted by session controllers (and expected by renderers).
|
|
12
|
+
EVENT_KINDS: frozenset[str] = frozenset(
|
|
13
|
+
{
|
|
14
|
+
"usage_updated",
|
|
15
|
+
"session_ready",
|
|
16
|
+
"connection_state",
|
|
17
|
+
"transcript_backfill",
|
|
18
|
+
"thinking",
|
|
19
|
+
"thinking_clear",
|
|
20
|
+
"turn_started",
|
|
21
|
+
"assistant_start",
|
|
22
|
+
"assistant_delta",
|
|
23
|
+
"tool_started",
|
|
24
|
+
"tool_finished",
|
|
25
|
+
"summarizing",
|
|
26
|
+
"summarized",
|
|
27
|
+
"grounding",
|
|
28
|
+
"turn_error",
|
|
29
|
+
"turn_complete",
|
|
30
|
+
"turn_aborted",
|
|
31
|
+
"hitl_required",
|
|
32
|
+
"hitl_failed",
|
|
33
|
+
"hitl_frontend_unsupported",
|
|
34
|
+
"session_busy",
|
|
35
|
+
"error",
|
|
36
|
+
"stream_failed",
|
|
37
|
+
"stream_ended",
|
|
38
|
+
"thinking_trace",
|
|
39
|
+
"thinking_block_delta",
|
|
40
|
+
"thinking_block_complete",
|
|
41
|
+
"voice_state",
|
|
42
|
+
"audio_chunk",
|
|
43
|
+
"device_error",
|
|
44
|
+
"user_transcript",
|
|
45
|
+
}
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@runtime_checkable
|
|
50
|
+
class SessionController(Protocol):
|
|
51
|
+
"""Minimal surface the TUI / plain renderer need from a session backend."""
|
|
52
|
+
|
|
53
|
+
turn_based: bool
|
|
54
|
+
stream_alive: bool
|
|
55
|
+
stream_error: bool
|
|
56
|
+
reconnecting: bool
|
|
57
|
+
show_usage: bool
|
|
58
|
+
usage: UsageStore
|
|
59
|
+
session_id: str | None
|
|
60
|
+
|
|
61
|
+
async def connect(self, resume_session_id: str | None = None) -> None: ...
|
|
62
|
+
|
|
63
|
+
async def submit(self, message: str) -> None: ...
|
|
64
|
+
|
|
65
|
+
def abort_turn(self) -> None: ...
|
|
66
|
+
|
|
67
|
+
def provide_hitl_answer(self, answer: HitlAnswer) -> None: ...
|
|
68
|
+
|
|
69
|
+
def set_emit(self, emit: Any) -> None: ...
|
|
70
|
+
|
|
71
|
+
async def close(self) -> None: ...
|
|
72
|
+
|
|
73
|
+
async def restart_session(self) -> None: ...
|
|
74
|
+
|
|
75
|
+
async def resume_session(self, session_id: str) -> None: ...
|
|
76
|
+
|
|
77
|
+
async def refresh_usage(self) -> None: ...
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
@runtime_checkable
|
|
81
|
+
class ChatRenderer(Protocol):
|
|
82
|
+
"""Sink for ``ChatUiEvent``s from a session controller."""
|
|
83
|
+
|
|
84
|
+
def on_event(self, event: ChatUiEvent, controller: SessionController) -> None: ...
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
__all__ = ["EVENT_KINDS", "ChatRenderer", "SessionController"]
|