Files
goclaw/internal/tools/workspace_dir.go
T
viettranx 2c5ae04c01 feat(teams): implement workspace scope setting (shared vs isolated)
- IsSharedWorkspace() reads team.settings.workspace_scope
- Shared: workspace at teams/{teamID}/ (all chats share)
- Isolated (default): workspace at teams/{teamID}/{chatID}/
- Remove _default fallback; isolated mode requires chat_id
- Update loop.go, task creation, task listing, message dispatch,
  workspace API (list/read/delete), task board snapshot
- Update UI descriptions to reflect per-conversation scoping
2026-03-16 22:46:35 +07:00

53 lines
1.5 KiB
Go

package tools
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"github.com/google/uuid"
)
// Workspace limits shared across workspace interceptor.
const (
maxFileSizeBytes = 10 * 1024 * 1024 // 10MB
maxFilesPerScope = 100
)
// WorkspaceDir returns the disk directory for a team workspace scope.
// - chatID="" → team root: {dataDir}/teams/{teamID}/ (shared mode)
// - chatID="x" → per-chat: {dataDir}/teams/{teamID}/{chatID}/ (isolated mode)
// Creates directory with 0750 if not exists.
func WorkspaceDir(dataDir string, teamID uuid.UUID, chatID string) (string, error) {
dir := filepath.Join(dataDir, "teams", teamID.String())
if chatID != "" {
dir = filepath.Join(dir, chatID)
}
if err := os.MkdirAll(dir, 0750); err != nil {
return "", fmt.Errorf("failed to create workspace dir: %w", err)
}
return dir, nil
}
// IsSharedWorkspace returns true if the team's workspace_scope setting is "shared".
// Default (unset or "isolated") returns false.
func IsSharedWorkspace(settings json.RawMessage) bool {
if settings == nil {
return false
}
var s struct {
WorkspaceScope string `json:"workspace_scope"`
}
if json.Unmarshal(settings, &s) != nil {
return false
}
return s.WorkspaceScope == "shared"
}
// blockedExtensions lists executable file types that are not allowed in team workspaces.
var blockedExtensions = map[string]bool{
".exe": true, ".sh": true, ".bat": true, ".cmd": true,
".ps1": true, ".com": true, ".msi": true, ".scr": true,
}