Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
a3d9797
feat(router)!: make worker-selection plugins thread-safe and runnable…
karen-sy Oct 30, 2026
f659360
refactor(router)!: rename dynamo-custom-policy-builtin to dynamo-rout…
karen-sy Oct 30, 2026
a1be7e1
refactor(router)!: run the router modes as builtin plugins
karen-sy Oct 30, 2026
9d6c6ce
refactor(router): give each router mode its own file
karen-sy Oct 30, 2026
8a62d01
trim doc changes
karen-sy Oct 30, 2026
8b58fb0
minor refactor, deslop
karen-sy Oct 30, 2026
51be950
deslop comment
karen-sy Oct 30, 2026
ad301c2
refactor(router): address review nits
karen-sy Nov 2, 2026
23068e8
refactor(router): trim the hosted picker's unused surface
karen-sy Nov 2, 2026
b2337db
nit doc
karen-sy Nov 2, 2026
a369170
refactor(router)!: run PushRouter's routing modes through plugin inst…
karen-sy Nov 2, 2026
a7afeb0
fix(router): resolve the router modes from every installed catalog
karen-sy Nov 3, 2026
f1b4e76
refactor(router): shrink the hosted selection request and return the …
karen-sy Nov 3, 2026
b92e621
Merge main into karenc/router-modes-1-hosted-plugins
karen-sy Nov 3, 2026
1c00e9c
Merge karenc/router-modes-1-hosted-plugins into karenc/router-modes-2…
karen-sy Nov 3, 2026
add51b7
Update docs/fern/pages/reference/general/releases/deprecations.mdx
karen-sy Nov 3, 2026
82e1340
fix(router): track occupancy when a selector reads in-flight counts
karen-sy Nov 3, 2026
02a9e66
docs(router): note the PushRouter migration for custom Rust callers
karen-sy Nov 3, 2026
464d176
Merge karenc/router-modes-1-hosted-plugins into karenc/router-modes-2…
karen-sy Nov 3, 2026
d0362f6
Merge main up to the PR 1 squash into karenc/router-modes-2-plugin-modes
karen-sy Nov 3, 2026
45eb54f
Merge main into karenc/router-modes-2-plugin-modes
karen-sy Nov 3, 2026
067808e
Merge main into karenc/router-modes-2-plugin-modes
karen-sy Nov 3, 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
42 changes: 21 additions & 21 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ repository = "https://github.com/ai-dynamo/dynamo.git"
keywords = ["llm", "genai", "inference", "nvidia", "distributed"]

[workspace.dependencies]
dynamo-custom-policy-builtin = { path = "lib/router-plugins/builtin", version = "1.7.0" }
dynamo-router-policies = { path = "lib/router-plugins/builtin", version = "1.7.0" }
dynamo-generate-format-catalog = { path = "lib/generate-format-catalog", version = "1.7.0" }
# Published separately by https://github.com/ai-dynamo/aisimulate.
aisimulate-core = { version = "=0.13.0-dev.202610290000000087" }
Expand Down
2 changes: 1 addition & 1 deletion deploy/inference-gateway/ext-proc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ name = "dynamo-ext-proc"
path = "src/bin/dynamo-ext-proc.rs"

[dependencies]
dynamo-custom-policy-builtin = { workspace = true }
dynamo-router-policies = { workspace = true }
async-trait = { workspace = true }
dynamo-kv-router = { workspace = true, features = [
"metrics",
Expand Down
2 changes: 1 addition & 1 deletion deploy/inference-gateway/ext-proc/src/peer_discovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ mod tests {
SelectionServiceBuilder::new(
kv_router_config_from_dynamo_env(),
WorkerType::Aggregated,
dynamo_custom_policy_builtin::default_registry(),
dynamo_router_policies::default_registry(),
)
.indexer_threads(1)
.replica_sync(listener_port, Vec::new())
Expand Down
2 changes: 1 addition & 1 deletion deploy/inference-gateway/ext-proc/src/selector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ impl Selector {
let mut builder = SelectionServiceBuilder::new(
kv_router_config,
WorkerType::Aggregated,
policy_registry.with_default_factory(dynamo_custom_policy_builtin::default_factory()),
dynamo_router_policies::with_defaults(policy_registry),
)
.indexer_threads(cfg.selector_threads);
if let Some(peer_replication) = peer_replication {
Expand Down
4 changes: 4 additions & 0 deletions docs/fern/pages/reference/general/releases/deprecations.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ Upgrading? Pick the version you run today to see the dependency migration and th

> **Migrate:** Replace `WorkerInputs::OCCUPANCY` with `WorkerInputs::ACTIVE_REQUESTS` in custom worker-selection policies.

<span className="dynref-badge dynref-badge--blue">Behavioral</span> **Your own Rust code that constructs a round-robin, random or least-loaded `PushRouter` must pass the router-mode plugins** ([#17713](https://github.com/ai-dynamo/dynamo/pull/17713)). Without them, the router fails to build.

> **Migrate:** CLI, Python and Kubernetes deployments need no change. If your Rust code creates a `PushRouter` in one of these modes, replace `PushRouter::from_client(client, RouterMode::RoundRobin)` with `PushRouter::from_client_with_options(client, RouterMode::RoundRobin, dynamo_llm::kv_router::plugins::push_router_options())`. If your code depends only on `dynamo-runtime`, add `dynamo-llm`, or implement `InstanceSelector`.
Comment thread
karen-sy marked this conversation as resolved.
Resolved

<a id="v160"></a>

## v1.6.0 - Oct 22, 2026
Expand Down
34 changes: 17 additions & 17 deletions lib/bindings/kvbm/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 18 additions & 18 deletions lib/bindings/python/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lib/bindings/python/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ uuid = { version = "1.18.1" }

# kv-indexer / slot-tracker / shared kv-router types
dynamo-kv-router = { path = "../../kv-router" }
dynamo-custom-policy-builtin = { path = "../../router-plugins/builtin" }
dynamo-router-policies = { path = "../../router-plugins/builtin" }
dynamo-worker-selection-policy-catalog = { path = "../../router-plugins/catalog", optional = true }
# The replaceable /generate format catalog; custom images point this name at their own.
dynamo-generate-format-catalog = { path = "../../generate-format-catalog" }
Expand Down
7 changes: 4 additions & 3 deletions lib/bindings/python/rust/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -492,10 +492,10 @@ pub(crate) fn linked_worker_selection_policy_registry() -> RouterPluginRegistry

#[cfg(feature = "custom-policy")]
fn register_core_with_router_plugins(m: &Bound<'_, PyModule>) -> PyResult<()> {
let mut registry = dynamo_kv_router::plugins::RouterPluginRegistry::default();
let mut registry = dynamo_router_policies::default_registry();
// The policies Dynamo ships register first, so a replaced catalog that reuses one of their
// type names fails here instead of silently overriding it.
dynamo_custom_policy_builtin::register(&mut registry)
dynamo_router_policies::register(&mut registry)
.map_err(|error| PyRuntimeError::new_err(error.to_string()))?;
dynamo_worker_selection_policy_catalog::register(&mut registry)
.map_err(|error| PyRuntimeError::new_err(error.to_string()))?;
Expand Down Expand Up @@ -1934,9 +1934,10 @@ impl Endpoint {
crate::future_into_py(py, async move {
let client = inner.client().await.map_err(to_pyerr)?;
let push_router =
rs::pipeline::PushRouter::<rmpv::Value, RsAnnotated<rmpv::Value>>::from_client(
rs::pipeline::PushRouter::<rmpv::Value, RsAnnotated<rmpv::Value>>::from_client_with_options(
client,
router_mode.into(),
dynamo_llm::kv_router::plugins::push_router_options(),
)
.await
.map_err(to_pyerr)?;
Expand Down
4 changes: 2 additions & 2 deletions lib/bindings/python/rust/llm/entrypoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ impl KvRouterConfig {
selects worker-selection policy instance {instance:?} for {worker_type}"
)));
}
dynamo_custom_policy_builtin::startup_policy_parameters(&self.inner, role)
dynamo_router_policies::startup_policy_parameters(&self.inner, role)
.into_iter()
.map(|(name, value)| match value.as_f64() {
Some(value) => Ok((name, value)),
Expand Down Expand Up @@ -985,7 +985,7 @@ mod plugin_input_tests {
#[test]
fn explicit_policy_retains_frontend_restrictions() {
let plugins = RouterPlugins::default()
.with_worker_selection(dynamo_custom_policy_builtin::default_factory());
.with_worker_selection(dynamo_router_policies::default_factory());
assert!(validate_router_plugin_input(&plugins, &Input::Http, true).is_ok());
assert_eq!(
validate_router_plugin_input(&plugins, &Input::Http, false),
Expand Down
21 changes: 21 additions & 0 deletions lib/kv-router/src/plugins/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,27 @@ impl RouterPluginRegistry {
})
}

/// Build the factory for one registered policy type with default parameters, as a routing
/// mode names it (for example `round-robin`) without a policy file.
pub fn resolve_type(
&self,
policy_type: &str,
) -> Result<WorkerSelectionPolicyFactory, WorkerSelectionPolicyRegistryError> {
let provider = self.providers.get(policy_type).ok_or_else(|| {
WorkerSelectionPolicyRegistryError::UnknownType {
name: policy_type.to_owned(),
available: self.available_policy_types(),
}
})?;
provider(&WorkerSelectionPolicyParameters::new(
serde_yaml::Value::Mapping(Default::default()),
))
.map_err(|source| WorkerSelectionPolicyRegistryError::Provider {
policy_type: policy_type.to_owned(),
source,
})
}

fn available_policy_types(&self) -> String {
let mut available = self.providers.keys().cloned().collect::<Vec<_>>();
available.sort_unstable();
Expand Down
12 changes: 12 additions & 0 deletions lib/kv-router/src/plugins/worker_selection/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub struct WorkerSelectionContext<'a> {
pub(crate) track_prefill_tokens: bool,
pub(crate) pinned_worker: Option<WorkerWithDpRank>,
pub(crate) router_temperature_override: Option<f64>,
pub(crate) preview: bool,
}

impl WorkerSelectionContext<'_> {
Expand Down Expand Up @@ -90,4 +91,15 @@ impl WorkerSelectionContext<'_> {
pub fn router_temperature_override(&self) -> Option<f64> {
self.router_temperature_override
}

/// Whether this selection only previews a worker, as a peek does, without routing the
/// request to it. A picker that keeps state between selections, such as a rotation
/// cursor, should read that state without advancing it. Always `false` when the router
/// routes with KV state.
// TODO(v1.8): document once custom pickers can run on the hosted path; until then only the
// builtin router-mode plugins receive previews.
#[doc(hidden)]
pub fn is_preview(&self) -> bool {
Comment thread
karen-sy marked this conversation as resolved.
Resolved
self.preview
}
}
Loading
Loading