Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
2548aa7
common: add proptest dev-dependency for configuration tests
TroyMitchell911 Apr 28, 2026
a58a283
common: add RetryPolicy configuration types
TroyMitchell911 Apr 28, 2026
388fbff
common: add RetryPolicy proptest and YAML pattern tests
TroyMitchell911 Apr 28, 2026
18dbbd2
config: add retry_policy to plano_config_schema.yaml
TroyMitchell911 Apr 28, 2026
6853e4d
common: add sha2, dashmap, tokio runtime dependencies for retry module
TroyMitchell911 Apr 28, 2026
5a2d0aa
retry: add core retry types and module structure
TroyMitchell911 Apr 28, 2026
3c7fefa
retry: add backoff calculator with jitter strategies
TroyMitchell911 Apr 28, 2026
ea56176
retry: add error detector for HTTP response classification
TroyMitchell911 Apr 28, 2026
47a3e8a
retry: add error response builder for retry exhaustion
TroyMitchell911 Apr 28, 2026
46b6324
retry: add state managers for latency blocking and retry-after
TroyMitchell911 Apr 28, 2026
d6a9ada
retry: add configuration validation for retry policies
TroyMitchell911 Apr 28, 2026
52c71fe
retry: add provider selector with failover logic
TroyMitchell911 Apr 28, 2026
ed5e1d6
retry: add retry orchestrator coordinating all components
TroyMitchell911 Apr 28, 2026
d29ed70
retry: update Cargo.lock for retry module dependencies
TroyMitchell911 Apr 28, 2026
c34ff5b
feat: preserve original JSON bytes for prompt cache compatibility
TroyMitchell911 Apr 28, 2026
f3e3591
feat: integrate retry orchestrator into LLM handler
TroyMitchell911 Apr 28, 2026
a295337
config_generator: allow multiple providers for the same model
TroyMitchell911 Apr 28, 2026
7fecea1
llm handler: capture request_path for failover forwarding
TroyMitchell911 Apr 28, 2026
4da0c63
add example plano_config.yaml with retry/failover settings
TroyMitchell911 Apr 28, 2026
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
22 changes: 10 additions & 12 deletions cli/planoai/config_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -415,12 +415,10 @@ def validate_and_render_schema():
)

# For wildcard models, don't add model_id to the keys since it's "*"
if not is_wildcard:
if model_id in model_name_keys:
raise Exception(
f"Duplicate model_id {model_id}, please provide unique model_id for each model_provider"
)
model_name_keys.add(model_id)
# Note: full model_name dedup is already done above (line 226).
# We no longer dedup on model_id alone, because different providers
# can serve the same model (e.g., custom/claude-opus-4-6 and
# custom-aws/claude-opus-4-6 share model_id but are distinct providers).

# Warn if both passthrough_auth and access_key are configured
if model_provider.get("passthrough_auth") and model_provider.get(
Expand All @@ -431,7 +429,7 @@ def validate_and_render_schema():
f"The access_key will be ignored and the client's Authorization header will be forwarded instead."
)

model_provider["model"] = model_id
model_provider["model"] = model_name
model_provider["provider_interface"] = provider
model_provider_name_set.add(model_provider.get("name"))
if model_provider.get("provider") and model_provider.get(
Expand Down Expand Up @@ -501,15 +499,15 @@ def validate_and_render_schema():
llms_with_endpoint_cluster_names.add(cluster_name)

overrides_config = config_yaml.get("overrides", {})
# Build lookup of model names (already prefix-stripped by config processing)
# Build lookup of model names (full provider/model format)
model_name_set = {mp.get("model") for mp in updated_model_providers}

# Auto-add plano-orchestrator provider if routing preferences exist and no provider matches the routing model
router_model = overrides_config.get("llm_routing_model", "Plano-Orchestrator")
router_model_id = (
router_model.split("/", 1)[1] if "/" in router_model else router_model
)
if len(seen_pref_names) > 0 and router_model_id not in model_name_set:
if len(seen_pref_names) > 0 and router_model not in model_name_set:
router_model_id = (
router_model.split("/", 1)[1] if "/" in router_model else router_model
)
updated_model_providers.append(
{
"name": "plano-orchestrator",
Expand Down
Loading