refactor(pkg): move atomic file write to dedicated fileutil package

This commit is contained in:
mosir
2026-02-24 23:57:13 +08:00
parent 4aed3591e7
commit 11996f1a0b
10 changed files with 21 additions and 19 deletions
+3 -3
View File
@@ -13,7 +13,7 @@ import (
"strings"
"time"
"github.com/sipeed/picoclaw/pkg/utils"
"github.com/sipeed/picoclaw/pkg/fileutil"
)
// MemoryStore manages persistent memory for the agent.
@@ -62,7 +62,7 @@ func (ms *MemoryStore) ReadLongTerm() string {
func (ms *MemoryStore) WriteLongTerm(content string) error {
// Use unified atomic write utility with explicit sync for flash storage reliability.
// Using 0o600 (owner read/write only) for secure default permissions.
return utils.WriteFileAtomic(ms.memoryFile, []byte(content), 0o600)
return fileutil.WriteFileAtomic(ms.memoryFile, []byte(content), 0o600)
}
// ReadToday reads today's daily note.
@@ -102,7 +102,7 @@ func (ms *MemoryStore) AppendToday(content string) error {
}
// Use unified atomic write utility with explicit sync for flash storage reliability.
return utils.WriteFileAtomic(todayFile, []byte(newContent), 0o600)
return fileutil.WriteFileAtomic(todayFile, []byte(newContent), 0o600)
}
// GetRecentDailyNotes returns daily notes from the last N days.
+2 -2
View File
@@ -6,7 +6,7 @@ import (
"path/filepath"
"time"
"github.com/sipeed/picoclaw/pkg/utils"
"github.com/sipeed/picoclaw/pkg/fileutil"
)
type AuthCredential struct {
@@ -71,7 +71,7 @@ func SaveStore(store *AuthStore) error {
}
// Use unified atomic write utility with explicit sync for flash storage reliability.
return utils.WriteFileAtomic(path, data, 0o600)
return fileutil.WriteFileAtomic(path, data, 0o600)
}
func GetCredential(provider string) (*AuthCredential, error) {
+2 -2
View File
@@ -7,7 +7,7 @@ import (
"sync/atomic"
"github.com/caarlos0/env/v11"
"github.com/sipeed/picoclaw/pkg/utils"
"github.com/sipeed/picoclaw/pkg/fileutil"
)
// rrCounter is a global counter for round-robin load balancing across models.
@@ -527,7 +527,7 @@ func SaveConfig(path string, cfg *Config) error {
}
// Use unified atomic write utility with explicit sync for flash storage reliability.
return utils.WriteFileAtomic(path, data, 0o600)
return fileutil.WriteFileAtomic(path, data, 0o600)
}
func (c *Config) WorkspacePath() string {
+2 -2
View File
@@ -11,7 +11,7 @@ import (
"time"
"github.com/adhocore/gronx"
"github.com/sipeed/picoclaw/pkg/utils"
"github.com/sipeed/picoclaw/pkg/fileutil"
)
type CronSchedule struct {
@@ -336,7 +336,7 @@ func (cs *CronService) saveStoreUnsafe() error {
}
// Use unified atomic write utility with explicit sync for flash storage reliability.
return utils.WriteFileAtomic(cs.storePath, data, 0o600)
return fileutil.WriteFileAtomic(cs.storePath, data, 0o600)
}
func (cs *CronService) AddJob(
+2 -1
View File
@@ -4,7 +4,8 @@
//
// Copyright (c) 2026 PicoClaw contributors
package utils
// Package fileutil provides file manipulation utilities.
package fileutil
import (
"fmt"
+2 -2
View File
@@ -19,7 +19,7 @@ import (
"github.com/sipeed/picoclaw/pkg/logger"
"github.com/sipeed/picoclaw/pkg/state"
"github.com/sipeed/picoclaw/pkg/tools"
"github.com/sipeed/picoclaw/pkg/utils"
"github.com/sipeed/picoclaw/pkg/fileutil"
)
const (
@@ -276,7 +276,7 @@ This file contains tasks for the heartbeat service to check periodically.
Add your heartbeat tasks below this line:
`
if err := utils.WriteFileAtomic(heartbeatPath, []byte(defaultContent), 0o644); err != nil {
if err := fileutil.WriteFileAtomic(heartbeatPath, []byte(defaultContent), 0o644); err != nil {
hs.logError("Failed to create default HEARTBEAT.md: %v", err)
} else {
hs.logInfo("Created default HEARTBEAT.md template")
+2 -2
View File
@@ -10,7 +10,7 @@ import (
"path/filepath"
"time"
"github.com/sipeed/picoclaw/pkg/utils"
"github.com/sipeed/picoclaw/pkg/fileutil"
)
type SkillInstaller struct {
@@ -68,7 +68,7 @@ func (si *SkillInstaller) InstallFromGitHub(ctx context.Context, repo string) er
skillPath := filepath.Join(skillDir, "SKILL.md")
// Use unified atomic write utility with explicit sync for flash storage reliability.
if err := utils.WriteFileAtomic(skillPath, body, 0o600); err != nil {
if err := fileutil.WriteFileAtomic(skillPath, body, 0o600); err != nil {
return fmt.Errorf("failed to write skill file: %w", err)
}
+2 -2
View File
@@ -9,7 +9,7 @@ import (
"sync"
"time"
"github.com/sipeed/picoclaw/pkg/utils"
"github.com/sipeed/picoclaw/pkg/fileutil"
)
// State represents the persistent state for a workspace.
@@ -139,7 +139,7 @@ func (sm *Manager) saveAtomic() error {
return fmt.Errorf("failed to marshal state: %w", err)
}
return utils.WriteFileAtomic(sm.stateFile, data, 0o600)
return fileutil.WriteFileAtomic(sm.stateFile, data, 0o600)
}
// load loads the state from disk.
+2 -2
View File
@@ -9,7 +9,7 @@ import (
"strings"
"time"
"github.com/sipeed/picoclaw/pkg/utils"
"github.com/sipeed/picoclaw/pkg/fileutil"
)
// validatePath ensures the given path is within the workspace if restrict is true.
@@ -280,7 +280,7 @@ func (h *hostFs) ReadDir(path string) ([]os.DirEntry, error) {
func (h *hostFs) WriteFile(path string, data []byte) error {
// Use unified atomic write utility with explicit sync for flash storage reliability.
// Using 0o600 (owner read/write only) for secure default permissions.
return utils.WriteFileAtomic(path, data, 0o600)
return fileutil.WriteFileAtomic(path, data, 0o600)
}
// sandboxFs is a sandboxed fileSystem that operates within a strictly defined workspace using os.Root.
+2 -1
View File
@@ -9,6 +9,7 @@ import (
"sync"
"time"
"github.com/sipeed/picoclaw/pkg/fileutil"
"github.com/sipeed/picoclaw/pkg/logger"
"github.com/sipeed/picoclaw/pkg/skills"
"github.com/sipeed/picoclaw/pkg/utils"
@@ -198,5 +199,5 @@ func writeOriginMeta(targetDir, registryName, slug, version string) error {
}
// Use unified atomic write utility with explicit sync for flash storage reliability.
return utils.WriteFileAtomic(filepath.Join(targetDir, ".skill-origin.json"), data, 0o600)
return fileutil.WriteFileAtomic(filepath.Join(targetDir, ".skill-origin.json"), data, 0o600)
}