2026-07-07 10:40:02 +00:00
|
|
|
use std::fs;
|
2026-07-28 07:29:31 +00:00
|
|
|
use std::path::Path;
|
2026-07-07 10:40:02 +00:00
|
|
|
|
|
|
|
|
use serde::Deserialize;
|
|
|
|
|
|
2026-07-29 20:23:26 +00:00
|
|
|
pub(crate) const DEFAULT_CONFIG_PATH: &str = ".config/config.toml";
|
2026-07-07 10:40:02 +00:00
|
|
|
|
refactor: prune public api
Collapse mvp-system's public surface to three binary entrypoints and make every domain module private, deleting dead provider/worker/membership implementations and inlining provider config.
- lib.rs: expose only run_chat_from_args/run_orchestrator_from_args/run_worker_node_from_env (plus a crate-private in-process helper) and the cached-model consts, and demote chat/node/observability/orchestration/prompt/staging/transport to private mods
- orchestration/mod.rs: make app private, gate engine_builder behind cfg(test), drop docker_cluster from provider_adapters, tighten vastai to pub(super), and replace pub re-exports with pub(super) run_from_args/run_in_process_from_args
- orchestration/config.rs: inline VastAiConfig/ResolvedVastAiConfig/looks_remote_image (removing provider_adapters/vastai/config.rs) and drop the DEFAULT_PIPELINE_CACHED_MODEL_* consts (hoisted to lib.rs)
- orchestration/provider_adapters/vastai: delete the ProviderPlugin impl VastAiProviderPlugin and all client/bootstrap/config accessors; repoint call sites to crate-level #[path] mods for provisioning/node_provisioning/node_actor/gguf_shard/run_fsm/run_plan
- delete orchestration/{membership_readiness,token_endpoint,resource_inventory}, node/{boot_lifecycle,data_plane_bridge(-74)}, and the worker crate-internal modules (control/device_bridge/process_adapter) along with their guarantees tests
- chat/node: narrow node_image and worker_node_runtime to private and expose only pub(super) run_from_args / run_worker_node_from_env
Signed-off-by: Zachery Aaron Shores-Chmielewski <zacheryasc@gmail.com>
2026-07-29 10:02:50 +00:00
|
|
|
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
|
|
|
|
|
#[serde(default)]
|
2026-07-29 20:23:26 +00:00
|
|
|
pub(crate) struct VastAiConfig {
|
refactor: prune public api
Collapse mvp-system's public surface to three binary entrypoints and make every domain module private, deleting dead provider/worker/membership implementations and inlining provider config.
- lib.rs: expose only run_chat_from_args/run_orchestrator_from_args/run_worker_node_from_env (plus a crate-private in-process helper) and the cached-model consts, and demote chat/node/observability/orchestration/prompt/staging/transport to private mods
- orchestration/mod.rs: make app private, gate engine_builder behind cfg(test), drop docker_cluster from provider_adapters, tighten vastai to pub(super), and replace pub re-exports with pub(super) run_from_args/run_in_process_from_args
- orchestration/config.rs: inline VastAiConfig/ResolvedVastAiConfig/looks_remote_image (removing provider_adapters/vastai/config.rs) and drop the DEFAULT_PIPELINE_CACHED_MODEL_* consts (hoisted to lib.rs)
- orchestration/provider_adapters/vastai: delete the ProviderPlugin impl VastAiProviderPlugin and all client/bootstrap/config accessors; repoint call sites to crate-level #[path] mods for provisioning/node_provisioning/node_actor/gguf_shard/run_fsm/run_plan
- delete orchestration/{membership_readiness,token_endpoint,resource_inventory}, node/{boot_lifecycle,data_plane_bridge(-74)}, and the worker crate-internal modules (control/device_bridge/process_adapter) along with their guarantees tests
- chat/node: narrow node_image and worker_node_runtime to private and expose only pub(super) run_from_args / run_worker_node_from_env
Signed-off-by: Zachery Aaron Shores-Chmielewski <zacheryasc@gmail.com>
2026-07-29 10:02:50 +00:00
|
|
|
pub api_key: Option<String>,
|
|
|
|
|
pub image: Option<String>,
|
|
|
|
|
pub relay_url: Option<String>,
|
|
|
|
|
pub bootstrap_command: Option<String>,
|
|
|
|
|
pub disk_gb: Option<u32>,
|
|
|
|
|
pub ssh_user: Option<String>,
|
|
|
|
|
pub confirm_lease: Option<bool>,
|
|
|
|
|
pub gpu_name: Option<String>,
|
|
|
|
|
pub min_gpu_ram_mb: Option<u64>,
|
|
|
|
|
pub min_down_mbps: Option<f64>,
|
|
|
|
|
pub min_up_mbps: Option<f64>,
|
|
|
|
|
pub max_dph_total: Option<f64>,
|
|
|
|
|
pub min_reliability: Option<f64>,
|
|
|
|
|
pub require_verified: Option<bool>,
|
|
|
|
|
pub blacklist_hosts: Vec<u64>,
|
|
|
|
|
pub poll_interval_secs: Option<u64>,
|
|
|
|
|
pub onstart: Option<String>,
|
|
|
|
|
pub ssh_identity: Option<String>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
2026-07-29 20:23:26 +00:00
|
|
|
pub(crate) struct ResolvedVastAiConfig {
|
refactor: prune public api
Collapse mvp-system's public surface to three binary entrypoints and make every domain module private, deleting dead provider/worker/membership implementations and inlining provider config.
- lib.rs: expose only run_chat_from_args/run_orchestrator_from_args/run_worker_node_from_env (plus a crate-private in-process helper) and the cached-model consts, and demote chat/node/observability/orchestration/prompt/staging/transport to private mods
- orchestration/mod.rs: make app private, gate engine_builder behind cfg(test), drop docker_cluster from provider_adapters, tighten vastai to pub(super), and replace pub re-exports with pub(super) run_from_args/run_in_process_from_args
- orchestration/config.rs: inline VastAiConfig/ResolvedVastAiConfig/looks_remote_image (removing provider_adapters/vastai/config.rs) and drop the DEFAULT_PIPELINE_CACHED_MODEL_* consts (hoisted to lib.rs)
- orchestration/provider_adapters/vastai: delete the ProviderPlugin impl VastAiProviderPlugin and all client/bootstrap/config accessors; repoint call sites to crate-level #[path] mods for provisioning/node_provisioning/node_actor/gguf_shard/run_fsm/run_plan
- delete orchestration/{membership_readiness,token_endpoint,resource_inventory}, node/{boot_lifecycle,data_plane_bridge(-74)}, and the worker crate-internal modules (control/device_bridge/process_adapter) along with their guarantees tests
- chat/node: narrow node_image and worker_node_runtime to private and expose only pub(super) run_from_args / run_worker_node_from_env
Signed-off-by: Zachery Aaron Shores-Chmielewski <zacheryasc@gmail.com>
2026-07-29 10:02:50 +00:00
|
|
|
pub api_key: String,
|
|
|
|
|
pub relay_url: String,
|
|
|
|
|
pub image: String,
|
|
|
|
|
pub bootstrap_command: String,
|
|
|
|
|
pub disk_gb: Option<u32>,
|
|
|
|
|
pub gpu_name: Option<String>,
|
|
|
|
|
pub min_gpu_ram_mb: Option<u64>,
|
|
|
|
|
pub min_down_mbps: Option<f64>,
|
|
|
|
|
pub min_up_mbps: Option<f64>,
|
|
|
|
|
pub max_dph_total: Option<f64>,
|
|
|
|
|
pub min_reliability: Option<f64>,
|
|
|
|
|
pub require_verified: Option<bool>,
|
|
|
|
|
pub blacklist_hosts: Vec<u64>,
|
|
|
|
|
pub onstart: Option<String>,
|
|
|
|
|
pub ssh_identity: Option<String>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ResolvedVastAiConfig {
|
2026-07-29 20:23:26 +00:00
|
|
|
pub(crate) fn validate(self) -> Result<Self, String> {
|
refactor: prune public api
Collapse mvp-system's public surface to three binary entrypoints and make every domain module private, deleting dead provider/worker/membership implementations and inlining provider config.
- lib.rs: expose only run_chat_from_args/run_orchestrator_from_args/run_worker_node_from_env (plus a crate-private in-process helper) and the cached-model consts, and demote chat/node/observability/orchestration/prompt/staging/transport to private mods
- orchestration/mod.rs: make app private, gate engine_builder behind cfg(test), drop docker_cluster from provider_adapters, tighten vastai to pub(super), and replace pub re-exports with pub(super) run_from_args/run_in_process_from_args
- orchestration/config.rs: inline VastAiConfig/ResolvedVastAiConfig/looks_remote_image (removing provider_adapters/vastai/config.rs) and drop the DEFAULT_PIPELINE_CACHED_MODEL_* consts (hoisted to lib.rs)
- orchestration/provider_adapters/vastai: delete the ProviderPlugin impl VastAiProviderPlugin and all client/bootstrap/config accessors; repoint call sites to crate-level #[path] mods for provisioning/node_provisioning/node_actor/gguf_shard/run_fsm/run_plan
- delete orchestration/{membership_readiness,token_endpoint,resource_inventory}, node/{boot_lifecycle,data_plane_bridge(-74)}, and the worker crate-internal modules (control/device_bridge/process_adapter) along with their guarantees tests
- chat/node: narrow node_image and worker_node_runtime to private and expose only pub(super) run_from_args / run_worker_node_from_env
Signed-off-by: Zachery Aaron Shores-Chmielewski <zacheryasc@gmail.com>
2026-07-29 10:02:50 +00:00
|
|
|
require_non_empty("VAST_API_KEY", &self.api_key)?;
|
|
|
|
|
require_non_empty("relay.url", &self.relay_url)?;
|
|
|
|
|
require_non_empty("vastai.image", &self.image)?;
|
|
|
|
|
require_non_empty("vastai.bootstrap_command", &self.bootstrap_command)?;
|
|
|
|
|
if let Some(identity) = &self.ssh_identity {
|
|
|
|
|
require_non_empty("vastai.ssh_identity", identity)?;
|
|
|
|
|
}
|
|
|
|
|
if !looks_remote_image(&self.image) {
|
|
|
|
|
return Err(format!(
|
|
|
|
|
"vastai.image {:?} must include a registry namespace",
|
|
|
|
|
self.image
|
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
Ok(self)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn require_non_empty(label: &str, value: &str) -> Result<(), String> {
|
|
|
|
|
if value.trim().is_empty() {
|
|
|
|
|
Err(format!("missing required {label}"))
|
|
|
|
|
} else {
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-29 20:23:26 +00:00
|
|
|
pub(crate) fn looks_remote_image(image: &str) -> bool {
|
refactor: prune public api
Collapse mvp-system's public surface to three binary entrypoints and make every domain module private, deleting dead provider/worker/membership implementations and inlining provider config.
- lib.rs: expose only run_chat_from_args/run_orchestrator_from_args/run_worker_node_from_env (plus a crate-private in-process helper) and the cached-model consts, and demote chat/node/observability/orchestration/prompt/staging/transport to private mods
- orchestration/mod.rs: make app private, gate engine_builder behind cfg(test), drop docker_cluster from provider_adapters, tighten vastai to pub(super), and replace pub re-exports with pub(super) run_from_args/run_in_process_from_args
- orchestration/config.rs: inline VastAiConfig/ResolvedVastAiConfig/looks_remote_image (removing provider_adapters/vastai/config.rs) and drop the DEFAULT_PIPELINE_CACHED_MODEL_* consts (hoisted to lib.rs)
- orchestration/provider_adapters/vastai: delete the ProviderPlugin impl VastAiProviderPlugin and all client/bootstrap/config accessors; repoint call sites to crate-level #[path] mods for provisioning/node_provisioning/node_actor/gguf_shard/run_fsm/run_plan
- delete orchestration/{membership_readiness,token_endpoint,resource_inventory}, node/{boot_lifecycle,data_plane_bridge(-74)}, and the worker crate-internal modules (control/device_bridge/process_adapter) along with their guarantees tests
- chat/node: narrow node_image and worker_node_runtime to private and expose only pub(super) run_from_args / run_worker_node_from_env
Signed-off-by: Zachery Aaron Shores-Chmielewski <zacheryasc@gmail.com>
2026-07-29 10:02:50 +00:00
|
|
|
let repository = image.split('@').next().unwrap_or(image);
|
|
|
|
|
let last_slash = repository.rfind('/');
|
|
|
|
|
let tag_separator = repository
|
|
|
|
|
.rfind(':')
|
|
|
|
|
.filter(|separator| last_slash.is_some_and(|slash| *separator > slash));
|
|
|
|
|
let repository = tag_separator.map_or(repository, |separator| &repository[..separator]);
|
|
|
|
|
let Some((host, _)) = repository.split_once('/') else {
|
|
|
|
|
return false;
|
|
|
|
|
};
|
|
|
|
|
host == "localhost" || host.contains('.') || host.contains(':')
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-15 08:49:56 +00:00
|
|
|
/// Shared overlay for legacy and multi-binary configuration parsing. This accepts
|
|
|
|
|
/// fields outside the fixed `mvp-chat` public config surface; `mvp-chat` uses a
|
|
|
|
|
/// bin-local strict config loader instead.
|
2026-07-07 10:40:02 +00:00
|
|
|
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
|
|
|
|
|
#[serde(default)]
|
2026-07-29 20:23:26 +00:00
|
|
|
pub(crate) struct TomlConfigOverlay {
|
2026-07-08 09:14:49 +00:00
|
|
|
pub runtime: RuntimeConfigOverlay,
|
|
|
|
|
pub provider: ProviderConfigOverlay,
|
2026-07-07 10:40:02 +00:00
|
|
|
pub image: ImageConfig,
|
|
|
|
|
pub relay: RelayConfig,
|
|
|
|
|
pub prompt: PromptConfig,
|
|
|
|
|
pub model: ModelConfig,
|
2026-07-08 09:14:49 +00:00
|
|
|
pub docker: DockerConfigOverlay,
|
|
|
|
|
pub observability: ObservabilityConfigOverlay,
|
2026-07-07 10:40:02 +00:00
|
|
|
pub vastai: VastAiConfig,
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-08 09:14:49 +00:00
|
|
|
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
|
|
|
|
|
#[serde(default)]
|
2026-07-29 20:23:26 +00:00
|
|
|
pub(crate) struct RuntimeConfigOverlay {
|
2026-07-08 09:14:49 +00:00
|
|
|
pub profile: Option<String>,
|
|
|
|
|
pub run_id: Option<u64>,
|
|
|
|
|
pub node_id: Option<u64>,
|
|
|
|
|
pub stage_index: Option<u32>,
|
|
|
|
|
pub layer_end_exclusive: Option<u32>,
|
2026-07-12 06:14:34 +00:00
|
|
|
pub pipeline_stages: Option<u32>,
|
2026-07-08 09:14:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
|
|
|
|
|
#[serde(default)]
|
2026-07-29 20:23:26 +00:00
|
|
|
pub(crate) struct ProviderConfigOverlay {
|
2026-07-08 09:14:49 +00:00
|
|
|
pub kind: Option<String>,
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-07 10:40:02 +00:00
|
|
|
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
|
|
|
|
|
#[serde(default)]
|
2026-07-29 20:23:26 +00:00
|
|
|
pub(crate) struct ImageConfig {
|
2026-07-07 10:40:02 +00:00
|
|
|
pub node: Option<String>,
|
|
|
|
|
pub tag: Option<String>,
|
|
|
|
|
pub build: Option<bool>,
|
|
|
|
|
pub push: Option<bool>,
|
|
|
|
|
pub force_refresh: Option<bool>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
|
|
|
|
|
#[serde(default)]
|
2026-07-29 20:23:26 +00:00
|
|
|
pub(crate) struct RelayConfig {
|
2026-07-07 10:40:02 +00:00
|
|
|
pub mode: Option<String>,
|
|
|
|
|
pub url: Option<String>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
|
|
|
|
|
#[serde(default)]
|
2026-07-29 20:23:26 +00:00
|
|
|
pub(crate) struct PromptConfig {
|
2026-07-07 10:40:02 +00:00
|
|
|
pub rpc_addr: Option<String>,
|
|
|
|
|
pub max_tokens: Option<u32>,
|
|
|
|
|
pub dashboard: Option<bool>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
|
|
|
|
|
#[serde(default)]
|
2026-07-29 20:23:26 +00:00
|
|
|
pub(crate) struct ModelConfig {
|
2026-07-07 10:40:02 +00:00
|
|
|
pub id: Option<String>,
|
2026-07-08 09:14:49 +00:00
|
|
|
pub gguf_local_path: Option<String>,
|
2026-07-07 10:40:02 +00:00
|
|
|
pub gguf_repo: Option<String>,
|
|
|
|
|
pub gguf_file: Option<String>,
|
|
|
|
|
pub gguf_revision: Option<String>,
|
2026-07-08 09:14:49 +00:00
|
|
|
pub tokenizer_local_path: Option<String>,
|
2026-07-07 10:40:02 +00:00
|
|
|
pub max_context: Option<u32>,
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-08 09:14:49 +00:00
|
|
|
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
|
|
|
|
|
#[serde(default)]
|
2026-07-29 20:23:26 +00:00
|
|
|
pub(crate) struct DockerConfigOverlay {
|
2026-07-08 09:14:49 +00:00
|
|
|
pub gpus: Option<String>,
|
|
|
|
|
pub cached_model_host_path: Option<String>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
|
|
|
|
|
#[serde(default)]
|
2026-07-29 20:23:26 +00:00
|
|
|
pub(crate) struct ObservabilityConfigOverlay {
|
2026-07-15 08:49:56 +00:00
|
|
|
pub dump_logs: Option<bool>,
|
|
|
|
|
pub dump_log_path: Option<String>,
|
2026-07-08 09:14:49 +00:00
|
|
|
pub datastream_frame_log: Option<String>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl TomlConfigOverlay {
|
2026-07-29 20:23:26 +00:00
|
|
|
pub(crate) fn load_optional(path: &Path) -> Result<Option<Self>, String> {
|
2026-07-08 09:14:49 +00:00
|
|
|
if path.is_file() {
|
|
|
|
|
Self::load_required(path).map(Some)
|
|
|
|
|
} else {
|
|
|
|
|
Ok(None)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-29 20:23:26 +00:00
|
|
|
pub(crate) fn load_required(path: &Path) -> Result<Self, String> {
|
2026-07-07 10:40:02 +00:00
|
|
|
let text =
|
|
|
|
|
fs::read_to_string(path).map_err(|e| format!("read config {}: {e}", path.display()))?;
|
|
|
|
|
Self::from_str(&text).map_err(|e| format!("parse config {}: {e}", path.display()))
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-29 20:23:26 +00:00
|
|
|
pub(crate) fn from_str(text: &str) -> Result<Self, toml::de::Error> {
|
2026-07-07 10:40:02 +00:00
|
|
|
toml::from_str(text)
|
|
|
|
|
}
|
|
|
|
|
}
|