yao/tai/docs/volume.md
Max d70694b7ac ci: update Tai to 1.2.0 with new default ports and fix documentation
- Update CI (unit-test.yml, pr-test.yml) to use yaoapp/tai:1.2.0
  with new default ports (gRPC:19100, HTTP:8099, VNC:16080, Docker:12375)
- Add explicit 0.0.0.0 bind for containerized Tai instances
- Fix sandbox/v2 grpc.go default port fallback (9100 → 19100)
- Fix tai/tunnel/proxy.go fallback ports (8080→8099, 6080→16080)
- Sync tai SDK and sandbox/v2 documentation with implementation
- Add new docs: api.md, registry.md, tunnel.md

Made-with: Cursor
2026-03-08 11:33:56 +08:00

120 lines
3.7 KiB
Markdown

# Package `volume`
File IO and directory synchronization. Provides a `Volume` interface with two implementations:
| Implementation | Constructor | Backend | Mode |
|----------------|-------------|---------|------|
| **Local** | `NewLocal(root)` | Direct filesystem | Local |
| **Remote** | `NewRemote(conn)` | gRPC to Tai :19100 | Remote |
## Interface
```go
type Volume interface {
ReadFile(ctx context.Context, sessionID, path string) (data []byte, perm os.FileMode, err error)
WriteFile(ctx context.Context, sessionID, path string, data []byte, perm os.FileMode) error
Stat(ctx context.Context, sessionID, path string) (*FileInfo, error)
ListDir(ctx context.Context, sessionID, path string) ([]FileInfo, error)
Remove(ctx context.Context, sessionID, path string, recursive bool) error
Rename(ctx context.Context, sessionID, oldPath, newPath string) error
MkdirAll(ctx context.Context, sessionID, path string) error
SyncPush(ctx context.Context, sessionID, localDir string, opts ...SyncOption) (*SyncResult, error)
SyncPull(ctx context.Context, sessionID, localDir string, opts ...SyncOption) (*SyncResult, error)
Close() error
}
```
All paths are **relative** to the session's workspace root. The `sessionID` identifies the workspace partition — in Local mode this maps to `<root>/<sessionID>/`, in Remote mode the Tai server manages the path.
## Constructors
### NewLocal
```go
func NewLocal(dataDir string) Volume
```
Creates a Volume backed by the local filesystem. Files are stored under `<dataDir>/<sessionID>/`.
### NewRemote
```go
func NewRemote(conn *grpc.ClientConn) Volume
```
Creates a Volume backed by Tai's gRPC Volume service. The connection should target Tai's gRPC port (default 19100). Uses lz4 compression for `SyncPush`/`SyncPull` bulk transfers.
## Types
### FileInfo
```go
type FileInfo struct {
Path string
Size int64
Mtime time.Time
Mode fs.FileMode
IsDir bool
}
```
### SyncResult
```go
type SyncResult struct {
FilesSynced int
BytesTransferred int64
Duration time.Duration
}
```
## Sync Options
```go
volume.WithForceFull() // skip snapshot cache, diff against actual disk
volume.WithExcludes("*.log", ".DS_Store") // glob patterns to exclude
```
## File Operations
| Method | Description |
|--------|-------------|
| `ReadFile` | Read file contents and permissions |
| `WriteFile` | Write file with specified permissions (creates parent dirs) |
| `Stat` | Get file/directory metadata |
| `ListDir` | List directory contents (one level) |
| `Remove` | Delete file or directory (`recursive=true` for tree) |
| `Rename` | Move/rename a file or directory |
| `MkdirAll` | Create directory tree |
## Sync Operations
| Method | Direction | Description |
|--------|-----------|-------------|
| `SyncPush` | local → remote | Upload a local directory to the session workspace |
| `SyncPull` | remote → local | Download the session workspace to a local directory |
Both sync methods use snapshot-based diffing to transfer only changed files. Use `WithForceFull()` to bypass the cache and force a full transfer.
Remote sync uses **lz4 compression** on the wire, streaming files via gRPC bidirectional streaming.
## Example
```go
vol := volume.NewLocal("/data/volumes")
defer vol.Close()
// Write a file
vol.WriteFile(ctx, "session-1", "main.py", []byte("print('hi')"), 0644)
// Read it back
data, perm, _ := vol.ReadFile(ctx, "session-1", "main.py")
// Sync a local directory to the session
result, _ := vol.SyncPush(ctx, "session-1", "/tmp/project",
volume.WithExcludes("node_modules", ".git"),
)
fmt.Printf("synced %d files (%d bytes)\n", result.FilesSynced, result.BytesTransferred)
```