modelpipe 0.5.0

Reach an OpenAI-compatible model server from anywhere over p2p — no VPN, no account, no cloud in the path
Documentation
[package]
name = "modelpipe"
description = "Reach an OpenAI-compatible model server from anywhere over p2p — no VPN, no account, no cloud in the path"
version.workspace = true
rust-version.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
authors.workspace = true
# The README lives at the workspace root, outside this package directory, so
# without this it is simply absent from the published tarball and the
# crates.io page renders empty; it is also the ticket-format draft other
# clients will eventually implement against, so that is not a cosmetic loss.
# LICENSE is a checked-in symlink in this directory instead (cargo packages
# it as a regular file): a `license-file` field alongside `license` makes
# every cargo invocation warn that the two are mutually exclusive.
readme = "../README.md"
keywords = ["p2p", "iroh", "llm", "openai", "proxy"]
categories = ["network-programming", "asynchronous"]

[lints]
workspace = true

[features]
# `Serialize`/`Deserialize` for `Ticket` (as its canonical string),
# `PipeStatus`, `PeerView` and `NetworkMetrics`. Off by default: the CLI never
# needs them, and an embedder that puts a ticket or a status page's numbers in
# a DTO opts in with one line.
serde = ["dep:serde"]

# What docs.rs builds. The `serde` impls only exist under the feature, so
# without this the published page would show the types and not the impls an
# embedder is deciding whether to opt into.
[package.metadata.docs.rs]
all-features = true

[dependencies]
# `metrics` is one of iroh's own defaults, so this changes nothing about what
# is compiled; it is named because `Endpoint::metrics` is now what
# `NetworkMetrics` reads and a `cfg`-gated method that vanishes is a compile
# error nobody would connect to a feature they never chose. Declared because
# it is used — the same rule the `tokio` entry below states at length, and
# the same failure it was written to prevent.
iroh = { workspace = true, features = ["metrics"] }
# Optional, and behind the feature of the same name. Already in the graph
# via iroh (which serializes its own address records), so turning the
# feature on costs no additional compilation; `derive` is what `PipeStatus`
# and `PeerView` use, and `serde_derive` is in the graph for the same reason.
serde = { version = "1", optional = true, default-features = false, features = ["derive"] }
# Constant-time comparison for the bearer check. Taken rather than
# hand-rolled: the README promises the comparison is constant time, and at
# `opt-level = 2` with `lto = "thin"`, under `unsafe_code = "deny"` and with
# no `black_box` discipline, a hand-written loop is an unverifiable claim
# rather than asceticism. Already in the graph via iroh's `aes-gcm`, so this
# costs no additional compilation.
subtle = { version = "2", default-features = false }
# The OS CSPRNG, for minting tokens. Also already in the graph.
getrandom = "0.4"
# HTTP/1.1 head parsing. Hand-rolling a framer inside an authentication
# boundary is where CL-vs-TE request smuggling gets in; this is the one place
# in the crate where asceticism about dependencies would be the wrong call.
# Already in the graph via iroh's relay client.
httparse = "1"
# Backend URL parsing. Splitting a URL by hand is where a host ends up being
# something other than what the operator wrote, which for this crate is a
# security boundary rather than a papercut. Already in the graph via iroh.
url = "2"
# Structured diagnostics. Events only: this crate emits and never installs a
# subscriber, because a library that installs one takes the choice away from
# the binary it is linked into — and `modelpipe` is a library first. Already
# in the graph, and not marginally: seventeen crates pull it, iroh among
# them, with `attributes` and `std` already on. So this costs no additional
# compilation, which is the same test the four dependencies above had to
# pass.
#
# What it must never carry is the reason `tracing` is named three times in
# this crate already, every time as the thing a derived `Debug` would leak
# into — see `credential.rs` and `ticket.rs`. No span field and no event
# field here holds a token, a ticket, or a header value.
tracing = { version = "0.1", default-features = false, features = ["std", "attributes"] }
# `rt` is load-bearing and is declared here: both `serve` and `connect` return
# a handle over a background accept loop, so the first real body spawns, and
# `tokio::spawn` is gated on it. It was once absent and compiled anyway, on
# iroh enabling `rt` on its own copy of tokio while cargo unified the features
# — which is exactly the problem, and the reason every feature this crate uses
# is named here: the build would otherwise depend on a dependency's private
# choice, and iroh narrowing it would surface as a confusing error in a release
# that changed nothing here.
#
# What that does NOT buy is a runtime *flavour*. An embedder chooses that, and
# nothing in this list asks for `rt-multi-thread` — iroh 1.1 does not enable it
# either, so a caller on `#[tokio::main(flavor = "current_thread")]` gets one
# thread and everything here still works: the accept loops and the path watcher
# are tasks, not threads. The dev-dependency below turns it on for the tests
# alone, and the reason it gives is a test's reason.
tokio = { workspace = true, features = ["net", "io-util", "rt", "sync", "time"] }

[dev-dependencies]
# `macros` for #[tokio::test]; `rt-multi-thread` because a test that pumps a
# stream while reading the other end needs a second task to make progress.
# `test-util` is what #[tokio::test(start_paused = true)] needs, and it is
# deliberately not part of any default: a timeout test that waited thirty real
# seconds would be one nobody runs.
tokio = { workspace = true, features = ["macros", "rt-multi-thread", "io-util", "test-util"] }
# The capture subscriber the diagnostics tests read back. A dev-dependency
# and deliberately not a normal one: this crate emits events and installs no
# subscriber, so the only code here that may install one is a test asserting
# what those events say — and, more to the point, what they never say.
#
# Unlike `tracing` above this is NOT already in the graph. Before this
# dependency existed it reached `Cargo.lock` only through a `cfg(loom)` edge
# that is never built, so nothing in the workspace compiled it. It is new
# compilation, in the test profile only, and saying so is the point of these
# comments — the "already in the graph" line the four dependencies above
# carry is a justification, not a formula, and it does not apply here.
tracing-subscriber = { version = "0.3", default-features = false, features = ["std", "fmt"] }
# For the `serde` feature's tests only, which run under `--all-features`.
# Like `tracing-subscriber` above, this is NOT already in the graph: it is
# new compilation, in the test profile, and only when the feature is on —
# which is the honest price of proving what the feature emits rather than
# asserting it.
serde_json = "1"