Entropic 2.3.8
Local-first agentic inference engine
Loading...
Searching...
No Matches
validate.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
10
11static auto s_log = entropic::log::get("config");
12
13namespace entropic::config {
14
22std::string validate_allowed_tools(const std::vector<std::string>& tools)
23{
24 for (const auto& entry : tools) {
25 if (entry.find('.') == std::string::npos) {
26 return "allowed_tools entry '" + entry
27 + "' must use '{server_name}.{tool_name}' format";
28 }
29 }
30 return "";
31}
32
40std::string validate(const ModelConfig& config)
41{
42 std::string err;
43
44 if (config.context_length < 512 || config.context_length > 131072) {
45 err = "context_length must be in [512, 131072], got "
46 + std::to_string(config.context_length);
47 } else if (config.adapter.empty()) {
48 err = "adapter must not be empty";
49 } else if (config.n_batch < 1) {
50 err = "n_batch must be >= 1, got "
51 + std::to_string(config.n_batch);
52 } else if (config.allowed_tools.has_value()) {
54 }
55
56 return err;
57}
58
66std::string validate(const ModelsConfig& config)
67{
68 if (!config.tiers.empty()
69 && config.tiers.count(config.default_tier) == 0) {
70 return "default tier '" + config.default_tier
71 + "' not in tiers";
72 }
73 return "";
74}
75
83std::string validate(const CompactionConfig& config)
84{
85 std::string err;
86
87 if (config.threshold_percent < 0.5f
88 || config.threshold_percent > 0.99f) {
89 err = "compaction.threshold_percent must be in [0.5, 0.99], got "
90 + std::to_string(config.threshold_percent);
91 } else if (config.warning_threshold_percent
92 >= config.threshold_percent) {
93 err = "compaction.warning_threshold_percent ("
94 + std::to_string(config.warning_threshold_percent)
95 + ") must be less than threshold_percent ("
96 + std::to_string(config.threshold_percent) + ")";
97 } else if (config.preserve_recent_turns < 1
98 || config.preserve_recent_turns > 10) {
99 err = "compaction.preserve_recent_turns must be in [1, 10], got "
100 + std::to_string(config.preserve_recent_turns);
101 } else if (config.tool_result_ttl < 1) {
102 // v2.1.3 #6 / TTL clamp removal: tool_result_ttl was previously
103 // documented as "1–20" but never actually validated. The upper
104 // bound was always advisory — consumers can pick whatever
105 // makes sense for their workload (long delegations on large
106 // context windows benefit from large TTLs). Lower bound IS
107 // enforced because TTL=0 would prune every result on the next
108 // iteration, which is nonsensical and almost certainly a
109 // misconfiguration rather than an intent.
110 err = "compaction.tool_result_ttl must be >= 1, got "
111 + std::to_string(config.tool_result_ttl);
112 }
113
114 return err;
115}
116
126 const std::string& fallback,
127 const std::unordered_map<std::string, TierConfig>& tiers)
128{
129 if (tiers.count(fallback) == 0) {
130 return "routing.fallback_tier '" + fallback + "' not in tiers";
131 }
132 return "";
133}
134
144 const std::unordered_map<std::string, std::string>& tier_map,
145 const std::unordered_map<std::string, TierConfig>& tiers)
146{
147 for (const auto& [key, tier] : tier_map) {
148 if (tiers.count(tier) == 0) {
149 return "routing.tier_map['" + key + "'] = '" + tier
150 + "' not in tiers";
151 }
152 }
153 return "";
154}
155
165 const std::unordered_map<std::string, std::vector<std::string>>& rules,
166 const std::unordered_map<std::string, TierConfig>& tiers)
167{
168 for (const auto& [source, targets] : rules) {
169 if (tiers.count(source) == 0) {
170 return "routing.handoff_rules key '" + source
171 + "' not in tiers";
172 }
173 for (const auto& target : targets) {
174 if (tiers.count(target) == 0) {
175 return "routing.handoff_rules['" + source
176 + "'] contains '" + target + "' not in tiers";
177 }
178 }
179 }
180 return "";
181}
182
192 const RoutingConfig& routing,
193 const ModelsConfig& models)
194{
195 std::string err;
196
197 if (models.tiers.empty()) {
198 /* no tiers — nothing to validate */
199 } else if (routing.enabled && !models.router.has_value()) {
200 err = "routing.enabled is true but models.router is not configured";
201 } else {
202 err = validate_fallback_tier(routing.fallback_tier, models.tiers);
203
204 if (err.empty()) {
205 err = validate_tier_map(routing.tier_map, models.tiers);
206 }
207 if (err.empty()) {
208 err = validate_handoff_rules(routing.handoff_rules, models.tiers);
209 }
210 }
211
212 return err;
213}
214
224 const std::unordered_map<std::string, TierConfig>& tiers,
225 const std::unordered_map<std::string, std::vector<std::string>>&
226 handoff_rules)
227{
228 std::string warnings;
229 for (const auto& [name, tier] : tiers) {
230 if (tier.auto_chain.has_value() && !tier.auto_chain->empty()
231 && handoff_rules.count(name) == 0) {
232 if (!warnings.empty()) {
233 warnings += "; ";
234 }
235 warnings += "tier '" + name
236 + "' has auto_chain but no handoff_rules entry";
237 }
238 }
239 return warnings;
240}
241
249std::string validate(const PromptCacheConfig& config)
250{
251 if (config.enabled && config.max_bytes == 0) {
252 return "inference.prompt_cache: enabled=true but max_bytes=0";
253 }
254 return "";
255}
256
264static std::string validate_model_tiers(const ModelsConfig& models)
265{
266 std::string err = validate(models);
267
268 if (err.empty()) {
269 for (const auto& [name, tier] : models.tiers) {
270 err = validate(static_cast<const ModelConfig&>(tier));
271 if (!err.empty()) {
272 err = "models." + name + ": " + err;
273 break;
274 }
275 }
276 }
277
278 if (err.empty() && models.router.has_value()) {
279 err = validate(*models.router);
280 if (!err.empty()) {
281 err = "models.router: " + err;
282 }
283 }
284
285 return err;
286}
287
296std::string validate_config(
297 const ParsedConfig& config,
298 std::vector<std::string>& warnings)
299{
300 s_log->info("Config validation start");
301 std::string err = validate_model_tiers(config.models);
302
303 if (err.empty()) {
304 err = validate_routing(config.routing, config.models);
305 }
306 if (err.empty()) {
307 err = validate(config.compaction);
308 }
309 if (err.empty()) {
310 err = validate(config.prompt_cache);
311 }
312 if (err.empty()) {
314 config.models.tiers, config.routing.handoff_rules);
315 if (!w.empty()) {
316 warnings.push_back(w);
317 }
318 }
319
320 if (err.empty()) {
321 s_log->info("Config validation passed ({} warning(s))",
322 warnings.size());
323 } else {
324 s_log->error("Config validation failed: {}", err);
325 }
326 return err;
327}
328
329} // namespace entropic::config
spdlog initialization and logger access.
ENTROPIC_EXPORT std::shared_ptr< spdlog::logger > get(const std::string &name)
Get or create a named logger.
Definition logging.cpp:211
Auto-compaction configuration.
Definition config.h:508
float warning_threshold_percent
Warning trigger (0.3–0.9)
Definition config.h:516
int preserve_recent_turns
Turns to preserve (1–10)
Definition config.h:511
int tool_result_ttl
Tool result TTL in turns (>= 1; v2.1.3 #6: gated on fill, no upper bound)
Definition config.h:515
float threshold_percent
Compaction trigger (0.5–0.99)
Definition config.h:510
Model configuration for a single tier.
Definition config.h:148
int context_length
Context window size (512–131072)
Definition config.h:151
int n_batch
Batch size for prompt processing.
Definition config.h:160
std::optional< std::vector< std::string > > allowed_tools
Tool whitelist (nullopt = all)
Definition config.h:166
std::string adapter
Chat adapter name.
Definition config.h:150
Configuration for all models (tiers + router).
Definition config.h:356
std::optional< ModelConfig > router
Router model (separate from tiers)
Definition config.h:358
std::unordered_map< std::string, TierConfig > tiers
Tier name → config.
Definition config.h:357
std::string default_tier
Default tier name.
Definition config.h:359
Full parsed configuration.
Definition config.h:714
PromptCacheConfig prompt_cache
Prompt KV cache settings.
Definition config.h:722
CompactionConfig compaction
Auto-compaction settings.
Definition config.h:720
RoutingConfig routing
Routing rules.
Definition config.h:716
ModelsConfig models
Tiers + router.
Definition config.h:715
Prompt caching configuration.
Definition config.h:196
size_t max_bytes
Maximum cache RAM (512 MB default)
Definition config.h:197
bool enabled
Master switch (false = no caching)
Definition config.h:198
Configuration for model routing.
Definition config.h:388
std::string fallback_tier
Fallback when routing fails.
Definition config.h:390
std::unordered_map< std::string, std::vector< std::string > > handoff_rules
Tier handoff rules.
Definition config.h:393
bool enabled
Enable routing.
Definition config.h:389
std::unordered_map< std::string, std::string > tier_map
Classification → tier mapping.
Definition config.h:392
static std::string validate_model_tiers(const ModelsConfig &models)
Validate model tiers and router.
Definition validate.cpp:264
Config validation functions.
ENTROPIC_EXPORT std::string validate_handoff_rules(const std::unordered_map< std::string, std::vector< std::string > > &rules, const std::unordered_map< std::string, TierConfig > &tiers)
Check all handoff_rules keys and values exist in tiers.
Definition validate.cpp:164
ENTROPIC_EXPORT std::string validate_routing(const RoutingConfig &routing, const ModelsConfig &models)
Validate RoutingConfig against defined tiers.
Definition validate.cpp:191
ENTROPIC_EXPORT std::string validate_tier_map(const std::unordered_map< std::string, std::string > &tier_map, const std::unordered_map< std::string, TierConfig > &tiers)
Check all tier_map values exist in tiers.
Definition validate.cpp:143
ENTROPIC_EXPORT std::string validate_config(const ParsedConfig &config, std::vector< std::string > &warnings)
Validate the full ParsedConfig.
Definition validate.cpp:296
ENTROPIC_EXPORT std::string validate_fallback_tier(const std::string &fallback, const std::unordered_map< std::string, TierConfig > &tiers)
Check fallback_tier exists in tiers.
Definition validate.cpp:125
ENTROPIC_EXPORT std::string warn_auto_chain_without_targets(const std::unordered_map< std::string, TierConfig > &tiers, const std::unordered_map< std::string, std::vector< std::string > > &handoff_rules)
Warn if tier has auto_chain but no handoff_rules entry.
Definition validate.cpp:223
ENTROPIC_EXPORT std::string validate(const ModelConfig &config)
Validate a ModelConfig.
Definition validate.cpp:40
ENTROPIC_EXPORT std::string validate_allowed_tools(const std::vector< std::string > &tools)
Validate allowed_tools entries use "server.tool" format.
Definition validate.cpp:22