feat: auto-detect API keys and default model for zero-config startup#81
feat: auto-detect API keys and default model for zero-config startup#81Nivesh353 wants to merge 2 commits into
Conversation
…ined
When model: is absent from agent.yaml entirely (not just missing
preferred), code reading manifest.model.constraints elsewhere (index.ts,
sdk.ts) would throw "Cannot read properties of undefined". Previously
masked because a missing model always hit the "No model configured"
error first — now that auto-detection can resolve a model even without
a model: block, execution reaches further and needs this to hold.
Normalizes manifest.model to { fallback: [] } right after parsing
agent.yaml, and marks model.preferred as optional in the type, since
it's genuinely allowed to be absent now.
shreyas-lyzr
left a comment
There was a problem hiding this comment.
Clean implementation of zero-config model auto-detection. The fallback chain is well-ordered, the normalization fix for manifest.model is correct and needed, and the build + all 27 tests pass.
One thing worth knowing: getEnvApiKey('github-copilot') in pi-ai resolves against COPILOT_GITHUB_TOKEN, GH_TOKEN, and GITHUB_TOKEN. Since gitagent itself requires a GitHub token, github-copilot will match on any machine where no other LLM provider key is set. The PR already places it last in the priority list, so it only fires as a last resort — but it means a user with only GITHUB_TOKEN set and no actual Copilot access will see github-copilot auto-selected and then get an auth error at call time rather than a clean config error. Worth a note in the README or error message so it's not confusing.
Minor: claude-sonnet-4-6 (dash) for anthropic/bedrock vs claude-sonnet-4.6 (dot) for github-copilot — looked correct against the pi-ai model registry, so not a bug.
No tests for autoDetectModel() itself — the function is simple and pure enough that the risk is low, but a few unit tests covering key detection order and the undefined-when-no-keys path would be a useful addition.
Problem
gitagent required an explicit model configuration (
model.preferredinagent.yaml, or--modelon the CLI) to start — even when a validprovider API key was already present in the environment. Users had to
manually configure a model before gitagent would run at all.
Fix
New file:
src/auto-detect-model.tsChecks known providers in a fixed order and returns a sensible default
model for the first one with usable credentials, using
pi-ai'sgetEnvApiKey()rather than a hardcoded env-var check — so ambientcredential sources are picked up too, not just direct API keys.
Providers checked, in order:
anthropic,openai,google,xai,groq,mistralbe present incidentally):
amazon-bedrock,google-vertex,azure-openai-responses,github-copilotAll defaults use versionless model aliases (e.g.
claude-sonnet-4-6,gpt-4o) rather than dated model IDs, so they don't go stale as newpoint releases ship.
src/loader.tsautoDetectModel()in as the final fallback in model resolution,preserving existing priority:
--modelflag >agent.yamlmodel.preferred> env config override > auto-detected from API key.Using <model> (auto-detected from <provider> credentials).manifest.modelis now normalized to{ fallback: [] }right after parsing
agent.yaml, andmodel.preferredis now correctlytyped as optional. Previously, a
model:block missing entirely (notjust missing
preferred) crashed downstream code (index.ts,sdk.ts)with
Cannot read properties of undefined (reading 'constraints')—masked before this change because a missing model always hit the "no
model configured" error first; auto-detection now gets further and
exposed it.
.envfile loading was already implemented separately (src/index.tsloads
.envfrom~/.gitagent/.envand the agent directory before modelresolution runs), so no changes were needed there.
Testing
npm run build— compiles cleanly, no type errors.npm test— all 27 existing tests pass, no regressions.auto-detects and logs the choice, proceeds to a real API call.
no crash.
model:block inagent.yamlat all → previously crashed withCannot read properties of undefined (reading 'constraints'); nowresolves correctly via auto-detect.
Closes #14