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.
Files changed (72) hide show
  1. monkeybot_cli-0.2.1/.gitignore +64 -0
  2. monkeybot_cli-0.2.1/PKG-INFO +10 -0
  3. monkeybot_cli-0.2.1/pyproject.toml +42 -0
  4. monkeybot_cli-0.2.1/skills/monkeybot/SKILL.md +197 -0
  5. monkeybot_cli-0.2.1/skills/monkeybot/references/config-sections.md +160 -0
  6. monkeybot_cli-0.2.1/src/monkeybot_cli/__init__.py +3 -0
  7. monkeybot_cli-0.2.1/src/monkeybot_cli/chat_renderer.py +87 -0
  8. monkeybot_cli-0.2.1/src/monkeybot_cli/chat_session.py +911 -0
  9. monkeybot_cli-0.2.1/src/monkeybot_cli/chat_status_bar.py +205 -0
  10. monkeybot_cli-0.2.1/src/monkeybot_cli/chat_theme.py +91 -0
  11. monkeybot_cli-0.2.1/src/monkeybot_cli/chat_tool_display.py +334 -0
  12. monkeybot_cli-0.2.1/src/monkeybot_cli/chat_tui.py +1491 -0
  13. monkeybot_cli-0.2.1/src/monkeybot_cli/chat_tui_widgets.py +996 -0
  14. monkeybot_cli-0.2.1/src/monkeybot_cli/commands/__init__.py +1 -0
  15. monkeybot_cli-0.2.1/src/monkeybot_cli/commands/chat.py +817 -0
  16. monkeybot_cli-0.2.1/src/monkeybot_cli/commands/doctor.py +293 -0
  17. monkeybot_cli-0.2.1/src/monkeybot_cli/commands/loop.py +207 -0
  18. monkeybot_cli-0.2.1/src/monkeybot_cli/commands/new.py +207 -0
  19. monkeybot_cli-0.2.1/src/monkeybot_cli/commands/run_cmd.py +41 -0
  20. monkeybot_cli-0.2.1/src/monkeybot_cli/commands/talk.py +102 -0
  21. monkeybot_cli-0.2.1/src/monkeybot_cli/commands/validate.py +385 -0
  22. monkeybot_cli-0.2.1/src/monkeybot_cli/compat.py +7 -0
  23. monkeybot_cli-0.2.1/src/monkeybot_cli/config_resolve.py +55 -0
  24. monkeybot_cli-0.2.1/src/monkeybot_cli/exit_commands.py +13 -0
  25. monkeybot_cli-0.2.1/src/monkeybot_cli/extras_catalog.py +95 -0
  26. monkeybot_cli-0.2.1/src/monkeybot_cli/gateway_health.py +34 -0
  27. monkeybot_cli-0.2.1/src/monkeybot_cli/main.py +38 -0
  28. monkeybot_cli-0.2.1/src/monkeybot_cli/opensandbox_lifecycle.py +314 -0
  29. monkeybot_cli-0.2.1/src/monkeybot_cli/output.py +110 -0
  30. monkeybot_cli-0.2.1/src/monkeybot_cli/providers.py +112 -0
  31. monkeybot_cli-0.2.1/src/monkeybot_cli/realtime/__init__.py +13 -0
  32. monkeybot_cli-0.2.1/src/monkeybot_cli/realtime/audio_io.py +147 -0
  33. monkeybot_cli-0.2.1/src/monkeybot_cli/realtime/client.py +17 -0
  34. monkeybot_cli-0.2.1/src/monkeybot_cli/realtime/gateway_manager.py +142 -0
  35. monkeybot_cli-0.2.1/src/monkeybot_cli/realtime/push_to_talk.py +128 -0
  36. monkeybot_cli-0.2.1/src/monkeybot_cli/realtime/session.py +256 -0
  37. monkeybot_cli-0.2.1/src/monkeybot_cli/realtime/session_controller.py +501 -0
  38. monkeybot_cli-0.2.1/src/monkeybot_cli/realtime/talk_ui.py +243 -0
  39. monkeybot_cli-0.2.1/src/monkeybot_cli/realtime/wire_encode.py +39 -0
  40. monkeybot_cli-0.2.1/src/monkeybot_cli/runtime_python.py +91 -0
  41. monkeybot_cli-0.2.1/src/monkeybot_cli/scaffold.py +287 -0
  42. monkeybot_cli-0.2.1/src/monkeybot_cli/scaffold_defaults/AGENT.md +56 -0
  43. monkeybot_cli-0.2.1/src/monkeybot_cli/scaffold_defaults/__init__.py +1 -0
  44. monkeybot_cli-0.2.1/src/monkeybot_cli/scaffold_defaults/command_allowlist.yaml +57 -0
  45. monkeybot_cli-0.2.1/src/monkeybot_cli/scaffold_defaults/env.example +35 -0
  46. monkeybot_cli-0.2.1/src/monkeybot_cli/scaffold_defaults/mcp.json +49 -0
  47. monkeybot_cli-0.2.1/src/monkeybot_cli/scaffold_defaults/monkeybot.example.yaml +191 -0
  48. monkeybot_cli-0.2.1/src/monkeybot_cli/scaffold_defaults/otel-collector.example.yaml +57 -0
  49. monkeybot_cli-0.2.1/src/monkeybot_cli/scaffold_defaults/permissions.yaml +32 -0
  50. monkeybot_cli-0.2.1/src/monkeybot_cli/scaffold_defaults/setup-workspace.sh +24 -0
  51. monkeybot_cli-0.2.1/src/monkeybot_cli/session_controller.py +7 -0
  52. monkeybot_cli-0.2.1/src/monkeybot_cli/terminal_markdown.py +48 -0
  53. monkeybot_cli-0.2.1/tests/test_chat_e2e.py +86 -0
  54. monkeybot_cli-0.2.1/tests/test_chat_errors.py +218 -0
  55. monkeybot_cli-0.2.1/tests/test_chat_grounding.py +54 -0
  56. monkeybot_cli-0.2.1/tests/test_chat_renderer_parity.py +26 -0
  57. monkeybot_cli-0.2.1/tests/test_chat_session.py +363 -0
  58. monkeybot_cli-0.2.1/tests/test_chat_status_bar.py +149 -0
  59. monkeybot_cli-0.2.1/tests/test_chat_theme.py +71 -0
  60. monkeybot_cli-0.2.1/tests/test_chat_tool_display.py +154 -0
  61. monkeybot_cli-0.2.1/tests/test_chat_tui.py +1243 -0
  62. monkeybot_cli-0.2.1/tests/test_cli.py +132 -0
  63. monkeybot_cli-0.2.1/tests/test_config_resolve.py +21 -0
  64. monkeybot_cli-0.2.1/tests/test_doctor.py +49 -0
  65. monkeybot_cli-0.2.1/tests/test_extras_catalog.py +87 -0
  66. monkeybot_cli-0.2.1/tests/test_opensandbox_lifecycle.py +41 -0
  67. monkeybot_cli-0.2.1/tests/test_realtime_session_controller.py +301 -0
  68. monkeybot_cli-0.2.1/tests/test_run_cmd.py +79 -0
  69. monkeybot_cli-0.2.1/tests/test_runtime_python.py +109 -0
  70. monkeybot_cli-0.2.1/tests/test_scaffold.py +115 -0
  71. monkeybot_cli-0.2.1/tests/test_terminal_markdown.py +47 -0
  72. 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,3 @@
1
+ """monkeybot setup CLI — create, configure, validate, and chat with agents."""
2
+
3
+ __version__ = "0.1.10"
@@ -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"]