stash before refactor

This commit is contained in:
Zachery Aaron Shores-Chmielewski 2026-07-21 10:25:52 +04:00
parent 808435ce2a
commit 7a7283ab85
7 changed files with 1834 additions and 2591 deletions

View file

@ -12,6 +12,7 @@ swactor = { path = "../..", features = ["serde", "transport"] }
swactor-transport = { path = "../transport" } swactor-transport = { path = "../transport" }
distribution = { path = "../distribution" } distribution = { path = "../distribution" }
datastream = { path = "../datastream" } datastream = { path = "../datastream" }
crossbeam-channel = "0.5"
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
serde_json = "1" serde_json = "1"
iroh = "0.98" iroh = "0.98"

File diff suppressed because it is too large Load diff

View file

@ -1,12 +1,12 @@
//! Iroh/QUIC transport adapter for datastream subscriptions. //! Iroh/QUIC transport adapter for datastream subscriptions.
use std::collections::BTreeMap;
use std::error::Error; use std::error::Error;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use crossbeam_channel::TryRecvError;
use datastream::{ use datastream::{
CatalogSnapshot, ChannelDescriptor, ChannelId, ChannelRef, DatastreamEvent, DatastreamSnapshot, ChannelDescriptor, ChannelId, ChannelRef, DatastreamEvent, DatastreamSnapshot,
DatastreamSubscription, FrameDelivery, Position, StreamDescriptor, DatastreamSubscription, FrameDelivery, Position, StreamDescriptor,
}; };
use iroh::endpoint::{Connection, RecvStream, SendStream}; use iroh::endpoint::{Connection, RecvStream, SendStream};
@ -117,10 +117,10 @@ pub async fn write_subscription_until_closed(
stats.events += 1; stats.events += 1;
} }
} }
Err(std::sync::mpsc::TryRecvError::Empty) => { Err(TryRecvError::Empty) => {
tokio::time::sleep(idle_sleep).await; tokio::time::sleep(idle_sleep).await;
} }
Err(std::sync::mpsc::TryRecvError::Disconnected) => break, Err(TryRecvError::Disconnected) => break,
} }
} }
send.finish()?; send.finish()?;
@ -144,11 +144,11 @@ async fn write_subscription_inner(
stats.events += 1; stats.events += 1;
} }
} }
Err(std::sync::mpsc::TryRecvError::Empty) => match idle_sleep { Err(TryRecvError::Empty) => match idle_sleep {
Some(delay) => tokio::time::sleep(delay).await, Some(delay) => tokio::time::sleep(delay).await,
None => break, None => break,
}, },
Err(std::sync::mpsc::TryRecvError::Disconnected) => break, Err(TryRecvError::Disconnected) => break,
} }
} }
send.finish()?; send.finish()?;
@ -332,30 +332,10 @@ pub async fn read_stream_into_fanout(
fanout: Arc<datastream::DeliveryFanout>, fanout: Arc<datastream::DeliveryFanout>,
) -> Result<DatastreamQuicHeader, BoxError> { ) -> Result<DatastreamQuicHeader, BoxError> {
let read = read_events_from_stream(recv).await?; let read = read_events_from_stream(recv).await?;
let catalog = catalog_from_header(&read.header); fanout.publish_batch(read.events);
fanout.publish_batch(read.events, &catalog);
Ok(read.header) Ok(read.header)
} }
fn catalog_from_header(header: &DatastreamQuicHeader) -> CatalogSnapshot {
let mut streams = BTreeMap::new();
streams.insert(header.stream.stream.clone(), header.stream.clone());
let channels = header
.channels
.iter()
.map(|descriptor| {
(
ChannelRef {
stream: descriptor.stream.clone(),
channel: descriptor.id,
},
descriptor.clone(),
)
})
.collect();
CatalogSnapshot { streams, channels }
}
fn put_json<T: serde::Serialize>(out: &mut Vec<u8>, value: &T) -> Result<(), BoxError> { fn put_json<T: serde::Serialize>(out: &mut Vec<u8>, value: &T) -> Result<(), BoxError> {
out.extend_from_slice(&serde_json::to_vec(value)?); out.extend_from_slice(&serde_json::to_vec(value)?);
Ok(()) Ok(())

View file

@ -29,7 +29,6 @@ async fn iroh_datastream_alpn_carries_catalog_and_numeric_frames() {
let stream = StreamId::new(NodeId::new("source-node"), Lifetime(1)); let stream = StreamId::new(NodeId::new("source-node"), Lifetime(1));
let endpoint = DatastreamEndpoint::with_capacity(stream.clone(), 8, 8); let endpoint = DatastreamEndpoint::with_capacity(stream.clone(), 8, 8);
let producer = endpoint.producer(); let producer = endpoint.producer();
producer.set_frame_timing_enabled(false);
let runtime_log = producer.register_channel("runtime.log", ChannelContent::TextStream); let runtime_log = producer.register_channel("runtime.log", ChannelContent::TextStream);
let subscription = endpoint.subscribe_all("iroh"); let subscription = endpoint.subscribe_all("iroh");

View file

@ -1390,7 +1390,7 @@ Each node has one `GpuWorkerCtl` actor. It owns:
- worker process spawn and termination through `swactor_process` - worker process spawn and termination through `swactor_process`
- worker generation numbering - worker generation numbering
- arena fd inheritance or passing setup - arena fd inheritance or passing setup
- process actor address and notification bridge - process actor address and upstream `ProcessOutput` handling
- table of installed rings for current worker generation - table of installed rings for current worker generation
- routing worker events to EdgeEstablisher, Driver, Tx/Rx actors, and role layer - routing worker events to EdgeEstablisher, Driver, Tx/Rx actors, and role layer
- crash detection and crash fanout - crash detection and crash fanout
@ -1717,7 +1717,7 @@ Stopping
Killing Killing
close/kill ProcessActor according to policy close/kill ProcessActor according to policy
reap process notification handle terminal ProcessOutput
mark installed rings faulted mark installed rings faulted
-> Stopped -> Stopped

View file

@ -10,8 +10,8 @@ contract.
## 1. Purpose ## 1. Purpose
`mvp-chat` is the user-facing process that starts an MVP runtime and attaches an `mvp-chat` is the user-facing process that starts the `mvp-chat` library runtime
interactive prompt session to it. and attaches an interactive prompt session to it.
The wrapper is responsible for: The wrapper is responsible for:
@ -19,7 +19,7 @@ The wrapper is responsible for:
- resolving provider and runtime launch configuration; - resolving provider and runtime launch configuration;
- preparing required local runtime artifacts through Cargo unless rebuilds are - preparing required local runtime artifacts through Cargo unless rebuilds are
explicitly skipped; explicitly skipped;
- starting the orchestrator through the approved orchestrator launch contract; - starting the library runtime and its orchestrator, prompt, and datastream leaves;
- waiting until the runtime can accept prompt requests; - waiting until the runtime can accept prompt requests;
- running the interactive prompt loop; - running the interactive prompt loop;
- notifying the runtime to shut down on normal exit or interruption; - notifying the runtime to shut down on normal exit or interruption;
@ -42,9 +42,9 @@ The wrapper is responsible for:
This specification covers Linux only. This specification covers Linux only.
Linux signal handling, child-process lifecycle, Cargo artifact discovery, and Linux signal handling, managed component and process-leaf lifecycle, Cargo
runtime shutdown semantics are the only supported platform behavior. Non-Linux artifact discovery, and runtime shutdown semantics are the only supported
behavior is out of scope until explicitly specified. platform behavior. Non-Linux behavior is out of scope until explicitly specified.
--- ---
@ -267,11 +267,11 @@ in the runtime launch request.
### 3.7 Network and Runtime Inputs ### 3.7 Network and Runtime Inputs
Network inputs: Runtime inputs:
- prompt RPC readiness outcome; - prompt engine readiness outcome;
- prompt RPC stream records; - prompt engine `PromptEvent` stream records;
- orchestrator progress events received through the progress datastream. - orchestrator and component progress events written to the local datastream.
Additional provider/image inputs: Additional provider/image inputs:
@ -279,27 +279,30 @@ Additional provider/image inputs:
- registry responses when checking remote image availability; - registry responses when checking remote image availability;
- registry responses when pushing images for remote providers. - registry responses when pushing images for remote providers.
Prompt RPC stream records are newline-delimited prompt events: Prompt engine stream records are runtime-local prompt events:
- text delta; - text delta;
- request completion; - request completion;
- request fault. - request fault.
The detailed progress-event channel schema is not specified here. This spec only Detailed progress payload schemas are not specified here. This spec only
requires that `mvp-chat` receive enough progress information to present the requires that `mvp-chat` receive enough progress information to present the
user-facing progress states defined in Section 7. user-facing progress states defined in Section 7.
### 3.8 Child-Process Inputs ### 3.8 Managed Component Inputs
Child-process inputs observed by `mvp-chat`: Managed component inputs observed by `mvp-chat`:
- orchestrator process start success or failure; - orchestrator leaf start success or failure;
- orchestrator process readiness result; - orchestrator leaf readiness result;
- orchestrator process exit before readiness; - orchestrator leaf fault or exit before readiness;
- failure to notify or wait for orchestrator shutdown. - prompt engine leaf readiness result;
- prompt engine leaf fault before readiness;
- failure to request or wait for managed-component shutdown.
The OS process APIs used to observe these states are implementation details. The The OS process APIs, process actors, and actor-runtime notifications used to
observable contract is the resulting success, failure, or controlled shutdown. observe these states are implementation details. The observable contract is the
resulting success, failure, readiness, fault, or controlled shutdown.
--- ---
@ -483,17 +486,26 @@ to the path parsing rules in Section 3.1.
`mvp-chat` must not create hidden startup archive files as part of the public `mvp-chat` must not create hidden startup archive files as part of the public
contract. contract.
Progress observation uses datastream, not archive-file polling. Progress observation uses the `mvp-chat` local datastream endpoint, not
archive-file polling.
The intended topology is: The runtime owns one local endpoint:
- the orchestrator exposes or publishes runtime progress; - stream id: `StreamId::new(NodeId::new("mvp-chat"), Lifetime(run_id))`;
- `mvp-chat` subscribes to orchestrator progress; - label: `"mvp chat"`;
- `mvp-chat` exposes a process datastream endpoint for dashboard and user-facing - origin: `StreamOrigin::Orchestrator` until a chat-specific origin exists.
observers.
Detailed progress channel names and payload schemas are out of scope. They belong Required channels:
in a datastream/progress contract.
- `mvp.chat.lifecycle`;
- `mvp.chat.runtime`;
- `mvp.chat.prompt`;
- `mvp.chat.component`.
Components write through cloned `DatastreamProducer` handles or through local
adapters installed when a component leaf starts. The datastream task drains the
local endpoint and fans frames out to subscribers. Payload schemas remain owned
by the datastream/progress contract.
The user-facing progress model must eventually define visible transitions for The user-facing progress model must eventually define visible transitions for
runtime startup. Until that model is approved, this spec only fixes prompt-loop runtime startup. Until that model is approved, this spec only fixes prompt-loop
@ -545,7 +557,9 @@ Exact orchestrator argv is out of scope until the orchestrator launch contract i
specified. specified.
`mvp-chat` is responsible for handing the resolved runtime request to the `mvp-chat` is responsible for handing the resolved runtime request to the
orchestrator through that approved launch contract. orchestrator leaf through the library runtime. The production process-backed leaf
owns binary resolution, `ProcessSpec` construction, and managed process actor
startup; successor in-process leaves start the orchestrator actor group directly.
The semantic launch request must include, as applicable: The semantic launch request must include, as applicable:
@ -555,25 +569,25 @@ The semantic launch request must include, as applicable:
- cached model selection result; - cached model selection result;
- dump-log configuration; - dump-log configuration;
- provider-specific runtime configuration; - provider-specific runtime configuration;
- prompt RPC connection information required by the orchestrator contract; - datastream producer or adapter wiring required by the orchestrator leaf.
- progress datastream connection information required by the orchestrator
contract.
The orchestrator launch contract must define the prompt RPC address shared by The orchestrator launch contract does not define prompt transport. Prompt work is
the orchestrator and `mvp-chat`. The default prompt RPC address is handled by the `mvp-chat` prompt engine actor/task through runtime-local
`127.0.0.1:19777` unless the orchestrator launch contract provides another messages.
address.
The resolved node image reference is the image the orchestrator must use for the The resolved node image reference is the image the orchestrator must use for the
provider-backed node. Exact argv or wire encoding remains owned by the provider-backed node. Exact argv or wire encoding remains owned by the
orchestrator launch contract. orchestrator launch contract.
The wrapper starts the orchestrator as a child runtime process or through the The wrapper starts the `mvp-chat` library runtime. The runtime starts the
approved successor mechanism. orchestrator leaf, prompt engine leaf, datastream task, swactor runtime, and
control path. Production process-backed leaves are managed by process actors;
`mvp-chat` must not directly own `std::process::Child` for long-lived
components.
On shutdown, `mvp-chat` must notify the orchestrator process to stop. This spec On shutdown, `mvp-chat` must request shutdown through the runtime control path.
does not expose stdin or any specific control string as the normative shutdown The shutdown mechanism for each managed component is owned by that component's
mechanism. The shutdown mechanism is owned by the orchestrator contract. leaf contract.
Shutdown must be idempotent from the user's perspective. Normal prompt exit, Shutdown must be idempotent from the user's perspective. Normal prompt exit,
input EOF, startup interruption, and signal interruption must not leave the input EOF, startup interruption, and signal interruption must not leave the
@ -593,21 +607,28 @@ For each cycle, `mvp-chat` must:
preserving leading whitespace; preserving leading whitespace;
- exit cleanly for EOF, input disconnection, or standard-input read error; - exit cleanly for EOF, input disconnection, or standard-input read error;
- ignore prompts that are empty after whitespace trimming; - ignore prompts that are empty after whitespace trimming;
- submit non-empty prompts to prompt RPC; - submit non-empty prompts to the prompt engine actor/task;
- display that decoding has started; - display that decoding has started;
- stream response text as prompt RPC events arrive; - stream response text as `PromptEvent` values arrive;
- return to the prompt marker after completion or prompt fault. - return to the prompt marker after completion or prompt fault.
Prompt RPC submissions carry: Prompt requests carry:
- request id; - request id;
- prompt text; - prompt text;
- max token limit resolved from `mvp-chat` configuration. - max token limit resolved from `mvp-chat` configuration;
- reply target for the `PromptEvent` stream.
`mvp-chat` submits at most one prompt at a time on its prompt RPC connection. It Prompt responses are:
waits for a terminal `Done` or `Fault` event before submitting the next prompt.
Prompt RPC guarantees that response events on the connection belong to the active - `PromptEvent::TextDelta`;
request and arrive in order. - `PromptEvent::Done`;
- `PromptEvent::Fault`.
`mvp-chat` submits at most one prompt at a time to the prompt engine. It waits
for a terminal `Done` or `Fault` event before submitting the next prompt. The
prompt engine guarantees that response events for an active request arrive in
order on the reply target.
The prompt-loop output states are: The prompt-loop output states are:
@ -622,8 +643,8 @@ The prompt-loop output states are:
Prompt-loop user output goes to standard output unless it is an actual wrapper Prompt-loop user output goes to standard output unless it is an actual wrapper
error. Expected model faults are prompt-loop results, not wrapper diagnostics. error. Expected model faults are prompt-loop results, not wrapper diagnostics.
A fixed TCP read timeout is not part of the contract. The implementation must A fixed transport or read timeout is not part of the contract. The implementation
remain interruptible, but this spec does not require a specific timeout-based must remain interruptible, but this spec does not require a timeout-based
mechanism. mechanism.
--- ---
@ -635,7 +656,7 @@ mechanism.
Exit code `0` means clean completion or controlled interrupted shutdown. Exit code `0` means clean completion or controlled interrupted shutdown.
Exit code `1` means configuration failure, preparation failure, startup failure, Exit code `1` means configuration failure, preparation failure, startup failure,
prompt RPC failure, or another wrapper error. prompt engine failure, managed runtime failure, or another wrapper error.
### 11.2 Standard Output ### 11.2 Standard Output
@ -696,8 +717,6 @@ Filesystem outputs are limited to:
Network-visible outputs: Network-visible outputs:
- prompt RPC connection attempts;
- prompt RPC prompt submissions;
- `mvp-chat` datastream endpoint for dashboard/user observers when progress - `mvp-chat` datastream endpoint for dashboard/user observers when progress
observation is active. observation is active.
@ -707,16 +726,18 @@ Additional network-visible outputs when preparing remote images:
- image layer uploads; - image layer uploads;
- image manifest or tag pushes. - image manifest or tag pushes.
Prompt RPC submissions are newline-delimited request messages according to the Prompt submissions are runtime-local messages to the prompt engine actor/task;
prompt RPC contract. The prompt RPC contract owns the exact wire schema. they are not network-visible outputs.
### 11.6 Child Runtime Outputs ### 11.6 Managed Runtime Outputs
Outputs to the child runtime are limited to the approved orchestrator launch and Outputs to managed runtime components are limited to the approved orchestrator
shutdown contracts. leaf launch and shutdown contracts, prompt engine request messages, and
datastream frames.
This spec does not define exact argv names, stdin control strings, or private This spec does not define exact argv names, stdin control strings, private
orchestrator flags. orchestrator flags, or internal actor message encodings beyond the prompt request
and event shapes in Section 10.
--- ---
@ -730,8 +751,8 @@ operation, or invalid provider configuration.
Startup errors must identify the failed startup phase when progress information Startup errors must identify the failed startup phase when progress information
is available. is available.
Prompt RPC errors must identify whether connection, write, read, protocol, or Unexpected prompt engine errors must identify whether request submission,
remote closure failed. event-stream closure, prompt event handling, or component fault failed.
Controlled shutdown is not an error. Controlled shutdown is not an error.
@ -746,7 +767,7 @@ Out of scope for this document:
- path display formatting as a standalone contract; - path display formatting as a standalone contract;
- exact orchestrator argv; - exact orchestrator argv;
- detailed datastream channel schemas; - detailed datastream payload schemas;
- non-Linux support; - non-Linux support;
- Dockerfile contents; - Dockerfile contents;
- base-image implementation details; - base-image implementation details;

File diff suppressed because it is too large Load diff