mirror of
https://github.com/YspCoder/clawgo.git
synced 2026-05-17 09:27:28 +08:00
fix
This commit is contained in:
19
Makefile
19
Makefile
@@ -1,4 +1,4 @@
|
|||||||
.PHONY: all build install uninstall clean help test install-bootstrap-docs
|
.PHONY: all build build-all install uninstall clean help test install-bootstrap-docs sync-embed-workspace
|
||||||
|
|
||||||
# Build variables
|
# Build variables
|
||||||
BINARY_NAME=clawgo
|
BINARY_NAME=clawgo
|
||||||
@@ -32,6 +32,8 @@ CLAWGO_HOME?=$(USER_HOME)/.clawgo
|
|||||||
WORKSPACE_DIR?=$(CLAWGO_HOME)/workspace
|
WORKSPACE_DIR?=$(CLAWGO_HOME)/workspace
|
||||||
WORKSPACE_SKILLS_DIR=$(WORKSPACE_DIR)/skills
|
WORKSPACE_SKILLS_DIR=$(WORKSPACE_DIR)/skills
|
||||||
BUILTIN_SKILLS_DIR=$(CURDIR)/skills
|
BUILTIN_SKILLS_DIR=$(CURDIR)/skills
|
||||||
|
WORKSPACE_SOURCE_DIR=$(CURDIR)/workspace
|
||||||
|
EMBED_WORKSPACE_DIR=$(CURDIR)/cmd/$(BINARY_NAME)/workspace
|
||||||
|
|
||||||
# OS detection
|
# OS detection
|
||||||
UNAME_S:=$(shell uname -s)
|
UNAME_S:=$(shell uname -s)
|
||||||
@@ -69,7 +71,7 @@ BINARY_PATH=$(BUILD_DIR)/$(BINARY_NAME)-$(PLATFORM)-$(ARCH)
|
|||||||
all: build
|
all: build
|
||||||
|
|
||||||
## build: Build the clawgo binary for current platform
|
## build: Build the clawgo binary for current platform
|
||||||
build:
|
build: sync-embed-workspace
|
||||||
@echo "Building $(BINARY_NAME) for $(PLATFORM)/$(ARCH)..."
|
@echo "Building $(BINARY_NAME) for $(PLATFORM)/$(ARCH)..."
|
||||||
@mkdir -p $(BUILD_DIR)
|
@mkdir -p $(BUILD_DIR)
|
||||||
$(GO) build $(GOFLAGS) $(LDFLAGS) -o $(BINARY_PATH) ./$(CMD_DIR)
|
$(GO) build $(GOFLAGS) $(LDFLAGS) -o $(BINARY_PATH) ./$(CMD_DIR)
|
||||||
@@ -77,7 +79,7 @@ build:
|
|||||||
@ln -sf $(BINARY_NAME)-$(PLATFORM)-$(ARCH) $(BUILD_DIR)/$(BINARY_NAME)
|
@ln -sf $(BINARY_NAME)-$(PLATFORM)-$(ARCH) $(BUILD_DIR)/$(BINARY_NAME)
|
||||||
|
|
||||||
## build-all: Build clawgo for all platforms
|
## build-all: Build clawgo for all platforms
|
||||||
build-all:
|
build-all: sync-embed-workspace
|
||||||
@echo "Building for multiple platforms..."
|
@echo "Building for multiple platforms..."
|
||||||
@mkdir -p $(BUILD_DIR)
|
@mkdir -p $(BUILD_DIR)
|
||||||
GOOS=linux GOARCH=amd64 $(GO) build $(LDFLAGS) -o $(BUILD_DIR)/$(BINARY_NAME)-linux-amd64 ./$(CMD_DIR)
|
GOOS=linux GOARCH=amd64 $(GO) build $(LDFLAGS) -o $(BUILD_DIR)/$(BINARY_NAME)-linux-amd64 ./$(CMD_DIR)
|
||||||
@@ -87,6 +89,17 @@ build-all:
|
|||||||
GOOS=windows GOARCH=amd64 $(GO) build $(LDFLAGS) -o $(BUILD_DIR)/$(BINARY_NAME)-windows-amd64.exe ./$(CMD_DIR)
|
GOOS=windows GOARCH=amd64 $(GO) build $(LDFLAGS) -o $(BUILD_DIR)/$(BINARY_NAME)-windows-amd64.exe ./$(CMD_DIR)
|
||||||
@echo "All builds complete"
|
@echo "All builds complete"
|
||||||
|
|
||||||
|
## sync-embed-workspace: Sync root workspace files into cmd/clawgo/workspace for go:embed
|
||||||
|
sync-embed-workspace:
|
||||||
|
@echo "Syncing workspace seed files for embedding..."
|
||||||
|
@if [ ! -d "$(WORKSPACE_SOURCE_DIR)" ]; then \
|
||||||
|
echo "✗ Missing source workspace directory: $(WORKSPACE_SOURCE_DIR)"; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
@mkdir -p "$(EMBED_WORKSPACE_DIR)"
|
||||||
|
@rsync -a --delete "$(WORKSPACE_SOURCE_DIR)/" "$(EMBED_WORKSPACE_DIR)/"
|
||||||
|
@echo "✓ Synced to $(EMBED_WORKSPACE_DIR)"
|
||||||
|
|
||||||
## install: Install clawgo to system and copy builtin skills
|
## install: Install clawgo to system and copy builtin skills
|
||||||
install: build
|
install: build
|
||||||
@echo "Installing $(BINARY_NAME)..."
|
@echo "Installing $(BINARY_NAME)..."
|
||||||
|
|||||||
@@ -9,10 +9,12 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"context"
|
"context"
|
||||||
|
"embed"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
||||||
@@ -40,6 +42,9 @@ import (
|
|||||||
"github.com/chzyer/readline"
|
"github.com/chzyer/readline"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//go:embed workspace
|
||||||
|
var embeddedFiles embed.FS
|
||||||
|
|
||||||
const version = "0.1.0"
|
const version = "0.1.0"
|
||||||
const logo = "🦞"
|
const logo = "🦞"
|
||||||
const gatewayServiceName = "clawgo-gateway.service"
|
const gatewayServiceName = "clawgo-gateway.service"
|
||||||
@@ -262,35 +267,25 @@ func printHelp() {
|
|||||||
func onboard() {
|
func onboard() {
|
||||||
configPath := getConfigPath()
|
configPath := getConfigPath()
|
||||||
|
|
||||||
cfg := config.DefaultConfig()
|
if _, err := os.Stat(configPath); err == nil {
|
||||||
if strings.EqualFold(strings.TrimSpace(os.Getenv(envRootGranted)), "1") || strings.EqualFold(strings.TrimSpace(os.Getenv(envRootGranted)), "true") {
|
fmt.Printf("Config already exists at %s\n", configPath)
|
||||||
applyMaximumPermissionPolicy(cfg)
|
fmt.Print("Overwrite? (y/n): ")
|
||||||
|
var response string
|
||||||
|
fmt.Scanln(&response)
|
||||||
|
if response != "y" {
|
||||||
|
fmt.Println("Aborted.")
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
configStatus, err := ensureConfigOnboard(configPath, cfg)
|
|
||||||
if err != nil {
|
cfg := config.DefaultConfig()
|
||||||
fmt.Printf("Error preparing config: %v\n", err)
|
if err := config.SaveConfig(configPath, cfg); err != nil {
|
||||||
|
fmt.Printf("Error saving config: %v\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
fmt.Printf("Config: %s (%s)\n", configPath, configStatus)
|
|
||||||
|
|
||||||
workspace := cfg.WorkspacePath()
|
workspace := cfg.WorkspacePath()
|
||||||
if err := os.MkdirAll(workspace, 0755); err != nil {
|
createWorkspaceTemplates(workspace)
|
||||||
fmt.Printf("Error creating workspace: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
if err := os.MkdirAll(filepath.Join(workspace, "memory"), 0755); err != nil {
|
|
||||||
fmt.Printf("Error creating memory directory: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
if err := os.MkdirAll(filepath.Join(workspace, "skills"), 0755); err != nil {
|
|
||||||
fmt.Printf("Error creating skills directory: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := createWorkspaceTemplates(workspace); err != nil {
|
|
||||||
fmt.Printf("Error creating workspace templates: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("%s clawgo is ready!\n", logo)
|
fmt.Printf("%s clawgo is ready!\n", logo)
|
||||||
fmt.Println("\nNext steps:")
|
fmt.Println("\nNext steps:")
|
||||||
@@ -321,88 +316,51 @@ func ensureConfigOnboard(configPath string, defaults *config.Config) (string, er
|
|||||||
return "created", nil
|
return "created", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createWorkspaceTemplates(workspace string) error {
|
func copyEmbeddedToTarget(targetDir string) error {
|
||||||
templateRoot, err := resolveOnboardTemplateRoot()
|
if err := os.MkdirAll(targetDir, 0755); err != nil {
|
||||||
if err != nil {
|
return fmt.Errorf("failed to create target directory: %w", err)
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
templateFiles := []string{
|
return fs.WalkDir(embeddedFiles, "workspace", func(path string, d fs.DirEntry, err error) error {
|
||||||
"AGENTS.md",
|
|
||||||
"SOUL.md",
|
|
||||||
"USER.md",
|
|
||||||
"IDENTITY.md",
|
|
||||||
"memory/MEMORY.md",
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, relPath := range templateFiles {
|
|
||||||
srcPath := filepath.Join(templateRoot, filepath.FromSlash(relPath))
|
|
||||||
data, err := os.ReadFile(srcPath)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to read template %s: %w", relPath, err)
|
return err
|
||||||
|
}
|
||||||
|
if d.IsDir() {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
dstPath := filepath.Join(workspace, filepath.FromSlash(relPath))
|
data, err := embeddedFiles.ReadFile(path)
|
||||||
if _, err := os.Stat(dstPath); err == nil {
|
if err != nil {
|
||||||
continue
|
return fmt.Errorf("failed to read embedded file %s: %w", path, err)
|
||||||
} else if !os.IsNotExist(err) {
|
|
||||||
return fmt.Errorf("failed to stat %s: %w", relPath, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.MkdirAll(filepath.Dir(dstPath), 0755); err != nil {
|
relPath, err := filepath.Rel("workspace", path)
|
||||||
return fmt.Errorf("failed to create directory for %s: %w", relPath, err)
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get relative path for %s: %w", path, err)
|
||||||
}
|
}
|
||||||
if err := os.WriteFile(dstPath, data, 0644); err != nil {
|
targetPath := filepath.Join(targetDir, relPath)
|
||||||
return fmt.Errorf("failed to write %s: %w", relPath, err)
|
if _, statErr := os.Stat(targetPath); statErr == nil {
|
||||||
|
return nil
|
||||||
|
} else if !os.IsNotExist(statErr) {
|
||||||
|
return statErr
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.MkdirAll(filepath.Dir(targetPath), 0755); err != nil {
|
||||||
|
return fmt.Errorf("failed to create directory %s: %w", filepath.Dir(targetPath), err)
|
||||||
|
}
|
||||||
|
if err := os.WriteFile(targetPath, data, 0644); err != nil {
|
||||||
|
return fmt.Errorf("failed to write file %s: %w", targetPath, err)
|
||||||
}
|
}
|
||||||
fmt.Printf(" Created %s\n", relPath)
|
fmt.Printf(" Created %s\n", relPath)
|
||||||
}
|
return nil
|
||||||
|
})
|
||||||
skillsDir := filepath.Join(workspace, "skills")
|
|
||||||
if _, err := os.Stat(skillsDir); os.IsNotExist(err) {
|
|
||||||
if err := os.MkdirAll(skillsDir, 0755); err != nil {
|
|
||||||
return fmt.Errorf("failed to create skills directory: %w", err)
|
|
||||||
}
|
|
||||||
fmt.Println(" Created skills/")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveOnboardTemplateRoot() (string, error) {
|
func createWorkspaceTemplates(workspace string) {
|
||||||
required := []string{
|
err := copyEmbeddedToTarget(workspace)
|
||||||
"AGENTS.md",
|
if err != nil {
|
||||||
"SOUL.md",
|
fmt.Printf("Error copying workspace templates: %v\n", err)
|
||||||
"USER.md",
|
|
||||||
"IDENTITY.md",
|
|
||||||
"memory/MEMORY.md",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
candidates := []string{
|
|
||||||
filepath.Join("workspace"),
|
|
||||||
}
|
|
||||||
if exePath, err := os.Executable(); err == nil {
|
|
||||||
exeDir := filepath.Dir(exePath)
|
|
||||||
candidates = append(candidates,
|
|
||||||
filepath.Join(exeDir, "workspace"),
|
|
||||||
filepath.Join(exeDir, "..", "workspace"),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, candidate := range candidates {
|
|
||||||
root := filepath.Clean(candidate)
|
|
||||||
ok := true
|
|
||||||
for _, relPath := range required {
|
|
||||||
if _, err := os.Stat(filepath.Join(root, filepath.FromSlash(relPath))); err != nil {
|
|
||||||
ok = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ok {
|
|
||||||
return root, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", fmt.Errorf("workspace templates not found; expected AGENTS.md/SOUL.md/USER.md/IDENTITY.md and memory/MEMORY.md under ./workspace")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func agentCmd() {
|
func agentCmd() {
|
||||||
|
|||||||
Reference in New Issue
Block a user