What happened?
resolveConfigValue("public") returns "C:\Users\Public" on Windows instead of the literal string "public".
On Windows, process.env is case-insensitive. The function does process.env["public"] which matches the PUBLIC env var (C:\Users\Public). This corrupts any literal API key that happens to match a Windows env var name.
This breaks opencode free models -- the Zen proxy expects the literal "public" sentinel but receives "C:\Users\Public" and returns 401.
Steps to reproduce
- Don't set
OPENCODE_API_KEY env var
- Put
{"opencode": {"type": "api_key", "key": "public"}} in ~/.pi/agent/auth.json
- Run
pi --model opencode/mimo-v2.5-free -p "hi"
- Get
401 Invalid API key
The --api-key public flag works because it bypasses resolveConfigValue via runtime overrides.
Expected behavior
Literal API keys in auth.json should be returned as-is, not resolved as env var names. "public" should return "public", not "C:\Users\Public".
Root cause
resolveConfigValue treats all non-!-prefixed strings as potential env var names:
const envValue = process.env[config]; // case-insensitive on Windows!
return envValue || config;
On Windows, process.env["public"] returns "C:\Users\Public" (the PUBLIC env var), so the literal string is never returned.
What happened?
resolveConfigValue("public")returns"C:\Users\Public"on Windows instead of the literal string"public".On Windows,
process.envis case-insensitive. The function doesprocess.env["public"]which matches thePUBLICenv var (C:\Users\Public). This corrupts any literal API key that happens to match a Windows env var name.This breaks opencode free models -- the Zen proxy expects the literal
"public"sentinel but receives"C:\Users\Public"and returns 401.Steps to reproduce
OPENCODE_API_KEYenv var{"opencode": {"type": "api_key", "key": "public"}}in~/.pi/agent/auth.jsonpi --model opencode/mimo-v2.5-free -p "hi"401 Invalid API keyThe
--api-key publicflag works because it bypassesresolveConfigValuevia runtime overrides.Expected behavior
Literal API keys in
auth.jsonshould be returned as-is, not resolved as env var names."public"should return"public", not"C:\Users\Public".Root cause
resolveConfigValuetreats all non-!-prefixed strings as potential env var names:On Windows,
process.env["public"]returns"C:\Users\Public"(thePUBLICenv var), so the literal string is never returned.