[2026-06-15] taiga-vault: personal/projects/personal-os/claude-proxy-node-internals.md

This commit is contained in:
Taiga
2026-06-15 11:20:19 +00:00
parent 9c4355f553
commit b12849d0ce
@@ -84,21 +84,41 @@ CMD ["claude-proxy", "3456"]
В режиме `print` проблема та же — proxy ждёт завершения `claude --print` и возвращает результат целиком, не транслируя промежуточный вывод.
### 3. claude spawn'ит свой bash без контекста Hermes
### 3. Claude CLI сам исполняет инструменты вместо Hermes
**Механизм:** proxy запускает `claude` через `child_process.spawn('claude', args, {env: process.env})`. Ниже по цепочке:
**Проблема:** Claude Code CLI **сам выполняет Bash/Read/Write/Edit инструменты внутри своей сессии**, а не возвращает tool_use блоки Hermes'у для исполнения.
Текущий flow:
```
launchd → claude-proxy-start.sh → claude-proxy (node) → claude CLI (subprocess)
└── bash -c "..."
Hermes → claude-proxy (Node.js) → claude CLI
└── сам делает Bash, Read, Write
└── bash -c "..."
```
Claude Code CLI для выполнения инструментов (Bash, Write, Edit) внутри себя спавнит `bash -c "..."`. Этот bash:
- наследует env от `claude` процесса
- НЕ имеет `HERMES_HOME`, кастомного `PATH`, `SHELL=/bin/zsh` с профилем Hermes
- использует системный `/bin/bash` или `/bin/sh`
Hermes видит только финальный текст ответа. Он теряет контроль над:
- какие файлы читаются
- какие команды выполняются
- кто их логирует и аудитит
- allower/denier политики Hermes игнорируются
В контейнере (alpine) bash вообще может отсутствовать — claude CLI использует `/bin/sh`.
Правильный flow (caller-dispatched tools):
```
Hermes → claude-proxy (Node.js) → claude CLI (только генерация)
↓ текст ответа с tool_use блоками
Hermes ── парсит tool_use ── выполняет через свои инструменты ── результат → обратно в claude CLI
```
Для этого proxy должен:
1. Выключить инструменты в `claude` CLI — передать `disallowed_tools = ["Bash", "Read", "Write", "Edit", "Glob", "Grep"]`
2. Остановиться после первого assistant-сообщения
3. Отдать tool_use блоки Hermes'у как OpenAI `tool_calls`
4. Принять результат выполнения от Hermes и передать обратно в `claude` для продолжения (multi-turn)
**Текущий `openclaw-claude-proxy` не поддерживает этот flow корректно:** stream-json протокол для multi-turn interaction сломан начиная с claude CLI 2.1.141. В режиме `print` multi-turn вообще невозможен.
**Python wrapper (`claude-code-openai-wrapper`) этот flow поддерживает**у него есть `stop_after_first_assistant` и `disallowed_tools`. Именно поэтому он активен, а Node.js — fallback.
## Предложенные подходы
@@ -113,9 +133,3 @@ Claude Code CLI для выполнения инструментов (Bash, Writ
1. **Проброс stderr:** pipe'ить stderr `claude` в stderr proxy — видно в `docker logs` или launchd логах.
2. **Режим `print`:** переключить `CLAUDE_PROXY_RUNTIME=print` — теряется производительность stream-json, но логов больше.
3. **Node.js `stream-json` мониторинг:** логировать каждую N-ную JSON строку из stdout claude для отладки.
### Против изоляции shell
1. **В Docker:** установить bash в контейнер (`apk add bash`), установить `SHELL=/bin/bash` в env.
2. **Передача `HERMES_HOME`:** смонтировать `~/.hermes` в контейнер и передать `HERMES_HOME` в env claude CLI.
3. **wrapper-скрипт для claude:** заменить бинарник `claude` в контейнере на shell wrapper, который ставит профиль Hermes перед вызовом реального `claude`.