phi-ext 0.2.0

Rust author SDK for Phi PXB extensions (port of ext/go)
Documentation
  • Coverage
  • 24.92%
    82 out of 329 items documented2 out of 43 items with examples
  • Size
  • Source code size: 122.22 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 3.59 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 3s Average build duration of successful builds.
  • all releases: 6s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • pulseaiclub/phi
    307 15 4
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • libinops

Phi Rust extension SDK (ext/rust)

Rust is a first-class language for Phi extensions — on par with the Go SDK in ext/go. Same PXB wire protocol on stdin/stdout, same host features (LLM tools, slash commands, intercepts, event subscriptions, confirm dialogs), byte-for-byte interop, and the same install flow (phi.yaml + a binary under ~/.phi/extensions/<name>/). This crate is the zero-dependency Rust authoring side: no JSON, no reflection, no runtime deps.

Wire compatibility with the Go SDK is pinned byte-for-byte by golden tests against ext/go/pxb/testdata/*.bin (tests/pxb_test.rs).

Layout

Path Role
src/pxb/ Wire protocol: frames (codec), tagged fields (fields), message codecs (msg), types/events (types)
src/phi/ Author SDK: Extension, Tool, Command, Context, Schema
examples/ Runnable extensions: hello (commands, intercepts, subscribe), full (tool, confirm, submit)
tests/ Golden byte-compat + end-to-end fake-host tests

Authoring

The crate publishes to crates.io; release tags are ext/rust/vX.Y.Z. Until the first publish, depend on it from the repo (main); after a release, use the published version:

[dependencies]
# pre-release: tracks the latest main
phi-ext = { git = "https://github.com/pulseaiclub/phi", branch = "main" }
# release: published crate version (tagged ext/rust/vX.Y.Z)
# phi-ext = "0.1.0"
use phi_ext::{phi, pxb};

fn main() -> Result<(), phi::Error> {
    let mut m = phi::Extension::new("hello", "0.1.0");
    m.register_command("hello", phi::Command::new("Say hi", |_args, ctx| {
        ctx.notify("info", "Hello!");
        // ctx.submit("follow-up");      // after /hello returns
        // ctx.send_user_message("…");   // enqueue a turn anytime
        Ok(())
    }));
    m.on_user_input(|_ev| None);   // return Some(UserInputResult { handled: true, .. }) to swallow
    m.on_tool_call(|_ev| None);    // return Some(ToolCallResult { block: true, reason: "…", .. }) to deny
    m.on_tool_result(|_ev| None);  // return Some(ToolResultResult { stop: true, .. }) to end the loop
    m.on_turn_stopping(|_ev| None); // return Some(TurnStoppingResult { continue_: true, message: "…", .. }) to steer
    m.subscribe(pxb::Event::SessionStart, |_ev| {});
    m.run()
}

Command handlers get a phi::Context for host interaction: notify, set_status, submit, send_user_message, confirm, confirm_opts.

Build and install (a phi.yaml manifest must live next to the binary):

cargo build --release --example hello
mkdir -p ~/.phi/extensions/hello
cp target/release/examples/hello phi.yaml ~/.phi/extensions/hello/

Reload in the TUI: Ctrl+K → extensions → reload.

PXB codec numbers (vs Go / JSON lines) live in the root README. Re-run the probe with cargo run --release --example bench.

Development

cargo test            # unit + golden + end-to-end fake-host tests
cargo fmt --check
cargo clippy --all-targets -- -D warnings

The run loop is single-threaded; the borrow checker replaces the Go SDK's mutexes (handlers get &mut state and cannot alias the registry).