fix(mem0-agent): read the key from the plugin config, add cross-surface verification
The desktop app never sources a shell rc, so a key that exists only as MEM0_API_KEY in .zshrc is invisible there and the plugin silently no-ops. Claude Code injects the userConfig value as CLAUDE_PLUGIN_OPTION_API_KEY (v1 read it, v2 did not). - resolve_api_key() -> (key, source): env, plugin config, legacy plugin config, keychain - health now reports WHERE the key came from, which is how you tell the two apart - every logged event records the editor, and a new 'sessions' command lists which surfaces have actually built packs and written memories Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
f4949c55af
commit
10b8fc4bed
@@ -93,17 +93,35 @@ class Settings:
|
||||
|
||||
|
||||
# --------------------------- credentials ---------------------------
|
||||
def get_api_key() -> str | None:
|
||||
"""Env first (explicit beats implicit), then the OS keychain. Never rc files."""
|
||||
key = os.environ.get("MEM0_API_KEY")
|
||||
if key:
|
||||
return key.strip()
|
||||
# Order matters. The desktop app does not source your shell rc, so a key that only exists
|
||||
# as MEM0_API_KEY in .zshrc is invisible there -- the plugin option is what makes the two
|
||||
# surfaces behave the same. Shell rc files are never read.
|
||||
KEY_SOURCES: tuple[tuple[str, str], ...] = (
|
||||
("env", "MEM0_API_KEY"),
|
||||
("plugin config", "CLAUDE_PLUGIN_OPTION_API_KEY"),
|
||||
("plugin config (legacy)", "CLAUDE_PLUGIN_OPTION_MEM0_API_KEY"),
|
||||
)
|
||||
|
||||
|
||||
def resolve_api_key() -> tuple[str | None, str]:
|
||||
"""Returns (key, where it came from). The source is what diagnostics report."""
|
||||
for label, var in KEY_SOURCES:
|
||||
val = (os.environ.get(var) or "").strip()
|
||||
if val:
|
||||
return val, label
|
||||
try:
|
||||
import keyring # optional dependency
|
||||
|
||||
return keyring.get_password(KEYRING_SERVICE, "api_key")
|
||||
val = keyring.get_password(KEYRING_SERVICE, "api_key")
|
||||
if val:
|
||||
return val.strip(), "keychain"
|
||||
except Exception:
|
||||
return None
|
||||
pass
|
||||
return None, "not found"
|
||||
|
||||
|
||||
def get_api_key() -> str | None:
|
||||
return resolve_api_key()[0]
|
||||
|
||||
|
||||
def store_api_key(key: str) -> bool:
|
||||
|
||||
Reference in New Issue
Block a user