fix: add Authorization Bearer header to remote generate requests#17
fix: add Authorization Bearer header to remote generate requests#17Oliverbot26 wants to merge 1 commit into
Conversation
generateRemote() never sent an Authorization header, causing 401 errors on API endpoints that require auth. This patch: - Adds remoteLlmApiKey config field + env var (CLAWMEM_LLM_API_KEY) - Sends Authorization: Bearer header when key is present - Injects CLAWMEM_LLM_API_KEY from plugin config (gpuLlmApiKey) - Follows existing pattern used for embed (remoteEmbedApiKey)
konradre
left a comment
There was a problem hiding this comment.
The core of this is right, and the missing Authorization header on remote generate is a real gap. The llm.ts side mirrors the embed path well: remoteLlmApiKey on the config, a Bearer header only when the key is set, and the CLAWMEM_LLM_API_KEY env read in getDefaultLlamaCpp. I checked the error paths too, and the key doesn't leak. The HTTP error branch logs only status and statusText, and the returned model comes from the response body, not the key. So the generate-side change is good as is.
The OpenClaw half is what I'd like reworked before this lands.
The plugin reads pluginCfg.gpuLlmApiKey, but that field isn't declared in the manifest, and the manifest is a closed schema. openclaw.plugin.json sets "additionalProperties": false, so a strict config validator can drop gpuLlmApiKey before register() ever sees it. As written, that injection may silently do nothing.
It's also redundant with a path that already works. OpenClaw spawns the clawmem subprocess with the parent environment spread in (see shell.ts and the two sibling spawn sites), so a CLAWMEM_LLM_API_KEY set on the gateway process already reaches generate once your llm.ts change is in. The plugin-config route adds a second way in that needs the manifest fixed to actually fire.
There's a secrets angle on top of that. The embed key has always been env-only, and putting an API key into plugin config as a plain string parks it wherever that config gets persisted. I'd rather not introduce a plaintext-secret config field unless OpenClaw gives us a redacted type for it.
Two ways forward, either works for me:
- Drop the
gpuLlmApiKeyplugin-config block and rely on the ambientCLAWMEM_LLM_API_KEYenv, with a README line pointing people at it. Smallest change, and it works today. - Keep the plugin-config route, but declare
gpuLlmApiKeyin the manifest, and only if we're comfortable storing it as a plain config string (or it gets proper secret handling).
Either way, could you add a couple of tests? One for remoteLlmApiKey passed directly on the config producing the Bearer header, and one for the CLAWMEM_LLM_API_KEY env path through getDefaultLlamaCpp. That pins down the behavior we actually want.
Happy to merge once the OpenClaw side is sorted.
Problem
generateRemote()never sends Authorization header — 401 on authenticated endpoints.Changes
src/llm.ts:remoteLlmApiKeyfield + Bearer header in generateRemote + env in getDefaultLlamaCppsrc/openclaw/index.ts: inject CLAWMEM_LLM_API_KEY from gpuLlmApiKeyFollows embed auth pattern (remoteEmbedApiKey / CLAWMEM_EMBED_API_KEY). Verified HTTP 200 with z.ai.