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
4 changes: 2 additions & 2 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ platform-specific service integration (macOS / Linux / Windows).
The wire-protocol Rust types are **generated from a JSON Schema** (via
`schemars`/`typify`). The schema is the single source of truth so the daemon and
its peer can be kept in lock-step; see
[`schema/tunnel-protocol.json`](./schema/tunnel-protocol.json).
[`schema/edison-tunnel-protocol.json`](./schema/edison-tunnel-protocol.json).

## Tunnel mechanism: reverse RPC over WebSocket

Expand All @@ -85,7 +85,7 @@ reverse tunnel because:

### Wire protocol

Defined as JSON Schema at `schema/tunnel-protocol.json`. Frames are JSON with a
Defined as JSON Schema at `schema/edison-tunnel-protocol.json`. Frames are JSON with a
`type` discriminator and fall into two categories.

**Control frames** (lifecycle / desired state):
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ cargo fmt --all --check && \
- **Match the surrounding style.** Follow the existing naming, comment density,
and module layout; `cargo fmt` handles formatting.
- **Update docs alongside code.** If you change the wire protocol, update
[`schema/tunnel-protocol.json`](./schema/tunnel-protocol.json) (the single
[`schema/edison-tunnel-protocol.json`](./schema/edison-tunnel-protocol.json) (the single

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The schema reference in CONTRIBUTING.md now points to schema/edison-tunnel-protocol.json, but that file doesn't exist yet — only schema/tunnel-protocol.json is present. This creates a broken documentation link for contributors. Consider renaming the schema file to match (since README.md also references the edison- prefixed name) or revert the references until the rename is done.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At CONTRIBUTING.md, line 43:

<comment>The schema reference in CONTRIBUTING.md now points to `schema/edison-tunnel-protocol.json`, but that file doesn't exist yet — only `schema/tunnel-protocol.json` is present. This creates a broken documentation link for contributors. Consider renaming the schema file to match (since README.md also references the `edison-` prefixed name) or revert the references until the rename is done.</comment>

<file context>
@@ -40,7 +40,7 @@ cargo fmt --all --check && \
   and module layout; `cargo fmt` handles formatting.
 - **Update docs alongside code.** If you change the wire protocol, update
-  [`schema/tunnel-protocol.json`](./schema/tunnel-protocol.json) (the single
+  [`schema/edison-tunnel-protocol.json`](./schema/edison-tunnel-protocol.json) (the single
   source of truth) and [`ARCHITECTURE.md`](./ARCHITECTURE.md). If you change the
   CLI or config, update [`README.md`](./README.md).
</file context>

source of truth) and [`ARCHITECTURE.md`](./ARCHITECTURE.md). If you change the
CLI or config, update [`README.md`](./README.md).
- **Add tests** for new behavior where practical.
Expand Down
18 changes: 9 additions & 9 deletions Cargo.lock

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

6 changes: 4 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@
resolver = "2"
members = [
"crates/edison-stdiod",
"crates/tunnel-protocol",
"crates/edison-tunnel-protocol",
]

[workspace.package]
edition = "2021"
version = "0.0.1"
license = "AGPL-3.0-only"
authors = ["Edison Watch"]
repository = "https://github.com/Edison-Watch/stdiod"
homepage = "https://github.com/Edison-Watch/stdiod"

[workspace.dependencies]
anyhow = "1"
Expand All @@ -29,4 +31,4 @@ tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }

# Workspace member crates
tunnel-protocol = { path = "crates/tunnel-protocol" }
edison-tunnel-protocol = { path = "crates/edison-tunnel-protocol", version = "0.0.1" }
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
- **Child supervision.** The backend pushes a desired set of servers; the daemon spawns/stops the matching subprocesses and pumps their stdio.
- **Survival.** It reconnects with backoff across network blips and machine sleep/resume, and reconciles desired state on every (re)connect.

See [`ARCHITECTURE.md`](./ARCHITECTURE.md) for the full design and [`schema/tunnel-protocol.json`](./schema/tunnel-protocol.json) for the wire protocol - the single source of truth for the frame types.
See [`ARCHITECTURE.md`](./ARCHITECTURE.md) for the full design and [`schema/edison-tunnel-protocol.json`](./schema/edison-tunnel-protocol.json) for the wire protocol - the single source of truth for the frame types.

## Install

Expand Down Expand Up @@ -223,7 +223,7 @@ cargo fmt --all --check # formatting
cargo clippy --workspace --all-targets -- -D warnings # lints
```

The `tunnel-protocol` crate's Rust types are generated from [`schema/tunnel-protocol.json`](./schema/tunnel-protocol.json) - keep the schema and the generated types in lock-step.
The `edison-tunnel-protocol` crate's Rust types are generated from [`schema/edison-tunnel-protocol.json`](./schema/edison-tunnel-protocol.json) - keep the schema and the generated types in lock-step.

[`dev/spike/`](./dev/spike/) holds a throwaway v0 Python prototype that validated the wire protocol before the Rust daemon was written; it is kept as a historical record and is not part of the build.

Expand Down
3 changes: 2 additions & 1 deletion crates/edison-stdiod/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ version.workspace = true
license.workspace = true
authors.workspace = true
description = "Edison Watch stdio MCP server daemon - bridges local stdio MCP servers to the backend tunnel."
readme = "../../README.md"

[[bin]]
name = "edison-stdiod"
Expand All @@ -26,5 +27,5 @@ tokio-tungstenite = { workspace = true }
toml = { workspace = true }
tracing = { workspace = true }
tracing-subscriber = { workspace = true }
tunnel-protocol = { workspace = true }
edison-tunnel-protocol = { workspace = true }
url = "2"
8 changes: 4 additions & 4 deletions crates/edison-stdiod/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,13 +140,13 @@ fn missing(name: &str, flag: &str) -> anyhow::Error {
}

/// Detected OS, mapped to the wire-protocol `Os` enum.
pub fn current_os() -> tunnel_protocol::Os {
pub fn current_os() -> edison_tunnel_protocol::Os {
if cfg!(target_os = "macos") {
tunnel_protocol::Os::Macos
edison_tunnel_protocol::Os::Macos
} else if cfg!(target_os = "linux") {
tunnel_protocol::Os::Linux
edison_tunnel_protocol::Os::Linux
} else {
tunnel_protocol::Os::Windows
edison_tunnel_protocol::Os::Windows
}
}

Expand Down
8 changes: 4 additions & 4 deletions crates/edison-stdiod/src/daemon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ use std::time::{Duration, Instant, SystemTime};

use anyhow::{bail, Result};
use clap::Args;
use tokio::sync::{mpsc, Mutex};
use tokio::time::sleep;
use tracing::{debug, info, warn};
use tunnel_protocol::{
use edison_tunnel_protocol::{
ClientHello, DesiredServer, DesiredStateUpdate, McpFrame, ServerHello, ServerSpawnResult,
ServerSpecUpdate, TunnelError, TunnelFrame, PROTOCOL_VERSION,
};
use tokio::sync::{mpsc, Mutex};
use tokio::time::sleep;
use tracing::{debug, info, warn};

use crate::config;
use crate::env_store::{resolve_env_for_spawn, substitute_templated_args, EnvStore};
Expand Down
2 changes: 1 addition & 1 deletion crates/edison-stdiod/src/proc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@
use std::process::Stdio;

use anyhow::{Context, Result};
use edison_tunnel_protocol::{DesiredServer, McpFrame, TunnelError, TunnelFrame};
use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
use tokio::process::{Child, Command};
use tokio::sync::mpsc;
use tokio::task::JoinHandle;
use tracing::{debug, info, warn};
use tunnel_protocol::{DesiredServer, McpFrame, TunnelError, TunnelFrame};

use crate::tunnel::OutgoingHandle;

Expand Down
2 changes: 1 addition & 1 deletion crates/edison-stdiod/src/tunnel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use std::sync::{Arc, Mutex};

use anyhow::{anyhow, bail, Context, Result};
use edison_tunnel_protocol::TunnelFrame;
use futures_util::{SinkExt, StreamExt};
use tokio::net::TcpStream;
use tokio::sync::mpsc;
Expand All @@ -20,7 +21,6 @@ use tokio_tungstenite::tungstenite::http::HeaderValue;
use tokio_tungstenite::tungstenite::Message;
use tokio_tungstenite::{MaybeTlsStream, WebSocketStream};
use tracing::{debug, info, warn};
use tunnel_protocol::TunnelFrame;

pub type WsStream = WebSocketStream<MaybeTlsStream<TcpStream>>;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "tunnel-protocol"
name = "edison-tunnel-protocol"
edition.workspace = true
version.workspace = true
license.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion dev/spike/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ kept here as a historical record, not part of the daemon build.

```
stub_mcp_server.py FastMCP stdio server: add, slow_count, ask_sample, crash
tunnel_protocol.py Pydantic models for the wire envelope (ClientHello,
edison_tunnel_protocol.py Pydantic models for the wire envelope (ClientHello,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: README references edison_tunnel_protocol.py but the actual file on disk is still named tunnel_protocol.py. Update the README to match the actual filename, or rename the file to match.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At dev/spike/README.md, line 13:

<comment>README references `edison_tunnel_protocol.py` but the actual file on disk is still named `tunnel_protocol.py`. Update the README to match the actual filename, or rename the file to match.</comment>

<file context>
@@ -10,7 +10,7 @@ kept here as a historical record, not part of the daemon build.

stub_mcp_server.py FastMCP stdio server: add, slow_count, ask_sample, crash
-tunnel_protocol.py Pydantic models for the wire envelope (ClientHello,
+edison_tunnel_protocol.py Pydantic models for the wire envelope (ClientHello,
ServerHello, McpFrame, TunnelError)
tunnel_transport.py Custom ClientTransport. Wraps SessionMessages as
</file context>


</details>

```suggestion
tunnel_protocol.py   Pydantic models for the wire envelope (ClientHello,

ServerHello, McpFrame, TunnelError)
tunnel_transport.py Custom ClientTransport. Wraps SessionMessages as
McpFrames; unwraps inbound frames into ClientSession's
Expand Down
Loading