From 583ffc474ec15fd410560efd81bba0f26ee430de Mon Sep 17 00:00:00 2001 From: h Date: Wed, 2 Sep 2026 00:25:20 +0200 Subject: [PATCH] docs: README follows the beaver_agent layout, MODELS.md moves to the vault --- MODELS.md | 65 ------------------------------------------------- README.md | 73 +++++++++++++++++++++++++++++++++++++------------------ 2 files changed, 50 insertions(+), 88 deletions(-) delete mode 100644 MODELS.md diff --git a/MODELS.md b/MODELS.md deleted file mode 100644 index eeb1164..0000000 --- a/MODELS.md +++ /dev/null @@ -1,65 +0,0 @@ -# Модели: как вводить новую (чеклист) - -Единственное место с процедурой. Проверено 2026-09-01 боевым тестом на dell. - -## Главный инвариант - -**API отбрасывает новые модели по версии клиента.** `claude` CLI 2.1.248 с -`--model claude-fable-5-1` получает от API -`400: version 2.1.251 or newer is required` — id проходит насквозь, но сервер -режет по минимальной версии Claude Code для этой модели. Поэтому порядок -строго такой: **сначала CLI, потом id в конфигах.** - -CLI живёт в двух местах: - -- **гейтвей (контейнер на dell)** — забандлен в питоновский пакет - `claude-agent-sdk` (`_bundled/claude`), замораживается при сборке образа. - Версия CLI = версия пакета, соответствие в - [CHANGELOG SDK](https://github.com/anthropics/claude-agent-sdk-python/blob/main/CHANGELOG.md) - (например 0.2.146 → CLI 2.1.248, 0.2.150 → 2.1.257). -- **t3code на машинах (mac, dell-хост)** — обычный `claude` пользователя - (`~/.local/share/claude/versions/…`, `/usr/local/bin/claude`), сам - автообновляется; вручную — `claude update`. - -## Чеклист «вышла новая модель X» - -1. **beaver-gateway**: поднять SDK до версии с достаточно новым CLI: - `pyproject.toml` (`claude-agent-sdk>=…`) + `uv lock -P claude-agent-sdk`, - закоммитить, запушить `main`. -2. **beaver-agent/config.py** (строки ~383–399, список агентов): поменять id - моделей у `deep`/`dispatcher`/… Effort там же. -3. **beaver-agent/t3code.toml** (дефолты t3code-mcp per-machine, - `model = "claudeAgent/…"`): поменять id. Внимание: t3code для незнакомого - ему слага теряет опции `effort`/`contextWindow` (см. ниже) — id должен - быть в каталоге t3code, т.е. t3code-приложение должно быть обновлено. -4. Деплой: `make deploy` (push `main:stable`; образ гейтвея собирается из - `beaver-gateway#main` при деплое, поэтому шаг 1 — раньше). -5. **t3code на машинах**: `claude --version` ≥ минимума модели (обычно уже - сам обновился); само приложение t3code (alpha) обновляется nightly и - привозит новую модель в каталог. - -Проверить, какие id вообще существуют: - -```bash -TOK=$(security find-generic-password -s "Claude Code-credentials" -w | jq -r .claudeAiOauth.accessToken) -curl -s https://api.anthropic.com/v1/models -H "Authorization: Bearer $TOK" \ - -H "anthropic-version: 2023-06-01" -H "anthropic-beta: oauth-2025-04-20" | jq -r '.data[].id' -``` - -## Алиасы `fable` / `opus` / `sonnet` - -CLI принимает голые алиасы и резолвит их в **новейшую модель, которую знает -установленный CLI** (проверено: CLI 2.1.248 резолвит `fable` → -`claude-fable-5`, не 5.1). Свойства: - -- никогда не дают 400 «слишком старый клиент» — деградируют до старой модели; -- «всегда новейшая» они дают только при свежем CLI, так что шаг 1 чеклиста - они не отменяют, но убирают шаги 2–3 (id в конфигах менять не надо); -- **в t3code** кастомный слаг (`fable`, `opus`, как и любой id вне каталога) - имеет пустые capabilities → t3 не передаёт `--effort` и суффикс `[1m]` - (`ClaudeAdapter.ts`: `resolveClaudeEffort(caps,…)` → undefined). Модель - работает, но на дефолтном effort и дефолтном окне CLI. - -Рекомендация: в `config.py` и `t3code.toml` можно перейти на алиасы, если -устраивает «новейшее из того, что знает CLI»; explicit id — когда нужен -точный контроль (и тогда обязательно проверять минимум версии CLI). diff --git a/README.md b/README.md index f394272..61b2a33 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ My real beaver-gateway setup (paired with the protocol from beaver.kotikot.com). -Uses Claude Code and Raycast subscriptions for agents, has some MCPs set up. You can use this as-is or modify to match your needs (config.py). +Uses Claude Code and Raycast subscriptions for agents, has some MCPs set up. You can use this as-is or modify to match your needs: `config.py` assembles the gateway from the `beaver_agent/` package. ## Requirements @@ -60,12 +60,14 @@ regular Claude Code; rotate it by running `claude setup-token` again. Claude agents run on the Claude Agent SDK. Prompts are granules under `мета/бобер/промпты/` in the vault - plain markdown, the `` wrappers -and the order live in `config.py`; skills are the folders under +and the order live in `beaver_agent/prompts.py`; skills are the folders under `мета/бобер/скиллы/` (each becomes a plugin, keep `name:` in SKILL.md -latin). The vault must be synced before the gateway can start. The model process runs as `beaver-runner` -with a whitelisted environment; the vault is mounted read-write (it is the -dispatcher's home), and `policy.py` keeps it out of `.obsidian`, `мета` -outside `мета/бобер`, and from deleting anything but its own files. +latin), which window loads which set is `beaver_agent/skills.py`. The vault +must be synced before the gateway can start. The model process runs as +`beaver-runner` with a whitelisted environment; the vault is mounted +read-write (it is the dispatcher's home), and `beaver_agent/policy.py` keeps +it out of `.obsidian`, `мета` outside `мета/бобер`, and from deleting +anything but its own files. ### 4. Mint a token @@ -131,30 +133,55 @@ Needs `KOMODO_URL` / `KOMODO_KEY` / `KOMODO_SECRET` in `.env` (and inject. Jobs, the queue and the subscription window are on the admin **Jobs** page. The same key backs the `komodo` tool the dispatcher and deep chats get -(`mcps/komodo.py`, архитектура §4.4): one MCP tool with an enumerated +(`beaver_agent/hands/komodo.py`): one MCP tool with an enumerated `action` - `status`, `stacks`, `containers`, `logs`, `search_logs`, `updates`, `update`, `deploy`, `restart`, `exec`. `exec` is `docker exec` into any container of the fleet except infrastructure ones (`exec_deny`, periphery by default); prune, destroy and a host terminal do not exist in the enumeration, so they cannot be asked for. The key never reaches the model process. -## Policy (`policy.py`) +## Layout: `config.py` + `beaver_agent/` -`bypassPermissions` everywhere; the boundary is the read-only vault mount -plus `PreToolUse` rules declared per agent (`ClaudeAgent.policy`, архитектура -§3.7): writes only under `мета/бобер/`, new files only under `💬 чаты/`, -`rm`/`mv`/`cp`/`tee`/`sed -i`/redirects into the vault outside those zones -are refused with a reason, and `mcp__firefly__store_*`/`update_*` need the -`firefly` skill opened first in the same session. Every tool call lands in -the admin **Audit** page as `tool_call`. Run `make check` - it includes the -policy and komodo tests. +`config.py` is a page: it imports the pieces and calls `Gateway(...)`. The +pieces live in `beaver_agent/`, one concern per module: -## Editing config.py on the mac +- `vault.py` - paths and the agent's zone, `TZ` +- `prompts.py` - how each role's system prompt is assembled from granules +- `skills.py` - which window loads which skill set +- `policy.py` - `PreToolUse` rules and vault zones (`ZONES`, `VAULT_POLICY`) +- `hands/` - every MCP the setup has and which agent gets which one; the + connectors (komodo, home assistant, vibegram) live here too +- `agents.py` - the roles (dispatcher, deep, distiller, curator, triage, + raycast) and the list of instances with models and effort +- `frontends.py` - the windows: Telegram for master and branches, vault + files for deep chats, `/api`, `/admin`, `/anthropic`, `/mcp` +- `texts.py` - everything the gateway says to the model or to the user, + in Russian (the gateway's own defaults are English) +- `memory/` - the recall block under a message, the reply log, handouts + and seeds, the vault watcher, the curator briefing +- `jobs/` - crons and webhooks, one file per job + +## Policy (`beaver_agent/policy.py`) + +`bypassPermissions` everywhere; the boundary is `PreToolUse` rules declared +per agent (`ClaudeAgent.policy`): the vault is the dispatcher's home, so it +may create, edit and move anywhere except `.obsidian` and `мета` outside +`мета/бобер`, and may delete only its own files; the distiller and curator +stay in `мета/бобер`; `rm`/`mv`/`cp`/`tee`/`sed -i`/redirects into the vault +outside those zones are refused with a reason; `mcp__firefly__store_*` and +`update_*` need the `firefly` skill opened first in the same session, and the +master cannot open the `vault/` skills at all (a branch can). Every tool call +lands in the admin **Audit** page as `tool_call`. Run `make check`. + +## Editing the setup on the mac `make sync` installs `../beaver-gateway` editable (extra `local`), so -imports in `config.py` resolve against the checkout you are working on; -`uv sync --extra prod` pulls the gateway from git instead. Neither is used -by the image - the container builds the gateway itself. +imports resolve against the checkout you are working on; `uv sync --extra +prod` pulls the gateway from git instead. Neither is used by the image - the +container builds the gateway itself. To assemble the config against your +local vault: `BEAVER_VAULT=~/path/to/vault uv run python -c +'from beaver_gateway import config; from pathlib import Path; +config.load(Path("config.py"))'` with a `.env` next to it. ## Useful commands @@ -175,13 +202,13 @@ docker compose logs -f obsidian-headless # pull the latest beaver-gateway (when GATEWAY_REF=main) docker compose build gateway && docker compose up -d gateway -# reload config.py without a full rebuild +# reload config.py / beaver_agent without a full rebuild docker compose restart gateway ``` ## Gotchas -- **claude in the container doesn't see the vault** - `cwd=VAULT` in `config.py` resolves to `/vault` *inside* the container, not on the host. Don't change it. +- **claude in the container doesn't see the vault** - `VAULT` in `beaver_agent/vault.py` is `/vault` *inside* the container, not on the host. Don't change it; `BEAVER_VAULT` is for assembling the config on the mac only. - **a claude turn fails immediately** - check `docker logs beaver-gateway` for the `claude[]:` stderr lines. Usually auth: redo step 3. -- **gateway restarts in a loop right after first `up`** - `config.py` reads prompt granules from `/vault/мета/бобер/промпты`; until Obsidian Sync has pulled the vault they are missing. Finish step 2, it settles. +- **gateway restarts in a loop right after first `up`** - `beaver_agent/prompts.py` reads prompt granules from `/vault/мета/бобер/промпты`; until Obsidian Sync has pulled the vault they are missing. Finish step 2, it settles. - **the model cannot write into `мета/бобер`** - the entrypoint grants `beaver-runner` an ACL on the two rw sub-mounts once at start; files that Sync creates later inherit it through the default ACL. If `setfacl` is unsupported on the volume it falls back to `chown`, and then files Sync writes afterwards as root stay read-only for the model until the next restart.