Omit empty fields from bootstrap config output

probod-bootstrap was writing empty strings and stub blocks such as
`esign: {}` into generated YAML. The post-marshal prune pass caused
part of that by stripping empty leaf strings while leaving empty
parent maps behind.

Drop the prune round-trip in WriteConfig and rely on struct-level
omitzero/omitempty tags plus custom IsZero() helpers on probodconfig.
Only include LLM providers when an API key is set, use a nil map for
extra API headers, and extend the dev-config Makefile recipe with the
local dev defaults already documented in .env.example.

Config loading is unchanged: omitted keys still decode to Go zero
values.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
This commit is contained in:
Ludovic Vielle
2026-07-01 10:15:28 +02:00
parent 2be3e18437
commit e22aaa8b67
17 changed files with 380 additions and 195 deletions

View File

@@ -18,17 +18,17 @@ type (
// LLMProviderConfig holds authentication and connection settings for an
// LLM provider (e.g. OpenAI, Anthropic).
LLMProviderConfig struct {
Type string `json:"type"` // "openai", "anthropic", "bedrock"
APIKey string `json:"api-key"` // for OpenAI and Anthropic
Type string `json:"type"` // "openai", "anthropic", "bedrock"
APIKey string `json:"api-key,omitempty"` // for OpenAI and Anthropic
}
// LLMAgentConfig holds model parameters for a single agent. Provider
// references one of the keys in AgentsConfig.Providers.
LLMAgentConfig struct {
Provider string `json:"provider"` // key into AgentsConfig.Providers
ModelName string `json:"model-name"`
Temperature *float64 `json:"temperature"`
MaxTokens *int `json:"max-tokens"`
Provider string `json:"provider,omitempty"` // key into AgentsConfig.Providers
ModelName string `json:"model-name,omitempty"`
Temperature *float64 `json:"temperature,omitempty"`
MaxTokens *int `json:"max-tokens,omitempty"`
}
// EvidenceDescriberConfig holds worker-side tuning for the evidence
@@ -95,26 +95,38 @@ type (
// AgentToolsConfig holds API keys and settings for external tools
// that agents can use (web search, scraping, etc.).
AgentToolsConfig struct {
FirecrawlAPIKey string `json:"firecrawl-api-key"`
FirecrawlAPIKey string `json:"firecrawl-api-key,omitempty"`
}
// AgentsConfig groups LLM provider credentials and per-agent model
// settings. Default is used as a fallback when an agent-specific field
// is zero-valued.
AgentsConfig struct {
Providers map[string]LLMProviderConfig `json:"providers"`
Providers map[string]LLMProviderConfig `json:"providers,omitempty"`
Default LLMAgentConfig `json:"defaults"`
Probo LLMAgentConfig `json:"probo"`
EvidenceDescriber LLMAgentConfig `json:"evidence-describer"`
ThirdPartyVetter LLMAgentConfig `json:"third-party-vetter"`
ThirdPartyDisambiguation LLMAgentConfig `json:"third-party-disambiguation"`
TrackerMapping LLMAgentConfig `json:"tracker-mapping"`
TrackerEnrichment LLMAgentConfig `json:"tracker-enrichment"`
CommonThirdPartyEnrichment LLMAgentConfig `json:"common-third-party-enrichment"`
Tools AgentToolsConfig `json:"tools"`
Probo LLMAgentConfig `json:"probo,omitzero"`
EvidenceDescriber LLMAgentConfig `json:"evidence-describer,omitzero"`
ThirdPartyVetter LLMAgentConfig `json:"third-party-vetter,omitzero"`
ThirdPartyDisambiguation LLMAgentConfig `json:"third-party-disambiguation,omitzero"`
TrackerMapping LLMAgentConfig `json:"tracker-mapping,omitzero"`
TrackerEnrichment LLMAgentConfig `json:"tracker-enrichment,omitzero"`
CommonThirdPartyEnrichment LLMAgentConfig `json:"common-third-party-enrichment,omitzero"`
Tools AgentToolsConfig `json:"tools,omitzero"`
}
)
func (c LLMProviderConfig) IsZero() bool {
return c.APIKey == ""
}
func (c LLMAgentConfig) IsZero() bool {
return c.Provider == "" && c.ModelName == ""
}
func (c AgentToolsConfig) IsZero() bool {
return c.FirecrawlAPIKey == ""
}
// ResolveAgent returns a fully populated LLMAgentConfig by filling in
// zero-valued fields from the default config.
func (c *AgentsConfig) ResolveAgent(agent LLMAgentConfig) LLMAgentConfig {