mirror of
https://github.com/dtzp555-max/ocp.git
synced 2026-07-22 05:25:08 +00:00
Motivation (the OpenClaw case). OCP's `-p` path prepends OCP_SYSTEM_PROMPT_WRAPPER, which tells the model it has NO local filesystem/shell/env access. Correct for a shared/multi-tenant gateway. But an OpenClaw agent pointed at its own local OCP runs the model SERVER-SIDE via `claude -p`, which already passes --allowedTools and has the CLI's built-in tools — and on a loopback instance the OCP host IS the operator's machine, so those are local tools. The wrapper gags them: the agent replies "I don't have filesystem access" for tools it actually holds. OCP_LOCAL_TOOLS=1 swaps in a positive wrapper for that case. (It does NOT enable client-side tool_calls for OpenClaw/Cline — that remains unsupported by design; OCP is a text-prompt bridge.) Safety: changes ONLY the system-prompt text, never the tool surface. Tools are governed solely by --allowedTools/--disallowedTools; AUTH_MODE=multi still --disallowedTools the whole FS/web/agent surface regardless of the wrapper. Fail-closed boot gate mirroring OCP_TUI_FULL_TOOLS (ADR 0007): refuse to start when =1 is combined with CLAUDE_AUTH_MODE=multi, a non-loopback bind, or PROXY_ANONYMOUS_KEY. Scope/alignment: no new endpoint/header/field/wire operation. The wrapper text is OCP-owned prompt composition (same class as OCP_SYSTEM_PROMPT_WRAPPER and CLAUDE_SYSTEM_PROMPT), passed via the already-cited `claude --system-prompt` flag (unchanged). ALIGNMENT.md Rule 2: nothing invented on the wire. - lib/prompt.mjs: pure selectPromptWrapper() + localToolsSafetyError() (unit-tested). - server.mjs: single hoisted flag LOCAL_TOOLS_ACTIVE = OCP_LOCAL_TOOLS && !TUI_MODE (the wrapper is only applied on the -p path; TUI composes its own prompt, so the flag is inert under TUI — announced with a warning rather than a misleading "ON"). Wrapper selection, boot gate, and the CONFIG_EPOCH fold all key off it, so toggling the flag + restarting invalidates the standard response cache (#177). Default path byte-for-byte unchanged. - README env-var row + tool-model note; CHANGELOG Unreleased entry. Tests (+14): unit-test both ternary branches and every gate condition; plus an INTEGRATION harness that boots real server.mjs with a fake `claude` capturing the --system-prompt — asserting the POSITIVE wrapper reaches a request under =1 and the EXACT negative wrapper when unset, the boot gate refuses all three unsafe configs, the safe config boots, TUI announces inert, and toggling the flag re-spawns (cache invalidated). Mutation-verified: reverting the wiring / neutering the gate / reverting the epoch fold each turns a test RED. 443 passed, 0 failed. Noticed but scoped out (Iron Rule 11): the structured-output cache path (handleChatCompletions, the response_format branch) does not fold CONFIG_EPOCH at all — a pre-existing gap from #177/#153, independent of this flag. Happy to fix in a follow-up. Co-authored-by: vvlasy-openclaw <vvlasy@gmail.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>