9.1 KiB
date, status, parent, source_buffer, title, type, ingested_at, ingested_by, source_project
| date | status | parent | source_buffer | title | type | ingested_at | ingested_by | source_project |
|---|---|---|---|---|---|---|---|---|
| 2026-05-05 | design-approved | concepts/interns-design.md | .meeting-room/.brainstorm/repo-read.md | interns-repo-read-design | concept | 2026-05-05T20:04:56.490Z | OpeItcLoc03@DESKTOP-NSEF0UK | .meeting-room |
Interns — repo_read intern (v0.1.0)
Расширение каталога interns-mcp MVP: добавляет интерн repo_read, специализированный на «прочитай эту директорию/репо и ответь на вопрос». Реализуется поверх существующей трёхслойной архитектуры (config / MCP server / skills) без изменений в архитектуре, только новый tool + routing-добавка в using-interns.
Context
Из исходного research line: «Repomix лучше код». Интерн оборачивает repomix CLI + cheap LLM (deepseek-v4-flash) в один MCP tool, чтобы Claude делегировал понимание целой кодовой базы дешёвой модели вместо того чтобы прочитать репо своим Read'ом и сжечь Anthropic-квоту.
Это первый tool-wrapping интерн (subprocess + LLM-call в одной операции) — паттерн под будущие PDF (Marker) и JS-web (Firecrawl) интерны.
Decisions
| # | Решение | Аргумент |
|---|---|---|
| 1 | Шейп — композитный repo_read(paths, question) → answer |
Симметрия с bulk_text_read(paths, question) → answer. Pure pack не экономит квоту — Claude всё равно читает результат. |
| 2 | Tool name repo_read (не repo_qa, не code_read) |
Симметрия с bulk_text_read (тоже семантически Q&A, но _read). Не code_read — repomix именно про директорию целиком, оставляем code_read под будущий grep+cheap-LLM интерн. |
| 3 | Overflow при превышении контекста — hard fail с подсказкой | YAGNI. Без авто-compress / map-reduce / smart-selection. Параметр compress: bool = False явный, user-controlled. |
| 4 | Runtime — npx repomix@latest |
Zero-config: setup-interns только проверяет node в PATH. Всегда свежая версия. Первый запуск 5-10s (npm cache populate), потом instant. Pin'ить версию — позже, если будут регрессии. |
| 5 | Safety — два слоя: input matcher + transitive --ignore |
Always-ask matcher проверяет input paths (как у остальных interns). Дополнительно: safety.always_ask_globs() транслируется в флаги --ignore для repomix subprocess'а. Repomix walks recursively, нельзя надеяться что .gitignore юзера полный. Защита on-server. |
| 6 | Без include/ignore параметров от Claude |
YAGNI: исключение через узкие paths + .gitignore + always-ask. Если упрёмся — добавим в v0.2.0. |
Сигнатура
repo_read(
paths: list[str], # директории и/или файлы — targets для repomix
question: str, # вопрос
compress: bool = False, # repomix --compress (lossy: убирает комменты/whitespace)
) -> InternResponse
InternResponse = {text: str, usage: {tokens_in, tokens_out, cost_usd, packed_files: int, packed_tokens: int}}
При overflow: вместо InternResponse возвращается BudgetExceededError{tokens, limit, top_files: [...], hint} — Claude получает structured ответ и переформулирует (узкие paths или compress=True).
Реализация (interns_mcp/interns/repo_read.py)
class RepoRead(Intern):
id = "repo_read"
def run(self, paths, question, compress=False):
safety.check_paths(paths) # raise if always-ask
ignore_globs = safety.always_ask_globs() # transitive guard
with tempfile.NamedTemporaryFile(suffix=".xml", delete=False) as packed:
args = ["npx", "repomix@latest", *paths,
"--output", packed.name, "--style", "xml"]
if compress:
args.append("--compress")
for glob in ignore_globs:
args += ["--ignore", glob]
subprocess.run(args, check=True, timeout=120)
packed_text = Path(packed.name).read_text()
tokens = count_tokens(packed_text, model=self.config.model)
if tokens > self.config.context_budget:
return BudgetExceededError(
tokens=tokens,
limit=self.config.context_budget,
top_files=top_files_by_size(packed_text, n=5),
hint="use compress=True or narrow paths",
)
return self.client.complete(
system=self.config.system_prompt,
user=f"# Packed repo\n\n{packed_text}\n\n# Question\n\n{question}",
max_tokens=self.config.max_tokens,
)
Layer 1 — config (.common/config/interns/config.yaml)
interns:
repo_read:
description: "Pack a repo/directory via repomix and answer a focused question via cheap LLM."
endpoint: ollama_cloud
model: deepseek-v4-flash
max_tokens: 4096
temperature: 0.2
context_budget: 120000 # input-token cap before BudgetExceededError
system_prompt: |
You are reading a packed code repository. Answer ONLY what the user asks,
citing file:line refs from the packed structure. Do not hallucinate file
contents. If the answer requires files outside the pack, say so explicitly.
Layer 3 — skill update
using-interns/SKILL.md, секция Routing-подсказки — добавить:
- Вопрос про целое репо/директорию (архитектура, «где используется X», «что делает модуль Y», обзор кодбазы) и нужно прочесть >5 файлов кода →
repo_read.bulk_text_readvsrepo_read: первый — пути известны и явные; второй — нужна целая директория без явного выбора файлов.- Не делегировать
repo_readдля редактирования или отладки конкретного файла — читать файл сам.
Setup-side change
setup-interns/SKILL.md — добавить runtime check:
shutil.which("node")— если нет, instruct: install Node.js 20+, retry.- (Опц.) Pre-warm:
npx --yes repomix@latest --versionчтобы первый реальный вызов был быстрым.
Bump setup-interns 0.1.0 → 0.2.0 (MINOR — capability added).
Cross-platform
| Слой | Windows | Linux | macOS |
|---|---|---|---|
npx repomix@latest |
OK через node from PATH | OK | OK |
tempfile.NamedTemporaryFile |
OK | OK | OK |
Always-ask globs (PurePath.match) |
OK POSIX-style работают везде | OK | OK |
subprocess.run timeout |
OK | OK | OK |
Action items
.common/lib/interns-mcp: реализоватьinterns_mcp/interns/repo_read.py, зарегистрировать вserver.py. Тесты: happy-path, safety-block (paths=[".env"]), budget-exceeded. Patch-bumpinterns-mcp..common/config/interns/config.yaml: добавить записьrepo_read.claude-skills/using-interns: добавить routing-подсказки в SKILL.md. Bump MINOR.claude-skills/setup-interns: добавить Node-check + (опц.) pre-warm. Bump MINOR.
Open questions
- Реальный context window
deepseek-v4-flashна Ollama Cloud — проверить эмпирически после первого боевого вызова, скорректироватьcontext_budget. - Когда появится 2-3-й tool-wrapping интерн (PDF/web) — выделить общий helper
interns_mcp/tool_wrapper.pyдля пары (subprocess + safety-translation + budget-check). Сейчас inline вrepo_read.py. - Cost-cap >$0.10 (упомянут в parent spec как always-ask trigger) — не реализован. Если появится несколько tool-wrapping interns с разной стоимостью — добавим
safety.check_cost(estimated)рядом сcheck_paths.
References
concepts/interns-design.md— parent design (архитектура interns-mcp, "How to add an intern" recipe, action items).- Repomix — JS CLI, упаковывает директорию в один LLM-friendly файл.
using-interns/SKILL.md— целевой файл для routing-добавки.setup-interns/SKILL.md— целевой файл для Node-check.