coderouter-cli 2.9.1__py3-none-any.whl → 2.9.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1951,8 +1951,16 @@ class CodeRouterConfig(BaseModel):
1951
1951
  description="Master switch. ALLOW_PAID=false blocks all paid providers (plan.md §2.3).",
1952
1952
  )
1953
1953
  default_profile: str = Field(default="default")
1954
- providers: list[ProviderConfig] = Field(..., min_length=1)
1955
- profiles: list[FallbackChain] = Field(..., min_length=1)
1954
+ # [Unreleased]: relaxed from ``Field(..., min_length=1)`` so a
1955
+ # swap-only deployment (``launcher.swap.enabled`` with a non-empty
1956
+ # ``models`` catalog) can omit both fields entirely instead of
1957
+ # writing an unreachable dummy provider/profile just to satisfy the
1958
+ # schema. The "at least one" invariant is NOT dropped — it moves to
1959
+ # ``_check_providers_and_profiles_nonempty`` below, which still
1960
+ # fail-fasts at load for every other deployment shape (same
1961
+ # philosophy as the min_length constraint it replaces).
1962
+ providers: list[ProviderConfig] = Field(default_factory=list)
1963
+ profiles: list[FallbackChain] = Field(default_factory=list)
1956
1964
  mode_aliases: dict[str, str] = Field(
1957
1965
  default_factory=dict,
1958
1966
  description=(
@@ -2159,6 +2167,52 @@ class CodeRouterConfig(BaseModel):
2159
2167
  )
2160
2168
  return self
2161
2169
 
2170
+ @model_validator(mode="after")
2171
+ def _check_providers_and_profiles_nonempty(self) -> CodeRouterConfig:
2172
+ """[Unreleased]: enforce "at least one" unless launcher.swap covers it.
2173
+
2174
+ ``providers`` / ``profiles`` were relaxed from ``min_length=1`` to
2175
+ ``default_factory=list`` (see the field comments above) so a
2176
+ swap-only deployment can omit them — every request in that shape
2177
+ is routed through a ``launcher-swap-<name>`` profile that
2178
+ :meth:`_inject_swap_profiles_and_auto_router_rules` synthesizes
2179
+ below, and its backing provider is registered at runtime on first
2180
+ spawn (``SwapManager.register_provider``), so there is genuinely
2181
+ nothing to declare statically.
2182
+
2183
+ Runs BEFORE the swap injection (which only ever *adds* profiles,
2184
+ never providers) so it observes the operator's raw, undecorated
2185
+ input rather than the post-injection state — the injected
2186
+ profiles are not a substitute for a real provider declaration in
2187
+ every other deployment shape, only in the swap-only one this
2188
+ validator carves out.
2189
+
2190
+ Outside that carve-out, an empty ``providers`` or ``profiles``
2191
+ list has always been a load-time error (there would be nothing to
2192
+ route to); this validator keeps that fail-fast guarantee instead
2193
+ of silently trading it away when the ``min_length=1`` field
2194
+ constraint was dropped.
2195
+ """
2196
+ swap_cfg = self.launcher.swap if self.launcher is not None else None
2197
+ swap_covers_empty = (
2198
+ swap_cfg is not None and swap_cfg.enabled and bool(swap_cfg.models)
2199
+ )
2200
+ if swap_covers_empty:
2201
+ return self
2202
+ if not self.providers:
2203
+ raise ValueError(
2204
+ "providers: at least one entry is required (empty/omitted "
2205
+ "is only allowed when launcher.swap.enabled=true and "
2206
+ "launcher.swap.models has at least one entry)."
2207
+ )
2208
+ if not self.profiles:
2209
+ raise ValueError(
2210
+ "profiles: at least one entry is required (empty/omitted "
2211
+ "is only allowed when launcher.swap.enabled=true and "
2212
+ "launcher.swap.models has at least one entry)."
2213
+ )
2214
+ return self
2215
+
2162
2216
  @model_validator(mode="after")
2163
2217
  def _inject_swap_profiles_and_auto_router_rules(self) -> CodeRouterConfig:
2164
2218
  """§10 Q7 + design-deviation: bootstrap swap's dedicated profiles.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: coderouter-cli
3
- Version: 2.9.1
3
+ Version: 2.9.2
4
4
  Summary: Local-first, free-first, fallback-built-in LLM router. Claude Code / OpenAI compatible.
5
5
  Project-URL: Homepage, https://github.com/zephel01/CodeRouter
6
6
  Project-URL: Repository, https://github.com/zephel01/CodeRouter
@@ -25,7 +25,7 @@ coderouter/config/__init__.py,sha256=FODEn74fN-qZnt4INPSHswqhOlEgpL6-_onxsitSx8g
25
25
  coderouter/config/capability_registry.py,sha256=RZgzHF54dXy0CCDocRCz2ee21qXGbbgTSKTkRI9iLL4,16936
26
26
  coderouter/config/env_file.py,sha256=CoMK27fuAXm-NtoLzXb8yN2E-wDFjHQuFwiIlmgTBQw,10356
27
27
  coderouter/config/loader.py,sha256=FUEe8m4Tnmj_aul0vSctD8vKvNW-oLRoMRbTpSKqSmc,4077
28
- coderouter/config/schemas.py,sha256=U7AGOm88gtCqUYsRNYc6KVaiP-Cdg5yd_oOzYiiR3rs,114340
28
+ coderouter/config/schemas.py,sha256=zMv6UjL2ebcxc3dMIOa9lQjOGvvuHMWCPqoOVA35CEw,117181
29
29
  coderouter/data/__init__.py,sha256=uNyfD9jaCvTWsBAWtaw1Fr25OSxzv3psGMfBjT1z0Cc,328
30
30
  coderouter/data/model-capabilities.yaml,sha256=S9jt6SC6-3s2-icZ_n-a14iEMnc2yB1C2R6q-N_tZWQ,19309
31
31
  coderouter/guards/__init__.py,sha256=5qliYBqygvVPneej7nx0uSjxDKsz7t8VzvrDgVBJlvU,1170
@@ -69,8 +69,8 @@ coderouter/translation/__init__.py,sha256=PYXN7XVEwpG1uC8RLy6fvnGbzEZhhrEuUapH8I
69
69
  coderouter/translation/anthropic.py,sha256=aZkcYH4x82b0x7efJgJb9RWn9Hbyc9pEOthXe4vjUdU,11113
70
70
  coderouter/translation/convert.py,sha256=VV4kpu4dvLmGBmJfQnCLY5ryy_AnQcV2NuwjqRtaR8Q,52633
71
71
  coderouter/translation/tool_repair.py,sha256=DGOKArM53yfVbIfiAveoul1vGq9NEKmjagf43Qh4IkM,57630
72
- coderouter_cli-2.9.1.dist-info/METADATA,sha256=yfgVyK-eoyV3fde8w8Ngm9TvXw3h61CI3epBZOggdRI,15994
73
- coderouter_cli-2.9.1.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
74
- coderouter_cli-2.9.1.dist-info/entry_points.txt,sha256=-dnLfD1YZ2WjH2zSdNCvlO65wYltM9bsHt9Fhg3yGss,51
75
- coderouter_cli-2.9.1.dist-info/licenses/LICENSE,sha256=wkEzoR86jFw33jvfOHjULqmkGEfxTFMgMaJnpR8mPRw,1065
76
- coderouter_cli-2.9.1.dist-info/RECORD,,
72
+ coderouter_cli-2.9.2.dist-info/METADATA,sha256=dcDACrTxRsla8y8mcY05IC4KilzZD-co6xkEz9xC_H4,15994
73
+ coderouter_cli-2.9.2.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
74
+ coderouter_cli-2.9.2.dist-info/entry_points.txt,sha256=-dnLfD1YZ2WjH2zSdNCvlO65wYltM9bsHt9Fhg3yGss,51
75
+ coderouter_cli-2.9.2.dist-info/licenses/LICENSE,sha256=wkEzoR86jFw33jvfOHjULqmkGEfxTFMgMaJnpR8mPRw,1065
76
+ coderouter_cli-2.9.2.dist-info/RECORD,,