Skip to content

Commit 92e35f1

Browse files
committed
optimize the apis
Signed-off-by: kerthcet <kerthcet@gmail.com>
1 parent 2a9793f commit 92e35f1

23 files changed

Lines changed: 713 additions & 556 deletions

.github/workflows/rust-ci.yaml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,5 @@ jobs:
3636
with:
3737
toolchain: stable
3838

39-
- name: Run Unit tests
39+
- name: Run tests
4040
run: make test
41-
42-
- name: Run E2E tests
43-
run: make test-e2e

Makefile

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,12 @@ test-e2e: $(PYTEST) dev
6161
@echo "Cleaning up containers..."
6262
docker compose -f docker-compose.e2e.yml down
6363

64-
docker-build:
65-
docker compose -f docker-compose.e2e.yml build
64+
docker-up:
65+
docker compose -f docker-compose.e2e.yml up -d
6666

6767
docker-down:
6868
docker compose -f docker-compose.e2e.yml down
6969

70-
test-all: test test-e2e
71-
@echo "All tests completed successfully"
72-
7370
.PHONY: lint
7471
lint: $(RUFF)
7572
$(RUFF) check .

README.md

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
# SandD
44

5-
**A Lightweight Sandbox Daemon for Secure Agent Execution in Isolated Environments.**
5+
**A Lightweight Sandbox Daemon that Provides Secure, Isolated Execution Environments for Agents.**
66

77
[![Rust](https://img.shields.io/badge/rust-1.70+-orange.svg)](https://www.rust-lang.org/)
88
[![Python](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/)
@@ -18,8 +18,8 @@ Rust-powered WebSocket server with Python API for secure command execution in is
1818

1919
## Features
2020

21-
-**Command Execution**: Execute shell commands remotely with timeout support
22-
-**Interactive Shell (PTY)**: Full terminal sessions for debugging and manual work
21+
-**Command Execution**: Execute commands remotely with timeout support
22+
-**Interactive Sessions (PTY)**: Full terminal sessions for debugging and manual work
2323
-**File Transfer**: Upload/download files between agent and daemons
2424
-**High Performance**: Rust-powered WebSocket server handles 200+ concurrent connections
2525
-**Auto Reconnection**: Daemons automatically reconnect if connection drops
@@ -29,25 +29,25 @@ Rust-powered WebSocket server with Python API for secure command execution in is
2929
## Architecture
3030

3131
```
32-
┌─────────────────────────────────────────┐
33-
│ Python Agent Application │
34-
│ ┌────────────────────────────────────┐ │
35-
│ │ from sandd import Server │ │
36-
│ │ │ │
37-
│ │ server = Server("0.0.0.0", 8765) │ │
38-
│ │ result = server.execute_command( │ │
39-
│ │ "daemon-1", "ls -la" │ │
40-
│ │ ) │ │
41-
│ └────────────────────────────────────┘ │
42-
│ ▲ │
43-
│ │ Python bindings (PyO3) │
44-
│ ▼ │
45-
│ ┌────────────────────────────────────┐ │
46-
│ │ Rust WebSocket Server (tokio) │ │
47-
│ │ • Command routing │ │
48-
│ │ • Session management │ │
49-
│ └────────────────────────────────────┘ │
50-
└─────────────────────────────────────────┘
32+
┌─────────────────────────────────────────
33+
│ Python Agent Application
34+
│ ┌────────────────────────────────────┐
35+
│ │ from sandd import Server │
36+
│ │ │
37+
│ │ server = Server("0.0.0.0", 8765) │
38+
│ │ result = server.exec( │
39+
│ │ "daemon-1", "ls -la" │
40+
│ │ ) │
41+
│ └────────────────────────────────────┘
42+
│ ▲
43+
│ │ Python bindings (PyO3)
44+
│ ▼
45+
│ ┌────────────────────────────────────┐
46+
│ │ Rust WebSocket Server (tokio) │
47+
│ │ • Command routing │
48+
│ │ • Session management │
49+
│ └────────────────────────────────────┘
50+
└─────────────────────────────────────────
5151
5252
│ WebSocket (WSS)
5353
│ (Daemon initiates connection)
@@ -90,7 +90,7 @@ print(f"Server listening on {server.address}")
9090
server.wait_for_daemon("worker-1", timeout=30)
9191

9292
# Execute command
93-
result = server.execute_command("worker-1", "hostname")
93+
result = server.exec("worker-1", "hostname")
9494
print(f"Output: {result.stdout}")
9595
```
9696

docs/ARCHITECTURE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ At 200+ connections, Python asyncio:
2929
### Why WebSocket?
3030

3131
- Persistent bidirectional connection
32-
- Efficient for streaming (shell output)
32+
- Efficient for streaming (session output)
3333
- Well-supported libraries
3434
- Can multiplex multiple sessions over one connection
3535

docs/DEVELOP.md

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ SandD/
2424
│ ├── src/
2525
│ │ ├── main.rs # Daemon entry point
2626
│ │ ├── executor.rs # Command execution
27-
│ │ ├── shell.rs # Shell (not implemented)
27+
│ │ ├── session.rs # Interactive sessions (PTY)
2828
│ │ └── protocol.rs # Message protocol
2929
│ └── Cargo.toml
3030
@@ -124,7 +124,7 @@ command_tx: mpsc::UnboundedSender<Message> // Stored in registry
124124
**Incoming (Daemon → Python):**
125125
```rust
126126
pending_commands: oneshot::Sender<Result> // Request/Response
127-
shell_sessions: mpsc::Sender<Vec<u8>> // Streaming
127+
sessions: mpsc::Sender<Vec<u8>> // Streaming
128128
file_transfers: Vec<Vec<u8>> // Chunked buffering
129129
```
130130

@@ -211,11 +211,7 @@ RUST_LOG=server=debug python3 examples/simple_test.py
211211

212212
### Not Implemented
213213

214-
1. **Interactive Shell**: Infrastructure exists, daemon returns "not implemented"
215-
- Reason: `PtySystem` Sync issues
216-
- Fix: Refactor shell manager to avoid Sync constraints
217-
218-
2. **File Transfer**: Protocol defined, daemon just logs
214+
1. **File Transfer**: Protocol defined, daemon just logs
219215
- Reason: Deferred for MVP
220216
- Fix: Implement actual file I/O in daemon
221217

@@ -278,14 +274,14 @@ Include motivation and context.
278274
- Check daemon logs: `RUST_LOG=info ./target/release/sandd ...`
279275

280276
**Commands timing out:**
281-
- Increase `timeout` parameter in `execute_command()` (in seconds)
277+
- Increase `timeout` parameter in `exec()` (in seconds)
282278
- Check daemon system resources: `top`, `free -h`
283279
- Verify command actually completes when run manually
284280
- Check daemon logs for errors
285281

286282
**High memory usage:**
287-
- Monitor active shell sessions (they hold state)
288-
- Close unused shell sessions
283+
- Monitor active sessions (they hold state)
284+
- Close unused sessions with `session.close()`
289285
- Check number of connected daemons: `server.daemon_count()`
290286

291287
### Development Issues

docs/PROTOCOL.md

Lines changed: 46 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ All messages are JSON with a `type` field indicating the message type:
5656

5757
```json
5858
{
59-
"type": "execute_command",
60-
"command_id": "uuid-here",
59+
"type": "exec",
60+
"request_id": "uuid-here",
6161
"command": "ls -la",
6262
"timeout_secs": 300,
6363
"env": {},
@@ -130,8 +130,8 @@ All messages are JSON with a `type` field indicating the message type:
130130

131131
```json
132132
{
133-
"type": "execute_command",
134-
"command_id": "550e8400-e29b-41d4-a716-446655440000",
133+
"type": "exec",
134+
"request_id": "550e8400-e29b-41d4-a716-446655440000",
135135
"command": "python script.py",
136136
"timeout_secs": 300,
137137
"env": {
@@ -142,7 +142,7 @@ All messages are JSON with a `type` field indicating the message type:
142142
```
143143

144144
**Fields**:
145-
- `command_id`: Unique identifier for tracking this command
145+
- `request_id`: Unique identifier for tracking this request
146146
- `command`: Shell command to execute
147147
- `timeout_secs`: Maximum execution time (default: 300)
148148
- `env`: Environment variables (optional)
@@ -155,7 +155,7 @@ All messages are JSON with a `type` field indicating the message type:
155155
```json
156156
{
157157
"type": "command_output",
158-
"command_id": "550e8400-e29b-41d4-a716-446655440000",
158+
"request_id": "550e8400-e29b-41d4-a716-446655440000",
159159
"stdout": "output text...",
160160
"stderr": "",
161161
"exit_code": 0,
@@ -170,88 +170,99 @@ All messages are JSON with a `type` field indicating the message type:
170170
```json
171171
{
172172
"type": "command_error",
173-
"command_id": "550e8400-e29b-41d4-a716-446655440000",
173+
"request_id": "550e8400-e29b-41d4-a716-446655440000",
174174
"error": "command not found"
175175
}
176176
```
177177

178-
### Interactive Shell (PTY)
178+
### Interactive Session (PTY)
179179

180-
#### StartShell
180+
#### StartSession
181181
**Direction**: Agent → Daemon
182-
**Purpose**: Start an interactive shell session
182+
**Purpose**: Start an interactive session
183183

184184
```json
185185
{
186-
"type": "start_shell",
186+
"type": "start_session",
187187
"session_id": "550e8400-e29b-41d4-a716-446655440001",
188188
"rows": 24,
189189
"cols": 80,
190190
"term": "xterm-256color"
191191
}
192192
```
193193

194-
#### ShellStarted
194+
#### SessionStarted
195195
**Direction**: Daemon → Agent
196-
**Purpose**: Acknowledge shell started
196+
**Purpose**: Acknowledge session started
197197

198198
```json
199199
{
200-
"type": "shell_started",
200+
"type": "session_started",
201201
"session_id": "550e8400-e29b-41d4-a716-446655440001",
202202
"success": true,
203203
"error": null
204204
}
205205
```
206206

207-
#### ShellInput
207+
#### SessionInput
208208
**Direction**: Agent → Daemon
209-
**Purpose**: Send user input to shell
209+
**Purpose**: Send user input to session
210210

211211
```json
212212
{
213-
"type": "shell_input",
213+
"type": "session_input",
214214
"session_id": "550e8400-e29b-41d4-a716-446655440001",
215215
"data": "bHMgLWxhCg=="
216216
}
217217
```
218218

219219
**Note**: `data` is base64-encoded bytes
220220

221-
#### ShellOutput
221+
#### SessionOutput
222222
**Direction**: Daemon → Agent
223-
**Purpose**: Stream shell output back to agent
223+
**Purpose**: Stream session output back to agent
224224

225225
```json
226226
{
227-
"type": "shell_output",
227+
"type": "session_output",
228228
"session_id": "550e8400-e29b-41d4-a716-446655440001",
229229
"data": "ZmlsZTEgIGZpbGUyICBmaWxlMwo="
230230
}
231231
```
232232

233233
**Note**: `data` is base64-encoded bytes
234234

235-
#### ShellResize
235+
#### SessionResize
236236
**Direction**: Agent → Daemon
237237
**Purpose**: Resize terminal window
238238

239239
```json
240240
{
241-
"type": "shell_resize",
241+
"type": "session_resize",
242242
"session_id": "550e8400-e29b-41d4-a716-446655440001",
243243
"rows": 50,
244244
"cols": 120
245245
}
246246
```
247247

248-
#### ShellExit
248+
#### SessionClose
249+
**Direction**: Agent → Daemon
250+
**Purpose**: Close session
251+
252+
```json
253+
{
254+
"type": "session_close",
255+
"session_id": "550e8400-e29b-41d4-a716-446655440001"
256+
}
257+
```
258+
259+
#### SessionExit
249260
**Direction**: Daemon → Agent
250-
**Purpose**: Shell session terminated
261+
**Purpose**: Session terminated
251262

252263
```json
253264
{
254-
"type": "shell_exit",
265+
"type": "session_exit",
255266
"session_id": "550e8400-e29b-41d4-a716-446655440001",
256267
"exit_code": 0
257268
}
@@ -367,25 +378,25 @@ All messages are JSON with a `type` field indicating the message type:
367378

368379
### Request/Response (Command Execution)
369380

370-
1. Agent generates unique `command_id`
371-
2. Agent registers oneshot channel for this command
381+
1. Agent generates unique `request_id`
382+
2. Agent registers oneshot channel for this request
372383
3. Agent sends `ExecuteCommand` message
373384
4. Daemon executes and sends back `CommandOutput`
374385
5. Agent resolves channel, Python receives result
375386

376387
**Concurrency**: Multiple commands can execute in parallel
377388

378-
### Streaming (Shell Sessions)
389+
### Streaming (Interactive Sessions)
379390

380391
1. Agent generates unique `session_id`
381392
2. Agent registers mpsc channel for this session
382-
3. Agent sends `StartShell` message
393+
3. Agent sends `StartSession` message
383394
4. Daemon starts PTY and begins streaming output
384-
5. Agent sends `ShellInput` as user types
385-
6. Daemon sends `ShellOutput` continuously
386-
7. Session ends with `ShellExit`
395+
5. Agent sends `SessionInput` as user types
396+
6. Daemon sends `SessionOutput` continuously
397+
7. Session ends with `SessionExit`
387398

388-
**Concurrency**: Multiple shell sessions per daemon supported
399+
**Concurrency**: Multiple sessions per daemon supported
389400

390401
### Chunked Transfer (File Download)
391402

@@ -413,7 +424,7 @@ All messages are JSON with a `type` field indicating the message type:
413424
- Agent detects closed connection
414425
- Registry removes daemon
415426
- All pending commands fail
416-
- Shell sessions terminate
427+
- Terminate
417428
```
418429

419430
## Heartbeat & Connection Monitoring
@@ -434,4 +445,4 @@ All messages are JSON with a `type` field indicating the message type:
434445

435446
See `server/src/protocol.rs` for the complete Rust implementation using serde for JSON serialization.
436447

437-
Binary data (shell I/O, file chunks) is base64-encoded for JSON compatibility.
448+
Binary data (session I/O, file chunks) is base64-encoded for JSON compatibility.

0 commit comments

Comments
 (0)