feat(harness): show credentials for all in-use engines across agent configs#1056
feat(harness): show credentials for all in-use engines across agent configs#1056
Conversation
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
nhopeatall
left a comment
There was a problem hiding this comment.
Summary
Clean, well-structured feature with proper auth checks, good test coverage, and all CI passing. One should-fix issue around duplicated credential mappings that will drift out of sync.
Architecture & Design
-
[SHOULD_FIX] Duplicated engine-to-credential mapping:
ENGINE_CREDENTIAL_KEYSinproject-agent-configs.tsx(line 487) duplicates the credential-to-engine mapping already defined byENGINE_SECRETSinproject-harness-form.tsx, but with different data. Specifically,ENGINE_CREDENTIAL_KEYSmapsllmistto['OPENROUTER_API_KEY'], butENGINE_SECRETSonly mapsOPENROUTER_API_KEYto engines['opencode']— it does not includellmist. This creates a concrete UX inconsistency introduced by this PR:- When an agent has a
llmistengine override, the new agent row badge shows "Missing credentials" (becauseENGINE_CREDENTIAL_KEYSsaysllmistneedsOPENROUTER_API_KEY) - But navigating to the Harness tab will NOT show the
OPENROUTER_API_KEYfield forllmist(becauseENGINE_SECRETSdoes not includellmistin theOPENROUTER_API_KEYengines list) - The user sees a warning they cannot act on from the same UI
Fix options:
- Extract a shared
ENGINE_CREDENTIAL_MAPconstant that both files import - Derive
ENGINE_CREDENTIAL_KEYSfromENGINE_SECRETSprogrammatically - At minimum, add
llmistto theOPENROUTER_API_KEYentry'senginesarray inENGINE_SECRETS
- When an agent has a
Code Issues
Should Fix
- web/src/components/projects/project-agent-configs.tsx:487-492 — The duplicated mapping will become a maintenance burden. Every time an engine or credential is added/changed in
ENGINE_SECRETS, this map needs manual updating in a separate file. Thellmistdiscrepancy is already causing a real issue as described above.
Everything else looks good — the backend query is clean and correct (using selectDistinct with isNotNull filter), auth checks follow existing patterns, tests are thorough, CLI gracefully degrades with .catch(() => []), and the frontend properly merges project-level + agent-level engines for the credentials display.
🕵️ claude-code · claude-opus-4-6 · run details
…te duplicate credential mapping Moves the engine-to-credential mapping out of project-harness-form.tsx and into a new engine-secrets.ts shared module. project-agent-configs.tsx now derives its engineCredentialKeys map directly from ENGINE_SECRETS at module load time, so both files always agree on which credentials belong to which engine. Also adds llmist to the OPENROUTER_API_KEY engines list so the Harness tab credential field appears for llmist engine overrides — fixing the concrete UX inconsistency where agent rows showed "Missing credentials" for llmist but the Harness tab never showed an OPENROUTER_API_KEY field. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
nhopeatall
left a comment
There was a problem hiding this comment.
Summary
LGTM — Clean, well-structured feature addition with proper layering across backend, frontend, and CLI.
What I verified:
- Repository layer:
listDistinctEnginesByProjectcorrectly usesselectDistinctwithisNotNullfilter and theas stringcast is safe given theisNotNullWHERE clause. - tRPC endpoint: Properly guarded by
protectedProcedurewithverifyProjectOrgAccess, re-exported cleanly throughsettingsRepository.tswildcard export. - Shared module extraction:
ENGINE_SECRETS+engineCredentialKeyscomputed once at module load — bothproject-harness-form.tsxandproject-agent-configs.tsxshare a single source of truth. Minor intentional behavioral change:OPENROUTER_API_KEYnow also maps tollmistengine (correct, since llmist supports OpenRouter). - Harness form credentials:
allEnginesInUsemerge logic deduplicates viaSet, condition changed from!effectiveEngineIdtoallEnginesInUse.length === 0which correctly handles the case where no project engine is selected but agents have overrides. - Missing credentials badge:
engineHasCredentialsuses.some()semantics — correct since credential keys for an engine are alternatives (API key auth vs subscription auth), not all required simultaneously. Only shown on agent rows with explicit engine overrides to avoid false positives. - CLI:
enginesInUsequery is gracefully wrapped with.catch(() => [])for backward compatibility with older backends.nullvalue correctly renders as '—' via theprintDetailformatter. - Tests: Comprehensive coverage for repository, tRPC endpoint (happy path, empty, auth, access), and CLI mock wiring.
- CI: All 7 checks passing.
🕵️ claude-code · claude-opus-4-6 · run details
Summary
listDistinctEnginesByProjectrepository query — queriesagent_configsfor all distinct non-nullagent_enginevalues for a project, returning astring[]of engine IDs actively used by agent configsenginesInUsetRPC endpoint — aprotectedProcedurethat calls the new repository query, enabling the frontend and CLI to discover which engines need credentials configuredenginesInUseand merges with the project-leveleffectiveEngineIdto show credential fields for ALL engines in use (not just the project default)projects show— displays which engines are actively used by agent configs in the project (beyond the project-level default)listDistinctEnginesByProject(repository) andenginesInUse(tRPC endpoint), plus fixes to existing CLI tests for the new endpoint dependencyTest plan
listDistinctEnginesByProject(returns distinct engine IDs, excludes nulls, empty results)enginesInUsetRPC endpoint (org access, auth, empty response)claude-codeas default enginecodexengine overridecascade projects show <id>should list "codex" under "Agent Engines In Use"Key decisions
agent_enginecolumn inagent_configsallEnginesInUsemerges project default + per-agent overrides — ensures all needed credentials are displayed even when the project default engine changesselectDistinctadded to mock DB helper — backward-compatible addition tocreateMockDbResolves: https://trello.com/c/vlJYL9eD/566-lets-make-all-engines-available-in-engine-configuration-in-dashboard-cli-on-per-project-basis-we-can-select-default-engine-and-c
🤖 Generated with Claude Code
🕵️ claude-code · claude-sonnet-4-6 · run details