syntax = "proto3"; package volume; option go_package = "github.com/yaoapp/yao/tai/volume/pb"; // Volume provides bulk file synchronization, real-time filesystem I/O, // and archive/compression operations. // Shares gRPC port :19100 with Yao Gateway. service Volume { // --- Bulk Sync --- // SyncPush: Yao sends code to Tai (before container start). // Bidirectional stream: // 1. Yao sends SyncManifest (file list with mtime+size) // 2. Tai diffs, replies with SyncDiff (which files to send) // 3. Yao sends only needed FileChunks // 4. Tai replies with SyncResult rpc SyncPush(stream SyncMessage) returns (stream SyncMessage); // SyncPull: Yao pulls changes from Tai (after container stop). // Yao sends its file manifest; Tai diffs internally and streams back changed files. rpc SyncPull(SyncManifest) returns (stream SyncMessage); // --- Real-Time FS IO --- rpc ReadFile(FSReadRequest) returns (stream FSDataChunk); rpc WriteFile(stream FSWriteChunk) returns (FSWriteResponse); rpc Stat(FSRequest) returns (FileInfo); rpc ListDir(FSRequest) returns (FSListResponse); rpc Remove(FSRemoveRequest) returns (FSOpResponse); rpc Rename(FSRenameRequest) returns (FSOpResponse); rpc MkdirAll(FSRequest) returns (FSOpResponse); // Abs: resolve a session-relative path to its absolute path on the host. rpc Abs(FSRequest) returns (FSAbsResponse); // Copy: copy src to dst within the same workspace (server-side when remote). rpc Copy(FSCopyRequest) returns (SyncResult); // --- Archive / Compression --- rpc Zip(ArchiveRequest) returns (ArchiveResponse); rpc Unzip(ArchiveRequest) returns (ArchiveResponse); rpc Gzip(ArchiveRequest) returns (ArchiveResponse); rpc Gunzip(ArchiveRequest) returns (ArchiveResponse); rpc Tar(ArchiveRequest) returns (ArchiveResponse); rpc Untar(ArchiveRequest) returns (ArchiveResponse); rpc Tgz(ArchiveRequest) returns (ArchiveResponse); rpc Untgz(ArchiveRequest) returns (ArchiveResponse); } // --- File Metadata --- message FileInfo { string path = 1; int64 size = 2; int64 mtime = 3; // unix timestamp (nanoseconds) uint32 mode = 4; bool is_dir = 5; } // --- Sync Messages --- message SyncManifest { string session_id = 1; repeated FileInfo files = 2; bool force_full = 3; // skip snapshot cache, diff against actual disk string remote_path = 4; // sub-path within workspace root; empty = root } message SyncMessage { oneof payload { SyncManifest manifest = 1; SyncDiff diff = 2; FileChunk chunk = 3; SyncResult result = 4; } } message SyncDiff { repeated string need_files = 1; // paths needing full transfer repeated string delete_files = 2; // paths Tai should delete } message FileChunk { string path = 1; ChunkType type = 2; bytes data = 3; // lz4 compressed (V1: always FULL) uint32 mode = 4; // file mode (first chunk only) int64 mtime = 5; // modification time (first chunk only) bool eof = 6; enum ChunkType { FULL = 0; DELTA = 1; // reserved for future rsync delta DELETE = 2; MKDIR = 3; } } message SyncResult { int32 files_synced = 1; int64 bytes_transferred = 2; int64 duration_ms = 3; } // --- FS IO Messages --- message FSRequest { string session_id = 1; string path = 2; } message FSOpResponse { bool ok = 1; string error = 2; } message FSAbsResponse { string path = 1; // absolute path on the host filesystem } message FSReadRequest { string session_id = 1; string path = 2; } message FSDataChunk { bytes data = 1; // up to 64KB per message uint32 mode = 2; // first chunk only int64 size = 3; // total file size (first chunk only) int64 mtime = 4; // modification time (first chunk only) } message FSWriteChunk { string session_id = 1; // first chunk only string path = 2; // first chunk only bytes data = 3; uint32 mode = 4; // first chunk only, 0 = keep existing bool create_dirs = 5; // auto-create parent directories (first chunk only) } message FSWriteResponse { int64 size = 1; } message FSListResponse { repeated FileInfo entries = 1; } message FSRemoveRequest { string session_id = 1; string path = 2; bool recursive = 3; // true = RemoveAll, false = Remove } message FSRenameRequest { string session_id = 1; string old_path = 2; string new_path = 3; } message FSCopyRequest { string session_id = 1; string src_path = 2; string dst_path = 3; repeated string excludes = 4; // glob patterns bool force = 5; // overwrite even if mtime/size match } // --- Archive / Compression Messages --- message ArchiveRequest { string session_id = 1; string src_path = 2; // relative to workspace root string dst_path = 3; // relative to workspace root repeated string excludes = 4; // glob patterns (pack ops only) } message ArchiveResponse { int64 size_bytes = 1; // output file size (pack) or total extracted size (unpack) int32 files_count = 2; // number of files processed }