feat: scaffold codespace backend

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
tao.chen
2026-07-02 15:07:54 +08:00
co-authored by Claude Fable 5
commit 411ed1f8ba
43 changed files with 4428 additions and 0 deletions
+73
View File
@@ -0,0 +1,73 @@
package workspace
import (
"os"
"path/filepath"
"codespace/internal/util"
)
// Manager manages workspace lifecycle.
type Manager interface {
Create(id string) (*Workspace, error)
Get(id string) (*Workspace, error)
Delete(id string) error
}
// LocalManager implements Manager using the local filesystem.
type LocalManager struct {
root string
}
// NewLocalManager creates a LocalManager rooted at root. The root is made
// absolute and cleaned if possible.
func NewLocalManager(root string) *LocalManager {
abs, err := filepath.Abs(root)
if err != nil {
abs = filepath.Clean(root)
}
return &LocalManager{root: abs}
}
// Create creates a workspace directory and returns the workspace.
func (m *LocalManager) Create(id string) (*Workspace, error) {
if !ValidID(id) {
return nil, util.New(util.CodeBadRequest, "invalid workspace id")
}
root := RootFor(m.root, id)
if err := os.MkdirAll(root, 0o755); err != nil {
return nil, util.Wrap(util.CodeInternal, "failed to create workspace", err)
}
return &Workspace{ID: id, Root: root}, nil
}
// Get returns the workspace if its directory exists.
func (m *LocalManager) Get(id string) (*Workspace, error) {
if !ValidID(id) {
return nil, util.New(util.CodeBadRequest, "invalid workspace id")
}
root := RootFor(m.root, id)
info, err := os.Stat(root)
if err != nil {
if os.IsNotExist(err) {
return nil, util.New(util.CodeNotFound, "workspace not found")
}
return nil, util.Wrap(util.CodeInternal, "failed to stat workspace", err)
}
if !info.IsDir() {
return nil, util.New(util.CodeNotFound, "workspace not found")
}
return &Workspace{ID: id, Root: root}, nil
}
// Delete removes the workspace directory recursively.
func (m *LocalManager) Delete(id string) error {
if !ValidID(id) {
return util.New(util.CodeBadRequest, "invalid workspace id")
}
root := RootFor(m.root, id)
if err := os.RemoveAll(root); err != nil {
return util.Wrap(util.CodeInternal, "failed to delete workspace", err)
}
return nil
}