Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 0 additions & 19 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,6 @@ jobs:
with:
version: v2.10.1

# TODO: Remove once linter is properly configured
vet:
name: Vet
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Setup Go
uses: actions/setup-go@v6
with:
go-version-file: go.mod

- name: Run go generate
run: go generate ./...

- name: Run go vet
run: go vet ./...

test:
name: Tests
runs-on: ubuntu-latest
Expand Down
1 change: 0 additions & 1 deletion .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ linters:
- godox
- goprintffuncname
- gosec
- govet
- ineffassign
- lll
- maintidx
Expand Down
6 changes: 3 additions & 3 deletions cmd/picoclaw/cmd_auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ func authLoginOpenAI(useDeviceCode bool) {
os.Exit(1)
}

if err := auth.SetCredential("openai", cred); err != nil {
if err = auth.SetCredential("openai", cred); err != nil {
fmt.Printf("Failed to save credentials: %v\n", err)
os.Exit(1)
}
Expand Down Expand Up @@ -188,7 +188,7 @@ func authLoginGoogleAntigravity() {
fmt.Printf("Project: %s\n", projectID)
}

if err := auth.SetCredential("google-antigravity", cred); err != nil {
if err = auth.SetCredential("google-antigravity", cred); err != nil {
fmt.Printf("Failed to save credentials: %v\n", err)
os.Exit(1)
}
Expand Down Expand Up @@ -265,7 +265,7 @@ func authLoginPasteToken(provider string) {
os.Exit(1)
}

if err := auth.SetCredential(provider, cred); err != nil {
if err = auth.SetCredential(provider, cred); err != nil {
fmt.Printf("Failed to save credentials: %v\n", err)
os.Exit(1)
}
Expand Down
3 changes: 2 additions & 1 deletion cmd/picoclaw/cmd_gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ func gatewayCmd() {
channel, chatID = "cli", "direct"
}
// Use ProcessHeartbeat - no session history, each heartbeat is independent
response, err := agentLoop.ProcessHeartbeat(context.Background(), prompt, channel, chatID)
var response string
response, err = agentLoop.ProcessHeartbeat(context.Background(), prompt, channel, chatID)
if err != nil {
return tools.ErrorResult(fmt.Sprintf("Heartbeat error: %v", err))
}
Expand Down
4 changes: 2 additions & 2 deletions cmd/picoclaw/cmd_skills.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,15 +118,15 @@ func skillsInstallFromRegistry(cfg *config.Config, registryName, slug string) {
workspace := cfg.WorkspacePath()
targetDir := filepath.Join(workspace, "skills", slug)

if _, err := os.Stat(targetDir); err == nil {
if _, err = os.Stat(targetDir); err == nil {
fmt.Printf("\u2717 Skill '%s' already installed at %s\n", slug, targetDir)
os.Exit(1)
}

ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()

if err := os.MkdirAll(filepath.Join(workspace, "skills"), 0o755); err != nil {
if err = os.MkdirAll(filepath.Join(workspace, "skills"), 0o755); err != nil {
fmt.Printf("\u2717 Failed to create skills directory: %v\n", err)
os.Exit(1)
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/channels/telegram.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,10 +267,10 @@ func (c *TelegramChannel) handleMessage(ctx context.Context, message *telego.Mes

transcribedText := ""
if c.transcriber != nil && c.transcriber.IsAvailable() {
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
transcriberCtx, cancel := context.WithTimeout(ctx, 30*time.Second)
defer cancel()

result, err := c.transcriber.Transcribe(ctx, voicePath)
result, err := c.transcriber.Transcribe(transcriberCtx, voicePath)
if err != nil {
logger.ErrorCF("telegram", "Voice transcription failed", map[string]any{
"error": err.Error(),
Expand Down
2 changes: 1 addition & 1 deletion pkg/channels/wecom.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ func (c *WeComBotChannel) handleMessageCallback(ctx context.Context, w http.Resp
AgentID string `xml:"AgentID"`
}

if err := xml.Unmarshal(body, &encryptedMsg); err != nil {
if err = xml.Unmarshal(body, &encryptedMsg); err != nil {
logger.ErrorCF("wecom", "Failed to parse XML", map[string]any{
"error": err.Error(),
})
Expand Down
2 changes: 1 addition & 1 deletion pkg/channels/wecom_app.go
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ func (c *WeComAppChannel) handleMessageCallback(ctx context.Context, w http.Resp
AgentID string `xml:"AgentID"`
}

if err := xml.Unmarshal(body, &encryptedMsg); err != nil {
if err = xml.Unmarshal(body, &encryptedMsg); err != nil {
logger.ErrorCF("wecom_app", "Failed to parse XML", map[string]any{
"error": err.Error(),
})
Expand Down
13 changes: 0 additions & 13 deletions pkg/channels/wecom_app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -852,19 +852,6 @@ func TestWeComAppMessageStructures(t *testing.T) {
}
})

t.Run("WeComImageMessage structure", func(t *testing.T) {
msg := WeComImageMessage{
ToUser: "user123",
MsgType: "image",
AgentID: 1000002,
}
msg.Image.MediaID = "media_123456"

if msg.Image.MediaID != "media_123456" {
t.Errorf("Image.MediaID = %q, want %q", msg.Image.MediaID, "media_123456")
}
})

t.Run("WeComAccessTokenResponse structure", func(t *testing.T) {
jsonData := `{
"errcode": 0,
Expand Down
4 changes: 1 addition & 3 deletions pkg/channels/wecom_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,10 +198,8 @@ func TestWeComBotVerifySignature(t *testing.T) {
Token: "",
WebhookURL: "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=test",
}
base := NewBaseChannel("wecom", cfgEmpty, msgBus, cfgEmpty.AllowFrom)
chEmpty := &WeComBotChannel{
BaseChannel: base,
config: cfgEmpty,
config: cfgEmpty,
}

if !WeComVerifySignature(chEmpty.config.Token, "any_sig", "any_ts", "any_nonce", "any_msg") {
Expand Down
2 changes: 1 addition & 1 deletion pkg/migrate/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func Run(opts Options) (*Result, error) {
return nil, err
}

if _, err := os.Stat(openclawHome); os.IsNotExist(err) {
if _, err = os.Stat(openclawHome); os.IsNotExist(err) {
return nil, fmt.Errorf("OpenClaw installation not found at %s", openclawHome)
}

Expand Down
10 changes: 5 additions & 5 deletions pkg/migrate/migrate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,21 +58,21 @@ func TestConvertKeysToSnake(t *testing.T) {
t.Fatal("expected map[string]interface{}")
}

if _, ok := m["api_key"]; !ok {
if _, ok = m["api_key"]; !ok {
t.Error("expected key 'api_key' after conversion")
}
if _, ok := m["api_base"]; !ok {
if _, ok = m["api_base"]; !ok {
t.Error("expected key 'api_base' after conversion")
}

nested, ok := m["nested"].(map[string]any)
if !ok {
t.Fatal("expected nested map")
}
if _, ok := nested["max_tokens"]; !ok {
if _, ok = nested["max_tokens"]; !ok {
t.Error("expected key 'max_tokens' in nested map")
}
if _, ok := nested["allow_from"]; !ok {
if _, ok = nested["allow_from"]; !ok {
t.Error("expected key 'allow_from' in nested map")
}

Expand Down Expand Up @@ -108,7 +108,7 @@ func TestLoadOpenClawConfig(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if err := os.WriteFile(configPath, data, 0o644); err != nil {
if err = os.WriteFile(configPath, data, 0o644); err != nil {
t.Fatal(err)
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/providers/codex_cli_credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func ReadCodexCliCredentials() (accessToken, accountID string, expiresAt time.Ti
}

var auth CodexCliAuth
if err := json.Unmarshal(data, &auth); err != nil {
if err = json.Unmarshal(data, &auth); err != nil {
return "", "", time.Time{}, fmt.Errorf("parsing %s: %w", authPath, err)
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/tools/edit.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func (t *EditFileTool) Execute(ctx context.Context, args map[string]any) *ToolRe
return ErrorResult(err.Error())
}

if _, err := os.Stat(resolvedPath); os.IsNotExist(err) {
if _, err = os.Stat(resolvedPath); os.IsNotExist(err) {
return ErrorResult(fmt.Sprintf("file not found: %s", path))
}

Expand Down
8 changes: 5 additions & 3 deletions pkg/tools/filesystem.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,19 @@ func validatePath(path, workspace string, restrict bool) (string, error) {
return "", fmt.Errorf("access denied: path is outside the workspace")
}

var resolved string
workspaceReal := absWorkspace
if resolved, err := filepath.EvalSymlinks(absWorkspace); err == nil {
if resolved, err = filepath.EvalSymlinks(absWorkspace); err == nil {
workspaceReal = resolved
}

if resolved, err := filepath.EvalSymlinks(absPath); err == nil {
if resolved, err = filepath.EvalSymlinks(absPath); err == nil {
if !isWithinWorkspace(resolved, workspaceReal) {
return "", fmt.Errorf("access denied: symlink resolves outside workspace")
}
} else if os.IsNotExist(err) {
if parentResolved, err := resolveExistingAncestor(filepath.Dir(absPath)); err == nil {
var parentResolved string
if parentResolved, err = resolveExistingAncestor(filepath.Dir(absPath)); err == nil {
if !isWithinWorkspace(parentResolved, workspaceReal) {
return "", fmt.Errorf("access denied: symlink resolves outside workspace")
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/tools/i2c_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ func (t *I2CTool) readDevice(args map[string]any) *ToolResult {
if reg < 0 || reg > 255 {
return ErrorResult("register must be between 0x00 and 0xFF")
}
_, err := syscall.Write(fd, []byte{byte(reg)})
_, err = syscall.Write(fd, []byte{byte(reg)})
if err != nil {
return ErrorResult(fmt.Sprintf("failed to write register 0x%02x: %v", reg, err))
}
Expand Down
6 changes: 3 additions & 3 deletions pkg/voice/transcriber.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,17 +79,17 @@ func (t *GroqTranscriber) Transcribe(ctx context.Context, audioFilePath string)

logger.DebugCF("voice", "File copied to request", map[string]any{"bytes_copied": copied})

if err := writer.WriteField("model", "whisper-large-v3"); err != nil {
if err = writer.WriteField("model", "whisper-large-v3"); err != nil {
logger.ErrorCF("voice", "Failed to write model field", map[string]any{"error": err})
return nil, fmt.Errorf("failed to write model field: %w", err)
}

if err := writer.WriteField("response_format", "json"); err != nil {
if err = writer.WriteField("response_format", "json"); err != nil {
logger.ErrorCF("voice", "Failed to write response_format field", map[string]any{"error": err})
return nil, fmt.Errorf("failed to write response_format field: %w", err)
}

if err := writer.Close(); err != nil {
if err = writer.Close(); err != nil {
logger.ErrorCF("voice", "Failed to close multipart writer", map[string]any{"error": err})
return nil, fmt.Errorf("failed to close multipart writer: %w", err)
}
Expand Down