Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 52 additions & 2 deletions core/framework/tools/queen_lifecycle_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -1312,20 +1312,40 @@ async def list_credentials(credential_id: str = "") -> str:
Returns credential IDs, aliases, status, and identity metadata.
Never returns secret values. Optionally filter by credential_id.
"""
# Load shell config vars into os.environ — same first step as check-agent.
# Ensures keys set in ~/.zshrc/~/.bashrc are visible to is_available() checks.
try:
from framework.credentials.validation import ensure_credential_key_env

ensure_credential_key_env()
except Exception:
pass

try:
# Primary: CredentialStoreAdapter sees both Aden OAuth and local accounts
from aden_tools.credentials import CredentialStoreAdapter

store = CredentialStoreAdapter.default()
all_accounts = store.get_all_account_info()

# Filter by credential_id / provider if requested
# Filter by credential_id / provider if requested.
# A spec name like "gmail_oauth" maps to provider "google" via
# credential_id field — resolve that alias before filtering.
if credential_id:
try:
from aden_tools.credentials import CREDENTIAL_SPECS

spec = CREDENTIAL_SPECS.get(credential_id)
resolved_provider = (
(spec.credential_id or credential_id) if spec else credential_id
)
except Exception:
resolved_provider = credential_id
all_accounts = [
a
for a in all_accounts
if a.get("credential_id", "").startswith(credential_id)
or a.get("provider", "") == credential_id
or a.get("provider", "") in (credential_id, resolved_provider)
]

return json.dumps(
Expand All @@ -1342,13 +1362,43 @@ async def list_credentials(credential_id: str = "") -> str:

# Fallback: local encrypted store only
try:
from framework.credentials.local.models import LocalAccountInfo
from framework.credentials.local.registry import LocalCredentialRegistry
from framework.credentials.storage import EncryptedFileStorage

registry = LocalCredentialRegistry.default()
accounts = registry.list_accounts(
credential_id=credential_id or None,
)

# Also include flat-file credentials saved by the GUI (no "/" separator).
# LocalCredentialRegistry.list_accounts() skips these — read them directly.
seen_cred_ids = {info.credential_id for info in accounts}
storage = EncryptedFileStorage()
for storage_id in storage.list_all():
if "/" in storage_id:
continue # already handled by LocalCredentialRegistry above
if credential_id and storage_id != credential_id:
continue
if storage_id in seen_cred_ids:
continue
try:
cred_obj = storage.load(storage_id)
except Exception:
continue
if cred_obj is None:
continue
accounts.append(
LocalAccountInfo(
credential_id=storage_id,
alias="default",
status="unknown",
identity=cred_obj.identity,
last_validated=cred_obj.last_refreshed,
created_at=cred_obj.created_at,
)
)

credentials = []
for info in accounts:
entry: dict[str, Any] = {
Expand Down
Loading