2026-07-08 14:06:00 +00:00
|
|
|
use iroh::EndpointAddr;
|
2026-06-24 09:30:29 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
use swactor::actor::{ActorAddress, ActorInterface};
|
|
|
|
|
use swactor::runtime::Ctx;
|
|
|
|
|
use swactor_transport::{CodecRegistry, NetworkMessage};
|
|
|
|
|
|
2026-07-28 07:29:31 +00:00
|
|
|
use crate::orchestration::run_fsm as core;
|
2026-06-24 09:30:29 +00:00
|
|
|
|
refactor: final filetree shape
Reorganize crates/mvp-system from flat files into domain module trees (chat, node, node_data, observability, orchestration, prompt, staging, transport, worker) with documented mod.rs boundaries, and drop the stale inline spec docs.
- lib.rs: replace ~20 flat mod declarations with one pub-mod-per-domain (chat/node/node_data/observability/orchestration/prompt/staging/transport/worker)
- node/, chat/, observability/, orchestration/, staging/, prompt/, transport/, worker/: add mod.rs files with module-boundary doc comments and re-exports (e.g. chat re-exports run_from_args; orchestration re-exports RunConfig/RunId/GgufSource/TokenizerSource/ProviderKind)
- orchestration: group providers under provider_adapters/{docker_cluster,relay,vastai} and fold engine_builder/, config, run_fsm, run_plan, provisioning, resource_inventory, membership_readiness, and token_endpoint under orchestration/
- transport: consolidate codec registration into transport/codec_registry::register_mvp_actor_codecs (was crate::actors::register_mvp_actor_codecs) and rename actors/codec.rs to transport/json_codec.rs
- rename and relocate files into their domains (arena_manager->node_data/arena, actors/node_agent->node/actor, actors/orchestrator->orchestration/actor, stage_controller->staging/actor, telemetry/dashboard_view/etc->observability/, benchmark_observability->observability::benchmark, edge_establisher->node::edge_lifecycle, prompt_rpc->prompt::rpc) and update all crate:: imports accordingly
- remove the stale crates/mvp-system/specs/*.md (MVP_SYSTEM_MODULE_BOUNDARY_SPEC, mvp_chat, orchestrator) now that module boundaries live in mod.rs docs
Signed-off-by: Zachery Aaron Shores-Chmielewski <zacheryasc@gmail.com>
2026-07-28 09:04:13 +00:00
|
|
|
use crate::transport::json_codec::JsonCodec;
|
2026-06-24 09:30:29 +00:00
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
|
|
|
|
pub struct StageRefWire {
|
|
|
|
|
pub stage_index: u32,
|
|
|
|
|
pub node_id: u64,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
|
|
|
|
pub enum OrchestratorMsg {
|
|
|
|
|
ObservePoolReady {
|
|
|
|
|
nodes: Vec<u64>,
|
|
|
|
|
},
|
|
|
|
|
ObservePlanAvailable {
|
|
|
|
|
run_id: u64,
|
|
|
|
|
stages: Vec<StageRefWire>,
|
|
|
|
|
},
|
|
|
|
|
ObserveStageReady {
|
|
|
|
|
run_id: u64,
|
|
|
|
|
stage_index: u32,
|
|
|
|
|
},
|
2026-07-08 14:06:00 +00:00
|
|
|
ObserveNodeRuntimeReady {
|
|
|
|
|
run_id: u64,
|
|
|
|
|
node_id: u64,
|
|
|
|
|
stage_index: u32,
|
|
|
|
|
endpoint: EndpointAddr,
|
|
|
|
|
node_actor: ActorAddress,
|
2026-07-12 06:14:34 +00:00
|
|
|
datastream_publisher: ActorAddress,
|
2026-07-09 08:53:53 +00:00
|
|
|
readiness_id: u64,
|
2026-07-08 14:06:00 +00:00
|
|
|
},
|
2026-07-12 06:14:34 +00:00
|
|
|
ObserveNodeRuntimeReadyAck {
|
|
|
|
|
run_id: u64,
|
|
|
|
|
node_id: u64,
|
|
|
|
|
stage_index: u32,
|
|
|
|
|
readiness_id: u64,
|
|
|
|
|
},
|
|
|
|
|
ObserveWeightsReady {
|
|
|
|
|
run_id: u64,
|
|
|
|
|
node_id: u64,
|
|
|
|
|
stage_index: u32,
|
|
|
|
|
},
|
2026-06-24 09:30:29 +00:00
|
|
|
ObserveTokenInEndpointReady,
|
|
|
|
|
ObserveTokenOutEndpointReady,
|
|
|
|
|
ObserveTokenReceived {
|
|
|
|
|
sequence: u64,
|
|
|
|
|
token_id: u32,
|
|
|
|
|
eos: bool,
|
|
|
|
|
},
|
|
|
|
|
ObserveStageFault {
|
|
|
|
|
run_id: u64,
|
|
|
|
|
stage_index: u32,
|
|
|
|
|
},
|
|
|
|
|
ObserveEndpointFault {
|
|
|
|
|
run_id: u64,
|
|
|
|
|
endpoint: EndpointKindWire,
|
|
|
|
|
},
|
|
|
|
|
ObserveStageStopped {
|
|
|
|
|
run_id: u64,
|
|
|
|
|
stage_index: u32,
|
|
|
|
|
},
|
|
|
|
|
ObserveTokenEndpointsStopped,
|
|
|
|
|
AdvanceTimeMs(u64),
|
|
|
|
|
Snapshot {
|
|
|
|
|
reply_to: ActorAddress,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl NetworkMessage for OrchestratorMsg {
|
|
|
|
|
fn type_tag() -> &'static str {
|
|
|
|
|
"mvp_system::OrchestratorMsg"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
|
|
|
|
pub enum EndpointKindWire {
|
|
|
|
|
TokenIn,
|
|
|
|
|
TokenOut,
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-25 12:30:18 +00:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
|
|
|
|
pub struct SamplingDataWire {
|
|
|
|
|
pub source_sequence: u64,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
|
|
|
|
pub enum TokenObjectPayloadWire {
|
|
|
|
|
Prompt {
|
|
|
|
|
tokens: Vec<u32>,
|
|
|
|
|
},
|
|
|
|
|
Decode {
|
|
|
|
|
token_id: u32,
|
|
|
|
|
sampling: SamplingDataWire,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-24 09:30:29 +00:00
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
|
|
|
|
pub enum RunCommandWire {
|
|
|
|
|
ProvisionStage {
|
|
|
|
|
run_id: u64,
|
|
|
|
|
stage_index: u32,
|
|
|
|
|
node_id: u64,
|
|
|
|
|
},
|
|
|
|
|
CreateTokenInEndpoint {
|
|
|
|
|
run_id: u64,
|
|
|
|
|
},
|
|
|
|
|
CreateTokenOutEndpoint {
|
|
|
|
|
run_id: u64,
|
|
|
|
|
},
|
2026-06-25 12:30:18 +00:00
|
|
|
InjectTokenObject {
|
2026-06-24 09:30:29 +00:00
|
|
|
run_id: u64,
|
|
|
|
|
sequence: u64,
|
2026-06-25 12:30:18 +00:00
|
|
|
payload: TokenObjectPayloadWire,
|
2026-06-24 09:30:29 +00:00
|
|
|
},
|
|
|
|
|
StopRun {
|
|
|
|
|
run_id: u64,
|
|
|
|
|
stage_index: u32,
|
|
|
|
|
},
|
|
|
|
|
TearDownTokenEndpoints {
|
|
|
|
|
run_id: u64,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
|
|
|
|
pub enum LifecycleEventWire {
|
|
|
|
|
RunRejected { run_id: u64 },
|
|
|
|
|
RunFaulted { run_id: u64 },
|
|
|
|
|
RunCompleted { run_id: u64 },
|
2026-06-25 12:30:18 +00:00
|
|
|
RunOperatorStopped { run_id: u64 },
|
2026-06-24 09:30:29 +00:00
|
|
|
RunTornDown { run_id: u64 },
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
|
|
|
|
pub enum OrchestratorReport {
|
|
|
|
|
Command(RunCommandWire),
|
|
|
|
|
Lifecycle(LifecycleEventWire),
|
2026-07-08 14:06:00 +00:00
|
|
|
NodeRuntimeReady {
|
|
|
|
|
run_id: u64,
|
|
|
|
|
node_id: u64,
|
|
|
|
|
stage_index: u32,
|
|
|
|
|
endpoint: EndpointAddr,
|
|
|
|
|
node_actor: ActorAddress,
|
2026-07-12 06:14:34 +00:00
|
|
|
datastream_publisher: ActorAddress,
|
2026-07-09 08:53:53 +00:00
|
|
|
readiness_id: u64,
|
2026-07-08 14:06:00 +00:00
|
|
|
},
|
2026-07-12 06:14:34 +00:00
|
|
|
NodeRuntimeReadyAck {
|
|
|
|
|
run_id: u64,
|
|
|
|
|
node_id: u64,
|
|
|
|
|
stage_index: u32,
|
|
|
|
|
readiness_id: u64,
|
|
|
|
|
},
|
|
|
|
|
WeightsReady {
|
|
|
|
|
run_id: u64,
|
|
|
|
|
node_id: u64,
|
|
|
|
|
stage_index: u32,
|
|
|
|
|
},
|
|
|
|
|
StageReady {
|
|
|
|
|
run_id: u64,
|
|
|
|
|
stage_index: u32,
|
|
|
|
|
},
|
|
|
|
|
StageFault {
|
|
|
|
|
run_id: u64,
|
|
|
|
|
stage_index: u32,
|
|
|
|
|
},
|
2026-06-24 09:30:29 +00:00
|
|
|
Snapshot {
|
|
|
|
|
commands: Vec<RunCommandWire>,
|
|
|
|
|
events: Vec<LifecycleEventWire>,
|
|
|
|
|
injected_sequences: Vec<u64>,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl NetworkMessage for OrchestratorReport {
|
|
|
|
|
fn type_tag() -> &'static str {
|
|
|
|
|
"mvp_system::OrchestratorReport"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct OrchestratorActor {
|
|
|
|
|
core: core::OrchestratorRun,
|
|
|
|
|
report_to: Option<ActorAddress>,
|
|
|
|
|
command_cursor: usize,
|
|
|
|
|
event_cursor: usize,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl OrchestratorActor {
|
|
|
|
|
pub fn new(config: core::RunConfig, report_to: Option<ActorAddress>) -> Self {
|
|
|
|
|
Self {
|
|
|
|
|
core: core::OrchestratorRun::new(config),
|
|
|
|
|
report_to,
|
|
|
|
|
command_cursor: 0,
|
|
|
|
|
event_cursor: 0,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn observe(&mut self, msg: OrchestratorMsg) {
|
|
|
|
|
match msg {
|
|
|
|
|
OrchestratorMsg::ObservePoolReady { nodes } => {
|
|
|
|
|
self.core.observe(core::RunEvent::PoolReady {
|
|
|
|
|
nodes: nodes.into_iter().map(core::NodeId).collect(),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
OrchestratorMsg::ObservePlanAvailable { run_id, stages } => {
|
|
|
|
|
self.core
|
|
|
|
|
.observe(core::RunEvent::PlanAvailable(core::RunPlan {
|
|
|
|
|
run_id: core::RunId(run_id),
|
|
|
|
|
stages: stages
|
|
|
|
|
.into_iter()
|
|
|
|
|
.map(|stage| core::StageRef {
|
|
|
|
|
stage_index: stage.stage_index,
|
|
|
|
|
node_id: core::NodeId(stage.node_id),
|
|
|
|
|
})
|
|
|
|
|
.collect(),
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
OrchestratorMsg::ObserveStageReady {
|
|
|
|
|
run_id,
|
|
|
|
|
stage_index,
|
|
|
|
|
} => self.core.observe(core::RunEvent::StageReady {
|
|
|
|
|
run_id: core::RunId(run_id),
|
|
|
|
|
stage_index,
|
|
|
|
|
}),
|
2026-07-08 14:06:00 +00:00
|
|
|
OrchestratorMsg::ObserveNodeRuntimeReady { .. } => {}
|
2026-07-12 06:14:34 +00:00
|
|
|
OrchestratorMsg::ObserveNodeRuntimeReadyAck { .. } => {}
|
|
|
|
|
OrchestratorMsg::ObserveWeightsReady { .. } => {}
|
2026-06-24 09:30:29 +00:00
|
|
|
OrchestratorMsg::ObserveTokenInEndpointReady => {
|
|
|
|
|
self.core.observe(core::RunEvent::TokenInEndpointReady)
|
|
|
|
|
}
|
|
|
|
|
OrchestratorMsg::ObserveTokenOutEndpointReady => {
|
|
|
|
|
self.core.observe(core::RunEvent::TokenOutEndpointReady)
|
|
|
|
|
}
|
|
|
|
|
OrchestratorMsg::ObserveTokenReceived {
|
|
|
|
|
sequence,
|
|
|
|
|
token_id,
|
|
|
|
|
eos,
|
|
|
|
|
} => self.core.observe(core::RunEvent::TokenReceived {
|
|
|
|
|
sequence,
|
|
|
|
|
token_id,
|
|
|
|
|
eos,
|
|
|
|
|
}),
|
|
|
|
|
OrchestratorMsg::ObserveStageFault {
|
|
|
|
|
run_id,
|
|
|
|
|
stage_index,
|
|
|
|
|
} => self.core.observe(core::RunEvent::StageFault {
|
|
|
|
|
run_id: core::RunId(run_id),
|
|
|
|
|
stage_index,
|
|
|
|
|
reason: core::StageFaultReason::WorkerCrashed,
|
|
|
|
|
}),
|
|
|
|
|
OrchestratorMsg::ObserveEndpointFault { run_id, endpoint } => {
|
|
|
|
|
self.core.observe(core::RunEvent::EndpointFault {
|
|
|
|
|
run_id: core::RunId(run_id),
|
|
|
|
|
endpoint: match endpoint {
|
|
|
|
|
EndpointKindWire::TokenIn => core::EndpointKind::TokenIn,
|
|
|
|
|
EndpointKindWire::TokenOut => core::EndpointKind::TokenOut,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
OrchestratorMsg::ObserveStageStopped {
|
|
|
|
|
run_id,
|
|
|
|
|
stage_index,
|
|
|
|
|
} => self.core.observe(core::RunEvent::StageStopped {
|
|
|
|
|
run_id: core::RunId(run_id),
|
|
|
|
|
stage_index,
|
|
|
|
|
}),
|
|
|
|
|
OrchestratorMsg::ObserveTokenEndpointsStopped => {
|
|
|
|
|
self.core.observe(core::RunEvent::TokenEndpointsStopped)
|
|
|
|
|
}
|
|
|
|
|
OrchestratorMsg::AdvanceTimeMs(delta) => self.core.advance_time_ms(delta),
|
|
|
|
|
OrchestratorMsg::Snapshot { .. } => {}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn drain_outputs(&mut self, ctx: &Ctx) {
|
|
|
|
|
let Some(report_to) = self.report_to else {
|
|
|
|
|
self.command_cursor = self.core.commands().len();
|
|
|
|
|
self.event_cursor = self.core.events().len();
|
|
|
|
|
return;
|
|
|
|
|
};
|
|
|
|
|
for command in &self.core.commands()[self.command_cursor..] {
|
|
|
|
|
let _ = ctx.send(report_to, OrchestratorReport::Command(command.into()));
|
|
|
|
|
}
|
|
|
|
|
self.command_cursor = self.core.commands().len();
|
|
|
|
|
|
|
|
|
|
for event in &self.core.events()[self.event_cursor..] {
|
|
|
|
|
let _ = ctx.send(report_to, OrchestratorReport::Lifecycle(event.into()));
|
|
|
|
|
}
|
|
|
|
|
self.event_cursor = self.core.events().len();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ActorInterface for OrchestratorActor {
|
|
|
|
|
type Incoming = OrchestratorMsg;
|
|
|
|
|
type Response = ();
|
|
|
|
|
|
|
|
|
|
fn handle(&mut self, ctx: &Ctx, msg: Self::Incoming) {
|
2026-07-12 06:14:34 +00:00
|
|
|
match msg.clone() {
|
|
|
|
|
OrchestratorMsg::ObserveNodeRuntimeReady {
|
|
|
|
|
run_id,
|
|
|
|
|
node_id,
|
|
|
|
|
stage_index,
|
|
|
|
|
endpoint,
|
|
|
|
|
node_actor,
|
|
|
|
|
datastream_publisher,
|
|
|
|
|
readiness_id,
|
|
|
|
|
} => {
|
|
|
|
|
if let Some(report_to) = self.report_to {
|
|
|
|
|
let _ = ctx.send(
|
|
|
|
|
report_to,
|
|
|
|
|
OrchestratorReport::NodeRuntimeReady {
|
|
|
|
|
run_id,
|
|
|
|
|
node_id,
|
|
|
|
|
stage_index,
|
|
|
|
|
endpoint,
|
|
|
|
|
node_actor,
|
|
|
|
|
datastream_publisher,
|
|
|
|
|
readiness_id,
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
OrchestratorMsg::ObserveNodeRuntimeReadyAck {
|
|
|
|
|
run_id,
|
|
|
|
|
node_id,
|
|
|
|
|
stage_index,
|
|
|
|
|
readiness_id,
|
|
|
|
|
} => {
|
|
|
|
|
if let Some(report_to) = self.report_to {
|
|
|
|
|
let _ = ctx.send(
|
|
|
|
|
report_to,
|
|
|
|
|
OrchestratorReport::NodeRuntimeReadyAck {
|
|
|
|
|
run_id,
|
|
|
|
|
node_id,
|
|
|
|
|
stage_index,
|
|
|
|
|
readiness_id,
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
OrchestratorMsg::ObserveWeightsReady {
|
|
|
|
|
run_id,
|
|
|
|
|
node_id,
|
|
|
|
|
stage_index,
|
|
|
|
|
} => {
|
|
|
|
|
if let Some(report_to) = self.report_to {
|
|
|
|
|
let _ = ctx.send(
|
|
|
|
|
report_to,
|
|
|
|
|
OrchestratorReport::WeightsReady {
|
|
|
|
|
run_id,
|
|
|
|
|
node_id,
|
|
|
|
|
stage_index,
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
OrchestratorMsg::Snapshot { reply_to } => {
|
2026-07-08 14:06:00 +00:00
|
|
|
let _ = ctx.send(
|
2026-07-12 06:14:34 +00:00
|
|
|
reply_to,
|
|
|
|
|
OrchestratorReport::Snapshot {
|
|
|
|
|
commands: self
|
|
|
|
|
.core
|
|
|
|
|
.commands()
|
|
|
|
|
.iter()
|
|
|
|
|
.map(RunCommandWire::from)
|
|
|
|
|
.collect(),
|
|
|
|
|
events: self
|
|
|
|
|
.core
|
|
|
|
|
.events()
|
|
|
|
|
.iter()
|
|
|
|
|
.map(LifecycleEventWire::from)
|
|
|
|
|
.collect(),
|
|
|
|
|
injected_sequences: self.core.injected_sequences(),
|
2026-07-08 14:06:00 +00:00
|
|
|
},
|
|
|
|
|
);
|
2026-07-12 06:14:34 +00:00
|
|
|
return;
|
2026-07-08 14:06:00 +00:00
|
|
|
}
|
2026-07-12 06:14:34 +00:00
|
|
|
_ => {}
|
2026-06-24 09:30:29 +00:00
|
|
|
}
|
2026-07-12 06:14:34 +00:00
|
|
|
|
|
|
|
|
let direct_report = match msg.clone() {
|
|
|
|
|
OrchestratorMsg::ObserveStageReady {
|
|
|
|
|
run_id,
|
|
|
|
|
stage_index,
|
|
|
|
|
} => Some(OrchestratorReport::StageReady {
|
|
|
|
|
run_id,
|
|
|
|
|
stage_index,
|
|
|
|
|
}),
|
|
|
|
|
OrchestratorMsg::ObserveStageFault {
|
|
|
|
|
run_id,
|
|
|
|
|
stage_index,
|
|
|
|
|
} => Some(OrchestratorReport::StageFault {
|
|
|
|
|
run_id,
|
|
|
|
|
stage_index,
|
|
|
|
|
}),
|
|
|
|
|
_ => None,
|
|
|
|
|
};
|
|
|
|
|
|
2026-06-24 09:30:29 +00:00
|
|
|
self.observe(msg);
|
2026-07-12 06:14:34 +00:00
|
|
|
if let (Some(report_to), Some(report)) = (self.report_to, direct_report) {
|
|
|
|
|
let _ = ctx.send(report_to, report);
|
|
|
|
|
}
|
2026-06-24 09:30:29 +00:00
|
|
|
self.drain_outputs(ctx);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<&core::RunCommand> for RunCommandWire {
|
|
|
|
|
fn from(command: &core::RunCommand) -> Self {
|
|
|
|
|
match command {
|
|
|
|
|
core::RunCommand::ProvisionStage { provision } => Self::ProvisionStage {
|
|
|
|
|
run_id: provision.run_id.0,
|
|
|
|
|
stage_index: provision.stage_index,
|
|
|
|
|
node_id: provision.node_id.0,
|
|
|
|
|
},
|
|
|
|
|
core::RunCommand::CreateTokenInEndpoint { run_id } => {
|
|
|
|
|
Self::CreateTokenInEndpoint { run_id: run_id.0 }
|
|
|
|
|
}
|
|
|
|
|
core::RunCommand::CreateTokenOutEndpoint { run_id } => {
|
|
|
|
|
Self::CreateTokenOutEndpoint { run_id: run_id.0 }
|
|
|
|
|
}
|
2026-06-25 12:30:18 +00:00
|
|
|
core::RunCommand::InjectTokenObject { run_id, object } => Self::InjectTokenObject {
|
2026-06-24 09:30:29 +00:00
|
|
|
run_id: run_id.0,
|
2026-06-25 12:30:18 +00:00
|
|
|
sequence: object.sequence,
|
|
|
|
|
payload: (&object.payload).into(),
|
2026-06-24 09:30:29 +00:00
|
|
|
},
|
|
|
|
|
core::RunCommand::StopRun {
|
|
|
|
|
run_id,
|
|
|
|
|
stage_index,
|
|
|
|
|
} => Self::StopRun {
|
|
|
|
|
run_id: run_id.0,
|
|
|
|
|
stage_index: *stage_index,
|
|
|
|
|
},
|
|
|
|
|
core::RunCommand::TearDownTokenEndpoints { run_id } => {
|
|
|
|
|
Self::TearDownTokenEndpoints { run_id: run_id.0 }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<&core::LifecycleEvent> for LifecycleEventWire {
|
|
|
|
|
fn from(event: &core::LifecycleEvent) -> Self {
|
|
|
|
|
match event {
|
|
|
|
|
core::LifecycleEvent::RunRejected { run_id, .. } => {
|
|
|
|
|
Self::RunRejected { run_id: run_id.0 }
|
|
|
|
|
}
|
|
|
|
|
core::LifecycleEvent::RunFaulted { run_id, .. } => {
|
|
|
|
|
Self::RunFaulted { run_id: run_id.0 }
|
|
|
|
|
}
|
|
|
|
|
core::LifecycleEvent::RunCompleted { run_id } => {
|
|
|
|
|
Self::RunCompleted { run_id: run_id.0 }
|
|
|
|
|
}
|
2026-06-25 12:30:18 +00:00
|
|
|
core::LifecycleEvent::RunOperatorStopped { run_id } => {
|
|
|
|
|
Self::RunOperatorStopped { run_id: run_id.0 }
|
|
|
|
|
}
|
2026-06-24 09:30:29 +00:00
|
|
|
core::LifecycleEvent::RunTornDown { run_id } => Self::RunTornDown { run_id: run_id.0 },
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn register_codecs(registry: &mut CodecRegistry) {
|
|
|
|
|
registry.register::<OrchestratorMsg, _>(JsonCodec::<OrchestratorMsg>::default());
|
|
|
|
|
registry.register::<OrchestratorReport, _>(JsonCodec::<OrchestratorReport>::default());
|
|
|
|
|
}
|
2026-06-25 12:30:18 +00:00
|
|
|
|
|
|
|
|
impl From<&core::TokenObjectPayload> for TokenObjectPayloadWire {
|
|
|
|
|
fn from(payload: &core::TokenObjectPayload) -> Self {
|
|
|
|
|
match payload {
|
|
|
|
|
core::TokenObjectPayload::Prompt { tokens } => Self::Prompt {
|
|
|
|
|
tokens: tokens.clone(),
|
|
|
|
|
},
|
|
|
|
|
core::TokenObjectPayload::Decode { token_id, sampling } => Self::Decode {
|
|
|
|
|
token_id: *token_id,
|
|
|
|
|
sampling: SamplingDataWire {
|
|
|
|
|
source_sequence: sampling.source_sequence,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-07-08 14:06:00 +00:00
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests {
|
|
|
|
|
use super::*;
|
|
|
|
|
use iroh::SecretKey;
|
|
|
|
|
use swactor::config::RuntimeConfig;
|
|
|
|
|
use swactor::runtime::Runtime;
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn orchestrator_actor_reports_node_runtime_ready() {
|
|
|
|
|
let runtime = Runtime::new(RuntimeConfig::default());
|
|
|
|
|
let reports = runtime
|
|
|
|
|
.new_inbox::<OrchestratorReport>()
|
|
|
|
|
.expect("orchestrator report inbox");
|
|
|
|
|
let report_to = *reports.addr();
|
|
|
|
|
let actor = runtime
|
|
|
|
|
.spawn(OrchestratorActor::new(
|
|
|
|
|
core::RunConfig {
|
|
|
|
|
run_id: core::RunId(7),
|
|
|
|
|
max_tokens: 1,
|
|
|
|
|
prompt: Vec::new(),
|
|
|
|
|
},
|
|
|
|
|
Some(report_to),
|
|
|
|
|
))
|
|
|
|
|
.expect("spawn orchestrator actor");
|
|
|
|
|
let endpoint = EndpointAddr::new(SecretKey::from_bytes(&[8; 32]).public());
|
|
|
|
|
let node_actor = ActorAddress::new_random();
|
2026-07-12 06:14:34 +00:00
|
|
|
let datastream_publisher = ActorAddress::new_random();
|
2026-07-08 14:06:00 +00:00
|
|
|
|
|
|
|
|
runtime
|
|
|
|
|
.send_to(
|
|
|
|
|
actor,
|
|
|
|
|
OrchestratorMsg::ObserveNodeRuntimeReady {
|
|
|
|
|
run_id: 7,
|
|
|
|
|
node_id: 11,
|
|
|
|
|
stage_index: 3,
|
|
|
|
|
endpoint: endpoint.clone(),
|
|
|
|
|
node_actor,
|
2026-07-12 06:14:34 +00:00
|
|
|
datastream_publisher,
|
2026-07-09 08:53:53 +00:00
|
|
|
readiness_id: 99,
|
2026-07-08 14:06:00 +00:00
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
.expect("send runtime ready");
|
|
|
|
|
runtime.tick();
|
|
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
|
reports.try_recv(),
|
|
|
|
|
Some(OrchestratorReport::NodeRuntimeReady {
|
|
|
|
|
run_id: 7,
|
|
|
|
|
node_id: 11,
|
|
|
|
|
stage_index: 3,
|
|
|
|
|
endpoint,
|
|
|
|
|
node_actor,
|
2026-07-12 06:14:34 +00:00
|
|
|
datastream_publisher,
|
2026-07-09 08:53:53 +00:00
|
|
|
readiness_id: 99,
|
2026-07-08 14:06:00 +00:00
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(reports.try_recv(), None);
|
|
|
|
|
}
|
|
|
|
|
}
|