Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

permissions:
contents: read

jobs:
test:
name: Cargo test
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Install stable Rust
uses: dtolnay/rust-toolchain@stable

- name: Cache Cargo
uses: Swatinem/rust-cache@v2

- name: Run workspace tests
run: cargo test --workspace
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ task-*.log
release-*.log
.claude/*
target/*

# Static frontend deployment bundle
.deploy/
23 changes: 23 additions & 0 deletions .issue-assets/copy.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<!doctype html>
<meta charset="utf-8">
<title>Copy screenshot</title>
<button id="interactive">Copy interactive screenshot</button>
<button id="working">Copy working screenshot</button>
<pre id="payload" hidden></pre>
<script>
async function copyImage(name) {
const response = await fetch(name);
const blob = await response.blob();
const bytes = new Uint8Array(await blob.arrayBuffer());
let binary = '';
for (const byte of bytes) binary += String.fromCharCode(byte);
payload.textContent = btoa(binary);
payload.hidden = false;
await navigator.clipboard.write([
new ClipboardItem({ [blob.type]: blob })
]);
document.title = `copied:${name}`;
}
interactive.onclick = () => copyImage('rpi-interactive.png');
working.onclick = () => copyImage('rpi-working.png');
</script>
Binary file added .issue-assets/rpi-interactive.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added .issue-assets/rpi-working.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
44 changes: 31 additions & 13 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 9 additions & 9 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ edition = "2021"
rust-version = "1.78"
license = "MIT"
repository = "https://github.com/bigfish193/pi-rust"
version = "0.1.5"
version = "0.1.6"
authors = ["BigFish <bigfish1913@gmail.com>"]

[workspace.dependencies]
Expand Down Expand Up @@ -65,16 +65,16 @@ rpassword = "7"

# pi-rust internal crates (published under the `rpi-` prefix; directories keep
# the `pi-` name — package `name` is what crates.io + `extern crate` see).
rpi-telemetry = { path = "crates/pi-telemetry", version = "0.1.5" }
rpi-ai = { path = "crates/pi-ai", version = "0.1.5" }
rpi-agent = { path = "crates/pi-agent", version = "0.1.5" }
rpi-tools = { path = "crates/pi-tools", version = "0.1.5" }
rpi-harness = { path = "crates/pi-harness", version = "0.1.5" }
rpi-telemetry = { path = "crates/pi-telemetry", version = "0.1.6" }
rpi-ai = { path = "crates/pi-ai", version = "0.1.6" }
rpi-agent = { path = "crates/pi-agent", version = "0.1.6" }
rpi-tools = { path = "crates/pi-tools", version = "0.1.6" }
rpi-harness = { path = "crates/pi-harness", version = "0.1.6" }

rpi-tui = { path = "crates/pi-tui", version = "0.1.5" }
rpi-tui = { path = "crates/pi-tui", version = "0.1.6" }

rpi-plugin-sdk = { path = "crates/rpi-plugin-sdk", version = "0.1.5" }
rpi-extensions = { path = "crates/rpi-extensions", version = "0.1.5" }
rpi-plugin-sdk = { path = "crates/rpi-plugin-sdk", version = "0.1.6" }
rpi-extensions = { path = "crates/rpi-extensions", version = "0.1.6" }

[profile.release]
lto = "thin"
Expand Down
47 changes: 45 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# rpi — Rust port of the Pi agent SDK

[![rpi-cli on crates.io](https://img.shields.io/crates/v/rpi-cli.svg)](https://crates.io/crates/rpi-cli)
[![rpi-plugin-sdk docs](https://docs.rs/rpi-plugin-sdk/badge.svg)](https://docs.rs/rpi-plugin-sdk)
[![CI](https://github.com/bigfish1913/pi-rust/actions/workflows/ci.yml/badge.svg)](https://github.com/bigfish1913/pi-rust/actions)

A Rust port of [earendil-works/pi](https://github.com/earendil-works/pi)'s SDK
layer — a library-first, multi-crate workspace for building personal LLM coding
agents in Rust, plus an `rpi` CLI built on top.
Expand All @@ -19,9 +23,25 @@ agents in Rust, plus an `rpi` CLI built on top.
| `rpi-tools` | `pi-tools/` | Built-in tools (`read`/`write`/`edit`/`bash`/`grep`/`find`/`ls`) + `ExecutionEnv`. |
| `rpi-harness` | `pi-harness/` | `AgentHarness`: session tree, JSONL persistence, compaction, run loop. |
| `rpi-cli` | `pi-cli/` | Terminal coding-agent CLI (`rpi` binary) on top of the library crates. |
| `rpi-plugin-sdk` | `rpi-plugin-sdk/` | Stable C ABI for Rust-native plugins and extension discovery. |
| `rpi-extensions` | `rpi-extensions/` | Dynamic plugin loader and `AgentTool` adapter. |
| `rpi-tui` | `pi-tui/` | Terminal UI primitives used by the interactive CLI. |

Dependency direction: `rpi-telemetry → rpi-ai → rpi-agent → rpi-tools → rpi-harness → rpi-cli`.

### Rust registry links

| Package | crates.io | docs.rs |
| --- | --- | --- |
| `rpi-cli` | [crates.io](https://crates.io/crates/rpi-cli) | [docs.rs](https://docs.rs/rpi-cli) |
| `rpi-agent` | [crates.io](https://crates.io/crates/rpi-agent) | [docs.rs](https://docs.rs/rpi-agent) |
| `rpi-plugin-sdk` | [crates.io](https://crates.io/crates/rpi-plugin-sdk) | [docs.rs](https://docs.rs/rpi-plugin-sdk) |
| `rpi-extensions` | [crates.io](https://crates.io/crates/rpi-extensions) | [docs.rs](https://docs.rs/rpi-extensions) |

The registry pages are the canonical entry points for installing the CLI or
embedding the SDK. The repository may contain unreleased changes; check the
published version shown on crates.io before depending on a new API.

## Relationship to the TypeScript source

The TypeScript reference is checked out under `.reference/pi/` (read-only). Every
Expand Down Expand Up @@ -55,6 +75,29 @@ agent.prompt("Hello!").await.unwrap();

See [docs/architecture.md](docs/architecture.md) for the full design.

## Build a plugin

Plugins are Rust `cdylib` libraries loaded through the stable ABI exposed by
`rpi-plugin-sdk`. The repository includes a complete `echo` tool example that
also exercises event and resource discovery:

```bash
cargo build -p plugin-stub
```

Then point the CLI at the directory containing the generated library (the
extension is named `plugin_stub.dll`, `libplugin_stub.so`, or
`libplugin_stub.dylib` depending on the platform):

```bash
rpi --extensions-dir target/debug -p 'echo "hi"'
```

The plugin depends on `rpi-plugin-sdk` only; the host-side loader lives in
`rpi-extensions`. See [`examples/plugin-stub`](examples/plugin-stub) and the
[`rpi-plugin-sdk` API docs](https://docs.rs/rpi-plugin-sdk) for the ABI
contract.

## Status (v1)

- **Providers:** Anthropic Messages and OpenAI-compatible Chat Completions,
Expand Down Expand Up @@ -131,8 +174,8 @@ Publish the crate family in dependency order with `cargo publish` (run
publish-scoped token; crates.io records are permanent):

```
# dep order: telemetry → ai → agent → tools → harness → cli
for c in rpi-telemetry rpi-ai rpi-agent rpi-tools rpi-harness rpi-cli; do
# dep order: telemetry → ai → agent → tools → harness → plugin-sdk → extensions → tui → cli
for c in rpi-telemetry rpi-ai rpi-agent rpi-tools rpi-harness rpi-plugin-sdk rpi-extensions rpi-tui rpi-cli; do
cargo publish -p "$c"
done
```
Expand Down
Loading
Loading