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

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.

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) {

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 {

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(

View file

@ -4,7 +4,8 @@
//
// Copyright (c) 2026 PicoClaw contributors
package utils
// Package fileutil provides file manipulation utilities.
package fileutil
import (
"fmt"

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")

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)
}

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.

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.

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)
}