- Replace Python test plugins (echo, ai_test, claudecode) with Rust implementations driven by the plugin SDK - Convert fs/network/process/timer syscall modules to async/await - Change Network.OpenConn to return stream ConnEvent (conn_id handed to client in first "open" frame for Send/Close routing) - Bind timer callbacks to plugin identity; stream_call subscriptions are identity-checked - Update docs and regenerate Python SDK protobuf stubs Verified: cargo build/test/clippy clean; echo + ai_test full syscall suites pass; hermes & claudecode register and heartbeat; cross-plugin bridge.call routing and auth denial verified end-to-end. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
219 lines
8.3 KiB
Protocol Buffer
219 lines
8.3 KiB
Protocol Buffer
syntax = "proto3";
|
|
package agentsd;
|
|
|
|
// ========== Display ==========
|
|
service Display {
|
|
rpc Text(DisplayTextRequest) returns (DisplayResponse);
|
|
rpc Rich(DisplayRichRequest) returns (DisplayResponse);
|
|
rpc Image(DisplayImageRequest) returns (DisplayResponse);
|
|
rpc Clear(Empty) returns (DisplayResponse);
|
|
rpc Notify(DisplayNotifyRequest) returns (DisplayResponse);
|
|
}
|
|
|
|
message DisplayTextRequest { string content = 1; }
|
|
message DisplayRichRequest { string markup = 1; string format = 2; }
|
|
message DisplayImageRequest { bytes data = 1; string format = 2; }
|
|
message DisplayNotifyRequest { string message = 1; }
|
|
message DisplayResponse { bool ok = 1; string error = 2; }
|
|
|
|
// ========== Audio ==========
|
|
service Audio {
|
|
rpc Play(stream AudioChunk) returns (AudioResponse);
|
|
rpc Stop(Empty) returns (AudioResponse);
|
|
rpc Volume(VolumeRequest) returns (AudioResponse);
|
|
rpc RecordStart(RecordStartRequest) returns (AudioResponse);
|
|
rpc RecordStop(Empty) returns (AudioData);
|
|
rpc RecordStream(RecordStartRequest) returns (stream AudioChunk);
|
|
}
|
|
|
|
message AudioChunk { bytes data = 1; string format = 2; }
|
|
message VolumeRequest { float level = 1; }
|
|
message RecordStartRequest { string format = 1; }
|
|
message AudioData { bytes data = 1; string format = 2; }
|
|
message AudioResponse { bool ok = 1; string error = 2; }
|
|
|
|
// ========== FS ==========
|
|
service FS {
|
|
rpc Read(FsReadRequest) returns (FsReadResponse);
|
|
rpc Write(FsWriteRequest) returns (FsResponse);
|
|
rpc Delete(FsPathRequest) returns (FsResponse);
|
|
rpc Rename(FsRenameRequest) returns (FsResponse);
|
|
rpc Stat(FsPathRequest) returns (FsStatResponse);
|
|
rpc List(FsPathRequest) returns (FsListResponse);
|
|
rpc Watch(FsPathRequest) returns (stream FsWatchEvent);
|
|
}
|
|
|
|
message FsPathRequest { string path = 1; }
|
|
message FsReadRequest { string path = 1; int64 offset = 2; int64 length = 3; }
|
|
message FsReadResponse { bytes data = 1; bool ok = 2; string error = 3; }
|
|
message FsWriteRequest { string path = 1; bytes data = 2; bool append = 3; }
|
|
message FsRenameRequest { string from = 1; string to = 2; }
|
|
message FsStatResponse {
|
|
bool ok = 1;
|
|
string error = 2;
|
|
int64 size = 3;
|
|
bool is_dir = 4;
|
|
bool is_file = 5;
|
|
int64 modified = 6;
|
|
int64 created = 7;
|
|
uint32 permissions = 8;
|
|
}
|
|
message FsListResponse {
|
|
bool ok = 1;
|
|
string error = 2;
|
|
repeated FsEntry entries = 3;
|
|
}
|
|
message FsEntry { string name = 1; bool is_dir = 2; int64 size = 3; }
|
|
message FsWatchEvent { string path = 1; string kind = 2; }
|
|
message FsResponse { bool ok = 1; string error = 2; }
|
|
|
|
// ========== Memory ==========
|
|
service Memory {
|
|
rpc Read(MemoryReadRequest) returns (MemoryReadResponse);
|
|
rpc Write(MemoryWriteRequest) returns (MemoryResponse);
|
|
rpc Delete(MemoryKeyRequest) returns (MemoryResponse);
|
|
rpc List(MemoryListRequest) returns (MemoryListResponse);
|
|
rpc Search(MemorySearchRequest) returns (MemorySearchResponse);
|
|
}
|
|
|
|
message MemoryKeyRequest { string key = 1; }
|
|
message MemoryReadRequest { string key = 1; }
|
|
message MemoryReadResponse { bytes value = 1; bool found = 2; string error = 3; }
|
|
message MemoryWriteRequest { string key = 1; bytes value = 2; }
|
|
message MemoryListRequest { string prefix = 1; int32 limit = 2; }
|
|
message MemoryListResponse { repeated string keys = 1; string error = 2; }
|
|
message MemorySearchRequest { string query = 1; int32 limit = 2; }
|
|
message MemorySearchResponse {
|
|
repeated MemorySearchHit hits = 1;
|
|
string error = 2;
|
|
}
|
|
message MemorySearchHit { string key = 1; string snippet = 2; float score = 3; }
|
|
message MemoryResponse { bool ok = 1; string error = 2; }
|
|
|
|
// ========== Network ==========
|
|
service Network {
|
|
rpc Request(HttpRequest) returns (HttpResponse);
|
|
rpc OpenConn(ConnectRequest) returns (stream ConnEvent);
|
|
rpc Listen(ListenRequest) returns (stream ConnEvent);
|
|
rpc Send(SendRequest) returns (NetResponse);
|
|
rpc Close(CloseRequest) returns (NetResponse);
|
|
rpc Available(Empty) returns (NetAvailableResponse);
|
|
}
|
|
|
|
message HttpRequest {
|
|
string url = 1;
|
|
string method = 2;
|
|
map<string, string> headers = 3;
|
|
bytes body = 4;
|
|
}
|
|
message HttpResponse {
|
|
int32 status = 1;
|
|
map<string, string> headers = 2;
|
|
bytes body = 3;
|
|
string error = 4;
|
|
}
|
|
message ConnectRequest { string addr = 1; string protocol = 2; }
|
|
message ListenRequest { uint32 port = 1; string protocol = 2; }
|
|
message ConnEvent { string conn_id = 1; bytes data = 2; string kind = 3; }
|
|
message SendRequest { string conn_id = 1; bytes data = 2; }
|
|
message CloseRequest { string conn_id = 1; }
|
|
message DataChunk { bytes data = 1; }
|
|
message NetResponse { bool ok = 1; string error = 2; }
|
|
message NetAvailableResponse { bool available = 1; }
|
|
|
|
// ========== Process ==========
|
|
service Process {
|
|
rpc Spawn(SpawnRequest) returns (SpawnResponse);
|
|
rpc Kill(PidRequest) returns (ProcResponse);
|
|
rpc Wait(PidRequest) returns (WaitResponse);
|
|
rpc Stdin(StdinRequest) returns (ProcResponse);
|
|
rpc Stdout(PidRequest) returns (stream DataChunk);
|
|
rpc Signal(SignalRequest) returns (ProcResponse);
|
|
rpc ListProc(Empty) returns (ProcListResponse);
|
|
}
|
|
|
|
message SpawnRequest {
|
|
string cmd = 1;
|
|
repeated string args = 2;
|
|
map<string, string> env = 3;
|
|
string cwd = 4;
|
|
}
|
|
message SpawnResponse { uint64 pid = 1; bool ok = 2; string error = 3; }
|
|
message PidRequest { uint64 pid = 1; }
|
|
message WaitResponse { int32 exit_code = 1; bool ok = 2; string error = 3; }
|
|
message StdinRequest { uint64 pid = 1; bytes data = 2; }
|
|
message SignalRequest { uint64 pid = 1; int32 signal = 2; }
|
|
message ProcResponse { bool ok = 1; string error = 2; }
|
|
message ProcListResponse { repeated ProcInfo procs = 1; }
|
|
message ProcInfo { uint64 pid = 1; string cmd = 2; string status = 3; }
|
|
|
|
// ========== Timer ==========
|
|
service Timer {
|
|
rpc Once(TimerOnceRequest) returns (TimerResponse);
|
|
rpc Cron(TimerCronRequest) returns (TimerResponse);
|
|
rpc Cancel(TimerCancelRequest) returns (TimerResponse);
|
|
rpc Now(Empty) returns (TimerNowResponse);
|
|
}
|
|
|
|
message TimerOnceRequest { uint64 delay_ms = 1; string callback_id = 2; }
|
|
message TimerCronRequest { string expr = 1; string callback_id = 2; }
|
|
message TimerCancelRequest { string timer_id = 1; }
|
|
message TimerResponse { string timer_id = 1; bool ok = 2; string error = 3; }
|
|
message TimerNowResponse { int64 timestamp_ms = 1; }
|
|
|
|
// ========== HID ==========
|
|
service HID {
|
|
rpc Capture(CaptureRequest) returns (CaptureResponse);
|
|
rpc Mouse(MouseRequest) returns (HidResponse);
|
|
rpc Keyboard(KeyboardRequest) returns (HidResponse);
|
|
rpc Ocr(CaptureRequest) returns (OcrResponse);
|
|
}
|
|
|
|
message CaptureRequest { int32 x = 1; int32 y = 2; int32 width = 3; int32 height = 4; }
|
|
message CaptureResponse { bytes image = 1; string format = 2; bool ok = 3; string error = 4; }
|
|
message MouseRequest { int32 x = 1; int32 y = 2; string action = 3; string button = 4; }
|
|
message KeyboardRequest { string key = 1; string action = 2; repeated string modifiers = 3; }
|
|
message HidResponse { bool ok = 1; string error = 2; }
|
|
message OcrResponse { string text = 1; bool ok = 2; string error = 3; }
|
|
|
|
// ========== Input ==========
|
|
service Input {
|
|
rpc Text(Empty) returns (InputTextResponse);
|
|
rpc Key(Empty) returns (InputKeyResponse);
|
|
rpc Clipboard(Empty) returns (InputClipboardResponse);
|
|
rpc Events(Empty) returns (stream InputEvent);
|
|
}
|
|
|
|
message InputTextResponse { string text = 1; bool ok = 2; string error = 3; }
|
|
message InputKeyResponse { string key = 1; string action = 2; repeated string modifiers = 3; }
|
|
message InputClipboardResponse { bytes data = 1; string mime = 2; bool ok = 3; string error = 4; }
|
|
message InputEvent { string type = 1; bytes data = 2; }
|
|
|
|
// ========== Plugin Bridge ==========
|
|
service PluginBridge {
|
|
rpc Register(PluginInfo) returns (RegisterResponse);
|
|
rpc Call(CallRequest) returns (CallResponse);
|
|
rpc StreamCall(CallRequest) returns (stream CallResponse);
|
|
rpc Heartbeat(HeartbeatRequest) returns (HeartbeatResponse);
|
|
}
|
|
|
|
message PluginInfo {
|
|
string id = 1;
|
|
string name = 2;
|
|
string version = 3;
|
|
string plugin_type = 4;
|
|
repeated string syscalls = 5;
|
|
repeated string depends = 6;
|
|
repeated ExportDef exports = 7;
|
|
string endpoint = 8;
|
|
}
|
|
message ExportDef { string name = 1; string description = 2; }
|
|
message RegisterResponse { bool ok = 1; string error = 2; string session_id = 3; }
|
|
message CallRequest { string target = 1; string fn = 2; bytes args = 3; }
|
|
message CallResponse { bytes result = 1; bool ok = 2; string error = 3; }
|
|
message HeartbeatRequest { string plugin_id = 1; }
|
|
message HeartbeatResponse { bool ok = 1; }
|
|
|
|
// ========== Common ==========
|
|
message Empty {}
|