fix: respect openai_api_key from ~/.gbrain/config.json in embed/search paths#482
fix: respect openai_api_key from ~/.gbrain/config.json in embed/search paths#482jacopone wants to merge 1 commit into
Conversation
…h paths `gbrain config set openai_api_key X` writes to engine.setConfig (PGLite/PG) but embedding.ts:24 instantiates `new OpenAI()` with no args, which only reads process.env.OPENAI_API_KEY. Same gap in operations.ts:278 (auto-embed gate) and search/hybrid.ts:81 (vector search gate). Users who set the key via `gbrain config set` or by editing ~/.gbrain/config.json directly hit "OPENAI_API_KEY missing" errors despite the key being persisted. Real UX issue on systems that deliberately keep API keys out of interactive shell env (NixOS+home-manager, per-process .env loading via python-dotenv, anywhere least-privilege shell hygiene is the convention). Adds `getOpenAIKey()` helper to core/config.ts: env first, then reads openai_api_key from the config file directly. Independent of engine config — works even when no DB is configured. Three call sites updated to use it. Same env > file precedence pattern that loadConfig() already uses for database_url. PGLite-stored copy from `config set` becomes dead code; a follow-up could route bootstrap-key writes to the file instead. Tests: bun test → 2164 pass, 0 fail, 250 skip (unrelated env-conditional). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Thanks for this contribution — and apologies for the slow triage. We did a full pass over the entire PR backlog. gbrain has moved fast, and the maintainer's larger "cathedral" rewrites have superseded a big share of community PRs: the AI gateway + recipes + user_provided_models system replaced almost all individual provider PRs; #1805 fixed the whole Postgres module-singleton class; #1542 unified the type taxonomy; #1657 the retrieval path; #1802 the doctor; and so on. We're closing this one in that cleanup — either the fix already landed on master, it duplicates another PR or merged change, or it's outside the current merge bar. Where a closed PR carried a genuinely valuable idea, we've recorded it in docs/designs/COMMUNITY_IDEAS.md so nothing good is lost (a few may graduate into TODOs). Please don't read the close as a judgment of the work — thank you for contributing. If you believe the underlying issue is still live on the latest master, reopen with a quick note and we'll take another look. 🙏 |
Summary
gbrain config set openai_api_key Xwrites the key to the engine's config table viaengine.setConfig, butembedding.ts:24instantiatesnew OpenAI()with no args — which only readsprocess.env.OPENAI_API_KEY. Same gap exists inoperations.ts:278(auto-embed-on-write gate) andsearch/hybrid.ts:81(vector search gate).Net effect: users who run
gbrain config set openai_api_key sk-...(or write the key to~/.gbrain/config.jsondirectly) hit"OPENAI_API_KEY environment variable is missing or empty"errors despite the key being persisted in two places gbrain reasonably reads from. The CLI says success, the embed says missing.This is a real UX issue on systems that deliberately don't shell-export API keys — NixOS + home-manager, per-process
.envloading viapython-dotenv, anywhere least-privilege shell hygiene is the convention.Repro
Fix
Adds
getOpenAIKey()helper tocore/config.tsthat returns env-first, then falls back to readingopenai_api_keyfrom~/.gbrain/config.jsondirectly (independent of engine config — works even when no DB is configured). Three call sites updated:core/embedding.tsnew OpenAI({ apiKey: getOpenAIKey() })core/operations.ts:278core/search/hybrid.ts:81Same env > file precedence that
loadConfig()already uses fordatabase_url.Verification
Tests
bun test → 2164 pass / 0 fail / 250 skip (skips are pre-existing env-conditional tests, unrelated). Patch is +27 / -4 lines.
Out of scope (possible follow-ups)
gbrain config set openai_api_key Xis now dead code. A future PR could route bootstrap-key writes (engine, database_url,*_api_key,*_token) to the file instead of the engine table.gbrain config unset <key>command would help users clean up the dead PGLite row left behind by old setups.Test plan
unset OPENAI_API_KEYand key in~/.gbrain/config.jsononlygbrain putauto-embeds via the patched gategbrain queryreturns semantic (not keyword-only) resultsgbrain embed --staleruns without env🤖 Generated with Claude Code