A safe, simple, extensible, and fast agent harness
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Make internal crate naming consistent

+52 -52
+1 -1
CLAUDE.md
··· 68 68 └─────────────────────────────┘ └──────────────────────────────┘ 69 69 ``` 70 70 71 - The protocol is defined in `crates/ein-proto/proto/ein.proto`. The client streams `UserInput` messages; the server streams back `AgentEvent` messages (`SessionStarted`, `ContentDelta`, `ToolCallStart`, `ToolCallEnd`, `ToolOutputChunk`, `AgentFinished`, `AgentError`, `TokenUsage`). 71 + The protocol is defined in `crates/ein_proto/proto/ein.proto`. The client streams `UserInput` messages; the server streams back `AgentEvent` messages (`SessionStarted`, `ContentDelta`, `ToolCallStart`, `ToolCallEnd`, `ToolOutputChunk`, `AgentFinished`, `AgentError`, `TokenUsage`). 72 72 73 73 ### Session lifecycle 74 74
+21 -21
Cargo.lock
··· 979 979 "clap", 980 980 "crossterm", 981 981 "dirs", 982 - "ein-proto", 982 + "ein_proto", 983 983 "notify", 984 984 "ratatui", 985 985 "reqwest", ··· 997 997 ] 998 998 999 999 [[package]] 1000 - name = "ein-agent" 1000 + name = "ein_agent" 1001 1001 version = "0.1.8" 1002 1002 dependencies = [ 1003 1003 "anyhow", 1004 1004 "async-trait", 1005 - "ein-core", 1005 + "ein_core", 1006 1006 "futures", 1007 1007 "serde", 1008 1008 "serde_json", ··· 1012 1012 ] 1013 1013 1014 1014 [[package]] 1015 - name = "ein-core" 1015 + name = "ein_anthropic" 1016 1016 version = "0.1.8" 1017 1017 dependencies = [ 1018 + "anyhow", 1019 + "ein_plugin", 1018 1020 "serde", 1019 1021 "serde_json", 1022 + "wit-bindgen 0.53.1", 1020 1023 ] 1021 1024 1022 1025 [[package]] 1023 - name = "ein-proto" 1024 - version = "0.1.8" 1025 - dependencies = [ 1026 - "prost", 1027 - "tonic", 1028 - "tonic-build", 1029 - ] 1030 - 1031 - [[package]] 1032 - name = "ein_anthropic" 1026 + name = "ein_bash" 1033 1027 version = "0.1.8" 1034 1028 dependencies = [ 1035 1029 "anyhow", ··· 1040 1034 ] 1041 1035 1042 1036 [[package]] 1043 - name = "ein_bash" 1037 + name = "ein_core" 1044 1038 version = "0.1.8" 1045 1039 dependencies = [ 1046 - "anyhow", 1047 - "ein_plugin", 1048 1040 "serde", 1049 1041 "serde_json", 1050 - "wit-bindgen 0.53.1", 1051 1042 ] 1052 1043 1053 1044 [[package]] ··· 1110 1101 version = "0.1.8" 1111 1102 dependencies = [ 1112 1103 "anyhow", 1113 - "ein-core", 1104 + "ein_core", 1114 1105 "ein_http", 1115 1106 "serde", 1116 1107 "serde_json", ··· 1118 1109 ] 1119 1110 1120 1111 [[package]] 1112 + name = "ein_proto" 1113 + version = "0.1.8" 1114 + dependencies = [ 1115 + "prost", 1116 + "tonic", 1117 + "tonic-build", 1118 + ] 1119 + 1120 + [[package]] 1121 1121 name = "ein_read" 1122 1122 version = "0.1.8" 1123 1123 dependencies = [ ··· 1149 1149 "async-trait", 1150 1150 "clap", 1151 1151 "dirs", 1152 - "ein-agent", 1153 - "ein-proto", 1152 + "ein_agent", 1154 1153 "ein_plugin", 1154 + "ein_proto", 1155 1155 "futures", 1156 1156 "hyper", 1157 1157 "reqwest",
+6 -6
Cargo.toml
··· 2 2 members = [ 3 3 "eind", 4 4 "ein", 5 - "crates/ein-proto", 6 - "crates/ein-agent", 7 - "crates/ein-core", 5 + "crates/ein_proto", 6 + "crates/ein_agent", 7 + "crates/ein_core", 8 8 "crates/ein_http", 9 9 "crates/ein_plugin", 10 10 "packages/*", ··· 12 12 default-members = [ 13 13 "eind", 14 14 "ein", 15 - "crates/ein-proto", 16 - "crates/ein-agent", 17 - "crates/ein-core", 15 + "crates/ein_proto", 16 + "crates/ein_agent", 17 + "crates/ein_core", 18 18 ] 19 19 resolver = "2" 20 20
+2 -2
README.md
··· 269 269 270 270 ``` 271 271 crates/ 272 - ein-proto/ Protocol Buffer definitions (gRPC service + message types) 272 + ein_proto/ Protocol Buffer definitions (gRPC service + message types) 273 273 ein/ Terminal UI client 274 274 eind/ gRPC server — agent loop, WASM plugin host, session persistence 275 275 packages/ ··· 288 288 289 289 ### Protocol 290 290 291 - The protocol (`crates/ein-proto/proto/ein.proto`) defines a bidirectional streaming RPC (`AgentSession`), a unary `ListSessions` RPC, and a unary `DeleteSession` RPC. Each session opens with a `SessionConfig` message (global sandbox constraints + per-plugin config map + optional `session_id` for resume), followed by `UserInput` prompt messages. The server streams back `AgentEvent` messages as the agent thinks, calls tools, and produces output — starting with a `SessionStarted` event carrying the session's UUID, a `resumed` boolean, and the prior conversation history when resuming. 291 + The protocol (`crates/ein_proto/proto/ein.proto`) defines a bidirectional streaming RPC (`AgentSession`), a unary `ListSessions` RPC, and a unary `DeleteSession` RPC. Each session opens with a `SessionConfig` message (global sandbox constraints + per-plugin config map + optional `session_id` for resume), followed by `UserInput` prompt messages. The server streams back `AgentEvent` messages as the agent thinks, calls tools, and produces output — starting with a `SessionStarted` event carrying the session's UUID, a `resumed` boolean, and the prior conversation history when resuming. 292 292 293 293 `UserInput` variants after `init`: 294 294 - `prompt` — a user message driving `run_agent`
+2 -2
crates/ein-agent/Cargo.toml crates/ein_agent/Cargo.toml
··· 1 1 [package] 2 - name = "ein-agent" 2 + name = "ein_agent" 3 3 version.workspace = true 4 4 edition.workspace = true 5 5 authors.workspace = true ··· 8 8 [dependencies] 9 9 anyhow = { workspace = true } 10 10 async-trait = "0.1" 11 - ein-core = { path = "../ein-core" } 11 + ein_core = { path = "../ein_core" } 12 12 futures = { workspace = true } 13 13 serde = { workspace = true } 14 14 serde_json = { workspace = true }
crates/ein-agent/src/agents.rs crates/ein_agent/src/agents.rs
crates/ein-agent/src/errors.rs crates/ein_agent/src/errors.rs
crates/ein-agent/src/lib.rs crates/ein_agent/src/lib.rs
crates/ein-agent/src/model_clients/mod.rs crates/ein_agent/src/model_clients/mod.rs
crates/ein-agent/src/tools/mod.rs crates/ein_agent/src/tools/mod.rs
crates/ein-agent/src/tools/native.rs crates/ein_agent/src/tools/native.rs
+1 -1
crates/ein-core/Cargo.toml crates/ein_core/Cargo.toml
··· 1 1 [package] 2 - name = "ein-core" 2 + name = "ein_core" 3 3 version.workspace = true 4 4 edition.workspace = true 5 5 authors.workspace = true
crates/ein-core/src/lib.rs crates/ein_core/src/lib.rs
crates/ein-core/src/types.rs crates/ein_core/src/types.rs
+1 -1
crates/ein-proto/Cargo.toml crates/ein_proto/Cargo.toml
··· 1 1 [package] 2 - name = "ein-proto" 2 + name = "ein_proto" 3 3 version.workspace = true 4 4 edition.workspace = true 5 5 authors.workspace = true
crates/ein-proto/build.rs crates/ein_proto/build.rs
crates/ein-proto/proto/ein.proto crates/ein_proto/proto/ein.proto
crates/ein-proto/src/lib.rs crates/ein_proto/src/lib.rs
+1 -1
crates/ein_plugin/Cargo.toml
··· 7 7 8 8 [dependencies] 9 9 anyhow = { workspace = true } 10 - ein-core = { path = "../ein-core" } 10 + ein_core = { path = "../ein_core" } 11 11 ein_http = { path = "../ein_http" } 12 12 serde = { workspace = true } 13 13 serde_json = { workspace = true }
+1 -1
ein/Cargo.toml
··· 23 23 crossterm = { version = "0.28", features = ["event-stream"] } 24 24 notify = "6" 25 25 dirs = "6.0.0" 26 - ein-proto = { path = "../crates/ein-proto" } 26 + ein_proto = { path = "../crates/ein_proto" } 27 27 ratatui = { version = "0.29", features = ["unstable-rendered-line-info"] } 28 28 serde = { workspace = true } 29 29 serde_json = { workspace = true }
+2 -2
eind/Cargo.toml
··· 21 21 async-trait = "0.1" 22 22 clap = { version = "4.3.14", features = ["derive"] } 23 23 dirs = "6.0.0" 24 - ein-agent = { path = "../crates/ein-agent" } 25 - ein-proto = { path = "../crates/ein-proto" } 24 + ein_agent = { path = "../crates/ein_agent" } 25 + ein_proto = { path = "../crates/ein_proto" } 26 26 ein_plugin = { path = "../crates/ein_plugin" } 27 27 futures = { workspace = true } 28 28 serde = { workspace = true }
+4 -4
notes/ein-agent-mcp-fit-analysis.md
··· 1 - # `ein-agent` Architecture Fit for MCP Server Building 1 + # `ein_agent` Architecture Fit for MCP Server Building 2 2 3 3 _Evaluation Date: 2026-04-20_ 4 4 ··· 6 6 7 7 ## Summary 8 8 9 - The `ein-agent` architecture maps well onto the *client* side of MCP but is missing the abstractions needed to be a proper MCP *server* framework. It is well-positioned to grow in that direction, but there are meaningful gaps. 9 + The `ein_agent` architecture maps well onto the *client* side of MCP but is missing the abstractions needed to be a proper MCP *server* framework. It is well-positioned to grow in that direction, but there are meaningful gaps. 10 10 11 11 --- 12 12 13 13 ## What Maps Cleanly 14 14 15 - ### `Tool` / `ToolSet` traits (`crates/ein-agent/src/tools/mod.rs`) 15 + ### `Tool` / `ToolSet` traits (`crates/ein_agent/src/tools/mod.rs`) 16 16 17 17 The best fit. MCP's core concept is a server that exposes named tools with JSON schemas — that is exactly what `Tool` and `ToolSet` model. An MCP server implementation would be a new `ToolSet` adapter that routes calls to MCP rather than local functions. 18 18 19 - ### `ToolDef` / `ToolFunction` / `ToolFunctionParams` (`crates/ein-core/src/types.rs`) 19 + ### `ToolDef` / `ToolFunction` / `ToolFunctionParams` (`crates/ein_core/src/types.rs`) 20 20 21 21 Already serialize to OpenAI function-calling format, which is structurally identical to MCP's tool definition schema. Very little translation needed. 22 22
+10 -10
notes/mcp-server-roadmap.md
··· 1 - # Roadmap: MCP Server Support for `ein-agent` 1 + # Roadmap: MCP Server Support for `ein_agent` 2 2 3 3 _Date: 2026-04-20_ 4 4 ··· 6 6 7 7 ## Goal 8 8 9 - Make `ein-agent` a competitive Rust SDK for building MCP servers. The primary differentiator is WASM-sandboxed tool execution — deny-by-default filesystem and network access per tool, with explicit per-tool capability grants. The Vercel/Context.ai incident (April 2026) demonstrated that the current generation of MCP tools has no answer to a compromised server exfiltrating OAuth tokens. Ein's existing WASM runtime directly addresses this, and the timing is good. 9 + Make `ein_agent` a competitive Rust SDK for building MCP servers. The primary differentiator is WASM-sandboxed tool execution — deny-by-default filesystem and network access per tool, with explicit per-tool capability grants. The Vercel/Context.ai incident (April 2026) demonstrated that the current generation of MCP tools has no answer to a compromised server exfiltrating OAuth tokens. Ein's existing WASM runtime directly addresses this, and the timing is good. 10 10 11 11 The target bar is parity with the official `rmcp` SDK on protocol coverage and ergonomics, with WASM sandboxing as a clear security advantage over everything in the ecosystem. 12 12 ··· 27 27 28 28 ## Phases 29 29 30 - ### Phase 1: `ein-agent` trait improvements (prerequisite) 30 + ### Phase 1: `ein_agent` trait improvements (prerequisite) 31 31 32 32 These changes are required before any MCP work begins. They unblock concurrent MCP calls and remove constraints that don't make sense for a server use case. 33 33 ··· 84 84 - Error codes and error objects 85 85 - Notification types (`notifications/cancelled`, etc.) 86 86 87 - Use `serde` for serialization. Keep these types in `ein-core` so they can be shared with a future MCP client. 87 + Use `serde` for serialization. Keep these types in `ein_core` so they can be shared with a future MCP client. 88 88 89 89 **Capability negotiation** 90 90 ··· 296 296 297 297 --- 298 298 299 - ### Phase 7: MCP client in `ein-agent` 299 + ### Phase 7: MCP client in `ein_agent` 300 300 301 301 Close the loop: let Ein agents consume tools from any MCP server, not just tools registered locally. This makes Ein bidirectional. 302 302 ··· 321 321 322 322 ``` 323 323 crates/ 324 - ein-core/ existing — add MCP JSON-RPC types here 325 - ein-agent/ existing — Phase 1 trait improvements 326 - ein-mcp/ new — McpServer, transports, auth middleware 327 - ein-mcp-macros/ new — #[mcp_tool], #[mcp_server] proc macros 324 + ein_core/ existing — add MCP JSON-RPC types here 325 + ein_agent/ existing — Phase 1 trait improvements 326 + ein_mcp/ new — McpServer, transports, auth middleware 327 + ein_mcp_macros/ new — #[mcp_tool], #[mcp_server] proc macros 328 328 ``` 329 329 330 - `ein-mcp` depends on `ein-agent` (for `ToolSet`) and `ein-core` (for shared types). The macro crate is a separate proc-macro crate depended on by `ein-mcp`. 330 + `ein_mcp` depends on `ein-agent` (for `ToolSet`) and `ein_core` (for shared types). The macro crate is a separate proc-macro crate depended on by `ein_mcp`. 331 331 332 332 --- 333 333